Design patterns·topic 10 of 10
The named ways it goes wrong
A pattern gives a good arrangement a name so it can be asked for. An anti-pattern gives a bad one a name so it can be pointed at without the argument starting from scratch, which is most of what these are for.
Read in order · tick what you already know
- 01
someone named the shape you had just described and the argument stopped, because everyone had seen it before.
Anti-pattern
- 02
you traced the control flow with a finger and it went up, down and into a file you did not expect, twice.
Spaghetti code
- 03
the code drifts right for six levels and back again, and the shape of it on screen is a wide arrowhead.
Arrow anti-pattern
- 04
the bug was fixed in one of the four near-identical blocks, and reported again a month later from the other three.
Copy-paste programming
- 05
there is a 3 in the middle of the expression and nobody left a note saying which three that is.
Magic number
- 06
the status is a string, the comparison was misspelled, and the branch silently never ran.
Stringly typed
- 07
money is a decimal, the email is a string, and the validation for both is repeated in nine call sites.
Primitive obsession
- 08
the call reads createUser(name, true, false) and you have to open the definition to find out what either means.
Boolean trap
- 09
the method takes nine arguments, four of them are the same type, and you got two of them the wrong way round.
Long parameter list
- 10
the method calls five getters on another object and one on itself, so it belongs on that other object.
Feature envy
- 11
the line is four dots long and a change to any object along the way breaks the code at the end of it.
Message chain
- 12
the service method's whole body is a call to the repository method with the same name and the same arguments.
Pass-through method
- 13
the class exists only to call one method on another class and then disappears, and it has Manager in its name.
Poltergeist
- 14
the same class is edited for tax rules, for the export format and for the retry policy, by three different people.
Divergent change
- 15
adding one field meant small edits in eleven files, and the review caught the two you missed.
Shotgun surgery
- 16
the subclass overrides three inherited methods to throw, because it never wanted them in the first place.
Refused bequest
- 17
understanding one method meant opening five files up and down the hierarchy, and then going back up again.
Yo-yo problem
- 18
the test passed alone and failed in the suite, and the difference was something another test had left behind.
Global mutable state
- 19
the class needed an environment variable, a file on disk and the current time, and its constructor took nothing.
Hidden dependency
- 20
two modules import each other, and which one is initialised first decides whether it works.
Circular dependency
- 21
there is an interface with one implementation and a config flag that has never been anything but its default.
Premature abstraction
- 22
the annotation is on every class because it was on the first one, and nobody can say what it does.
Cargo cult programming
- 23
the configuration grew conditionals and loops, and you realised you had written a programming language, badly.
Inner-platform effect
- 24
you changed the function, everything passed, and it turned out nothing had called it for a year.
Dead code
- 25
the old implementation is still there behind a flag nobody has turned on since the migration two years ago.
Lava flow
- 26
the component is fully wired in, fully maintained, and used by exactly nothing, kept because it might be needed.
Boat anchor
- 27
the first ignored warning became forty, because after the first one nobody felt the file was worth keeping tidy.
Broken window