0
SOLID
Good Object Oriented Design

Mario Rezende
http://about.me/mariorez
Agenda
❖ Good OO Design
❖ The principles of SOLID
❖ Where SOLID “fits”
❖ The Principles by examples
❖ Bonus: Robert Martin...
Good OO Design
1. Changing Requirements
2. Dependency Management

Change , Dependency , Coupling
Good OO Design
1 class Controller
2 {
3
public function action()
4
{
5
$myClass = new MyClass();
6
$result = $myClass->myM...
Good OO Design
1 class Controller
2 {
3
public function action()
4
{
5
$myClass = new MyClass();
6
$result = $myClass->myM...
Good OO Design
1 class Controller
2 {
3
public function action()
4
{
5
$myClass = new MyClass();
6
$otherClass = new Anoth...
Good OO Design
1 class Controller
2 {
3
public function action()
4
{
5
$myClass = new MyClass();
6
$otherClass = new Deriv...
Good OO Design

1 class MyClass
2 {
3
public function myMethod()
4
{
5
$otherClass = new AnotherClass();
x
6
$anyThing = $...
Good OO Design

1
2
3
4
5
6
7
8
9

class MyClass
{
public function myMethod(AnotherClass $class)
{
$anyThing = $class->doS...
Good OO Design
Manifesto for AGILE Software Development

Individuals and interactions
Working software
Customer collaborat...
The principles of SOLID

S ingle Responsibility
O pen / Closed
L iskov Substitution
I nterface Segregation
D ependency Inv...
Where SOLID “fits”
Abstraction
Encapsulation
Inheritance
Composition
Modularity
Polymorphism

Object
Oriented
Principles

...
Where SOLID “fits”
Abstraction
Encapsulation
Inheritance
Composition
Modularity
Polymorphism

Cohesion
Low Coupling
Orthog...
The Principles by examples S.O.L.I.D

Single Responsibility
A class should have only a single responsibility
(only one rea...
Single Responsibility
1 class AccessControlManager
2 {
3
public function __construct(Customer $customer)
4
{ //save refere...
Single Responsibility
1 class AccessControlManager
2 {
3
public function __construct(Customer $customer,
4
Login $login) {...
Single Responsibility
1 class Customer
2 {
3
public function
4
5
public function
6
7
public function
8
9
public function
1...
Single Responsibility

S.O.L.I.D

Conclusion
❖ SRP is the simplest, and the most difficult to get right
Finding and separa...
The Principles by examples S.O.L.I.D

Open / Closed
Software entities (classes, modules, functions, etc.)
should be open f...
Open / Closed

S.O.L.I.D
1 class Customer
2 {
3
public function
4
5
public function
6
7
public function
8
9
public functio...
Open / Closed

S.O.L.I.D
1 class Customer
2 {
3
public function
4
5
public function
6
7
public function
8
9
public functio...
Open / Closed
1 class AccessControlManager {
2
public function __construct(Customer $customer,
3
SignIn $sign, Permission ...
Open / Closed

S.O.L.I.D
1 class Customer
2 {
3
public function
4
5
public function
6
7
public function
8
9
public functio...
Open / Closed

S.O.L.I.D

Conclusion
❖ OCP is at the heart of object-oriented design
❖ Flexibility, Reusability and Mainta...
The Principles by examples S.O.L.I.D

Dependency Inversion
A. High-level modules should not depend on low-level
modules. B...
Dependency Inversion
1 class Customer
2 {
3
public function
4
5
public function
6
7
public function
8
9
public function
10...
Dependency Inversion

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface
Dependency Inversion

S.O.L.I.D

A. High-level modules should not depend on low-level
modules. Both should depend on abstr...
Dependency Inversion

S.O.L.I.D

Policy

Mechanism

A. High-level modules should not depend on low-level
modules. Both sho...
Dependency Inversion

S.O.L.I.D

Policy

Mechanism

A. High-level modules should not depend on low-level
modules. Both sho...
Dependency Inversion

S.O.L.I.D

1 interface UserIdentity { }

1 class AccessControlManager {
2
public function __construc...
Dependency Inversion

S.O.L.I.D

1 interface UserIdentity { }

1 class AccessControlManager {
2
public function __construc...
Dependency Inversion

S.O.L.I.D

Policy

Mechanism

B. Abstractions should not depend upon details.
Details should depend ...
Dependency Inversion
1 class AccessControlManager {
2
public function __construct(Customer $customer,
3
SignIn $sign, Perm...
Dependency Inversion

S.O.L.I.D

1 interface UserIdentity { }

1 class AccessControlManager {
2
public function __construc...
Dependency Inversion

1 interface UserIdentity { }

1 class AccessControlManager {
2
public function __construct(UserIdent...
Dependency Inversion

1 interface UserIdentity { }

1 class AccessControlManager {
2
public function __construct(UserIdent...
Dependency Inversion

S.O.L.I.D

Policy

Mechanism

B. Abstractions should not depend upon details.
Details should depend ...
Dependency Inversion

S.O.L.I.D

Policy

Mechanism

Utility

Change , Dependency , Coupling, Agile , Composition , Interfa...
Dependency Inversion

S.O.L.I.D

Conclusion
❖ Rules and details should depend on abstractions,
which are defined in terms ...
The Principles by examples S.O.L.I.D

Liskov Substitution
Objects in a program should be replaceable
with instances of the...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution
1 class PaymentManager
2 {
3
public function __construct(Payment $payment,
4
PaymentCalculator $calc) ...
Liskov Substitution

S.O.L.I.D

Conclusion
❖ LSP is one of the prime enablers of OCP
❖ Design by Contract (require no more...
The Principles by examples S.O.L.I.D

Interface Segregation
Many client-specific interfaces are better than
one general-pu...
Interface Segregation

S.O.L.I.D
AtmUI
+ requestDeposit
+ requestWithdrawl
+ requestTransfer
+ informeInsufficientFunds

C...
Interface Segregation

S.O.L.I.D
AtmUI
+ requestDeposit
+ requestWithdrawl
+ requestTransfer
+ informeInsufficientFunds

C...
Interface Segregation

S.O.L.I.D

Conclusion
❖ Avoids the use of "Fat Classes"
❖ Breaks the dependence of the clients on m...
Questions

?
Change , Dependency , Coupling, Agile , Composition , Interface
Robert Martin

S ingle responsibility
O pen/closed
L iskov substitution
I nterface segregation
D ependency inversion
Chang...
Robert Martin

S
O
L
I
D
Change , Dependency , Coupling, Agile , Composition , Interface
Recommended Books
Agile Software Development, Principles, Patterns, and Practices (Robert Martin - 2002)
Agile Principles,...
THANKS !!!
Mario Rezende
http://about.me/mariorez
Upcoming SlideShare
Loading in...5
×

Solid: Good Object Oriented Design

1,233

Published on

"SOLID" is an acronym for a set of principles to be used with Object Oriented programming, and that assist Developer in Good Software Design in order better reuse of classes and modules, application of unit tests and maintenance of Software.

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,233
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
33
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

Transcript of "Solid: Good Object Oriented Design"

  1. 1. SOLID Good Object Oriented Design Mario Rezende http://about.me/mariorez
  2. 2. Agenda ❖ Good OO Design ❖ The principles of SOLID ❖ Where SOLID “fits” ❖ The Principles by examples ❖ Bonus: Robert Martin & Books
  3. 3. Good OO Design 1. Changing Requirements 2. Dependency Management Change , Dependency , Coupling
  4. 4. Good OO Design 1 class Controller 2 { 3 public function action() 4 { 5 $myClass = new MyClass(); 6 $result = $myClass->myMethod(); 7 8 $this->render($result); 9 } 10 } 1 class MyClass 2 { 3 public function myMethod() 4 { 5 $otherClass = new AnotherClass(); x 6 $anyThing = $otherClass->doSomething(); 7 8 // solves some logic and returns the result 9 } 10 } Change , Dependency , Coupling 1 2 3 4 class AnotherClass { public function doSomething() { // logic } }
  5. 5. Good OO Design 1 class Controller 2 { 3 public function action() 4 { 5 $myClass = new MyClass(); 6 $result = $myClass->myMethod(); 7 8 $this->render($result); 9 } 10 } 1 class MyClass 2 { 3 public function myMethod() 4 { 5 $otherClass = new AnotherClass(); x 6 $anyThing = $otherClass->doSomething(); 7 8 // solves some logic and returns the result 9 } 10 } 1 2 3 4 class AnotherClass { public function doSomething() { // logic } } 1 class ClassA { // depends AnotherClass } 1 Change , Dependency , Coupling class ClassB { // depends AnotherClass }
  6. 6. Good OO Design 1 class Controller 2 { 3 public function action() 4 { 5 $myClass = new MyClass(); 6 $otherClass = new AnotherClass();xxx xxxxxx 7 $result = $myClass->myMethod($otherClass); 8 9 $this->render($result); 10 } 11 } 1 2 3 4 5 6 7 8 9 class MyClass { public function myMethod(AnotherClass $class) { $anyThing = $class->doSomething(); // solves some logic and returns the result 1 2 3 4 class AnotherClass { public function doSomething() { // logic } } 1 class ClassA { // depends AnotherClass } } } 1 Change , Dependency , Coupling class ClassB { // depends AnotherClass }
  7. 7. Good OO Design 1 class Controller 2 { 3 public function action() 4 { 5 $myClass = new MyClass(); 6 $otherClass = new DerivedClass();xxxxxx xxx 7 $result = $myClass->myMethod($otherClass); 8 9 $this->render($result); 10 } 11 } 1 2 3 4 5 6 7 8 9 class MyClass { public function myMethod(AnotherClass $class) { $anyThing = $class->doSomething(); // solves some logic and returns the result 1 2 3 4 class DerivedClass extends AnotherClass { public function doSomething() { // logic } } 1 2 3 4 class AnotherClass { public function doSomething() { // logic } } 1 x class ClassA { // depends AnotherClass } } } 1 Change , Dependency , Coupling class ClassB { // depends AnotherClass }
  8. 8. Good OO Design 1 class MyClass 2 { 3 public function myMethod() 4 { 5 $otherClass = new AnotherClass(); x 6 $anyThing = $otherClass->doSomething(); 7 8 // solves some logic and returns the result 9 } 10 } 1 2 3 4 class AnotherClass { public function doSomething() { // logic } } Change , Dependency , Coupling 1 2 3 4 5 6 7 8 class MyClassTest extends PHPUnit_Framework_TestCase { public function testMyMethod() { $class = new MyClass(); $this->assertEquals(1, $class->myMethod()); } } what will be the result of this test ?
  9. 9. Good OO Design 1 2 3 4 5 6 7 8 9 class MyClass { public function myMethod(AnotherClass $class) { $anyThing = $class->doSomething(); 1 2 3 4 class AnotherClass { public function doSomething() { // logic } } // solves some logic and returns the result } } Change , Dependency , Coupling 1 class MyClassTest extends PHPUnit_Framework_TestCase 2 { public function testMyMethod() 3 { 4 // Create a stub for the AnotherClass class. 5 $stub = $this->getMock('AnotherClass'); x 6 7 // Configure the stub. 8 $stub->expects($this->any()) 9 ->method('doSomething') 10 ->will($this->returnValue('mon')); x 11 12 $class = new MyClass($stub); 13 $this->assertEquals(1, $class->myMethod()); 14 } 15 16 }
  10. 10. Good OO Design Manifesto for AGILE Software Development Individuals and interactions Working software Customer collaboration Responding to change Change , Dependency , Coupling, Agile
  11. 11. The principles of SOLID S ingle Responsibility O pen / Closed L iskov Substitution I nterface Segregation D ependency Inversion Change , Dependency , Coupling, Agile
  12. 12. Where SOLID “fits” Abstraction Encapsulation Inheritance Composition Modularity Polymorphism Object Oriented Principles Cohesion Low Coupling Orthogonality Design by Contract Law of Demeter Principles of Class Design implementation General Solution Recurring problems Program to Interface Favor Composition Granularity Stability Metrics for stability and abstraction MVC DDD Frameworks Layered Principles of Architecture Package and Design Component Patterns Design conceptual Change , Dependency , Coupling, Agile , Composition , Interface
  13. 13. Where SOLID “fits” Abstraction Encapsulation Inheritance Composition Modularity Polymorphism Cohesion Low Coupling Orthogonality Design by Contract Law of Demeter SOLID Object Oriented Principles Principles of Class Design implementation General Solution Recurring problems Program to Interface Favor Composition Granularity Stability Metrics for stability and abstraction MVC DDD Frameworks Layered Principles of Architecture Package and Design Component Patterns Design conceptual Change , Dependency , Coupling, Agile , Composition , Interface
  14. 14. The Principles by examples S.O.L.I.D Single Responsibility A class should have only a single responsibility (only one reason to change) Change , Dependency , Coupling, Agile , Composition , Interface
  15. 15. Single Responsibility 1 class AccessControlManager 2 { 3 public function __construct(Customer $customer) 4 { //save reference } 5 6 public function login() 7 { 8 if ($this->customer->authenticate() && 9 $this->customer->authorize()) { 10 return true; 11 } 12 return false; 13 } 14 } S.O.L.I.D 1 class Customer 2 { 3 public function authenticate() 4 { 5 // authenticate user against a database 6 } 7 8 public function authorize() 9 { 10 // checks user privileges 11 } 12 13 public function setEmail($email) {} 14 15 public function getEmail() {} 16 17 public function setPassword($password) {} 18 19 public function getPassword() {} 20 } Change , Dependency , Coupling, Agile , Composition , Interface
  16. 16. Single Responsibility 1 class AccessControlManager 2 { 3 public function __construct(Customer $customer, 4 Login $login) { //save references } 5 6 public function login() 7 { 8 if ($this->login->authenticate($this->customer) && 9 $this->login->authorize($this->customer)) { 10 return true; 11 } 12 return false; 13 } 14 } S.O.L.I.D 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} 1 class Login 2 { 3 public function authenticate(Customer $customer) 4 { 5 // authenticate user against a database 6 } 7 8 public function authorize(Customer $customer) 9 { 10 // checks user privileges 11 } 12 } Change , Dependency , Coupling, Agile , Composition , Interface
  17. 17. Single Responsibility 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignIn $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 5 6 7 class Permission { public function authorize(Customer $customer) { // checks user privileges } } S.O.L.I.D 1 2 3 4 5 6 7 setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} class SignIn { public function authenticate(Customer $customer) { // authenticate user against a database } } Change , Dependency , Coupling, Agile , Composition , Interface
  18. 18. Single Responsibility S.O.L.I.D Conclusion ❖ SRP is the simplest, and the most difficult to get right Finding and separating those responsibilities is much of what software design is really about. Indeed, the rest of the principles we discuss come back to this issue in one way or another. (Robert Martin) Change , Dependency , Coupling, Agile , Composition , Interface
  19. 19. The Principles by examples S.O.L.I.D Open / Closed Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification Change , Dependency , Coupling, Agile , Composition , Interface
  20. 20. Open / Closed S.O.L.I.D 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignIn $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 5 6 7 class Permission { public function authorize(Customer $customer) { // checks user privileges } } 1 2 3 4 5 6 7 setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} class SignIn { public function authenticate(Customer $customer) { // authenticate user against a database } } Change , Dependency , Coupling, Agile , Composition , Interface
  21. 21. Open / Closed S.O.L.I.D 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignIn $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 5 6 7 class SignFacebook extends SignIn x { public function authenticate(Customer $customer) { // connect to third-party server resource } } 1 2 3 4 5 6 7 setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} class SignIn { public function authenticate(Customer $customer) { // authenticate user against a database } } Change , Dependency , Coupling, Agile , Composition , Interface
  22. 22. Open / Closed 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignIn $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 5 6 7 class SignFacebook extends SignIn { public function authenticate(Customer $customer) { // connect to third-party server resource } protected function getAccessToken(Oauth $client) { // retrieve a valid token } } S.O.L.I.D 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} 1 class SignIn { 2 public function authenticate(Customer $customer) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) x 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  23. 23. Open / Closed S.O.L.I.D 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignService $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 1 2 3 4 5 6 7 class SignFacebook implements SignService { x public function authenticate(Customer $customer) { // connect to third-party server resource } protected function getAccessToken(Oauth $client) { // retrieve a valid token } } setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} interface SignService { public function authenticate(Customer $customer); } 1 class SignDatabase implements SignService { x 2 public function authenticate(Customer $customer) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  24. 24. Open / Closed S.O.L.I.D Conclusion ❖ OCP is at the heart of object-oriented design ❖ Flexibility, Reusability and Maintainability Nor is it a good idea to apply rampant abstraction to every part of the application… Resisting premature abstraction is as important as abstraction itself. (Robert Martin) Change , Dependency , Coupling, Agile , Composition , Interface
  25. 25. The Principles by examples S.O.L.I.D Dependency Inversion 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. Change , Dependency , Coupling, Agile , Composition , Interface
  26. 26. Dependency Inversion 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignService $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 1 2 3 4 5 6 7 class Permission { public function authorize(Customer $customer) { // checks user privileges } } S.O.L.I.D setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} interface SignService { public function authenticate(Customer $customer); } 1 class SignDatabase implements SignService { 2 public function authenticate(Customer $customer) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  27. 27. Dependency Inversion S.O.L.I.D Change , Dependency , Coupling, Agile , Composition , Interface
  28. 28. Dependency Inversion S.O.L.I.D A. High-level modules should not depend on low-level modules. Both should depend on abstractions. Change , Dependency , Coupling, Agile , Composition , Interface
  29. 29. Dependency Inversion S.O.L.I.D Policy Mechanism A. High-level modules should not depend on low-level modules. Both should depend on abstractions. Change , Dependency , Coupling, Agile , Composition , Interface
  30. 30. Dependency Inversion S.O.L.I.D Policy Mechanism A. High-level modules should not depend on low-level modules. Both should depend on abstractions. Change , Dependency , Coupling, Agile , Composition , Interface
  31. 31. Dependency Inversion S.O.L.I.D 1 interface UserIdentity { } 1 class AccessControlManager { 2 public function __construct(UserIdentity $user, 3 SignService $sign, GrantService $grant) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->user) && 8 $this->grant->authorize($this->user)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 class Customer implements UserIdentity 2 { 3 public function setEmail($email) {} 4 5 public function getEmail() {} 6 7 public function setPassword($password) {} 8 9 public function getPassword() {} 10 } 1 2 3 4 interface GrantService { public function authorize(Customer $customer); } 1 2 3 4 interface SignService { public function authenticate(Customer $customer); } 1 2 3 4 class Permission implements GrantService { public function authorize(Customer $customer) { // checks user privileges } } 1 2 3 4 class SignDatabase implements SignService { public function authenticate(Customer $customer) { // authenticate user against a database } } Change , Dependency , Coupling, Agile , Composition , Interface
  32. 32. Dependency Inversion S.O.L.I.D 1 interface UserIdentity { } 1 class AccessControlManager { 2 public function __construct(UserIdentity $user, 3 SignService $sign, GrantService $grant) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->user) && 8 $this->grant->authorize($this->user)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 class Customer implements UserIdentity 2 { 3 public function setEmail($email) {} 4 5 public function getEmail() {} 6 7 public function setPassword($password) {} 8 9 public function getPassword() {} 10 } 1 2 3 4 interface GrantService { public function authorize(UserIdentity $user); } 1 2 3 4 interface SignService { public function authenticate(UserIdentity $user); } 1 2 3 4 class Permission implements GrantService { public function authorize(UserIdentity $user) { // checks user privileges } } 1 2 3 4 class SignDatabase implements SignService { public function authenticate(UserIdentity $user) { // authenticate user against a database } } Change , Dependency , Coupling, Agile , Composition , Interface
  33. 33. Dependency Inversion S.O.L.I.D Policy Mechanism B. Abstractions should not depend upon details. Details should depend upon abstractions. Change , Dependency , Coupling, Agile , Composition , Interface
  34. 34. Dependency Inversion 1 class AccessControlManager { 2 public function __construct(Customer $customer, 3 SignIn $sign, Permission $perm) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->customer) && 8 $this->perm->authorize($this->customer)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 2 3 4 5 6 7 class Permission { public function authorize(Customer $customer) { // checks user privileges } } 1 class Customer 2 { 3 public function 4 5 public function 6 7 public function 8 9 public function 10 } S.O.L.I.D setEmail($email) {} getEmail() {} setPassword($password) {} getPassword() {} 1 class SignIn { 2 public function authenticate(Customer $customer) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  35. 35. Dependency Inversion S.O.L.I.D 1 interface UserIdentity { } 1 class AccessControlManager { 2 public function __construct(UserIdentity $user, 3 SignService $sign, GrantService $grant) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->user) && 8 $this->grant->authorize($this->user)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 class Customer implements UserIdentity 2 { 3 public function setEmail($email) {} 4 5 public function getEmail() {} 6 7 public function setPassword($password) {} 8 9 public function getPassword() {} 10 } 1 2 3 4 interface GrantService { public function authorize(UserIdentity $user); } 1 2 3 4 interface SignService { public function authenticate(UserIdentity $user); protected function getRepository(Adapter $db); } 1 2 3 4 class Permission implements GrantService { public function authorize(UserIdentity $user) { // checks user privileges } } 1 class SignDatabase implements SignService { 2 public function authenticate(UserIdentity $user) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  36. 36. Dependency Inversion 1 interface UserIdentity { } 1 class AccessControlManager { 2 public function __construct(UserIdentity $user, 3 SignService $sign, GrantService $grant) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->user) && 8 $this->grant->authorize($this->user)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 class Customer implements UserIdentity 2 { 3 public function setEmail($email) {} 4 5 public function getEmail() {} 6 7 public function setPassword($password) {} 8 9 public function getPassword() {} 10 } 1 2 3 4 1 2 3 4 5 6 7 class SignFacebook implements SignService { public function authenticate(UserIdentity $user) { // connect to third-party server resource } protected function getAccessToken(Oauth $client) { // retrieve a valid token } } S.O.L.I.D interface SignService { public function authenticate(UserIdentity $user); protected function getRepository(Adapter $db); x } 1 class SignDatabase implements SignService { 2 public function authenticate(UserIdentity $user) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) x 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  37. 37. Dependency Inversion 1 interface UserIdentity { } 1 class AccessControlManager { 2 public function __construct(UserIdentity $user, 3 SignService $sign, GrantService $grant) 4 { //save references } 5 6 public function login() { 7 if ($this->sign->authenticate($this->user) && 8 $this->grant->authorize($this->user)) { 9 return true; 10 } 11 return false; 12 } 13 } 1 class Customer implements UserIdentity 2 { 3 public function setEmail($email) {} 4 5 public function getEmail() {} 6 7 public function setPassword($password) {} 8 9 public function getPassword() {} 10 } 1 2 3 4 1 2 3 4 5 6 7 class SignFacebook implements SignService { public function authenticate(UserIdentity $user) { // connect to third-party server resource } protected function getAccessToken(Oauth $client) { // retrieve a valid token } } S.O.L.I.D interface SignService { public function authenticate(UserIdentity $user); } 1 class SignDatabase implements SignService { 2 public function authenticate(UserIdentity $user) 3 { // authenticate user against a database } 4 5 protected function getRepository(Adapter $db) 6 { // connect to database } 7 } Change , Dependency , Coupling, Agile , Composition , Interface
  38. 38. Dependency Inversion S.O.L.I.D Policy Mechanism B. Abstractions should not depend upon details. Details should depend upon abstractions. Change , Dependency , Coupling, Agile , Composition , Interface
  39. 39. Dependency Inversion S.O.L.I.D Policy Mechanism Utility Change , Dependency , Coupling, Agile , Composition , Interface
  40. 40. Dependency Inversion S.O.L.I.D Conclusion ❖ Rules and details should depend on abstractions, which are defined in terms of use ❖ When abstractions and details are isolated, it's easier to maintain the code ... inversion of dependencies is the hallmark of good object-oriented design. (Robert Martin) Change , Dependency , Coupling, Agile , Composition , Interface
  41. 41. The Principles by examples S.O.L.I.D Liskov Substitution Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program Change , Dependency , Coupling, Agile , Composition , Interface
  42. 42. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } S.O.L.I.D 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 class PaymentCalculator 2 { public function calculatePayday(Payment $pay) 3 { 4 $calendar = $this->getBrazilianCalendar(); 5 $workDays = $this->getWorkDays($calendar); 6 // calculate 5+ days: 2013-10-06 Sunday 7 // find NEXT work day: 2013-10-07 Monday 8 return new DateTime('2013-10-07'); 9 } 10 11 } Change , Dependency , Coupling, Agile , Composition , Interface
  43. 43. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } 1 class PaymentCalcBefore extends PaymentCalculator 2 { public function calculatePayday(Payment $pay) 3 { 4 $calendar = $this->getBrazilianCalendar(); 5 $workDays = $this->getWorkDays($calendar); 6 // calculate 5+ days: 2013-10-06 Sunday 7 // find PREV work day: 2013-10-04 Friday 8 return date('2013-10-04'); 9 } 10 11 } S.O.L.I.D 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 class PaymentCalculator 2 { public function calculatePayday(Payment $pay) 3 { 4 $calendar = $this->getBrazilianCalendar(); 5 $workDays = $this->getWorkDays($calendar); 6 // calculate 5+ days: 2013-10-06 Sunday 7 // find NEXT work day: 2013-10-07 Monday 8 return new DateTime('2013-10-07'); 9 } 10 11 } Change , Dependency , Coupling, Agile , Composition , Interface
  44. 44. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } 1 class PaymentCalcBefore extends PaymentCalculator 2 { /** @return String */ 3 public function calculatePayday(Payment $pay) 4 { 5 $calendar = $this->getBrazilianCalendar(); 6 $workDays = $this->getWorkDays($calendar); 7 // calculate 5+ days: 2013-10-06 Sunday 8 // find PREV work day: 2013-10-04 Friday 9 return date('2013-10-04'); 10 } 11 12 } x S.O.L.I.D 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 class PaymentCalculator 2 { /** @return DateTime */ 3 public function calculatePayday(Payment $pay) 4 { 5 $calendar = $this->getBrazilianCalendar(); 6 $workDays = $this->getWorkDays($calendar); 7 // calculate 5+ days: 2013-10-06 Sunday 8 // find NEXT work day: 2013-10-07 Monday 9 return new DateTime('2013-10-07'); 10 } 11 12 } Change , Dependency , Coupling, Agile , Composition , Interface x
  45. 45. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } 1 class PaymentCalcBefore extends PaymentCalculator 2 { /** @return DateTime */ 3 public function calculatePayday(Payment $pay) 4 { 5 $calendar = $this->getBrazilianCalendar(); 6 $workDays = $this->getWorkDays($calendar); 7 // calculate 5+ days: 2013-10-06 Sunday 8 // find PREV work day: 2013-10-04 Friday 9 return new DateTime('2013-10-04'); 10 } 11 12 } x S.O.L.I.D 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 class PaymentCalculator 2 { /** @return DateTime */ 3 public function calculatePayday(Payment $pay) 4 { 5 $calendar = $this->getBrazilianCalendar(); 6 $workDays = $this->getWorkDays($calendar); 7 // calculate 5+ days: 2013-10-06 Sunday 8 // find NEXT work day: 2013-10-07 Monday 9 return new DateTime('2013-10-07'); 10 } 11 12 } Change , Dependency , Coupling, Agile , Composition , Interface x
  46. 46. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } 1 2 3 4 5 6 class PaymentCalcBefore extends PaymentCalculator { protected function resolvePayDay($workDays,$pay) { // calculate D+5 and find PREVIOUS work day return new DateTime('2013-10-04'); // Friday } } S.O.L.I.D 1 2 3 4 5 6 7 class Payment { private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday; } 1 class PaymentCalculator { public function calculatePayday(Payment $pay) { 2 $calendar = $this->getBrazilianCalendar(); 3 $workDays = $this->getWorkDays($calendar); 4 return $this->resolvePayDay($workDays, $pay); 5 } 6 7 protected function resolvePayDay($workDays,$pay) { 8 // calculate D+5 and find NEXT work day 9 return new DateTime('2013-10-07'); // Monday 10 } 11 12 } Change , Dependency , Coupling, Agile , Composition , Interface
  47. 47. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } 1 2 3 4 5 6 class AfterCalculator extends PaymentCalculator { protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-07'); // Monday } } 1 2 3 4 5 6 class BeforeCalculator extends PaymentCalculator { protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-04'); // Friday } } S.O.L.I.D 1 interface Payment { } 1 2 3 class CCardPayment implements Payment { // attributes and methods } 1 2 3 class BilletPayment implements Payment { // attributes and methods } 1 abstract class PaymentCalculator 2 { public function calculatePayday(Payment $pay) 3 { 4 $calendar = $this->getBrazilianCalendar(); 5 $workDays = $this->getWorkDays($calendar); 6 return $this->resolvePayDay($workDays,$payment); 7 } 8 9 abstract protected function resolvePayDay($wd,$p); 10 11 } Change , Dependency , Coupling, Agile , Composition , Interface
  48. 48. Liskov Substitution 1 class PaymentManager 2 { 3 public function __construct(Payment $payment, 4 PaymentCalculator $calc) { // save references } 5 6 public function schedulePayment() { 7 $payday = $this->calc->calculatePayday($this->payment); 8 $this->payment->setPayday($payday); 9 // save in database 10 } 11 } 1 2 3 4 5 6 class BilletCalculator extends PaymentCalculator { protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-07'); // Monday } } 1 2 3 4 5 6 class CreditCardCalculator extends PaymentCalculator { protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-04'); // Friday } } S.O.L.I.D 1 interface Payment { } 1 2 3 class CCardPayment implements Payment { // attributes and methods } 1 2 3 class BilletPayment implements Payment { // attributes and methods } 1 abstract class PaymentCalculator 2 { public function calculatePayday(Payment $pay) 3 { 4 $calendar = $this->getBrazilianCalendar(); 5 $workDays = $this->getWorkDays($calendar); 6 return $this->resolvePayDay($workDays,$payment); 7 } 8 9 abstract protected function resolvePayDay($wd,$p); 10 11 } Change , Dependency , Coupling, Agile , Composition , Interface
  49. 49. Liskov Substitution S.O.L.I.D Conclusion ❖ LSP is one of the prime enablers of OCP ❖ Design by Contract (require no more, promise no less) The term IS-A is too broad to act as a definition of a subtype. The true definition of a subtype is substitutable ... (Robert Martin) Change , Dependency , Coupling, Agile , Composition , Interface
  50. 50. The Principles by examples S.O.L.I.D Interface Segregation Many client-specific interfaces are better than one general-purpose interface Change , Dependency , Coupling, Agile , Composition , Interface
  51. 51. Interface Segregation S.O.L.I.D AtmUI + requestDeposit + requestWithdrawl + requestTransfer + informeInsufficientFunds Change , Dependency , Coupling, Agile , Composition , Interface
  52. 52. Interface Segregation S.O.L.I.D AtmUI + requestDeposit + requestWithdrawl + requestTransfer + informeInsufficientFunds Change , Dependency , Coupling, Agile , Composition , Interface
  53. 53. Interface Segregation S.O.L.I.D Conclusion ❖ Avoids the use of "Fat Classes" ❖ Breaks the dependence of the clients on methods that they don't invoke ❖ Allows the clients to be independent of one another Change , Dependency , Coupling, Agile , Composition , Interface
  54. 54. Questions ? Change , Dependency , Coupling, Agile , Composition , Interface
  55. 55. Robert Martin S ingle responsibility O pen/closed L iskov substitution I nterface segregation D ependency inversion Change , Dependency , Coupling, Agile , Composition , Interface
  56. 56. Robert Martin S O L I D Change , Dependency , Coupling, Agile , Composition , Interface
  57. 57. Recommended Books Agile Software Development, Principles, Patterns, and Practices (Robert Martin - 2002) Agile Principles, Patterns, and Practices in C# (Robert Martin - 2006) SOLID e Design Patterns The Pragmatic Programmer (Andrew Hunt and Devid Thomas - 1999) Coesão, Acoplamento, Ortogonalidade, Design por Contrato, Lei de Deméter Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin - 2008) Lei de Deméter, Data Transfer Objects, TDD Domain-Driven Design: Tackling Complexity in the Heart of Software (Erich Evans - 2003) Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four - 1994) Patternspara Android Apps of Enterprise Applications Architecture (Martin Fowler - 2002) Change , Dependency , Coupling, Agile , Composition , Interface
  58. 58. THANKS !!! Mario Rezende http://about.me/mariorez
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×