Notes on SOLID

And, finish digesting this: to finish this below:

SOLID principles for writing better object-oriented code

Single responsibility,
Liskov substitution,
Interface segregation and
Dependency inversion.

  1. Don't repeat yourself (DRY). Abstract repeated code to one place, use defined, public manifest constants.

    But, it also means don't abstract or fold trivially. If you use the same code to validate an order id and a social security number, which are two different things, you couple them falsely and when order id changes, social security numbers will break.

    Don't combine anything that uses similar or identical code when unrelated.

  2. Encapsulate what changes or is to change. The Factory pattern is one that uses encapsulation.

  3. Open-closed design principle: classes and methods should be open for extension, but closed for modification.

  4. Single-responsibility principle. A class should always handle a single responsibility. Multiple responsibilities tend to introduce coupling.

  5. Dependency injection. Dependency is provided by the framework, not the code.

  6. Favor composition over inheritance. has-a is more flexible than is-a.1

  7. Liskov substitution principle. Subtypes must be suitable for supertype methods. Methods must be able to work with an object of a subclass without issue.

  8. Interface segregation principle. A client should not implement an interface if it doesn't use it, interfaces should not attempt to do more than one thing (single-responsibility principle).

  9. Program for interface, not implementation. Use an object of the interface type, a method that return an object of the interface type, etc. rather than the implementing class.

  10. Delegation principle. Don't do it all in one class or method, delegate functionality to respective classes or methods. E.g.: Don't do both equals() and hashCode() as one method. Create method isEmpty(), but in it code against null, zero-length, etc. separately.

1 Five reasons to favor composition over inheritance:

  1. Java doesn't support multiple inheritance.
  2. Better testability, easier to mock out the composed element. In order to test a derived class, you need access to the superclass.
  3. Both approaches allow you to reuse code, but inheritance breaks encapsulation. A subclass depending on parent's behavior for its own is fragile.
  4. It's more flexible to be able to replace the composed object with another and better object later.
  5. Gang of Four, Head First Design Patterns, etc. Smart people recommend composition over inheritance.