SlideShare une entreprise Scribd logo
1  sur  47
Télécharger pour lire hors ligne
Make Your Project SOLID
PHP Conference Argentina 2013
Benjamin Eberlei, @beberlei
4th October 2013
About me

Helping people to create high quality web applications.

http://qafoo.com
Doctrine Developer
Symfony Contributor
Twitter @beberlei and @qafoo
About me

Helping people to create high quality web applications.

http://qafoo.com
Doctrine Developer
Symfony Contributor
Twitter @beberlei and @qafoo
About me

Helping people to create high quality web applications.

http://qafoo.com
Doctrine Developer
Symfony Contributor
Twitter @beberlei and @qafoo
About me

Helping people to create high quality web applications.

http://qafoo.com
Doctrine Developer
Symfony Contributor
Twitter @beberlei and @qafoo
About me

Helping people to create high quality web applications.

http://qafoo.com
Doctrine Developer
Symfony Contributor
Twitter @beberlei and @qafoo
Why Object Orientation?

So, why do you want object oriented code?
Manage complexity
Reusable code
Maintainable code
Why Object Orientation?

So, why do you want object oriented code?
Manage complexity
Reusable code
Maintainable code
Why Object Orientation?

So, why do you want object oriented code?
Manage complexity
Reusable code
Maintainable code
Why Object Orientation?

So, why do you want object oriented code?
Manage complexity
Reusable code
Maintainable code
The SOLID principles

5 essential principles of object oriented design
Introduced by Robert C. Martin (Uncle Bob)
not the inventor of the principles

Have proven to lead to better code
Scientific background (partly)
By Example
A weather loader component
Fetch weather for a city
Relevant data:
Condition
Temperature
Wind

Be service-agnostic
Weather service come and go
Data licenses may change

Log service failures
Make it possible to add service fallbacks later
Single Responsibility Principle

“There should never be more than one
reason for a class to change.”
The Issue
1

<?php

2
3

class GoogleWeatherService

4

{

5

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )

6

{
$xml
= $ t h i s −> getData ( $ l o c a t i o n ) ;
$weather = $ t h i s −> e x t r a c t W e a t h e r ( $xml ) ;
r e t u r n $weather ;

7
8
9

}

10
11
12

protected function e x t r a c t W e a t h e r ( $xml )

13

{
$weather = new Weather ( ) ;
$weather −> c o n d i t i o n s = $ t h i s −> p a r s e C o n d i t i o n s ( $xml ) ;
// ...
$weather −>windSpeed = $ t h i s −> c o n v e r t M i l e s T o K i l o m e t e r (
$ t h i s −>parseWindSpeed ( $xml )
);
r e t u r n $weather ;

14
15
16
17
18
19
20

}

21
22

/∗ . . . ∗/

23
24

}
The Fix

1

<?php

2
3

class GoogleWeatherService

4

{
public function
construct (
H t t p C l i e n t $ c l i e n t , GoogleDataParser $ p a r s e r )
{ /∗ . . . ∗/ }

5
6
7
8

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )

9

{

10

$xml = $ t h i s −> c l i e n t −> g e t ( s p r i n t f (
’ h t t p : / / . . . / ? c i t y=%s ’ ,
$ l o c a t i o n −> c i t y
) );
r e t u r n $ t h i s −> parser −> parseWeather ( $xml ) ;

11
12
13
14
15

}

16
17

}
Single Responsibility Principle

One responsibility per class
Separation of concerns
Responsibilities hard to detect
Single Responsibility Principle

One responsibility per class
Separation of concerns
Responsibilities hard to detect
Open/Close Principle

“Software entities (classes, modules,
functions, etc.) should be open for
extension, but closed for modification.”
The Wrong Way
3

class WeatherLoader

4

