2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!
-
Upload
php-conference-argentina -
Category
Technology
-
view
126 -
download
0
description
Transcript of 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!
![Page 1: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/1.jpg)
Make Your Project SOLIDPHP Conference Argentina 2013
Benjamin Eberlei, @beberlei4th October 2013
![Page 2: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/2.jpg)
About me
Helping people to create high quality web applications.http://qafoo.com
I Doctrine Developer
I Symfony Contributor
I Twitter @beberlei and @qafoo
![Page 3: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/3.jpg)
About me
Helping people to create high quality web applications.http://qafoo.com
I Doctrine Developer
I Symfony Contributor
I Twitter @beberlei and @qafoo
![Page 4: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/4.jpg)
About me
Helping people to create high quality web applications.http://qafoo.com
I Doctrine Developer
I Symfony Contributor
I Twitter @beberlei and @qafoo
![Page 5: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/5.jpg)
About me
Helping people to create high quality web applications.http://qafoo.com
I Doctrine Developer
I Symfony Contributor
I Twitter @beberlei and @qafoo
![Page 6: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/6.jpg)
About me
Helping people to create high quality web applications.http://qafoo.com
I Doctrine Developer
I Symfony Contributor
I Twitter @beberlei and @qafoo
![Page 7: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/7.jpg)
Why Object Orientation?
So, why do you want object oriented code?
I Manage complexityI Reusable codeI Maintainable code
![Page 8: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/8.jpg)
Why Object Orientation?
So, why do you want object oriented code?
I Manage complexityI Reusable codeI Maintainable code
![Page 9: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/9.jpg)
Why Object Orientation?
So, why do you want object oriented code?
I Manage complexityI Reusable codeI Maintainable code
![Page 10: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/10.jpg)
Why Object Orientation?
So, why do you want object oriented code?
I Manage complexityI Reusable codeI Maintainable code
![Page 11: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/11.jpg)
The SOLID principles
I 5 essential principles of object oriented designI Introduced by Robert C. Martin (Uncle Bob)
I not the inventor of the principles
I Have proven to lead to better codeI Scientific background (partly)
![Page 12: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/12.jpg)
By Example
A weather loader component
I Fetch weather for a cityI Relevant data:
I ConditionI TemperatureI Wind
I Be service-agnosticI Weather service come and goI Data licenses may change
I Log service failuresI Make it possible to add service fallbacks later
![Page 13: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/13.jpg)
Single Responsibility Principle
“There should never be more than onereason for a class to change.”
![Page 14: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/14.jpg)
The Issue
1 <?php2
3 class GoogleWeatherService4 {
5 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )6 {
7 $xml = $ th is −>getData ( $ l o c a t i o n ) ;8 $weather = $ th is −>extractWeather ( $xml ) ;9 return $weather ;
10 }
11
12 protected function extractWeather ( $xml )13 {
14 $weather = new Weather ( ) ;15 $weather−>cond i t i ons = $ th is −>parseCondi t ions ( $xml ) ;16 / / . . .17 $weather−>windSpeed = $th is −>conver tMi lesToKi lometer (18 $ th is −>parseWindSpeed ( $xml )19 ) ;20 return $weather ;21 }
22
23 /∗ . . . ∗ /24 }
![Page 15: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/15.jpg)
The Fix
1 <?php2
3 class GoogleWeatherService4 {
5 public function construct (6 H t t p C l i e n t $ c l i e n t , GoogleDataParser $parser )7 { /∗ . . . ∗ / }8
9 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )10 {
11 $xml = $ th is −>c l i e n t −>get ( s p r i n t f (12 ’ h t t p : / / . . . / ? c i t y=%s ’ ,13 $ loca t ion −>c i t y14 ) ) ;15 return $ th is −>parser−>parseWeather ( $xml ) ;16 }
17 }
![Page 16: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/16.jpg)
Single Responsibility Principle
I One responsibility per classI Separation of concernsI Responsibilities hard to detect
![Page 17: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/17.jpg)
Single Responsibility Principle
I One responsibility per classI Separation of concernsI Responsibilities hard to detect
![Page 18: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/18.jpg)
Open/Close Principle
“Software entities (classes, modules,functions, etc.) should be open forextension, but closed for modification.”
![Page 19: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/19.jpg)
The Wrong Way
3 class WeatherLoader4 {
5 public function construct ( $serv ice )6 { /∗ . . . ∗ / }7
8 public function getWeatherForLocat ion ( S t r u c t \ Locat ion $ l o c a t i o n )9 {
10 / / . . .11 switch ( ge t c l ass ( $ th i s −>serv i ce ) )12 {
13 case ’ GoogleWeatherService ’ :14 return $ th is −>serv ice−>getWeather ( $ l o ca t i o n ) ;15
16 case ’ WetterComWeatherService ’ :17 return $ th is −>serv ice−>re t r ieveWeather (18 $ loca t ion −>c i t y , $ loca t ion −>count ry19 ) ;20 / / . . .21 }
22 }
23 }
![Page 20: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/20.jpg)
The Right Way
3 class WeatherLoader4 {
5 public function construct ( WeatherService $serv ice )6 { /∗ . . . ∗ / }7
8 public function getWeatherForLocat ion ( S t r u c t \ Locat ion $ l o c a t i o n )9 {
10 / / . . .11 return $ th is −>serv ice−>getWeatherForLocat ion ( $ l o ca t i o n ) ;12 }
13 }
![Page 21: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/21.jpg)
Open/Close Principle
I Changes introduce errorsI Especially cascading changes
I Ideally: Write once, change never!I Extend software only by new code
I New interface implementationsI InheritanceI Aggregation
![Page 22: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/22.jpg)
Liskov Substitution Principle
“Functions that use pointers or referencesto base classes must be able to use objectsof derived classes without knowing it.”
![Page 23: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/23.jpg)
A Simple Class
1 <?php2
3 class DistanceConverter4 {
5 const FACTOR = 0.6214;6
7 public function milesToKi lometers ( $mi les )8 {
9 return $miles / s e l f : : FACTOR;10 }
11 }
![Page 24: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/24.jpg)
Getting into Trouble
1 <?php2
3 class Format t ingDis tanceConver ter extends DistanceConverer4 {
5 public function milesToKi lometers ( $mi les )6 {
7 i f ( $mi les < 0 )8 {
9 throw new Inva l idArgumentExcept ion ( ) ;10 }
11 return s p r i n t f (12 ’ %01.2 f km ’ , parent : : mi lesToKi lometers ( $mi les )13 ) ;14 }
15 }
![Page 25: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/25.jpg)
Liskov Substitution Principle
I Be less strict on inputI Be more strict on output
![Page 26: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/26.jpg)
Liskov Substitution Principle
I Be less strict on inputI Be more strict on output
milesToKilometers($miles)
float
float
![Page 27: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/27.jpg)
Liskov Substitution Principle
I Be less strict on inputI Be more strict on output
milesToKilometers($miles)
float
float
> 0
![Page 28: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/28.jpg)
Liskov Substitution Principle
I Be less strict on inputI Be more strict on output
milesToKilometers($miles)
float
floatstring or
![Page 29: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/29.jpg)
Liskov Substitution Principle
I Be less strict on inputI Be more strict on output
milesToKilometers($miles)
float
float
or string
![Page 30: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/30.jpg)
Liskov Substitution Principle
I Be less strict on inputI Be more strict on output
milesToKilometers($miles)
float
float> 0
![Page 31: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/31.jpg)
Liskov Substitution Principle
I Do not change contracts by inheritanceI Methods must work as expected in derived classesI Users must not distinguish between super- and subclassI Subtype polymorphism
![Page 32: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/32.jpg)
Liskov Substitution Principle
I Do not change contracts by inheritanceI Methods must work as expected in derived classesI Users must not distinguish between super- and subclassI Subtype polymorphism
![Page 33: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/33.jpg)
Dependency Inversion Principle
“A. High-level modules should not dependon low level modules. Both should dependon abstractions.”
“B. Abstractions should not depend upondetails. Details should depend uponabstractions.”
![Page 34: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/34.jpg)
Dependency Inversion Principle
“A. High-level modules should not dependon low level modules. Both should dependon abstractions.”
“B. Abstractions should not depend upondetails. Details should depend uponabstractions.”
![Page 35: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/35.jpg)
The Issue
1 <?php2
3 class WeatherLoader4 {
5 public function construct (6 GoogleWeatherService $weatherService , F i leLogger $logger )7 {
8 $ th is −>weatherService = $weatherService ;9 $ th is −> l ogger = $logger ;
10 }
11 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )12 {
13 / / . . .14 $ th is −> logger−> l og ( ’Some log message . ’ ) ;15 / / . . .16 $ th is −> logger−>w r i t e T o F i l e ( ) ;17 }
18 }
![Page 36: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/36.jpg)
Doing it Right
1 <?php2
3 class WeatherLoader4 {
5 public function construct (6 WeatherService $weatherService , Logger $ logger )7 {
8 $ th is −>weatherService = $weatherService ;9 $ th is −> l ogger = $logger ;
10 }
11 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )12 {
13 / / . . .14 $ th is −> logger−> l og ( ’Some log message . ’ ) ;15 / / . . .16 }
17 }
![Page 37: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/37.jpg)
Dependency Inversion Principle
I Use abstraction to encapsulate low level modulesI Abstractions are the APIsI Abstractions hide implementation detailsI Depend on interfaces, not realizationsI Define interfaces from a usage point of viewI Finding abstractions is not easyI Dependency Injection, anyone?
![Page 38: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/38.jpg)
Dependency Inversion Principle
I Use abstraction to encapsulate low level modulesI Abstractions are the APIsI Abstractions hide implementation detailsI Depend on interfaces, not realizationsI Define interfaces from a usage point of viewI Finding abstractions is not easyI Dependency Injection, anyone?
![Page 39: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/39.jpg)
Dependency Inversion Principle
I Use abstraction to encapsulate low level modulesI Abstractions are the APIsI Abstractions hide implementation detailsI Depend on interfaces, not realizationsI Define interfaces from a usage point of viewI Finding abstractions is not easyI Dependency Injection, anyone?
![Page 40: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/40.jpg)
Dependency Inversion Principle
I Use abstraction to encapsulate low level modulesI Abstractions are the APIsI Abstractions hide implementation detailsI Depend on interfaces, not realizationsI Define interfaces from a usage point of viewI Finding abstractions is not easyI Dependency Injection, anyone?
![Page 41: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/41.jpg)
Interface Segregation Principle
“Clients should not be forced to dependupon interfaces that they do not use.”
![Page 42: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/42.jpg)
Suboptimal
3 class Loader4 {
5 public function construct ( WeatherService $weatherService , Logger $logger )6 { /∗ . . . ∗ / }7
8 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )9 { /∗ . . . ∗ / }
10 }
3 abstract class WeatherService4 {
5 abstract public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n ) ;6
7 abstract public function getForecastForLocat ion ( Locat ion $ loca t ion , $weekDay ) ;8 }
![Page 43: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/43.jpg)
The Fix
1 in ter face Locat ionWeatherProvider2 {
3 function getWeatherForLocat ion ( Locat ion $ l o ca t i o n ) ;4 }
1 abstract class WeatherService implements Locat ionWeatherProvider2 {
3 abstract public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n ) ;4
5 abstract public function getForecastForLocat ion ( Locat ion $ loca t ion , $weekDay ) ;6 }
1 class Loader2 {
3 public function construct ( Locat ionWeatherProvider $prov ider , Logger $logger )4 { /∗ . . . ∗ / }5
6 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )7 { /∗ . . . ∗ / }8 }
![Page 44: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/44.jpg)
The Fix
1 in ter face Locat ionWeatherProvider2 {
3 function getWeatherForLocat ion ( Locat ion $ l o ca t i o n ) ;4 }
1 abstract class WeatherService implements Locat ionWeatherProvider2 {
3 abstract public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n ) ;4
5 abstract public function getForecastForLocat ion ( Locat ion $ loca t ion , $weekDay ) ;6 }
1 class Loader2 {
3 public function construct ( Locat ionWeatherProvider $prov ider , Logger $logger )4 { /∗ . . . ∗ / }5
6 public function getWeatherForLocat ion ( Locat ion $ l o ca t i o n )7 { /∗ . . . ∗ / }8 }
![Page 45: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/45.jpg)
Interface Segregation Principle
I Avoid not needed dependenciesI Design interfaces from a usage point of viewI Do not let unnecessary functionality float in
![Page 46: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/46.jpg)
The SOLID principles
I Single Responsibility PrincipleI Open/Closed PrincipleI Liskov Substitution PrincipleI Interface Segregation PrincipleI Dependency Inversion Principle
![Page 47: 2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!](https://reader033.fdocuments.us/reader033/viewer/2022060119/558df7a61a28ab5a348b4586/html5/thumbnails/47.jpg)