We usually add complexity because we want things to be flexible or reusable But sometimes are drawn to make things more complicated. How many times have you heard after you present a design or a solution to a problem, yeah that's great but what if they change X or Y? Why is flexibility and complexity our default option?
In the book Java Application Architecture Kirk Knoerschild talks about this use/reuse paradox. When we make things simple and usable with few dependencies the aren't very reusable. But they are easy to change and maintain. If we try to make things reusable, they become more complex and have more dependencies. Simply put flexibility leads to complexity which costs both time and money and makes the code harder to use.
So what is a developer to do? Well one way that Martin Fowler recommends is to build the system and evolve the flexibility through refactoring into common code or frameworks. I think that's great on systems that you get a chance to evolve or where refactoring time is hard to come by.
One thing that I've had some success with is make small usable components and composite them into more complex flexible components. This is not a perfect strategy, it actually takes some discipline to just focus on small components. However because you are relying on underlying simple components the cost of changing it is somewhat easier. You are also more likely to be able to easily rearrange the components to create other complex components.
We did this on JSP tags on my last project and it went well for the most part. There were sometimes when we didn't follow the pattern completely, but I think it created a decent framework for easily creating our Web pages. As I become more comfortable with doing this, I think there are more opportunities to use this kind of pattern, I've recently started to look at ATDD and I think the step definitions could be written in this manner.
We have to resist the push for flexibility and complexity. We need to communicate how, for instance, having a complex validation for a field increases coding and testing time and makes fixing defects and changes in the future harder. I think if we present the costs of the flexibility in this way, we can be more intentional when we choose to add complexity to our application and it will make our lives much more simpler.