This came out of a question posted on Hacker News
recentlyback in 2014. I wanted to expand upon some of my thoughts there.
I had latched on to a particular piece of the question:
Also I waste considerable amount of time trying to do things in the most readable, maintainable and simple way possible. This means weighing merits of different solutions and choosing one. I am a really hesitant decision maker, resulting in more wasted hours.
Others latched on to what they saw as burnout, but I remember this particular dread that took me years to overcome. The problem wasn’t the workload, the problem was that I hadn’t yet figured out how to conquer this problem, to the extent I have today. It still is something that slows me down, relatively speaking, but not to the point that it holds me back like it did then.
With what I now understand about developer skills, This is not one problem but three: it is a problem with wisdom, speed, and discipline, and can be attacked from multiple angles.
First, let me operationalize these terms within this context: By wisdom, I am referring to the accumulated best practices and patterns that lead to easy to maintain code. By speed, I am referring to the techniques we acquire to write code more quickly, from better mastery of our IDE to not spending time trying to reinvent the wheel with each new problem. By discipline, the ability to focus on the problem, avoiding distraction and the yak shaving that interferes with our productivity.
If we want to attack this from the wisdom perspective, it is this: we are afraid of making the wrong decision because we are afraid to refactor. We are afraid to refactor because we don’t have sufficient test coverage. What if I break something? Kent Beck, in his RIP TDD post, mentions this feeling of overwhelm, which I believe is the root of this sort of analysis paralysis.
The good news is, for developers like us, test driven development is very helpful as a technique for getting us over these problems. If our team is not test-friendly (by this I don’t necessarily mean TDD — I mean good old-fashioned automated tests that cover the system), however, it will be difficult for us to make the jump because their code will not be written in ways to make it easy to test.
Once we have sufficient test coverage, we can look at refactoring techniques which we can internalize to give us the tools at our fingertips to make the next move.
There are a few books I can suggest to help us jump the chasm:
Clean Code by Bob Martin. This book helped me think in more testable code, and also helped me understand how to make better decisions the first time around. It helped me by seeing patterns I didn’t know first.
Refactoring by Martin Fowler. This one is old, but knowing the patterns of changing code gives us more confidence in knowing what is right, rather than hemming and hawing over what is readable and maintainable.
Working Effectively with Legacy Code by Michael Feathers can help get from here to there. All of these help from three aspects: They help us develop a set of tests so we are less afraid of breaking existing things, they give us the freedom to experiment, and they help us break things down into smaller, more manageable problems by letting us think about “what is the next thing I can test?”
If we want to attack this from a Speed issue, these are the techniques I used to speed myself up, especially within new code where the problem wasn’t tests. As this wasn’t something I had internalized, I had to systematically look at how to solve this problem.
First, I looked for patterns within the application. Most features have a fairly similar flow, and the same patterns popped up. So, I made a checklist of things that were going to go into each feature and looked for patterns in the application that were used, rather than trying to figure out the best way for each feature. The fewer choices I make at any one point, the faster I can go. (Also, I’m not tied down to any particular implementation if I write tests. I don’t worry about regressions — the tests will cover that for me. Of course, I always do a double check manually before I check in, but I don’t have to worry about debugging something I broke a half hour ago.)
Second, I made a dedicated effort to move beyond learning just enough of my particular stack to get the next feature done, and made a deep dive both into the documentation, reference, books, and the source code. This gave me a better idea of the intended patterns, and I also recognized a few places my coworkers and I were reinventing the wheel unnecessarily, and plugins that had solved our problems already with only minor modifications.
Finally, in the worst case scenario, sometimes I have even written multiple solutions. It ended up faster to write all of them and choose one than to get stuck in analysis paralysis. (That isn’t to say you shouldn’t think before you write code!)
Finally, I attacked this from a discipline angle. When I started out, I wasn’t a particularly disciplined programmer, and have found these techniques helped me immensely.
First, I started meditating. By doing so, I became more self-aware of analysis paralysis. When I recognize it now, I take a few centering breaths to calm my mind, and mindfully choose a path.
Second, while I’m not as good as I have been at times, I try to exercise. In the same way as meditation, exercise helps us learn to clear our mind and focus on command, and it helps sharpen our discipline chops.
With these, we can develop an awareness of how our body feels. Then we can develop an awareness of how analysis paralysis feels. If we can catch ourselves in the act, and cannot find any way out, we can then institute a last ditch solution: When caught in the trap, I set 30 minutes on my timer, and bring out a pad of paper. If you feel you have the freedom, turn off the monitor.
Take a few deep breaths, and sketch out the solutions in the first ten minutes on the first page. Use UML or your own system.
In the next ten minutes, write a pro/con analysis on each path.
In the final ten minutes, make the decision. After this, my analysis time is up and I must code.
I don’t pretend to have conquered analysis paralysis, but then again those who have often don’t think before starting a solution, and I have to come in and clean up afterwards. :) Think before coding, but don’t get overwhelmed. Good luck!