SOLID Principle is a software fundamentals that helps the developers to write better maintainable code. Below is the expansion for SOLID
S- Single responsibility principle
This means, any particular class should be written with only one responsibility. So there should be only one reason to do any change to that class. This principle may cause developers to create more number of classes but in long run it will make the life easy to maintain
O- Open closed principle
This rule of this principle is, any class/method we write should be "Open for extension but closed for modification. To make it understandable, a simple example would, if any method is having select/ switch case statements to calculate shipping cost, then it is violating open close principle. Because if we need to add any new shipping method, then we need to modify that method and the chances are the developer may break the existing case. So, the better approach may be to have separate class for each shipping type and having its own method to calculate shipping cost. Call that method from client using reflection or some other pattern. This way we can easily extend the shipping types without affecting the existing classes
L- Liskov Substitution Principle
Based on this rule, any child classes must be suitable for their base class. I.e at any point of time, base class should be able to substituted by the child class. To make that happen, child class should never change the behavior of the base class also, it should not change anything that base class meant for. So that the client who call these child class or base class will see no difference.
I- Interface segregation principle
This rule says that,Any class should not force methods which are not required for the client class that uses this class. Ex. If you have a abstract base class and that has more abstract methods than what the child class has to override, then the base class is forcing the child class to override a method that is not really required for that child class. To solve this issue, we can create interfaces which are small and has only what is require to be implemented by the child classes. If there are any method that is not required can be movies into a separate interface.
D- Dependency Inversion Principle
This is one of the most important principle we need to follow. This says, at any point of the top layers or modules should not be directly depend on layers which are below. This principle also help us to achieve loose coupling between the layers. To understand this in simple sentence, if any method or class is calling another class or it needs any other information to execute the complete functionality, then all the required object should be passed by the calling method. So, if your business layer has to call data access layer, then we should create a new instance of the DAL in business layer ? Instead, UI layers should create the DAL instance and pass it as a parameter to the BL, so that BL is depend on DAL. But it can be made better by using interfaces. If the BL is depending on an interface instead of a concrete class, then we can pass any object that are implementing that interface and call the target. This help us to do unit testing fake classes to test BL.
To understand more, refer below links