SOLID Principles

In Object-Oriented Programming (OOP) Concept, SOLID principles are the acronym for five Object-Oriented Design (OOD) principles. These SOLID principles are used to improve the understand-ability, flexibility and maintainability of the code.

 


S.O.L.I.D. Stands For?

1.     S - Single-responsibility principle

2.     O - Open-closed principle

3.     L - Liskov substitution principle

4.     I - Interface segregation principle

5.     D - Dependency Inversion Principle

 

Let’s see what is the exact meaning of each principle using an example.

Ex: There is an online store. A registered customer can place an order and purchase them using the card or make payment when delivering the order. Let’s move to the principles again.

 

1.     Single-Responsibility Principle

The common definition of this principle is “A class should have one and only one reason to change, meaning that a class should have only one job.” When we consider the above online store, there is a class called “Customer”. This customer class should only contain the customer createCustomer(), retrieveCustomer(), updateCustomer() and deleteCustomer() methods. placeOrder() is not a method of the Customer class.

According to the single-responsibility principle, we can only use the methods and attributes that are actively regarding that particular class.

 

2.     Open-Closed Principle

The common definition of this principle is “Objects or entities should be open for extension, but closed for modification.” When considering the above online store, it has a payment method using card or cash. We can create an Order class and use if-else statements to find the payment type. If we have to include wallets as another type of payment, we should edit the code. So, we violate the “closed for modification”. As a solution for that we can use interfaces.

We can create a Payment interface with savePayment() method and implement the interface as CashPayment, CardPayment and WalletPayment. Using the interface code can extend avoiding the modification.

 

3.     Liskov Substitution Principle

The common definition of this principle is “Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.”  The children classes should be able to substitute the parent for providing the functionality promised by the parent in a meaningful way is the simple idea of the definition.

Let's assume the Order class is a parent class and it has two children classes named CashOnDeliveryOrder and OnlinePaymentOrder. Order class has a method savePayment() and both children classes should be able to use it. 

 

4.     Interface Segregation Principle

The common definition of this principle is “A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use.”  Let’s consider the above online store’s Payment interface. We need to store credit card information in a separate table and we create a separate method saveCardDetails() in the Payment interface. Now the class CashPayment has to implement both saveCardDetails() and savePayment(). 

So, it is a violation of “a client should never be forced to implement an interface that it doesn't use”. So we can create another separate interface named CardPayment to implement saveCardDetails()method. Now, CashPayment can implement only the Payment interface and CardPayment can implement both Payment and CardPayment interfaces.

 

5.     Dependency Inversion Principle

The common definition of this principle is “Entities must depend on abstractions not on concretions. It states that the high-level module must not depend on the low- level module, but they should depend on abstractions.”  Simple meaning of this is “The responsibility of creating the dependent object should be outsourced to that of consuming class”.

Let’s consider the Order class of the online store example. The responsibility of the payment type is a responsibility of Driven class and not a responsibility of Order class. The Driven class should select the payment type to continue the order.


Class Order{

Customer c;

Payment p;

Order (Customer c, Payment p){

this.c = c;

this.p = p;

}

save_Payment(){

p.savePayment();

}

}

Now, we can call the above Order class (a sample class for explaining) using different customers and payment types. Driven class can access the order using following way. 

Order order = new Order ( customer , new CashPayment()) 

Comments

Popular posts from this blog

C# Analog Clock

Basic Prolog (List)