Some OOP paradigms & SOLID

23
SOLID OOP paradigms

Transcript of Some OOP paradigms & SOLID

Page 1: Some OOP paradigms & SOLID

SOLIDOOP paradigms

Page 2: Some OOP paradigms & SOLID

● Basic principles

○ Favor Composition over Inheritance

○ Law of Demeter

○ Dependency Injection

● S.O.L.I.D. principles

SOLID

OOP paradigms

Page 3: Some OOP paradigms & SOLID

SOLID

Favor Composition over Inheritance

Page 4: Some OOP paradigms & SOLID

● 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

Page 5: Some OOP paradigms & SOLID

● 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)

Page 6: Some OOP paradigms & SOLID

● “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)

Page 7: Some OOP paradigms & SOLID

● 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; }

Page 8: Some OOP paradigms & SOLID

● 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 ...)

Page 9: Some OOP paradigms & SOLID

● 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);

Page 10: Some OOP paradigms & SOLID

● Improves decoupling

● Avoid hardcoding dependencies

● [Hint] Look for:

○ new Class()

○ build-in functions

■ Ex. date(), fopen()

SOLID

Dependency Injection

Page 11: Some OOP paradigms & SOLID

● Mnemonic acronym (by Feathers)

● “first five principles” of OOP design (by Uncle Bob)

SOLID

SOLID

Page 12: Some OOP paradigms & 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; }

Page 13: Some OOP paradigms & SOLID

● 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; }

Page 14: Some OOP paradigms & SOLID

● 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

Page 15: Some OOP paradigms & SOLID

● 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(); //(...)

Page 16: Some OOP paradigms & SOLID

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() }

Page 17: Some OOP paradigms & SOLID

● 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

Page 18: Some OOP paradigms & SOLID

● 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

Page 19: Some OOP paradigms & SOLID

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() }

Page 20: Some OOP paradigms & SOLID

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() }

Page 21: Some OOP paradigms & SOLID

● High-level modules should not depend on low-level modules.

Both should depend on abstractions.

● Does it look familiar?

SOLID

D: Dependency Inversion Principle

Page 22: Some OOP paradigms & SOLID

● 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; }

Page 23: Some OOP paradigms & SOLID

● 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