SOLID Design Principles (in 5 minutes)

SOLID is a mnemonic for five design principles intended to make your code more flexible, maintainable, and reusable.

Single Responsibility Principle:

A class should be responsible for a single functionality of your code. Therefore a Class should have only one reason to change.

Example:

Without applying the SRP, we risk breaking the working code while modifying other functions that don’t belong in the Document class.

Open/Closed Principle:

A class should open for extension but closed for modification. We should always aim to write a Class in which we can extend its behavior on-demand and not modify its code repetitively.

Example:

We shouldn’t modify the Shipping Cost function and the Order class every time we add a shipping method. Think about this principle when you have multiple If/Switch statements.

Liskov Substitution Principle:

Definitions:

  1. Covariance: Assigning a more derived type to a less derived type. For example : IEnumerable<string> s = new List<string>();
  2. Contravariance: Assigning a less derived type to a more derived type. For example :
    Action<object> act_o=….
    Action<string> act_s =act_o

Defined by Barbara Liskov in 1987. This principle is a set of rules to be respected while subclassing.

  • There must be contravariance of the method arguments Types in the subtype. (or preserve the types)
  • There must be covariance of the return Types in the subtype. (or preserve the types)
  • A method of a subclass should not throw types of exceptions that the base class method doesn’t throw.

Lucky for you, Statically typed programming languages have these rules built-in. They force you to apply these rules :).

  • Pre-conditions, cannot be strengthened in a subtype. For example: if the base class requires an integer for a function, the overridden method cannot require that the integer is negative.
  • Post-conditions cannot be weakened, in a subtype.
  • Invariants of a supertype must be preserved in a subtype. For example, A dog has four legs…always!

Interface Segregation Principle

Make your interfaces as compact as they can be, do not add behaviors that a client class may not use and/or doesn’t have the means to implement.

Dependency Inversion Principle

Definitions:

  1. Low-level modules implement basic operations such as interacting with a disk, connecting to a database, etc…
  2. High-level modules contain complex logic that orders low-level classes to perform a certain task.

High-level modules should not depend on low-level modules. Both should depend on abstractions(interfaces).

Example:

Making high-level classes dependent on interfaces is much softer than depending on low-level classes. Implementing the interfaces for low-level classes makes them depend on the business logic reversing the direction of the original dependency.

Great to see you have come this far, and remember practice makes perfect!