I've seen far too often where software was either under or over-designed. I want to talk about over-design, since that seems to be more common in my experience. Over the past several years there have been many patterns discovered and naturally, developers often try to take advantage of them when they learn about it (I was no exception in the past). Unfortunately, these design decisions all have a price, usually in terms of maintenance or initial development cost.

For example, imagine the simplest web application, it might be a 1-tier design, and all the code is in a single project and it is not modular, etc. Costs of development are relatively low, but adding new features or changing things around would likely require significant rewrites. A developer nowadays might never think of using such a simple design, but that is a bit shortsighted, as we have to always consider the requirements. Maybe this is a one-off application that has a short lifespan of less than a year, then who really cares if it requires a rewrite to add a new set of features? Perhaps it is only 10k lines of code, why make a 3-tier design with IoC and all that jazz if it would only take a week or two to rewrite the whole thing from scratch?

On the other end of the spectrum there are applications like SAP, that have indefinite lifespans and are so insanely monstrous that they must be modular and well-engineered to adapt to change over time. The expensive design patterns prove their worth in these kinds of applications. If you have to measure the effort of a solution in man-years, the owner probably will want it to last for a while, so it makes sense to engineer it to do so.

When designing a solution to a problem, we should always consider the lifespan of the product and the maintenance requirements. If the application only takes a few people a few months to write it, it will probably take these same people a fraction of that time to rewrite the whole thing or a portion of it, and a rewrite will always produce a better product in the future than a code change. In cases like that, which seems very common in consulting, there isn't any reason to build more than is absolutely necessary. Even if the product becomes outdated and needs a significant change every year, the costs would be pretty minimal to just brute force your way through it. That doesn't mean developing a 1-tier system like I mentioned above, but don't go overboard with all the fancy design patterns like SOA, IoC, WS, etc.

To use an analogy, imagine an architect (the traditional kind), who is designing a condominium complex. If it's a high-rise, he would probably decide to put one or more elevators in the building, because people often need to go up and down the building and going up 20 flights of stairs is quite tiresome. And moving furniture up and down those same stairs would be unimaginable. So even though it will cost the tenants hundreds of dollars a month in fees to maintain the elevator(s), the costs are worth the benefits. Now imagine the same scenario in a 2-story complex. The tenants probably wouldn't be happy paying such costs for an elevator when they'd be fine with using the stairs. Even if it would make moving furniture easier, it still probably would not be worth the cost to the tenants, since moving furniture doesn't happen often enough and moving it up 1 story isn't such a big deal anyway.

Software architecture isn't quite the same of course, but every design decision has a cost (or lack thereof) and some kind of potential benefit. We must measure the costs and benefits as best as we can before making any decision. Don't just throw patterns into your solution just because it sounds cool or it has a lot of buzz at the moment, it will likely end up being a waste of time now and in the future.