I don’t know if this has become clear to everybody yet, but you really need to design from the start. You need to be working on simplicity and the other Laws of Software Design from the very beginning of your project.
My policy on projects that I control is that we never add a feature unless the design can support it simply. This drives some people crazy, notably people who have no concept of the future. They start to foam at the mouth and say things like, “We can’t wait! This feature is so important!” or “Just put it in now and we’ll just clean it up later!” They don’t realize that this is their normal attitude. They’re going to say the same thing about the next feature. If you give in to them, then all of your code will be poorly designed and much too complex. It’ll be Frankenstein’s monster, jammed together out of broken parts. And just like the friendly green giant, it’ll be big, ugly, unstable, and harmful to your health.
Adding a tiny little piece and refactoring it afterward is fine. Landing a huge feature that the architecture can’t support and then trying to clean it up afterward is a terrible task. Size matters.
The worst situation, however, is when you let people keep adding features with no design for months or years, and then one day you wake up and realize that something is not right. Now you have to fix your whole codebase. This is a terrible task, because just like adding a new feature, it can’t be done all at once, unless you want to re-write. If you want to start doing things the right way, you have to start doing things the right way. And that means that you have to fix the design piece by piece, in simple steps. That usually requires months or years of effort–totally wasted effort, because you should have just designed from the start. You should have thought about the future.
If your project lacks a strict design, and it continues to grow, then you will eventually end up over your head in complexity. I understand that this is hard for some people to imagine. Some folks can’t imagine that there is a future beyond lunch. Other folks just haven’t had enough experience to understand how complex things can get. And I understand that there can be a corporate culture that says, “Oh, we just hack in new features, and we should do things the right way, but we can’t because blah blah blah.” But one day your project will fail. And no matter how many reasons you can give for that failure, it won’t change the fact that your project failed.
Often, when you’ve done your design right, there’s not a whole lot of credit that comes your way. Catastrophic failures in design are big and noticeable, small increments of work toward a good design are invisible to people who aren’t intimately connected with the code. So this can make it difficult–handling a big failure gets you a lot of thanks, preventing one in the first place, well, nobody noticed.
So I’ll congratulate you myself. Did you design from the start? That was awesome. You absolutely did the right thing. Have you started designing now? Well, you should have started earlier, but congratulations on starting to move in the right direction. Your users and fellow developers will see the benefits–working software, on-time releases, and a clear, understandable codebase. Will they know how much work it took to get it that way? Maybe not. But that’s OK. Sometimes doing things the right way is really its own reward.