SOLID
OOP 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 Principle
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() }
SOLID
I: Interface Segregation Principle
class 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

Some OOP paradigms & SOLID

  • 1.
  • 2.
    ● Basic principles ○Favor Composition over Inheritance ○ Law of Demeter ○ Dependency Injection ● S.O.L.I.D. principles SOLID OOP paradigms
  • 3.
  • 4.
    ● Inheritance generatesLOTS of problems ○ Ex: Circle-Ellipse problem ■ Class Ellipse with radiusX, radiusY ■ Class Circle extends from Ellipse ■ later add stretchX() SOLID Favor Composition over Inheritance
  • 5.
    ● 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)
  • 6.
    ● “Don’t askyour 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)
  • 7.
    ● What ifthe 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; }
  • 8.
    ● One objectsupplies 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 ...)
  • 9.
    ● When anew 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);
  • 10.
    ● Improves decoupling ●Avoid hardcoding dependencies ● [Hint] Look for: ○ new Class() ○ build-in functions ■ Ex. date(), fopen() SOLID Dependency Injection
  • 11.
    ● Mnemonic acronym(by Feathers) ● “first five principles” of OOP design (by Uncle Bob) SOLID SOLID
  • 12.
    ● A classshould 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; }
  • 13.
    ● A classshould 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; }
  • 14.
    ● 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
  • 15.
    ● What ifour 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(); //(...)
  • 16.
    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() }
  • 17.
    ● If ChildClassis 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
  • 18.
    ● No clientshould be forced to depend on methods it doesn’t use ● “Split a large interface in separated small interfaces” SOLID I: Interface Segregation Principle
  • 19.
    SOLID I: Interface SegregationPrinciple 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() }
  • 20.
    SOLID I: Interface SegregationPrinciple class 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() }
  • 21.
    ● High-level modulesshould not depend on low-level modules. Both should depend on abstractions. ● Does it look familiar? SOLID D: Dependency Inversion Principle
  • 22.
    ● We havealready 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; }
  • 23.
    ● Books: ○ HeadFirst 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