{
public function
{ /∗ . . . ∗/ }

5
6

construct ( $service )

7
8

public function getWeatherForLocation ( S t r u c t  L o c a t i o n $ l o c a t i o n )

9

{

11

// ...
switch ( g e t c l a s s ( $ t h i s −> s e r v i c e ) )

12

{

10

case ’ GoogleWeatherService ’ :
r e t u r n $ t h i s −> s e r v i c e −> getWeather ( $ l o c a t i o n ) ;

13
14
15

case ’ WetterComWeatherService ’ :
r e t u r n $ t h i s −> s e r v i c e −> r e t r i e v e W e a t h e r (
$ l o c a t i o n −> c i t y , $ l o c a t i o n −> c o u n t r y
);
// ...

16
17
18
19
20

}

21

}

22
23

}
The Right Way

3

class WeatherLoader

4

{
public function
{ /∗ . . . ∗/ }

5
6

c o n s t r u c t ( WeatherService $ s e r v i c e )

7
8

public function getWeatherForLocation ( S t r u c t  L o c a t i o n $ l o c a t i o n )

9

{
// ...
r e t u r n $ t h i s −> s e r v i c e −> getWeatherForLocation ( $ l o c a t i o n ) ;

10
11

}

12
13

}
Open/Close Principle

Changes introduce errors
Especially cascading changes

Ideally: Write once, change never!
Extend software only by new code
New interface implementations
Inheritance
Aggregation
Liskov Substitution Principle

“Functions that use pointers or references
to base classes must be able to use objects
of derived classes without knowing it.”
A Simple Class

1

<?php

2
3

class D i s t a n c e C o n v e r t e r

4

{
const FACTOR = 0 . 6 2 1 4 ;

5
6
7

public function m i l e s T o K i l o m e t e r s ( $ m i l e s )

8

{
r e t u r n $ m i l e s / s e l f : : FACTOR;

9

}

10
11

}
Getting into Trouble

1

<?php

2
3

class F o r m a t t i n g D i s t a n c e C o n v e r t e r extends DistanceConverer

4

{

5

public function m i l e s T o K i l o m e t e r s ( $ m i l e s )

6

{

7

i f ( $miles < 0 )

8

{
throw new I n v a l i d A r g u m e n t E x c e p t i o n ( ) ;

9
10

}

11

return s p r i n t f (
’ %01.2 f km ’ , p a r e n t : : m i l e s T o K i l o m e t e r s ( $ m i l e s )
);

12
13

}

14
15

}
Liskov Substitution Principle

Be less strict on input
Be more strict on output
Liskov Substitution Principle
Be less strict on input
Be more strict on output

float

milesToKilometers($miles)

float
Liskov Substitution Principle
Be less strict on input
Be more strict on output

float
>0

milesToKilometers($miles)

float
Liskov Substitution Principle
Be less strict on input
Be more strict on output

float

milesToKilometers($miles)
string or
float
Liskov Substitution Principle
Be less strict on input
Be more strict on output

float
or string

milesToKilometers($miles)

float
Liskov Substitution Principle
Be less strict on input
Be more strict on output

float

milesToKilometers($miles)
>0
float
Liskov Substitution Principle

Do not change contracts by inheritance
Methods must work as expected in derived classes
Users must not distinguish between super- and subclass
Subtype polymorphism
Liskov Substitution Principle

Do not change contracts by inheritance
Methods must work as expected in derived classes
Users must not distinguish between super- and subclass
Subtype polymorphism
Dependency Inversion Principle

“A. High-level modules should not depend
on low level modules. Both should depend
on abstractions.”
“B. Abstractions should not depend upon
details. Details should depend upon
abstractions.”
Dependency Inversion Principle

“A. High-level modules should not depend
on low level modules. Both should depend
on abstractions.”
“B. Abstractions should not depend upon
details. Details should depend upon
abstractions.”
The Issue

1

<?php

2
3

class WeatherLoader

4

{

6

public function
construct (
GoogleWeatherService $weatherService , F i l e L o g g e r $ l o g g e r )

7

{

5

$ t h i s −> w ea th e rS er v ic e = $weatherService ;
$ t h i s −> l o g g e r
= $logger ;

8
9
10

}

11

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )

