When should you stop planning and start working? In some projects I was ensnared by analysis paralysis and never got past the planning stage. In others I started writing code far too early and ended up redesigning the project several times. Both cases are obviously not productive and waste a lot of time.
I have been thinking about my process and why I get stuck so often. My fear of not starting seems to be greater than my fear of not finishing. I would often spend an hour or two thinking about how amazing the finished product would be and then jump into the code. Writing code must be more productive than designing code, right?
Being too eager to start working can be just as destructive and counter productive as over-planning. Without a solid plan the project is like a building without a foundation, it’ll sink into the mud when you start construction. Starting with a very detailed and rigid plan will produce a project like a house of cards; it’ll collapse under it’s own weight with the slightest disturbance. The process I’m describing tries to avoid the problems of both extremes by creating a solid plan and reevaluating it after each stage in development. It all starts with a good plan.
Plans shouldn’t be set in stone, but they are a good place to start.
This initial plan shouldn’t be a dense, complex monster. It’s meant to be a framework to guide your project to specific goals in an organized and deliberate fashion.
Before you start building this framework you need to know what you’re trying to accomplish and define what constitutes success. Knowing what the destination will look like will make it easier to plot a course.
Each milestone should be researched and explored. Creating a clear model of each feature in your project is crucial. It’s difficult to make a quality product when you don’t know what you’re making. This can be done in many ways. I like to use a combination of text files for more structured notes and sketches on paper for things like diagrams and illustrations.
The planning process shouldn’t stop here though. The plan should be reviewed and modified as needed during each step of the development process.
Now it’s time to take those milestones and turn them into a reality. Using Test Driven Development will make this process much easier in the long term. Every milestone should start with a quick and dirty implementation, a prototype. Make something you can play around with. This way you can figure out what will work, what breaks everything, what fits into your plan, and then throw it away. Whenever I play with a prototype I usually get new ideas and think of better ways to implement the feature. Going into the prototyping session with no expectations of using the code will make it easier to consider using a better solution if you come up with one.
After you’ve reviewed your prototype it’s time to start writing higher quality code. If any structural flaws or interface problems were found while building the prototype go back to the plan and update it. Start by writing the bare minimum needed to get the feature working. The prototype should serve as a guideline for dealing with any problems you may have encountered. When this step is done, the code probably won’t look very good or perform well, but at least it’s functional.
Now that you have some well-structured code implementing a specific feature in your plan it can be cleaned up. The code should have a clean interface and be fairly complete on the outside, but the inside still needs work. If you wrote tests it should be easy to refactor without accidentally breaking anything. A combination of reviewing, benchmarking, and editing the code while running tests after each change can be helpful, but the details of refactoring are beyond the scope of this post. When you’re done with this stage the code should be well-thought out, well-structured, and efficient.
This cycle of planning, prototyping, and refactoring should continue until the project is complete. Prototyping features first makes it easier to discover problems in the plan and implementation before committing to anything. Since the plan is reviewed and possibly updated after a prototype is built planning never really ends. The plan will evolve with the project as implementation reveals misconceptions. Once the feature’s problems are sorted out the code should be ready for rebuilding using the prototype as a guide. Once the internals of that clean structure are refactored the code should be finished for the moment. Then the cycle restarts and the next feature can be built using the same method.