Date post: | 12-Apr-2017 |
Category: |
Technology |
Upload: | pehapkari |
View: | 112 times |
Download: | 0 times |
SOLID | Štěpán Zikmund
krása
• změny v zadání
• nové funkce, které jsou v rozporu s původní funkcionalitou
• deadliny
Co by mohly být takový překážky..
no, mohly by…
source code
💩
Rigidity
Fragilitiy
Imobility
Coupling? How?
OOP
SOLID
Single Responsibility Principle Open Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
– Uncle Bob
„OOP is about managing dependency by selectively inverted some key dependencies in your architecture to prevent rigidity, fragility, not
reusability“
The Dependency Inversion Principle
Depend on abstractions, not on concretions
m
n
m n
m interface
n
class Authentication { private $userProvider;
public function __construct(UserProvider $userProvider) { $this->userProvider = $userProvider; } }
class Authentication { private $userProvider;
public function __construct(UserProviderInterface $userProvider) { $this->userProvider = $userProvider; } }
The Single Responsibility Principle
A class should have one, and only one, reason to change
Symptomy
• účel třídy nejde pospat bez spojek a, nebo
• třída obsahuje velké množství properties a public method
• třída obsahuje velké množství závislostí na další objekty
Řešení
• kompozice
• event listener
• …
Employee
+ getSalary() + getName() + setSalary() + setName() + getSalaryReport()
Employee
+ getSalary() + getName() + setSalary() + setName()
SalaryReportBuilder
+ getReport(Employee $employee)
The Open Closed Principle
You should be able to extend a classes behaviour, without modifying it
Pro přidání nové featury nechcete editovat stávající
kód, ale vytvořit nový
function doSomething($howToDoIt) { if ($howToDoIt == 'something') { return someBehaviour(); } else if ($howToDoIt == 'somethingOther') { return someOtherBehaviour(); } else { throw new \IllegalArgumentException(); } }
Symptomy
• switch statement
• třída zná více různých service se stejným interfacem nebo s podobným účelem
Employee
+ getSalary() + getName() + setSalary() + setName()
SalaryReportBuilder
+ getXmlReport(Employee $employee) + getJsonReport(Employee $employee)
Employee
+ getSalary() + getName() + setSalary() + setName()
SalaryReportBuilder
+ getXmlReport(Employee $employee) + getJsonReport(Employee $employee)SRP
XmlReportBuilder
+ getXmlReport(..)
SalaryReportBuilder
+ getReport($type)
JsonReportBuilder
+ getJsonReport(..)
function getReport($type, $employee) { switch ($type): case 'xml' return $this->xmlReportBuilder->getReport($employee); case 'json' return $this->jsonReportBuilder->getReport($employee); default: throw new \IllegalArgumentException(); }
function getReport($type, $employee) { switch ($type): case 'xml' return $this->xmlReportBuilder->getReport($employee); case 'json' return $this->jsonReportBuilder->getReport($employee); default: throw new \IllegalArgumentException(); } OCP
XmlReportBuilder
+ getReport(..) + getName()
SalaryReportBuilder
+ addBuilder(ReportInterface) + getReport($type)
ReportBuilderInterface
+ getReport(..) + getName
JsonReportBuilder
+ getReport(..) + getName()
function getReport($type, $employee) { foraech ($this->reportBuilders as $builder) { if ($builder->getName() == $type) { return $builder->getReport($employee); } }
throw new \IllegalArgumentException(); }
The Liskov Substitution Principle
Derived classes must be substitutable for their base classes.
app rectangle
app rectangle
square
class Square { public function setHeight($height) { $this->height = $height; parent::setWidth($height); } public function setWidth($width) { $this->width = $width; parent::setHeight($width); } }
if ($rectangle instanceof Square) { //.. } else { //.. }
app rectangle
square
OOP není modelování skutečného světa, ale
jeho reprezentací
class Rectangle { public function getHeight() {} public function getWidth() {} public function setHeight() {} public function setWidth() {} }
class Square { public function getSize() {} public function setSize() {} }
The Interface Segregation Principle
Make fine grained interfaces that are client specific
m interface
n
Client specific?
m interface
n
Fine grained?
interface FileInterface { public function changeName() public function changeOwner() }
class DropboxFile implements FileInterface { public function changeName() { } public function changeOwner() { // don’t need this method } }
interface FileInterface { public function changeName() }
interface SupportsChangeOfOwnershipInterface { public function changeOwner() }
SRP OCP LSP ISP DIP