some oop paradigms & solid
TRANSCRIPT
SOLIDOOP paradigms
● Basic principles
○ Favor Composition over Inheritance
○ Law of Demeter
○ Dependency Injection
● S.O.L.I.D. principles
SOLID
OOP paradigms
SOLID
Favor Composition over Inheritance
● Inheritance generates LOTS of problems
○ Ex: Circle-Ellipse problem
■ Class Ellipse with radiusX, radiusY
■ Class Circle extends from Ellipse
■ later add stretchX()
SOLID
Favor Composition over Inheritance
● Minimize coupling (least knowledge principle)
● In a class method you can use:
○ 1. Object itself
○ 2. Method’s parameters
○ 3. Objects created inside
○ 4. Any class’ components (properties+methods)
SOLID
Law of Demeter (LoD)
● “Don’t ask your dog to move legs but walk”
○ As code: dog.leg.move()
○ You do not care how your dog walk
○ Only the dog knows the way it walks
SOLID
Law of Demeter (LoD)
● What if the XML is located in a DB?
SOLID
Dependency Injection
class FeedParser{ public function __construct($filename) { $this->XmlFilename = $filename; } public function doParse() { $xmlData = $this->readXML($this->XmlFilename); $products = $this->extractProductsFromXmlData($xmlData); return $products; } private function readXML($filename) { $xmlData = simplexml_load_file($filename); //(... Guard clauses ...) return $xmlData; }
● One object supplies the dependencies of another object
SOLID
Dependency Injection
class FeedParser{ private $xmlReader;
public function __construct(XmlReader $xmlReader) { $this->xmlReader = $xmlReader; } public function doParse() { $xmlData = $this->readXML(); $products = $this->extractProductsFromXmlData($xmlData); return $products; } private function readXML() { $xmlData = $this->xmlReader->read(); //(... Guard clauses ...)
● When a new object is build, you can set concrete dependencies
SOLID
Dependency Injection
class FeedParser{ private $xmlReader;
public function __construct(XmlReader $xmlReader) { $this->xmlReader = $xmlReader; } //(...)}
class XmlReader{ //(...)}
$myXmlReader = new XMLReader($filename);$myParser = new FeedParser($myXmlReader);
● Improves decoupling
● Avoid hardcoding dependencies
● [Hint] Look for:
○ new Class()
○ build-in functions
■ Ex. date(), fopen()
SOLID
Dependency Injection
● Mnemonic acronym (by Feathers)
● “first five principles” of OOP design (by Uncle Bob)
SOLID
SOLID
● A class should have only a single responsibility
SOLID
S: Single Responsibility Principle (SRP)
public function doParse() { $xmlData = $this->readXML(); $products = $this->extractProductsFromXmlData($xmlData); return $products; } private function readXML() { $this->checkFileExists($filename); $xmlData = $this->xmlReader->read(); $this->checkXmlHasContent($xmlData); return $xmlData; }
● A class should have only a single responsibility
SOLID
S: Single Responsibility Principle (SRP)
public function doParse() { $xmlData = $this->xmlReader->read(); $products = $this->extractProductsFromXmlData($xmlData); return $products; } private function readXML() { $this->checkFileExists($filename); $xmlData = $this->xmlReader->read(); $this->checkXmlHasContent($xmlData); return $xmlData; }
● Software entities (classes, modules, etc) should be:
○ Open for extension
■ Doesn’t mean inheritance
○ Closed for modification
■ No need to touch the original code
● How could we do so?
SOLID
O: Open-Closed Principle
● What if our data comes from a CSV? And later from a JSON?
SOLID
O: Open-Closed Principle
class FeedParser{ private $xmlReader;
public function __construct(XmlReader $xmlReader) { $this->xmlReader = $xmlReader; } public function doParse() { $xmlData = $this->xmlReader->read(); //(...)
SOLID
O: Open-Closed Principle, using interfaces!class FeedParser{ private $reader; public function __construct(DataReaderWriter $reader) { $this->reader = $reader; } public function doParse() { $xmlData = $this->reader->read(); //(...) }}
interface DataReaderWriter{ public function read(); public function write($data);}
class XMLReaderWriter implements DataReaderWriter{ // ... implement read() and write() }
● If ChildClass is a subtype of ParentClass, then a ParentClass object
can replace a ChildClass object
● Remember Circle-Ellipse problem
● “Avoid most inheritance cases”
SOLID
L: Liskov Substitution Principle
● No client should be forced to depend on methods it doesn’t use
● “Split a large interface in separated small interfaces”
SOLID
I: Interface Segregation Principle
SOLID
I: Interface Segregation Principleclass FeedParser{ private $reader; public function __construct(DataReaderWriter $reader) { $this->reader = $reader; } public function doParse() { $xmlData = $this->reader->read(); //(...) }}
interface DataReaderWriter{ public function read(); public function write($data);}
class XMLReaderWriter implements DataReaderWriter{ // ... implement read() and write() }
SOLID
I: Interface Segregation Principleclass FeedParser{ private $reader; public function __construct(DataReader $reader) { $this->reader = $reader; } public function doParse() { $xmlData = $this->reader->read(); //(...) }}
interface DataReader{ public function read();}
class XMLReaderWriter implements DataReader, DataWriter{ // ... implement read() and write() }
● High-level modules should not depend on low-level modules.
Both should depend on abstractions.
● Does it look familiar?
SOLID
D: Dependency Inversion Principle
● We have already used it!
SOLID
D: Dependency Inversion Principle
class FeedParser{ private $xmlReader;
public function __construct(XmlReader $xmlReader) { $this->xmlReader = $xmlReader; }
//-----
class FeedParser{ private $reader; public function __construct(DataReaderWriter $reader) { $this->reader = $reader; }
● Books:
○ Head First OO Analysis and Design (McLaughlin)
○ Head First Design Patterns (Freeman)
● Internet:
○ https://sites.google.com/site/unclebobconsultingllc/getting-a-solid-start
■ About SOLID: “They are not laws. They are not perfect truths.”
SOLID
References