Don’t Use Design Patterns, but Know Them — Master Them!
Behind this catchy title (sorry) lies one of my dearest pieces of advice, nurtured by unfortunate experiences with enthusiastic developers that had just learned about patterns after a training session. How many times have I reviewed lines of code littered with useless classes and cluttered with pointless abstractions? I don’t want to know. (And I don't want to know how many times I was the culprit.)
Never, never try to put design patterns in practice. Never try to include them into the design of your new application. Don’t engage in aggressive refactoring to add patterns in any existing code for the sake of “making it look better,” or for the sake of flexibility, “so the code will be easier to update in the future.”
However, study them, understand them, re-read them, think about them and give them some attention.
Design patterns would be my scales. Scales develop finger nimbleness and train the spirit. Pianists have to know them, but scales aren’t music.
Imagine the surprise of the audience if, during a performance in a trendy auditorium, they read in the program, “Major scales played on a 3-beat rhythm followed by a playful syncopated minor scales inventory.”
Similarly, if a composer went through the Moonlight Sonata to refactor the piece by inserting a bland C# scale to ease the cramps of the interpreter’s fingers ... that would be the most terrible answer to a non-existent problem.
Design patterns would be the problems I solve scanning the newspapers, magazines or dedicated books: These puzzles highlight tactical aspects of the game such as deflection, pin, decoy, passed pawns, sacrifice, overloading … but they aren’t the game, they are just a tool that helps me learn a subset of chess. I couldn’t become a grand champion if I only studied tactics.
Of course, being a great tactician helps. Knowing tactics helps you find solutions you’d otherwise be oblivious to. But if all I tried to do during my games were to sacrifice my pieces for no reason beyond the fact that it is a tactical aspect of the game (and yet one of the most brilliant ones), I’d end up being a terrible chess player — and nobody would call my style romantic, just plain dumb.
Design patterns are fantastic when correctly put into practice. They help us when they are an additional source of inspiration but not a destination, not an end.
Design patterns let developers discuss possible solutions to common problems. They demonstrate simple study cases that are easy to understand and easy to put into practice into more substantial project, into real life designs. Put together, they form architecture catalogs that will welcome beginners and experts alike. They train us on specific and diverse aspects of object-oriented programming.
Each pattern ought to be used if and only if it fits the problem at hand. Not keeping this in mind will make our code sick and we’ll soon see known diseases such as “Singleton-aches,” along with “OnlyTheFormerDeveloperKnowsAboutThisObfuscatedCode.”
A pattern is not a defined and immutable solution. A pattern is by no means an implementation. It explains how to overcome common hurdles we'll find on our path.
Don’t let patterns guide you. Don’t seek to transform your problem so it fits your pet pattern, or you’ll end up writing mediocre solutions to problems you didn’t even have.
The most elegant solution is the simplest one, the easiest to understand.
Not a single “Hello World!” example justifies the use of a pattern, and no “Hello World” example corresponds to a user need. Hello World might even have become a pattern in itself — its sole intent being, "to give a glimpse of a new technology to developers." But no one teaches developers a new technology exclusively using, “Hello World!”
If a problem has two solutions, one that fits in ten lines of code, and another one with hundreds of lines of code along with a pattern, please consider not using the pattern. Their presence isn’t a quality measurement.
Of course, if your program is littered with the same ten lines scattered around, it might be time to reconsider.
Never develop for “if something happens … ” Develop because of your current problem. Developing for a blurry hypothetical future is the best way to transform a two-day project into a two-month project. If you happen to justify the presence of a pattern in your code only through a “you know, if … ”, then remove the pattern.