Ask HN: How did you become better at programming?

65 points by techsin101 ↗ HN
I've found that the difference between me and great programmers I've come across in person or online is that they have extreme mental fortitude, get unstuck on their own, and pick up new things with breeze.

Whereas, I find myself going for almost academic perfection (i.e read all docs first) / mastery. Really procrastinate hard when I hit the wall and just hope for things to click. And then just get sleepy when I do start reading code. This means if I'm in my space I'm super productive, but anytime I come across something I don't have an expert level knowledge I come to complete halt.

It took me lot of self introspection to realize this, so if there are other pitfalls that you have come across let me know, I might have them too.

43 comments

[ 8.8 ms ] story [ 101 ms ] thread
> they have extreme mental fortitude, get unstuck on their own, and pick up new things with breeze

Then have extreme mental fortitude. That sounds like a choice, not an intrinsic attribute.

> Whereas, I find myself going for almost academic perfection (i.e read all docs first) / mastery.

It sounds like you’re answering your own questions here.

I do the later so I don't get stuck, i.e. if I have mastery over language/framework/etc then I'll not get stuck, because when I do get stuck my stress goes to cloud 9 and rapidly start losing hope. Spend days alternating between procrastinating and trying things which feels like putting hands on sizzling pan. But "the PROS" I've seen encounter bigger problems and move past them in a day or two, without going through entire cycle of despair.
How long have you been in tech if you don’t mind my asking? I’ve found that (surprise) confidence is a function of experience. The kids that started early (age 8 to 13) always seemed to have a leg up on the rest of us, but it’s because they’ve got a solid 5-10 years “experience” (YMMV in terms of quality of course).

If you’re still junior in your career, just pay attention. If you’re getting senior level but you’re not getting enough work, start doing more personal projects that require you to “own” the whole thing from end to end.

about 7 years
Does that include education (uni/boot camp)? Because honestly I think unless you went to a school in a tech hub city, they didn’t teach you everything you need to know about CS.

Have you read the seminal literature (the thing they didn’t teach you in ugrad)? Gang of Four OOP design patterns, Patterns of enterprise architecture?

You might ask your employer for a subscription to O’reilly books online.

Take this for the Internet advice that it is, but...

Dealing with problems that you don't know the answers to right away is part of the job, and it's one that stresses you out. By doing extensive prep, you're avoiding some number of stressful incidents, but you're also making sure that the incidents you do have are higher stakes.

You might try doing a less detailed read of documentation before you start, then if you get stuck, you can expect to look at the documentation to get you unstuck. Maybe it will, maybe it won't, but you'll practice getting unstuck and it will hopefully be less stressful.

Some of us just despair on the inside.

I've been doing this for over ten years. Experience doesn't guarantee you'll be a great or even good programmer, but it sure helps especially if you're in environments where you will be pushed to take on more responsibilities and have mentorship.
I won't say I'm pushed, but rather I get put a knife to throat, each time that has happened it has chipped away at my passion for programming in general. Now that I think of coding then the emotions that come up are negative. When I was a beginner emotions were positive and exhilarating, like I couldn't wait to wake up tomorrow and try this new thing. I believe it's all thanks "being pushed". I hate managers who think like this.
Few common attributes I've seen in some of the master programmers I've had the privilege to work with,

* write lots and lots of code as beginner till some programs live in the muscle memory of your fingers

* humility, be easy on yourself; no one makes it in the first jump

* find better programs and copy but never paste, as a beginner always key-in your programs

* keep a count of the lines you write and the time you take to write (reach 100k lines, this is to motivate yourself)

* make programming habit

* seek better programmers and study their code

* always go from code to theory

>>Whereas, I find myself going for almost academic perfection (i.e read all docs first) / mastery.

I suffered from the same problem. The key for me was to say to myself, it's ok to write non-perfect programs, it's ok to fail, in fact it's a must to fail, humility, humility, humility is the key virtue for a true master programmer.

