I recently stumbled across an old joke about a software engineer that proposes an overly-complicated model for a simple problem. While I agree with the general sentiment of the joke, I don’t agree with the line of discourse that it represents. Among developers, overthinking is portrayed as wholly counterproductive. I disagree — I think overthinking a system is beneficial.
You may say, “But a toaster doesn’t need inheritance models for different types of breakfast foods!” I concede, this is true. But nonetheless, you should consider, “But what if it did?”
A lot of software systems unfortunately begin as a quick hack, with no formal model having ever been designed. Sometimes these systems are intended to be only temporary, stop-gap measures. Sometimes they are never intended to be used in production at all. However, with high probability, such systems end up being deployed for the long term. Through the life of the software, new requirements are born. Then new hacks are made, and the system becomes more complex (and more unstable). Finally, we end up with a mess of spaghetti code, and nobody is happy.
How do you prevent a codebase from becoming a disaster? Having good developers with good habits is not enough. You must also have a good design. This means you must consider every possibility before it becomes a requirement. You should think about what might be asked of your system in the future. You should think about how the objects it deals with could be modeled. Should you implement it this way? No, probably not. Once you have drawn up a complicated model for your system, throw it out.
Now you can start from scratch, and make a smaller, more practical model. Having considered the system in great detail, you know more about what to expect. With all those complexities in mind, you can build a simple system that still does the same job. But you will be more prepared for future changes, and you won’t need to use any dirty hacks to make them work.
Complexity is generally a bad thing, but modularity is good. Every piece of software is destined to become more complex, and the only thing you can do about it is to be prepared for that to happen.