Software Design Basics
Designing software requires a myriad of skills and knowledge to do well including: domain knowledge, market knowledge, technical aptitude, up-to-date knowledge of the technology relevant to the domain, and the ability to spot patterns and trends. If you have all of these, you have the basics required for the knowledge-based decisions that you must make as you design your software. But designing software also involves dealing with the unknown.
Predicting the Future
It is impossible to know exactly how many customers or users you will have, exactly what features will bring in the most revenue, which implementation technologies will work the best for you, the effective useful life of various implementation technologies, or which of many possible implementations will best satisfy your users. For these factors, you must make guesses. In other words, you must predict the future!
Predicting the future is hard. The more information you gather and the more variables you consider, the better your prediction will be, but the more time your prediction will take. Also, the more possibilities you take into account when you design your software, the bigger and more complex your design will become and the longer it will take you to produce the design. The bigger and more complex your design becomes, the more likely it is that you will have difficult design problems to solve. Solving difficult design problems can take a long time. Once you've finished this big and complex design, it will take a proportionately long time to implement that design.
When you put all of this together it is obvious that the more accurately you try to predict the future, the more time and effort it will take. The question is, how do you decide when your design is good enough? If you take it too far, you'll either never finish your design, or you'll never ship your software. But if you don't spend enough time on design, you may end up with unhappy users or software that needs to be rewritten.
Consider the problem of predicting the weather. Modern forecasting software is pretty good, but the further out you look, the longer it takes for the forecast to run and the more likely it is for the forecast to finish after the day you are forecasting has already come and gone. The other factor to consider when designing software is that technologies and user needs change almost as frequently as the weather.
Iterative Design and Iterative Implementation
What can we do to solve this dilemma? There are two choices: spend lots and lots of time on up-front design and the software that results from that large design or do iterative design on a smaller set of features. When you do big up-front design for a large set of features, it is inevitable that you will have to rewrite large parts of your software in the future to take into account changes in technology or user needs. Of course, you don't have to accommodate change, but then it is also less likely that you will maintain or increase your revenue stream. Since it is inevitable that you will have to make changes to keep your software relevant, why not just accept this fact and start building the skills and implementing the practices to get good at iterative design and iterative implementation? The alternative is that when you are forced to change your software, it wasn't written with change in mind and your team isn't used to making changes on a regular basis.
It isn't that hard to make this decision. After all, everybody knows that predicting the future is hard. What's more important, getting good at predicting the future, or getting good at adapting to change?
Next: The Simplest Thing That Could Possibly Work