> * find better programs and copy but never paste, as a beginner always key-in your programs

This is a surprisingly valuable tip. By manually typing in the code instead of just using copy/paste, you have the opportunity to make typing errors, causing programming problems you then have to debug. It forces you to dig into things in order to figure out what's going on and fix it.

Bonus points if you change some minor aspect of the code while you're typing it in. Change variable names, maybe genericize it a little. Something that theoretically shouldn't make any difference. The problems will be worse, forcing you to dig in even more to fix them.

I've learned so much this way over the years. YMMV, of course.

> And then just get sleepy when I do start reading code.

Could it be that the code you are looking at is solving a problem that is entirely uncompelling to you?

In my estimation, I got better at programming by trying to solve challenging, real-world problems rather than by laser-focusing on specific blocks of code or documentation.

Most of my time these days isn't even writing code. It's thinking about how to solve the problem abstractly. If you are trying to solve some problem in your head, it really helps if you find parts of it exciting or enjoyable.

You can very quickly spot a developer who is not interested in their problem domain. They are typically off in some devops Narnia constructing a matrix of new problems that are interesting to hide inside of.

By building things on my own for myself.

I first built a simple thing. But it was buggy. I learned about debugging. Then I wanted to add features to it. But the code was ugly. So I learned how to refactor. Then I learned about modules to separate things out better.

Then I started breaking up bigger features into smaller features and planning my implementation - sometimes in a notebook. So, white boarding was now easy.

I'd then write the pseudo code as comments first. For obvious things, I'd delete the comments as I replaced them with actual code. For less obvious things, I'd leave the comment in-place.

I also became proficient enough that I could write code for whatever I was thinking without needing to constantly look up syntax. This made me fearless during pair programming.

I also found myself solving problems that more senior engineers talk about when they talk about battle wounds. This was awesome because, as soon as I talked about my (fairly simple, really) projects, it made the interviewers happy. I've received at least two jobs this way.

One big takeaway for me from doing this has been that simple code is far nicer to work with and return to than clever code. If your code is so simple that even a freshman in college can understand it, then thats a good thing!

There's no shortcut to just building things, no 100 second YT tutorial or lengthy HN exposition can substitute pure hours in assembling software. Sure, some people might pick it up a bit quicker/slower but fundamentally there's no better replacement.

One of the side benefits is you can version these projs and iterate/recoil in horror every 6-12 months for the next few decades -- once you can open that repo and not be shaken up then you've made it: time to retire as you're finally losing your faculties.

Do your own projects start to finish.

At my job I have yet to do the same thing twice. It's hard to get any momentum like this. Maybe your situation is the same and by great programmers you mean people that do the same thing over and over.

Write down your requirements before you start (README.md).

Always write documentation.

For nontrivial projects, iterate your design on paper before writing it in code. Write down why you chose a particular design against other candidates (eg. buy vs build) as part of your documentation. Use CI/CD and automate testing. Document test results. Use an RCS/VCS.

You're not going to come up with a simple design through any kind of coding techniques or any kind of programming language concepts. Simplicity has to be achieved above the code level before you get to the point which you worry about how you actually implement this thing in code. - Leslie Lamport

You're not going to find the best algorithm in terms of computational complexity by coding. - Leslie Lamport

Write code, a lot of it, even if it is useless :)
I got better by doing the opposite of what you do, and find reading a lot of anything before trying it to be a complete waste of time. Unless it's a different way of explaining or building on something you're already familiar with. I've read numerous books on various languages and frameworks, but they've only been useful if I've been incrementally trying the code as I go. Documentation is basically pointless to read unless I needed it, and if someone interrogated me on the method signature for some api, I'd probably laugh. I used to think reading counted as learning, but it doesn't, and coming to that realization helped me learn a little more efficiently.

Other than that, like others have said, reading and poking at a lot of code, diguring out how to get something accepted in a big legacy open source project would help tremendously, and is something I recommend to anyone serious about starting a career in programming.

