Share via


OOPS Principles (SOLID Principles)

Targeted Audience:

1.       .NET Architects

2.       .NET Application Designers

3.       .NET Application Developers

Prerequisites:

1.       OOPS

2.       Any OOPS Programming language

 

Single Responsibility Principle:

One Class should be responsible for one task.

 

E.g.

Want to Save the SalesOrder and export that order in XML format.

So if We create a class to represent a SalesOrder, it should not used to save to the database (task 1), as well as export as XML format (task 2).

 

Problem:

We want to change database type or we want to change the XML schema, so we are allowing one responsibility's changes to possibly alter another.

 

Solution:

So create one class for saving into database and another class for exporting as XML.

 

Open Closed Principle:

Classes, modules, functions, etc. should be open for extension, but closed for modification.

 

Create a Base class with Required functionality, and ensure we will not modify that class. (closed for modification)

Create a Derived class by inheriting the Base class for extension (Open for modification)

 

Liskov Substitution Principle:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

 

E.g.

If you are calling a method defined at a base class upon an abstracted class, the function must be implemented properly on the subtype class.

 

 

Interface Segregation Principle:

Clients should not be forced to depend upon interfaces that they do not use.

 

E.g.

When a client depends upon a class that contains interfaces that the client does not use, but that other clients do use, then that client will be affected by the changes that those other clients force upon the class.

 

**Base Interface:   **                              IATM

**Derived Interfaces:  **       IBrailleUI, IScreenUI, ISpeechUI

Derived Classes:               BrailleUI, ScreenUI, SpeechUI

 

Each Derived class should implement functions from their respective interfaces.

No derived interface force other derived classes to implement the functionality which they wont use.

 

Dependency Inversion Principle:

A: High level modules should not depend upon low level modules. Both should depend upon abstractions.

B: Abstractions should not depend upon details. Details should depend upon abstractions.

 

By passing dependencies to classes as abstractions, you remove the need to program dependency specific.

 

E.g.

An Employee class that needs to be able to save to XML and a database.

 

Problem 1:

If we placed ToXML() and ToDB() functions in the class, we'd be violating the single responsibility principle.

 

Problem 2:

If we created a function that took a value that represented whether to print to XML or to DB, we'd be hard-coding a set of devices and thus be violating the open closed principle.

 

Solution:

 

1. Create an abstract class named 'DataWriter' that can be inherited from 'XMLDataWriter' and 'DbDataWriter'.

2. Then Create a class named 'EmployeeWriter' that would expose an Output 'DataWriter saveMethod' that accepts a dependency as an argument.

 

See how the Output method is dependent upon the abstractions just as the output types are?

 

The dependencies have been inverted.

 

Now we can create new types of ways for Employee data to be written, perhaps via HTTP/HTTPS by creating abstractions, and without modifying any of our previous code!