# Object Orient Programming-Course2 Week3-2: SOLID+ Principles
###### tags: `OOP` `Coursera`
<style>
.red {
color: red;
}
</style>
<style>
.blue {
color: blue;
}
</style>
<style>
.green {
color: green;
}
</style>
## Open/Closed Principle
### <span class = green> Classes should be open for extension but closed to change</span>
There are two parts mentioned in this principle, open and close:
* Close: You should consider a class being <span class = red>"closed" to editing</span> once it has been:
> * Tested to be functioning properly
> * All the attributes and behaviors are encapsulated
> * Proven to be stable within your system
The closing portion of this principle doesn't prevent you from changing or debugging during developement. Once you reach to the stage of finalizing the design of your system and you have implemented most part of your system, you can consider closing the classes. During the lifetime of the softwawre, certain classes should be closed(except fixing bugs) to avoid introducing side affect to the software.
How to add features? <span class = green> open </span>
* There are two different ways to extends existing classes that have been <span class = red>closed </span>:
> * Inheritance of a Superclass
> * The class is abstract and enforces the Open/Closed Principle through polymorphism.
#### Inheritance of a Superclass
Through Inheritance of a Superclass to extend a <span class = red>closed </span> class, you're subclasses will still have all the original functions of the superclass.
```graphviz
digraph obj{
node[shape=record];
rankdir="BT";
ClosedClass [label = "{<f0> ClosedClass|}"];
ConcreteClass1 [label = "{<f0> ConcreteClass1|<f1>\n }"];
ConcreteClass2 [label = "{<f0> ConcreteClass2|<F1>\n}"];
ConcreteClass3 [label = "{<f0> ConcreteClosedClass3|\n}"];
ConcreteFinalClass [label = "{<f0> ConcreteFinalClass3|This class can't be extended due to the ~final~ Modifier\n}"];
ConcreteClass1->ClosedClass [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "];
ConcreteClass2->ClosedClass [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
ConcreteClass3->ClosedClass [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
ConcreteFinalClass->ConcreteClass3 [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
}
```
When a subclass is closed and needed to be extended, another subclass can inherit from it. Mind you can stop the possibility of extension by using modifier <span class = red> Final </span>.
#### The class is abstract and enforces the Open/Closed Principle through polymorphism.
The abstract class can declare abtract methods with only method signiture. Each concrete class is forced to implement their own implementation. The methods in the superclass are preserved. You can extent your system by providing different implementing. This can be useful when you want to provide different ways to do the same task.
```graphviz
digraph obj{
node[shape=record];
rankdir="BT";
AbstractClass [label = "{<f0> AbstractClass|}"];
ConcreteClass1 [label = "{<f0> ConcreteClass1|<f1>\n }"];
ConcreteClass2 [label = "{<f0> ConcreteClass2|<F1>\n}"];
ConcreteClass3 [label = "{<f0> ConcreteClass3|\n}"];
ConcreteClass1->AbstractClass [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "];
ConcreteClass2->AbstractClass [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
ConcreteClass3->AbstractClass [style="normal",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
}
```
#### Conclusion
The Open/Closed Principle is used to keep the stable part of your system separate from the varing parts. While you want to be able to add more features to your system, you don't want to do it at the expense of disrupting something that works. By using <span class = green>extension</span> over <span class = red> change</span>, you can work on varing parts without introducing unwanted side effects into the stable parts.
## Dependency Inversion Principle
### <span class = green> The principle states that high level modules should be depend on high level generalizations, and not on low level details </span>
This means that your **client class should depend on an interface or abstract class instead of referring to concrete resouces**, and that your **concrete recouces should have their behaviors generalized into an interface or abstract class**. The idea is that <span class =green>Interfaces and abstract class</span> are considered high level resources. A <span class = red>concrete class </span> is considered a low level resource. This way, your client class can be independent to the low level funtionality.
#### **<span class = red>Example that breaks Dependency Inversion Principle</span>**
```graphviz
digraph obj{
node[shape=record];
rankdir="LR";
nodesep=1
ClientSubsystem [label = "{<f0> ClientSubsystem}"];
EnterpriseSubsystem [label = "{<f0> EnterpriseSubsystem}"];
BackendSubsystem [label = "{<f0> BackendSubsystem }"];
ClientSubsystem->EnterpriseSubsystem [style="normal,"dir="forward",arrowhead="vee",arrowtail="normal",headlabel="Depend on ",taillabel=" " minlen=2];
EnterpriseSubsystem->BackendSubsystem [style="normal,"dir="forward",arrowhead="vee",arrowtail="normal",headlabel="Depend on ",taillabel=" " minlen=2];
}
```
* The original code for this design:
```java=
public class ClientSubsystem{
public QuickSorting enterpriseSorting;
public void sortInput(List customerList){
this.enterpriseSorting.quickSort(customerList);
}
}
```
* The code when you have to make changes to the sorting part
```java=
public class ClientSubsystem{
public QuickSorting enterpriseSorting;
public MergeSort newEnterpriseSorting;
public void sortInput(List customerList){
// this.enterpriseSorting.quickSort(customerList);
this.newEnterpriseSorting.mergeSort(customerList);
}
}
```
Notice you have to change the <span class = green>type</span> of the sorting class and also the <span class = green>function</span> and its <span class = green>calling</span>. The <span class = red>change is vast and significant</span> which means lots of works. Not only is it impratical, these kind of changes can <span class = red>cause serious side effects</span> if you miss some old references.
#### **<span class = red>Example that followes Dependency Inversion Principle</span>**
The Dependency Inversion Principle addresses these issues by generalizing low level functionalities into interfaces or abstract classes. The overall architecture of these kind of system will be similar to the design patterns we've exposed. Your client classes will then make references to the interface rather than directly to the concrete classes.
```graphviz
digraph obj{
rankdir="LR";
nodesep=0.5
ClientSubsystem [label = " ClientSubsystem"];
EnterpriseSubsystem [label = " EnterpriseSubsystem"];
EnterpriseInterface [label = " \<\<interface\>\>\nIEnterpriseSubsystem"];
BackendSubsystem [label = " BackendSubsystem "];
BackendInterface [label = " \<\<interface\>\>\nIBackendSubsystem"];
subgraph details {
rank="same";
edge[style="dashed",dir="back",arrowhead="onormal",arrowtail="onormal",headlabel=" ",taillabel=" " minlen=2];
EnterpriseInterface -> EnterpriseSubsystem;
}
subgraph details1 {
rank="same";
edge[style="dashed",dir="back",arrowhead="onormal",arrowtail="onormal",headlabel=" ",taillabel=" " minlen=2];
BackendInterface -> BackendSubsystem;
}
ClientSubsystem->EnterpriseInterface [style="normal,"dir="forward",arrowhead="vee",arrowtail="normal",headlabel="Depend on ",taillabel=" " minlen=2];
EnterpriseSubsystem->BackendInterface [style="normal,"dir="forward",arrowhead="vee",arrowtail="normal",headlabel="Depend on ",taillabel=" " minlen=2];
}
```
* The original code for this design:
```java=
public class ClientSubsystem{
public Sorting enterpriseSorting;
public ClientSubsystem(Sorting concreteSortingClass)
{
this.enterpriseSorting = concreteSortingClass;
}
public void sortInput(List customerList){
this.enterpriseSorting.sort(customerList);
}
}
```
By declaring the sorting interface, you can determine which instance of sorting class you want to use during instantiation. Since you can generalize all sorting behavior into a method called sort, you won't need to change the client call when extending sort method.
**Since your client class is depending on a <span class = green>High Level Generalization</span> rather than a <span class = green>Low Level Concrete class</span>, you can easily change which resource your client will be using.**
#### **Conclusion**
The Dependency Inversion Principle is a means to:
1. Change the referencing of concrete classes from being direct to indirect
2. Generalize the behaviors of your concrete classes into abstract classes and interfaces
3. Have client classes interact with your system through a generalization rather than directly with concrete resources
4. Put emphisis on high level dependency over low level concrete dependency
## Composing Object Principle
### <span class = green> This principle states that classes should achieve code reuse through aggregation rather than inheritance </span>
<span class = red> Composite Design Pattern, Decorator Design Pattern</span> use this design principle
* Advantage:
> * Aggregation and delegation offer less coupling than inheritance
> * Provides your system more flexibility
> * Dynamically change the behaviors of objects at run time
* Disadvantage:
> * You must provide implemntations for all behavior without the benefit of inheritance to share code
### Conclusion:
The design principle will help you with reducing coupling in your system by using delegation and by composign objects with each other. In summary, the composing objects principle will provide a means of code reuse without the tight coupling of inheritance. It allows objects to dynamically add behaviors at runtime and provides more flexibility.
### <span class = red>Mind</span>
This principle is not indicating that inheritance should be prohibited. You need to examine the needs of your system in order to determine which design is appropriate.
## Interface Segregation Principle
### <span class = green> The principle states that a class should not be forced to depend on methods it does not use. This indicate that any classes that implement an interface should not have "dummy(useless)" implementations of any methods defined in the interface. Instead, you should split large interfaces into smaller generalizations. </span>
```graphviz
digraph obj{
node[shape=record];
rankdir="BT";
AbstractClass [label = "{<f0> \<\<interface\>\>\nICashier||+scanItem():void\n+takePayment():void\n+dispenseChange():void\n+startShift():void\n+takeBreak(float):void\ncompleteShift():void}"];
ConcreteClass1 [label = "{<f0> SelfServeMachine|<f1>\n |+scanItem():void\n+takePayment():void\n+dispenseChange():void\n+startShift():void\n+takeBreak(float):void\ncompleteShift():void}"];
ConcreteClass2 [label = "{<f0> HumanCashier|<F1>|+scanItem():void\n+takePayment():void\n+dispenseChange():void\n+startShift():void\n+takeBreak(float):void\ncompleteShift():void\n}"];
ConcreteClass1->AbstractClass [style="dashed",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "];
ConcreteClass2->AbstractClass [style="dashed",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
}
```
This design breaks the rule of <span class = red>Interface Segregation Principle</span> because the SelfServeMachine does not need to take breaks and shifting. SelfServeMachine is begin forced to provide the implementation of a method that's useless. We should use the <span class = red>Interface Segregation Principle</span> and split the original interface into two smaller ones. The will allow each interface to be more accurate with its description of expected behavior.
The design follows the Interface Segregation Principle:
```graphviz
digraph obj{
node[shape=record];
rankdir="BT";
AbstractClass [label = "{<f0> \<\<interface\>\>\nICashier||+scanItem():void\n+takePayment():void\n+dispenseChange():void}"];
AbstractClass1 [label = "{<f0> \<\<interface\>\>\nICashier||+startShift():void\n+takeBreak(float):void\ncompleteShift():void}"];
ConcreteClass1 [label = "{<f0> SelfServeMachine|<f1>\n |+scanItem():void\n+takePayment():void\n+dispenseChange():void\n}"];
ConcreteClass2 [label = "{<f0> HumanCashier|<F1>|+scanItem():void\n+takePayment():void\n+dispenseChange():void\n+startShift():void\n+takeBreak(float):void\ncompleteShift():void\n}"];
ConcreteClass1->AbstractClass [style="dashed",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "];
ConcreteClass2->AbstractClass [style="dashed",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
ConcreteClass2->AbstractClass1
[style="dashed",dir="forward",arrowhead="onormal",arrowtail="normal",headlabel=" ",taillabel=" "]
}
```
### Conclusion
1. A class should not be forced to depend on methods it does not use.
2. Interfaces should be split up in such a way that it can properly describe the seperate functionalities of your system
## Principle of Least Knowledge(Law of Demeter)
### <span class = green> </span>
The underlying idea of this Law is that classes should know about and interact with as few other classes as possible. This indicates that any class should only communicate with its "immediate friends". This principle help reduces coupling and make system stable.
* First Rule: A method, M, in an object, O, can call on any other method within O itself.
```java=
Public class O{
public void M(){
this.N();
}
public void N();
}
```
* Second Rule: A method, M, can call the methods of any parameter P.
```java=
public class Friend{
public void N();
}
Public class O{
public void M(Friend P){
P.N();
}
}
```
* Third Rule: A method, M, can call a method, N, of an object, I, if I is instantiated within M.
```java=
public class Friend{
public void N();
}
Public class O{
public void M(){
Friend I = new Friend();
I.N();
}
}
```
* Fourth Rule: Any method, M, in object O, can invoke methods of any type of object that is a direct component of O
```java=
public class Friend{
public void N();
}
Public class O{
public Friend I = new Friend();
public void M(){
I.N();
}
}
```
<span class = green>**All the rules above come down to the principle that you should not allow a method to access another method by </span> <span class = red>"reaching through"</span><span class = green>an object which is not local</span>**
#### Examples that break Law of Demeter: "Reaching through"
1. Chain of method calls to the object you shouldn't know
```java=
Public class Driver{
public Car myCar = new Car();
public void drive(){
this.myCar.engine.start(); //Engine is an object you shouldn't know because Engine class is not the component of the Driver
}
}
```
3. Use of unknown object that is returned to you by local method
```java=
Public class Driver{
public Car myCar = new Car();
public void rentVehicle(VehicleRentalStore store){
Motorcycle myRental = store.rent("Motorcycle");
myRental.drive();// Motorcycle is an unknown object for Driver
}
}
```
### Conclusion
Classes should know as little as possible about your system as a whole. This will help reduce the amount of coupling and prevent unwanted effect from cascading through your entire system.
## Liskov of Substitution Principle
### <span class = green> </span>