Book Notes: Practical Object Oriented Design in Ruby
Created: 9 October 2014 Modified:I recently read Practical Object-Oriented Design in Ruby by Sandi Metz. A fantastic book to help bridge the gap between theory and implementation of design. I highly recommend this book even for non Rubyists. Below are bullet points to help remember key points in the book.
- General
- Make design decisions based on what you know now.
- Design behavior not data.
- Checking types or classes indicates an opportunity for inheritance or interfaces.
- Inject dependencies.
- Use factories to centralize design that otherwise would be spread throughout multiple classes. Such as instantiating classes to be injected.
- Use shallow inheritance hierarchies
- Favor composition over inheritance when in doubt.
- When dependencies cannot be eliminated then they should be isolated from the rest of the code.
- Dependency has a direction and should be pointed toward the code least likely to change.
- Abstractions are less likely to change than concretions.
- A diagram of object interaction should look like a tree not a mesh.
- Use sequence diagrams to determine the classes you need.
- Methods
- Should have single responsibility
- Large methods indicate the need to be reduced to multiple smaller methods
- Many private methods indicate the possible need for a new class.
- Method parameter order is a dependency.
- Interfaces
- The messages sent between objects are how they interface.
- Interfaces are roles shared by otherwise unrelated objects.
- Classes
- Should have a single responsibility
- Use inheritance when classes are “is a”
- Use composition when classes “has a”
- May have roles which translate to interfaces. These roles may be implicit rather than explicit.
- Use dependency injection rather than explicitly using classes in other classes.
- Use Hashes for parameters. This helps prevent dependencies on method parameter order.
- Use template design pattern when using inheritance.
- Template design pattern should use hooks instead of using “super”. User of super creates dependency.
- Testing
- Test from the general to the specific.
- Test only the public interface of a class.
- Use modules/mixins in test to verify interfaces (modules/mixins) in the code. Then include in all classes implementing interface.
- Use modules/mixins in test to verify super classes. These then can be included in subclasses.
- Use a singular module/mixin to verify subclasses act correctly in relation to super class. Then include in all subclasses.
- SOLID
- Single Responsibility
- Open for extension, but Closed for modification
- Liskov Substitution: Subclasses stand in for parent classes
- Interface Segregation: Clients should only know the methods they use. (Adapter pattern?)
- Dependency Inversion