OOPS Principles (SOLID Principles):
SOLID is an acronym for the first five object-oriented design (OOD) principles.
It makes programmer life easy - used to write maintainable and extendible code.
Best suited for agile development.
Object or Entity should have only one responsibility.
- Every module or class should have responsibility over a single part of the functionality provided by the software, and that responsiblity should be entirly encapsulated by class.
- One Class should be responsible for one task.
- The class itself is a single unit that must either be entirely used or not at all (discounting static methods and data for the moment).
- If you can think of more than one motivation for changing a class, it probably has more than one responsibility.
Examples of Responsibilities:
- Error Handling
- Class Selection / Instantiation
Objects or Entities (classes, modules, methods/functions, etc.) should be Open for Extension, but Closed for Modification.
- New functionality shoudl be added with no change in existing code/Object/Entity but minimal change in new code/Object/Entity.
- Entities behavior can be changed without the need to edit and recompile the code itself
- The Open-Closed Principle can also be achieved in many other ways, including through the use of inheritance or through compositional design patterns (e.g. Strategy pattern).
- 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)
public class BasicFileLogger : LoggerHere we are extending/changing logger functionality using inheritance so that logger will have functionality related to file logging. Code Sample
Let f(objMainClass) be a property provable about objects objMainClass of type MainClass. Then f(objSublass) should be provable for objects objSublass of type SubClass where SubClass is a subtype of MainClass.
If a program module is using a Base class, then the reference to the Base class be replaced with a Derived calss without affecting the functionality of the program module.
The Liskov Substitution Principle (LSP) states that Liskov Substitution subtypes must be substitutable for their base types.
"Is-Substitutable-For" Not Just "Is-A"
- You should be able to substitute child types for their base types anywhere you need to work with them.
- This means that you can write methods that accept a base type as a parameter, and they can work with that base type's methods and properties, regardless of what actual child implementation of that base class is passed as an argument.
This principle is just an extension of the Open Close Principle.
It means that we must make sure that new derived classes are extending the base classes without changing their behavior.
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
If any module is using a Base class then the reference to that Base class can be replaced with a Derived class without affecting the functionality of the module.
While implementing derived classes, need to ensure that the derived classes just extend the functionality of base classes without replacing the functionality of base classes.
A client should never be forced to implement an interface that it doesn’t use
clients shouldn’t be forced to depend on method/interface they do not use.
- Many client-specific interfacess are better than one general purose interface
- We should not enforce clients to implment interfaces that they dont use. Instead of creating one big interface we can break donw it to smaller interfaces.
- If a given interface has more features than you require, create a new interface that includes only the functionality that your client code requires, and which you can implement fully.
- The Interface Segregation Principle (ISP) states that clients should not be forced to depend on methods that they do not use.
Don't Depend on What You Don't Use
Entities must depend on abstractions and not on concretions.
It states that the high level module must not depend on the low level module, but they should depend on abstractions.
Abstractions should not depend on details. Details should depend upon abstractions.
Highlevel modles shoudl not depends on low level modules
By passing dependencies to classes as abstractions, you remove the need to program dependency specific. aka IoC (Inversion of Control) principle and implements as DI (Dependency Injection) pattern in the programming world.