Design principles

We strive to write code that is easy to understand, extend and modify when new requirements arise. To write such flexible code, it needs to follow principles on how to design it to be this way.

SOLID

SOLID is collection of design principles introduced by Robert “Uncle Bob” C. Martin that are essential for writing flexible code. SOLID stands for:

  • Single responsibility principle.
  • Open-closed principle.
  • Liskov substitution principle.
  • Interface segregation.
  • Dependency inversion.

Single responsibility principle

A class should only contain functionality they are responsible for, and nothing more. Classes that adhere single responsibility principle are smaller, it’s easier to write tests for them, and results in reduced complexity in code.

Open-closed

Classes should be open for extension, but closed for modification. Ideally, when new requirements arise, it should be easy to add new functionality without changing exisiting code. Designing classes to be open-closed prevents bugs from appearing due to existing code change. Also this reduces future work when implementing new functionality.

Liskov substitution principle

Objects in program should be replaceable with instances of their subtypes without consuming code knowing about it. When this principle is violated, using subtypes can result in unexpected program behaviour.

Interface segregation

Use many small client-specific interfaces (protocols) instead of few general purpose interfaces. It’s easier to write implementations for smaller interfaces. Smaller interfaces are more reusable, composable, and their purpose is clearer.

Dependency inversion

Depend on abstractions (interfaces, protocols) instead of concrete implementations. Depending on abstractions prevents breaking code in dependencies when concrete implementation changes. Another benefit of dependency inversion principle is that it reduces coupling between classes.

Composition over inheritance

Using composition over inheritance increases encapsulation and transparency of classes. In inheritance, the behavior of children classes are dependent on parent class, so what may seem a simple change in parent class may result in multiple changes in inherited classes.

Law of Demeter

This law states that a method of an object can only call methods of other objects in cases when these other objects:

  • belong to the object.
  • are created by the method.
  • are parameters to the method.
  • are components of the object.

Using Law of Demeter results in code that has low object coupling, and thus, makes it easier to make changes to the system.