Design patterns are generally accepted solutions for common problems in software design. Patterns are also shorthand for explaining how software was designed. As with many useful tools, they tend to be misused.
Misuse happens when developers see a pattern as the only solution to a problem. Misuse also happens when developers misunderstand how a pattern solves a problem. In either case, patterns become a magic solution. “I don’t know why I’m doing this, but The Pattern applies,” says the developer and fits the problem to the solution.
In the worst cases, entire code bases are built around this misuse. Patterns are applied, which require abstractions, which reveal more opportunity for other patterns, and a bad design feedback loop starts. I saw one example of this years ago.
A developer was building a simple extract-transform-load (ETL) application. Extract data from one database, apply minor transformations, and load into another. Both databases were large legacy systems unlikely to change without months or years of planning. Minimal transformations were required for compatibility between them. No modularity was needed. We assumed two weeks of work based on the specs.
Two months later, the application was delivered. It featured a command-line parsing library, multiple layers of database abstraction, and a plugin-based transformation system. Nearly every pattern the developer knew had been implemented. The developer justified this based on SOLID principles and problems that could only be solved with design patterns.
I’ve jokingly called this “Pokémon Programming” – gotta collect all the design patterns. In this case, two design failures occurred:
- The developer overlooked the functional requirements during design. Almost no design pattern implemented was required. Don’t invent problems for the solutions you want to implement
- Simpler code would have solved the problems better than many of the patterns. Don’t write more code than you need to
When designing software and considering design patterns, review your requirements and consider these points:
- When considering a problem at the smallest level, what is the simplest solution? Does it fit a pattern? Good, consider that pattern. If not, start with the simplest design that does solve the problem
- When implementing a pattern, do you find yourself adjusting the problem to fit? Maybe that isn’t the correct pattern. See point 1
- Are you implementing more than required? Stop. Read about YAGNI. See point 1
Design patterns are good solutions to common problems, when they are the solution to the problem. The best solution to any problem is the simplest. To keep your code simple, understand your problem and understand your potential solutions. Learn why any particular design pattern might help you and don’t try to collect them all.