As a general observation, it seems that when software architects try to solve general problems, they come up with horrible designs; when they solve specific problems, they come up with good designs.
Designs made without reference to a problem often become complex and not very fit for purpose when we’re solving specific problems. As a general rule, avoid generalizations.
- An Enterprise Service Bus may create a big project and maintainable needs for something that turns out to be only a few simple integration points.
- Splitting a system into generic reusable services may make it harder to understand and maintain
- A generalized security role model may make be hard to understand while the only thing the system needed was an “is_admin?” toggle.
- A complex role based (“can create payment”) security model may hide control of authorization from the developers, making it harder to implement the usually more important data based (“can access account number 5”) security model
- A general model for workflow transition may make it harder to implement the specific workflow you need for a particular process. And it leads to endless discussions about the relationship between a workflow, a process and a process step.
- Generalized test strategies are often vague and require a large number of test environments. In the end, it doesn’t contribute to increased quality.
In “No Silver Bullet”, Fred Brooks introduces the concepts of “essential complexity” and “accidental complexity.” The complexity from generalization is always “accidental” (that is: not inherently necessary). When you focus on solving the essential complexity (that is: the users’ problem) as efficiently as possible, you may found the complexity of your problem shrink by half or more.
Have you ever found yourself thinking, “what specific problem was I trying to solve again”? Then you’ve probably been down the dark road of generic thinking.