This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== 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 *