FUNDAMENTALS OF DEVELOPMENT

SOLID Principals

Solid development refers to five architectural principals that make code more efficient to maintain. These principals all work together to create better code. They are not hard and fast rules and should be adhered to in a reasonable way.

1. Single Responsibility Principal (SRP): A class should only have one reason to change. This change should refer to the purpose of the class, so while there could be multiple changes they would all fall under the same purpose. Each class should have a clear and obvious job.

2. Open - Closed Principal (OCP): A class should be open for extension, but closed for modification. Once a class is in production it should not be changed. If new functionality is required it should be extended with a new class. This is to help avoid introducing bugs by changing classes that are working. Implementing interfaces is a good way to implement this.

3. Liskov Substitutin Principal (LSP): You should be able to change an instance using a sub-type and your code should still work. Any class based on a type should be able to be swapped out in code without breaking anything. Don’t make changes to how the base class works.

  • Covariance refers to no change in return type on inheritance.
  • Contravariance refers to no change in the input type.
  • When inheriting you can’t strengthen pre-conditions on input variables.
  • When inheriting you can’t weaken post-conditions on return variables.

4. Interface Segregation Principal: A client should not be forced to depend on interfaces they do not use. This is very similar to LSP, but in working with interfaces. Since a class can implement multiple interfaces make each interface specific.

5. Dependency Inversion Principal: High level modules should not depend on low level modules, but rather both should depend on abstractions and those abstractions should not depend on details.

  • One shold depend on abstraction and not concrete instances.
  • A high level module is anything that calls something else.
  • The simplest way to do an abstraction is by using an interface.
  • Any time you use the "new" key word instatiating an object that indicates a tight coupling.
  • Dependency injection is a way to make the principal of dependency inversion work. Another way would be to create a static factory to new up instances of classes in a centralized location.

Don’t Repeat Yourself (DRY)

When coding if you find that you are repeating similar code then see if there is a way to extrapilate it to a separate function.