12

{
// ...
$ t h i s −> l o g g e r −> l o g ( ’Some l o g message . ’ ) ;
// ...
$ t h i s −> l o g g e r −> w r i t e T o F i l e ( ) ;

13
14
15
16

}

17
18

}
Doing it Right

1

<?php

2
3

class WeatherLoader

4

{

6

public function
construct (
WeatherService $weatherService , Logger $ l o g g e r )

7

{

5

$ t h i s −> w ea th e rS er v ic e = $weatherService ;
$ t h i s −> l o g g e r
= $logger ;

8
9
10

}

11

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )

12

{
// ...
$ t h i s −> l o g g e r −> l o g ( ’Some l o g message . ’ ) ;
// ...

13
14
15

}

16
17

}
Dependency Inversion Principle

Use abstraction to encapsulate low level modules
Abstractions are the APIs
Abstractions hide implementation details
Depend on interfaces, not realizations
Define interfaces from a usage point of view
Finding abstractions is not easy
Dependency Injection, anyone?
Dependency Inversion Principle

Use abstraction to encapsulate low level modules
Abstractions are the APIs
Abstractions hide implementation details
Depend on interfaces, not realizations
Define interfaces from a usage point of view
Finding abstractions is not easy
Dependency Injection, anyone?
Dependency Inversion Principle

Use abstraction to encapsulate low level modules
Abstractions are the APIs
Abstractions hide implementation details
Depend on interfaces, not realizations
Define interfaces from a usage point of view
Finding abstractions is not easy
Dependency Injection, anyone?
Dependency Inversion Principle

Use abstraction to encapsulate low level modules
Abstractions are the APIs
Abstractions hide implementation details
Depend on interfaces, not realizations
Define interfaces from a usage point of view
Finding abstractions is not easy
Dependency Injection, anyone?
Interface Segregation Principle

“Clients should not be forced to depend
upon interfaces that they do not use.”
Suboptimal

3

class Loader

4

{
public function
{ /∗ . . . ∗/ }

5
6

c o n s t r u c t ( WeatherService $weatherService , Logger $ l o g g e r )

7

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )
{ /∗ . . . ∗/ }

8
9
10

}

3

a b s t r a c t class WeatherService

4

{
a b s t r a c t public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ;

5
6

a b s t r a c t public function g e t F o r e c a s t F o r L o c a t i o n ( L o c a t i o n $ l o c a t i o n , $weekDay ) ;

7
8

}
The Fix
1

interface LocationWeatherProvider

2

{
function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ;

3
4

}

1

a b s t r a c t class WeatherService implements L o c a t i o n W e a t h e r P r o v i d e r

2

{
a b s t r a c t public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ;

3
4

a b s t r a c t public function g e t F o r e c a s t F o r L o c a t i o n ( L o c a t i o n $ l o c a t i o n , $weekDay ) ;

5
6

}

1

class Loader

2

{
public function
{ /∗ . . . ∗/ }

3
4

c o n s t r u c t ( L o c a t i o n W e a t h e r P r o v i d e r $ p r o v i d e r , Logger $ l o g g e r )

5

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )
{ /∗ . . . ∗/ }

6
7
8

}
The Fix
1

interface LocationWeatherProvider

2

{
function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ;

3
4

}

1

a b s t r a c t class WeatherService implements L o c a t i o n W e a t h e r P r o v i d e r

2

{
a b s t r a c t public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ;

3
4

a b s t r a c t public function g e t F o r e c a s t F o r L o c a t i o n ( L o c a t i o n $ l o c a t i o n , $weekDay ) ;

5
6

}

1

class Loader

2

{
public function
{ /∗ . . . ∗/ }

3
4

c o n s t r u c t ( L o c a t i o n W e a t h e r P r o v i d e r $ p r o v i d e r , Logger $ l o g g e r )

5

public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n )
{ /∗ . . . ∗/ }

6
7
8

}
Interface Segregation Principle

