4. ● 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
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 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)
7. ● 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;
}
8. ● 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 ...)
9. ● 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);
11. ● Mnemonic acronym (by Feathers)
● “first five principles” of OOP design (by Uncle Bob)
SOLID
SOLID
12. ● 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;
}
13. ● 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;
}
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 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();
//(...)
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 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
18. ● 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
19. 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() }
20. 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() }
21. ● High-level modules should not depend on low-level modules.
Both should depend on abstractions.
● Does it look familiar?
SOLID
D: Dependency Inversion Principle
22. ● 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;
}
23. ● 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