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
>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.
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.
> 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.
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.
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
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
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.
For me, it was grabbing every bug ticket in the company. I just fixed bugs on top of whatever else was going on.
I learned all the ways in which bugs can appear, when to bring up potential issues ("if I fix this bug, our sales may drop by up to 25%"), how to find the causes of bugs, and how to fix them.
I think this makes you appear to be a better programmer, because you learn to look out for things that will increase/decrease sales, you can spot bugs before they're even merged into the codebase, and you can communicate technical issues well.
Note that I said "appear" because I bet most great programmers don't think they're all that great. Hell, I've done what I think is amazing work only to be told it is shit. I've also done what I think is shitty work and told it is great (or maybe they're just being nice and its shit, who knows). At the end of the day, if you're solving more problems than you're creating, you're succeeding.
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.
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.
My strategy is to build programs I actually need/want to use.
So basically, project-based learning.
> 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!
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
Whenever I get stuck, I will start chipping away at technical debt. This is usually simple refactoring work, cleaning up features or fixing bugs that result in a cleaner system. If I do this enough, things seem to magically get unstuck.
It’s a little like cleaning out a clogged drain. You start pulling out muck until the water starts to flow, and it will eventually start to flow on its own. Then you can jump back in the flow.
Refactoring your code until it is “perfect” is a good exercise. When I was starting out, I would refactor endlessly. That took a lot of time, but eventually I started writing code that didn’t need to be refactored immediately.
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.
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.
Write code, a lot of it, even if it is useless :)
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 :)
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.
> 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 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.
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.
It's a combination of the following:
1. By deep-diving in topics I encounter during work (this is not limited to programming skills, but also e.g. product/people management).
2. By taking on difficult projects
3. By working and keeping in touch with experts
4. By teaching other people what I know
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.
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.
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.
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!