Avoid not needed dependencies
Design interfaces from a usage point of view
Do not let unnecessary functionality float in
The SOLID principles

Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!

Contenu connexe

Plus de PHP Conference Argentina

2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...PHP Conference Argentina
 
2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services
2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services 2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services
2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services PHP Conference Argentina
 
2013 - Janis Janovskis: Liderando equipos de desarrollo Open Source
2013 -  Janis Janovskis: Liderando equipos de desarrollo Open Source 2013 -  Janis Janovskis: Liderando equipos de desarrollo Open Source
2013 - Janis Janovskis: Liderando equipos de desarrollo Open Source PHP Conference Argentina
 
2013 - Brian Stanley - Memcached, Cached all the things
2013 - Brian Stanley - Memcached, Cached all the things2013 - Brian Stanley - Memcached, Cached all the things
2013 - Brian Stanley - Memcached, Cached all the thingsPHP Conference Argentina
 
2013 - Nate Abele Wield AngularJS like a Pro
2013 - Nate Abele Wield AngularJS like a Pro2013 - Nate Abele Wield AngularJS like a Pro
2013 - Nate Abele Wield AngularJS like a ProPHP Conference Argentina
 
2013 - Dustin whittle - Escalando PHP en la vida real
2013 - Dustin whittle - Escalando PHP en la vida real2013 - Dustin whittle - Escalando PHP en la vida real
2013 - Dustin whittle - Escalando PHP en la vida realPHP Conference Argentina
 
2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...
2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...
2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...PHP Conference Argentina
 
2013 - Andrei Zmievski: Machine learning para datos
2013 - Andrei Zmievski: Machine learning para datos2013 - Andrei Zmievski: Machine learning para datos
2013 - Andrei Zmievski: Machine learning para datosPHP Conference Argentina
 

Plus de PHP Conference Argentina (11)

2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
 
2013 - Andrei Zmievski: Clínica Regex
2013 - Andrei Zmievski: Clínica Regex2013 - Andrei Zmievski: Clínica Regex
2013 - Andrei Zmievski: Clínica Regex
 
2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services
2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services 2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services
2013 - Matías Paterlini: Escalando PHP con sharding y Amazon Web Services
 
2013 - Mark story - Avoiding the Owasp
2013 - Mark story - Avoiding the Owasp2013 - Mark story - Avoiding the Owasp
2013 - Mark story - Avoiding the Owasp
 
2013 - Janis Janovskis: Liderando equipos de desarrollo Open Source
2013 -  Janis Janovskis: Liderando equipos de desarrollo Open Source 2013 -  Janis Janovskis: Liderando equipos de desarrollo Open Source
2013 - Janis Janovskis: Liderando equipos de desarrollo Open Source
 
2013 - Brian Stanley - Memcached, Cached all the things
2013 - Brian Stanley - Memcached, Cached all the things2013 - Brian Stanley - Memcached, Cached all the things
2013 - Brian Stanley - Memcached, Cached all the things
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
 
2013 - Nate Abele Wield AngularJS like a Pro
2013 - Nate Abele Wield AngularJS like a Pro2013 - Nate Abele Wield AngularJS like a Pro
2013 - Nate Abele Wield AngularJS like a Pro
 
2013 - Dustin whittle - Escalando PHP en la vida real
2013 - Dustin whittle - Escalando PHP en la vida real2013 - Dustin whittle - Escalando PHP en la vida real
2013 - Dustin whittle - Escalando PHP en la vida real
 
2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...
2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...
2013 - Igor Sysoev - NGINx: origen, evolución y futuro - PHP Conference Argen...
 
2013 - Andrei Zmievski: Machine learning para datos
2013 - Andrei Zmievski: Machine learning para datos2013 - Andrei Zmievski: Machine learning para datos
2013 - Andrei Zmievski: Machine learning para datos
 

Dernier

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 

