S: Single Responsibility Principle
A class should have a single and specific role. For instance, a Customer class should validate the customer’s data, interact with the underlying data layer etc.. Should not do logging activity. If we need the logging within a Customer class we should delegate this to an inner Logger class instance, which has the logging responsibility. This ensure us that if there’s something to change on some responsibility’s logic, we have to change only one class.
O: Open Closed Principle
A class should be Open to extensions, but closed to changes. For instance if we have different types of customers we should not represent this with a Type property within our Customer class, because in this way we are forced to change the class every time we need a new type. By respecting this principle we should represent every customer different type with a proper subclass of Customer.
L: Liskov Substitution Principle
If q(x) is a property that is valid for all x of type T, then q(y) should be valid as well for all y of type S, where S is a subclass of T.
This means that if a subclass of our Customer class don’t implement some of the Customer properties, we should remove the direct inheritance between them and use instead two interfaces to separate the properties that are valid for both the Customer class and the subclass (so that both of them can implement it) from the properties that are valid for the Customer class only (so that only the Customer class can implement it). In this way we can’t use the polymorphism to assign to a Customer reference an instance of a subclass that don’t implement some of the Customer’s properties.
I: Interface Segregation Principle
This principle says that we should have many little and specific interfaces (one for every behavior of our class clients) instead of having a single and big generic interface. This ensures that our class clients don’t depend on properties that they don’t use. For instance if some of our class clients use just a specific subset of properties, while another part of them uses all of them, we should have one interface for the first ones, with just the properties they use, and another one for the clients who use all of the properties. In this way the clients that don’t use all the properties don’t see the properties that they don’t use.
D: Dependency Inversion Principle
This principle says that is not a responsibility for a class to create (deciding their type) its dependencies. They should be injected from outside. From this principle came the IoC principle.