SlideShare uma empresa Scribd logo
1 de 47
Baixar para ler offline
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!

Mais conteúdo relacionado

Mais 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
 

Mais 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
 

Último

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
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
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
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
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
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
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
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
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
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
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
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

Último (20)

Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
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
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
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
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
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...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
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
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
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
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

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