Dernier (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 

2013 - Benjamin Eberlei: Hacé tu proyecto SOLID!

  • 1. Make Your Project SOLID PHP Conference Argentina 2013 Benjamin Eberlei, @beberlei 4th October 2013
  • 2. About me Helping people to create high quality web applications. http://qafoo.com Doctrine Developer Symfony Contributor Twitter @beberlei and @qafoo
  • 3. About me Helping people to create high quality web applications. http://qafoo.com Doctrine Developer Symfony Contributor Twitter @beberlei and @qafoo
  • 4. About me Helping people to create high quality web applications. http://qafoo.com Doctrine Developer Symfony Contributor Twitter @beberlei and @qafoo
  • 5. About me Helping people to create high quality web applications. http://qafoo.com Doctrine Developer Symfony Contributor Twitter @beberlei and @qafoo
  • 6. About me Helping people to create high quality web applications. http://qafoo.com Doctrine Developer Symfony Contributor Twitter @beberlei and @qafoo
  • 7. Why Object Orientation? So, why do you want object oriented code? Manage complexity Reusable code Maintainable code
  • 8. Why Object Orientation? So, why do you want object oriented code? Manage complexity Reusable code Maintainable code
  • 9. Why Object Orientation? So, why do you want object oriented code? Manage complexity Reusable code Maintainable code
  • 10. Why Object Orientation? So, why do you want object oriented code? Manage complexity Reusable code Maintainable code
  • 11. The SOLID principles 5 essential principles of object oriented design Introduced by Robert C. Martin (Uncle Bob) not the inventor of the principles Have proven to lead to better code Scientific background (partly)
  • 12. By Example A weather loader component Fetch weather for a city Relevant data: Condition Temperature Wind Be service-agnostic Weather service come and go Data licenses may change Log service failures Make it possible to add service fallbacks later
  • 13. Single Responsibility Principle “There should never be more than one reason for a class to change.”
  • 14. The Issue 1 <?php 2 3 class GoogleWeatherService 4 { 5 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) 6 { $xml = $ t h i s −> getData ( $ l o c a t i o n ) ; $weather = $ t h i s −> e x t r a c t W e a t h e r ( $xml ) ; r e t u r n $weather ; 7 8 9 } 10 11 12 protected function e x t r a c t W e a t h e r ( $xml ) 13 { $weather = new Weather ( ) ; $weather −> c o n d i t i o n s = $ t h i s −> p a r s e C o n d i t i o n s ( $xml ) ; // ... $weather −>windSpeed = $ t h i s −> c o n v e r t M i l e s T o K i l o m e t e r ( $ t h i s −>parseWindSpeed ( $xml ) ); r e t u r n $weather ; 14 15 16 17 18 19 20 } 21 22 /∗ . . . ∗/ 23 24 }
  • 15. The Fix 1 <?php 2 3 class GoogleWeatherService 4 { public function construct ( H t t p C l i e n t $ c l i e n t , GoogleDataParser $ p a r s e r ) { /∗ . . . ∗/ } 5 6 7 8 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) 9 { 10 $xml = $ t h i s −> c l i e n t −> g e t ( s p r i n t f ( ’ h t t p : / / . . . / ? c i t y=%s ’ , $ l o c a t i o n −> c i t y ) ); r e t u r n $ t h i s −> parser −> parseWeather ( $xml ) ; 11 12 13 14 15 } 16 17 }
  • 16. Single Responsibility Principle One responsibility per class Separation of concerns Responsibilities hard to detect
  • 17. Single Responsibility Principle One responsibility per class Separation of concerns Responsibilities hard to detect
  • 18. Open/Close Principle “Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”
  • 19. The Wrong Way 3 class WeatherLoader 4 { public function { /∗ . . . ∗/ } 5 6 construct ( $service ) 7 8 public function getWeatherForLocation ( S t r u c t L o c a t i o n $ l o c a t i o n ) 9 { 11 // ... switch ( g e t c l a s s ( $ t h i s −> s e r v i c e ) ) 12 { 10 case ’ GoogleWeatherService ’ : r e t u r n $ t h i s −> s e r v i c e −> getWeather ( $ l o c a t i o n ) ; 13 14 15 case ’ WetterComWeatherService ’ : r e t u r n $ t h i s −> s e r v i c e −> r e t r i e v e W e a t h e r ( $ l o c a t i o n −> c i t y , $ l o c a t i o n −> c o u n t r y ); // ... 16 17 18 19 20 } 21 } 22 23 }
  • 20. The Right Way 3 class WeatherLoader 4 { public function { /∗ . . . ∗/ } 5 6 c o n s t r u c t ( WeatherService $ s e r v i c e ) 7 8 public function getWeatherForLocation ( S t r u c t L o c a t i o n $ l o c a t i o n ) 9 { // ... r e t u r n $ t h i s −> s e r v i c e −> getWeatherForLocation ( $ l o c a t i o n ) ; 10 11 } 12 13 }
  • 21. Open/Close Principle Changes introduce errors Especially cascading changes Ideally: Write once, change never! Extend software only by new code New interface implementations Inheritance Aggregation
  • 22. Liskov Substitution Principle “Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.”
  • 23. A Simple Class 1 <?php 2 3 class D i s t a n c e C o n v e r t e r 4 { const FACTOR = 0 . 6 2 1 4 ; 5 6 7 public function m i l e s T o K i l o m e t e r s ( $ m i l e s ) 8 { r e t u r n $ m i l e s / s e l f : : FACTOR; 9 } 10 11 }
  • 24. Getting into Trouble 1 <?php 2 3 class F o r m a t t i n g D i s t a n c e C o n v e r t e r extends DistanceConverer 4 { 5 public function m i l e s T o K i l o m e t e r s ( $ m i l e s ) 6 { 7 i f ( $miles < 0 ) 8 { throw new I n v a l i d A r g u m e n t E x c e p t i o n ( ) ; 9 10 } 11 return s p r i n t f ( ’ %01.2 f km ’ , p a r e n t : : m i l e s T o K i l o m e t e r s ( $ m i l e s ) ); 12 13 } 14 15 }
  • 25. Liskov Substitution Principle Be less strict on input Be more strict on output
  • 26. Liskov Substitution Principle Be less strict on input Be more strict on output float milesToKilometers($miles) float
  • 27. Liskov Substitution Principle Be less strict on input Be more strict on output float >0 milesToKilometers($miles) float
  • 28. Liskov Substitution Principle Be less strict on input Be more strict on output float milesToKilometers($miles) string or float
  • 29. Liskov Substitution Principle Be less strict on input Be more strict on output float or string milesToKilometers($miles) float
  • 30. Liskov Substitution Principle Be less strict on input Be more strict on output float milesToKilometers($miles) >0 float
  • 31. Liskov Substitution Principle Do not change contracts by inheritance Methods must work as expected in derived classes Users must not distinguish between super- and subclass Subtype polymorphism
  • 32. Liskov Substitution Principle Do not change contracts by inheritance Methods must work as expected in derived classes Users must not distinguish between super- and subclass Subtype polymorphism
  • 33. Dependency Inversion Principle “A. High-level modules should not depend on low level modules. Both should depend on abstractions.” “B. Abstractions should not depend upon details. Details should depend upon abstractions.”
  • 34. Dependency Inversion Principle “A. High-level modules should not depend on low level modules. Both should depend on abstractions.” “B. Abstractions should not depend upon details. Details should depend upon abstractions.”
  • 35. The Issue 1 <?php 2 3 class WeatherLoader 4 { 6 public function construct ( GoogleWeatherService $weatherService , F i l e L o g g e r $ l o g g e r ) 7 { 5 $ t h i s −> w ea th e rS er v ic e = $weatherService ; $ t h i s −> l o g g e r = $logger ; 8 9 10 } 11 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) 12 { // ... $ t h i s −> l o g g e r −> l o g ( ’Some l o g message . ’ ) ; // ... $ t h i s −> l o g g e r −> w r i t e T o F i l e ( ) ; 13 14 15 16 } 17 18 }
  • 36. Doing it Right 1 <?php 2 3 class WeatherLoader 4 { 6 public function construct ( WeatherService $weatherService , Logger $ l o g g e r ) 7 { 5 $ t h i s −> w ea th e rS er v ic e = $weatherService ; $ t h i s −> l o g g e r = $logger ; 8 9 10 } 11 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) 12 { // ... $ t h i s −> l o g g e r −> l o g ( ’Some l o g message . ’ ) ; // ... 13 14 15 } 16 17 }
  • 37. Dependency Inversion Principle Use abstraction to encapsulate low level modules Abstractions are the APIs Abstractions hide implementation details Depend on interfaces, not realizations Define interfaces from a usage point of view Finding abstractions is not easy Dependency Injection, anyone?
  • 38. Dependency Inversion Principle Use abstraction to encapsulate low level modules Abstractions are the APIs Abstractions hide implementation details Depend on interfaces, not realizations Define interfaces from a usage point of view Finding abstractions is not easy Dependency Injection, anyone?
  • 39. Dependency Inversion Principle Use abstraction to encapsulate low level modules Abstractions are the APIs Abstractions hide implementation details Depend on interfaces, not realizations Define interfaces from a usage point of view Finding abstractions is not easy Dependency Injection, anyone?
  • 40. Dependency Inversion Principle Use abstraction to encapsulate low level modules Abstractions are the APIs Abstractions hide implementation details Depend on interfaces, not realizations Define interfaces from a usage point of view Finding abstractions is not easy Dependency Injection, anyone?
  • 41. Interface Segregation Principle “Clients should not be forced to depend upon interfaces that they do not use.”
  • 42. Suboptimal 3 class Loader 4 { public function { /∗ . . . ∗/ } 5 6 c o n s t r u c t ( WeatherService $weatherService , Logger $ l o g g e r ) 7 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) { /∗ . . . ∗/ } 8 9 10 } 3 a b s t r a c t class WeatherService 4 { a b s t r a c t public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ; 5 6 a b s t r a c t public function g e t F o r e c a s t F o r L o c a t i o n ( L o c a t i o n $ l o c a t i o n , $weekDay ) ; 7 8 }
  • 43. The Fix 1 interface LocationWeatherProvider 2 { function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ; 3 4 } 1 a b s t r a c t class WeatherService implements L o c a t i o n W e a t h e r P r o v i d e r 2 { a b s t r a c t public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ; 3 4 a b s t r a c t public function g e t F o r e c a s t F o r L o c a t i o n ( L o c a t i o n $ l o c a t i o n , $weekDay ) ; 5 6 } 1 class Loader 2 { public function { /∗ . . . ∗/ } 3 4 c o n s t r u c t ( L o c a t i o n W e a t h e r P r o v i d e r $ p r o v i d e r , Logger $ l o g g e r ) 5 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) { /∗ . . . ∗/ } 6 7 8 }
  • 44. The Fix 1 interface LocationWeatherProvider 2 { function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ; 3 4 } 1 a b s t r a c t class WeatherService implements L o c a t i o n W e a t h e r P r o v i d e r 2 { a b s t r a c t public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) ; 3 4 a b s t r a c t public function g e t F o r e c a s t F o r L o c a t i o n ( L o c a t i o n $ l o c a t i o n , $weekDay ) ; 5 6 } 1 class Loader 2 { public function { /∗ . . . ∗/ } 3 4 c o n s t r u c t ( L o c a t i o n W e a t h e r P r o v i d e r $ p r o v i d e r , Logger $ l o g g e r ) 5 public function getWeatherForLocation ( L o c a t i o n $ l o c a t i o n ) { /∗ . . . ∗/ } 6 7 8 }
  • 45. Interface Segregation Principle Avoid not needed dependencies Design interfaces from a usage point of view Do not let unnecessary functionality float in
  • 46. The SOLID principles Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle