Design patterns·topic 1 of 10
Objects, messages and the principles
Before any pattern there is a smaller question: what is one object allowed to know about another. Almost every named pattern is an answer to it, and almost every argument in a code review is really about it.
Read in order · tick what you already know
- 01
you stopped caring which of the three implementations you had, and the code got shorter in every caller.
Abstraction
- 02
the type on the field is the interface, and the only line that names the concrete class is the one that builds it.
Programming to an interface
- 03
the base class does half the job and leaves a method for you to fill in, and you cannot instantiate it on its own.
Abstract class
- 04
the same call site does three different things depending on what was passed in, and there is no branch anywhere.
Polymorphism
- 05
the method that runs is chosen by what the object actually is at that moment, not by the type the variable was declared with.
Dynamic dispatch
- 06
the subclass replaces the parent's version of a method, and every existing caller silently starts getting the new one.
Method overriding
- 07
there are four methods with the same name and different parameters, and the compiler picks one before the program ever runs.
Method overloading
- 08
you got twenty methods you never asked for along with the one you wanted, and you cannot give any of them back.
Inheritance
- 09
you said it out loud — a Stack is a List — and it sounded fine right up until someone called insert in the middle of it.
Is-a vs has-a
- 10
you deleted the order and the line items went with it, but the customer stayed, because only one of them belonged to it.
Aggregation vs composition
- 11
the method body is one line that calls the same method on a field, and that is the whole class's job for that method.
Delegation
- 12
a harmless-looking change inside the parent broke three subclasses in another repository that you had never seen.
Fragile base class
- 13
adding a third colour to a hierarchy that already had four shapes meant writing twelve classes instead of one.
Subclass explosion
- 14
the class picks up three methods from somewhere that is not its parent, and finding where they came from takes a search.
Mixin
- 15
two parents both define the method and the language has to pick one, and which one is a rule you had to look up.
Diamond problem
- 16
nothing declared a shared type anywhere, and the code worked because both objects happened to have the method.
Duck typing
- 17
the object had every method the interface asked for and the compiler still refused it, because it had not said it implemented it.
Nominal vs structural typing
- 18
a list of cats would not go where a list of animals was expected, and the compiler was right even though it felt wrong.
Covariance and contravariance
- 19
someone rejected the pull request citing a five-letter acronym, and only two of the five letters were actually about the problem.
SOLID
- 20
adding the fourth payment method meant editing the same switch statement for the fourth time.
Open–closed principle
- 21
the subclass threw on a method the parent promised, and every caller written against the parent was suddenly wrong.
Liskov substitution principle
- 22
you implemented an eleven-method interface to get at one of them and threw not-implemented from the other ten.
Interface segregation principle
- 23
the method states what must be true when you call it and what will be true when it returns, and it checks both.
Design by contract
- 24
there is a rule that is true of the object at every moment a caller can see it, and the constructor is where it starts being true.
Class invariant
- 25
the thing most likely to change is the only thing behind the interface, and nobody outside can name it.
Information hiding
- 26
every field is private with a public pair of methods around it, which is the same as public with more typing.
Getters and setters
- 27
the caller pulled three fields out, decided something, and wrote one back — a decision the object should have made itself.
Tell, don't ask
- 28
you put it in a set, put an identical one in, and the set had two of them.
Object equality
- 29
you passed it to a function, the function changed it, and your copy changed too — or it did not, and you had to know which.
Reference vs value semantics
- 30
you handed the object a list, changed your list afterwards, and the object's state changed with it.
Defensive copy
- 31
two pieces of code have to change together, and you can say precisely what kind of agreement binds them.
Connascence
- 32
the interface is three methods and the implementation is two thousand lines, and that ratio is the point.
Deep module