Also, ya having the humility to accept you're not as good as you might think is pretty pivotal. A few years ago I basically just started accepting that I'm only as good as some measure (that I accept as a valid measure) says I am, but my nebulous opinion of my own skill isn't as valuable. Could be commit count, could be code clarity, could be PR reviews, time to completion of a task, whatever. Pick some measure you agree with that would be relevant, and aim to reduce the variability in hitting a mark. Think about what 'good' means in the context that you want to be good in, and build a mental model of that

Working on good open source projects and reading the code.

What's a good open source project, that requires some research but I look for projects that are:

* Popular.

* Haven't a lot of open issues.

* Maye you need a certain level of proficiency to realize what good code looks like, but I think you'll know it when you see it, because good code is readable.

At one point I became very active in a web forum related to a language I was using (Objective-C). I tried to help as many people as possible. I learned a lot during that year because I was getting experience from other people's bugs instead of just from the bugs I was creating :)

Re: getting unstuck, see: https://news.ycombinator.com/item?id=32735905#32741746

There's no replacement for practice. I wrestle with the same problem; what's helped me is finding things to work on I'm interested in.

Say I want to brush up on C again. I'm not going to go reading books about it. 80% of it's going to be going over conventions I'm already familiar with.

Instead, I'll think about something I want to write with it... then dive in. Referring to manuals where necessary.

This being something I want in the end helps me push through the uncertainty, and not living in the documentation tests my memory while keeping my eyes from glazing over

Eventually it's less of a conscious effort to do things. The idea spawns the 'how' effortlessly

Keep in mind I burned myself out on programming/development. It's important to know when to sit it down and come back, too.

The closest I get anymore is DevOps, writing pseudocode in a higher level language that does the grunt work for me

Don't just fix errors, read the warnings from the compiler, understand what they mean and aim for a warning free compile. You'll improve rapidly and understand your build system.
Working on my psychological issues. I was too much of a perfectionist and had anger issues, now I can just let go and have fun writing code instead of worrying, that's how I got better.
I like to be thrown right into the fire. If I don’t know a language or tech I will piecemeal it together from stackoveflow snippets even if I don’t totally understand it.

There will be bugs inevitably in getting it running, but debugging these give me pound for pound the highest return in learning.

My strategy is to build programs I actually need/want to use.

So basically, project-based learning.

Embrace the mindset of start and stop. It's inherent to the concept of "programming something to be automatic": you finally succeed at automating something, so it happens instantly. Now you have a different bottleneck, so you automate that, so now it happens instantly. Repeat...

Coding has a lot of it, and it never gets better, you just get better at dealing with it. No moment magically arrives where it becomes smooth and natural. The actual terminus is to say "I don't need this to be further automated" and to live within the system you have and allow it to become muscle memory - a decidedly non-tech-centric thing to do. If you have something specific to say through programming, you absolutely have to let go of the dev tools at some point.

You can often exhaust some of the anxiety by approaching tasks in iterative fashion: not immediately going for the prize as you see it, but instead looking for an appropriate mode of study that gets you closer.

For example, earlier today I wrote a short Python script for someone on my Twitter feed who wanted to collate a set of scanned pages in a defined filename order(page 1, 3, 5... stay the same, pages 32, 31, 29... become page 2, 4, 6...)

The first thought that came to mind was that this did need some programming because it has an algorithmic logic to it. And that Python is a likely solution since it lets you do file renames with os.rename() - one line to import os, the other to rename.

But then I asked myself whether I wanted to share the most caveman programming way of doing it(hardcode 32 lines of renames) or if I wanted to share an algorithm. Since we're talking about an end user that isn't a professional developer but does work intensively with computers and has some grasp of their operational logic, and is interested in a genuine automation of file renames using that logic, not just a change in the interface.

And so I went ahead and coded a simple algorithm, but still using the most common mechanisms of imperative programming: no functional maps or iterators, just a while loop with three variables being mutated, string concatenation, and a function call to left-pad the numbers as a string.

