Clean Code notes
Liskov substitution principle
What is a type
It is a bag of operations
Subtypes
A subtype is a type that may be used as another type.
Refused bequest
This occurs when a subtype does something unexpected from the point of view of the user of the super type.
- does not implement method
- method does something unexpected
- etc.
Every refused bequest/LSP violation is a latent open/closed principle violation.
Representative rule
Representatives of things do not share the relationships of the things they represent. So, while geometrically a square is a rectangle, the class that represents a square is not a subtype of the class that represents a rectangle.
Single responsibility principle
- responsibility
- It is about users
- People served by a responsibility will request changes
- Set of functions that serve a particular actor
- The actor is the single source of change for the functions in a responsibility
- Primary and secondary value of software
- Primary: can be changed easily, so that it can continue to meet changing needs of customer
- Secondary: meets current needs of current customer
- Primary value is achieved in the process of assigning functions to modules
- Mixing responsibilities in one module reduces primary value of the software
- Fan out
- Multiple responsibilities result in a fan out of dependencies
- Minimize fan out by minimizing responsibilities
- Colocation of responsibilities couples actors
- change in one responsibility requires recompile of actors using other responsibilities
- SRP: module should have one and only one reason to change
- Examples
- logging
- separate log statements into subclass
- extract till you drop to make logging granularity eork
- subclass logs around super calls
- Solutions
- Extract classes
- Move responsibilities and impls into separate classes
- Facade
- Unify responsibility impls in one facade
- Interface segregation
- Create one interface per responsibility
- Implement in single class
- No perfect solution
- Keep responsibilities separate/makes stuff more difficult to find
- Put responsibilities together/makes stuff easier to find/work with
- Mastermind
- Actors
- Designer: responsible for game messages
- Strategist: algorithm that guesses the code
- Customer: how game progresses, badges, achievements, etc.
- Modules
- gameplay: supports customer
- strategy: supports strategist
- interface: supports sesifner
- see mastermind example
Open closed principle
- modules should be open for extension, closed for modification
- changing behavior of module should not require changing module's source
- problem: need crystal ball to anticipate future changes in order to design to protect yourself using open closed
- solutions: big design up front, agile design
- agile: do simplest thing now, refactor and abstract once customers ask for modifications
- get initial builds in front of customers. Customers will immediately request changes. Developers should change architecture to account for these changes, then refactor to implement new abstractions.
- each iteration should result in more code that conforms to open/closed