## SOLID ### Single responsability Definition: A class should have one and only one reason to change, meaning that a class should have only one job. Ex: A class that calculates area of a shape also manages authentication, connection to db and rendering. WRONG! Problems of GOD class: - Uses a lot of dependencies - Contains different types of logic - Nothing is decoupled - It's no opened to extension Solutions: - Use layers to separate logics - Proper naming - DI ### Open-Close Definition: Objects or entities should be open for extension, but closed for modification. For PHP: - Classes should allow the creation of new properties or methods - Classes should not allow modification of current properties or methods. - Classes should have rich documented interfaces or prototypes. ```php public function sum() { foreach ($this->shapes as $shape) { if(is_a($shape, 'Square')){ $area[] = pow($shape->length, 2); } elseif (is_a($shape, 'Circle')){ $area[] = pi() * pow($shape->radius, 2); } } return array_sum($area); } ``` => Create an interface for all different shapes and make the method "area" compulsory ### Liskov Substitution Definition: Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. - If we have a **`Tesla`** is a subtype of a **`Car`**, then I should be able to **`drive`** either a **`Car`** or a **`Tesla`** the same way. - Classes should depend on non-concrete class when possible, like abstract or interfaces - Classes extensions must use the same prototype as their parents. - When implementing an Interface there is a contract in the input but should be a contract on the output to. (Also exceptions) Problem: If we use the interface we act expecting some output. Code Smell: instanceof Solution: Doc Blocks and return type hinting ### Interface segregation Definition: A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use. - Many client-specific interfaces are better than one general-purpose interface Solution: - Use dependencies - Split the class into => interfaces + abstractions - Implement abstractions in a way that don't knoe about other classses' behavior ```php interface WorkerInterface { public function work(); public function sleep(); } class Worker implements WorkerInterface { public function work(){} public function sleep(){} } class Android implements WorkerInterface { public function work(){} public function sleep(){ return null; } } class Captain { public function manage (WorkerInterface $worker) { $worker->work(); $worker->sleep(); } } ``` => ```php interface WorkableInterface { public function work(); } interface SleepableInterface { public function sleep(); } class Worker implements WorkableInterface, SleepableInterface{ public function work(){} public function sleep(){} } class Android implements WorkableInterface { public function work(){} } class Captain { public function manage (¿?¿?¿? $worker) { $worker->work(); $worker->sleep(); } } ``` => ```php interface ManageableInterface { public function beManaged(); } interface WorkableInterface { public function work(); } interface SleepableInterface { public function sleep(); } class Worker implements WorkableInterface, SleepableInterface, ManageableInterface{ public function work(){} public function sleep(){} public function beManaged(){ $this->work(); $this->sleep(); } } class Android implements WorkableInterface, ManageableInterface { public function work(){} public function beManaged(){ $this->work(); } } class Captain { public function manage (ManageableInterface $worker) { $worker->beManaged(); } } ``` ### Dependency inversion Definition: - High-level modules should not depend on low-level modules. Both should depend on abstractions. A `Module` object should not depend on a `Child` object, but rather on `ChildInterface` or `AbstractChild`. - Abstractions should not depend upon details. Details should depend upon abstractions. And a `Child` object should receive calls not from a `Module`class but from a `ModuleInterface` Put simply, this means our dependencies should be interfaces/contracts or abstract classes rather than concrete implementations. ```php class PasswordReminder { private $dbConnection; public function __construct(MySQLConnection $dbConnection) { $this->dbConnection = $dbConnection; } } ``` PasswordReminder => hig level MySQLConnection => low level => ```php interface DBConnectionInterface { public function connect(); } class MySQLConnection implements DBConnectionInterface { public function connect() { return "Database connection"; } } class PasswordReminder { private $dbConnection; public function __construct(DBConnectionInterface $dbConnection) { $this->dbConnection = $dbConnection; } } ``` https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898