The solution is incomplete as an automation: the actual task needs the user to change the counts and string literals to fit the scans being processed. But the scope being addressed is "I don't know what tool to even use to automate this. Recommend me something." So setting up a piece of skeleton code that fit in a tweet and can be copy-paste-modified looked correct. It gets close enough to be a reference, it documents the involved syntax, and it isn't actively intimidating: Python is one dependency to install, plus a little bit of reading up on "how do I debug my script".

And when we're talking about when coding feels good, that's usually around the sweet spot. It's sufficiently empowering, but doesn't create a lengthy research loop. When I have to look at a new domain I still get stonewalled by the research loop, because, yeah, you really do have to go through the docs and poke around with it, possibly over a period of weeks to months, to know.

I start by writing a small amount of code at a level i understand. I add unit tests demonstrating that it behaves as it should. I attempt to improve it via a single small change and add tests validating this new behaviour is working as it should. I commit at each step too. I do this to ensure that the gap between my understanding at the last step and this new step is concise and easily testable. I try to be patient with this process, slowing adding functionality. It's slow, even tedious but methodical. After an hour or two you look at what you've got and as a whole it's impressive. Adding unit tests with every step as you go and committing at every success means you're continually 'saving your game' and can just revert / commit at every step.

I find this approach means you don't hit the 'its all too hard' barrier.

>Really procrastinate hard when I hit the wall and just hope for things to click. And then just get sleepy when I do start reading code.

This is a psychological thing called the freeze response that activates as your brain responds to stress.

You may want to find a therapist who can help you work it out. This can develop in school in response to "difficult" academic tasks as in ones we have no prior experience with. For example, a lot of folks will freeze in math class for example so much that they then decide not to do math to avoid triggering the response.

It is quite common in perfectionists and folks with high anxiety. Fortunately, you can reprogram your brain.

BTW you're not alone, happened to me a lot. It really hits hard when you also have imposter syndrome.

My advice is therapy to learn to enjoy the journey and problem solving process.

Many folks below have ideas for that. Most basic, work on programming projects that are low value to learn skills and take it step by step. When you get stuck, break something down into smaller steps or find away around it.

Even if your project or product doesn't ship, take comfort in that you learned something.

"This is a psychological thing called the freeze response that activates as your brain responds to stress."

Interesting, I'd never thought of it like that, fear of failure as a lazy perfectionist is too real

I am curious, why do you include the word "lazy" in your description of fear of failure?
Not wanting to do X or Y can be perceived as lazy (I consider myself lazy).
I found reading more code helped me to become a better programmer. It helps a lot that reading code (at least for me) is much faster than writing code, so you can do more of it.
Just keep building things. When you can't build it, google it. When you can't google it, ask. When the "internet" doesn't know, find the one guru that knows everything about that very specific problem. Repeat until you're that guru guiding others.

All that with just a hint of sarcasm. Just build :)

Always wanting to know more than what i did yesterday/last week/last month/last year/etc with a focus on Knowledge for Knowledge's sake.

Everything else follows from the above.

Projects at home and lots of coding. Practice makes perfect imo..there are so many things I learned at home on personal projects that i applied at work.
A big turning point for me was reading Code Complete, by Steve McConnell. A lot of things "clicked" for me from reading that book, more so than any other.
> Whereas, I find myself going for almost academic perfection (i.e read all docs first) / mastery. Really procrastinate hard when I hit the wall and just hope for things to click. And then just get sleepy when I do start reading code. This means if I'm in my space I'm super productive, but anytime I come across something I don't have an expert level knowledge I come to complete halt.

I had this problem too. I'm working on getting over it by writing dumbshit stuff that I need at work. Mourn the perfect crystalline structure you have in your head as to How It Should Work, and understand that Good Enough now beats the tar out of Perfect never. Eventually you'll start improving the dumbshit stuff bit by bit, and as you write more stuff you'll get asymptotically closer and closer to the perfect thing you imagined once, but can realistically never be realized.

Good luck!