Single Responsibility Principle

image.png

A component should have a single responsibility & no reason to change

The degree of cohesive responsibility is measured in relevance to its local scope

Aim for higher cohesive responsibility

Example 1: calculateArea() & calculatePermiter() methods should be in one class. Whereas draw() & rotate() should be in a different class.

Aim for loose component coupling

Example 2: A student class that also serializes the data to a particular database is not flexible if the database changes. Create another class that saves data.


Open-Closed Principle

image.png

Components should be closed for modification, but open for extension

New features or behaviors should NOT have to modify existing code

Refactor using cross-domain designs

Example: Composition and interfaces ("Has A" relationship), along with method overriding can be used to avoid changing existing code.


Liskov Substitution Principle

image.png

Objects should be replaceable with their subtypes

Unimplemented methods are almost always indicative of a design flaw

Break the hierarchy of clashing objects

Example 1: Decouple the inheritance that has unimplemented methods and give a new common parent class to inherit.

Insert a method inside another method

Example 2: Add another local method inside the inherited/overridden method to avoid changing the surround code.


Interface Segregation Principle

image.png

No client should be forced to depend on methods it does not use

Interfaces should be divided based on functionalities (responsibility)

Implement multiple interfaces in classes

Example: Too many/empty methods most likely means we are not following the Single Responsibility Principle. Make sure each interface has methods with higher cohesiveness.


Dependency Inversion Principle

image.png

Lower and higher level details should not depend on each other

A middle abstraction increases re-usability of higher layers while retaining the free lower ones

Call it at a higher layer through by using inversion of control

Example: Implement the abstraction/interface for lower layers and use composition at higher layers to separate the return data from the operations