Solid: Good Object Oriented Design

58
Mario Rezende http://about.me/mariorez SOLID Good Object Oriented Design

description

"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.

Transcript of Solid: Good Object Oriented Design

Page 1: Solid: Good Object Oriented Design

Mario Rezende

http://about.me/mariorez

SOLIDGood Object Oriented Design

Page 2: Solid: Good Object Oriented Design

Agenda

❖ Good OO Design

❖ The principles of SOLID

❖ Where SOLID “fits”

❖ The Principles by examples

❖ Bonus: Robert Martin & Books

Page 3: Solid: Good Object Oriented Design

Good OO Design

Change , Dependency , Coupling

1. Changing Requirements

2. Dependency Management

Page 4: Solid: Good Object Oriented Design

12345678910

1234

class AnotherClass{ public function doSomething() { // logic }}

12345678910

class Controller{ public function action() { $myClass = new MyClass(); $result = $myClass->myMethod();

$this->render($result); }}

class MyClass{ public function myMethod() { $otherClass = new AnotherClass(); x $anyThing = $otherClass->doSomething();

// solves some logic and returns the result }}

Good OO Design

Change , Dependency , Coupling

Page 5: Solid: Good Object Oriented Design

1234

class AnotherClass{ public function doSomething() { // logic }}

1 class ClassA { // depends AnotherClass }

1 class ClassB { // depends AnotherClass }

12345678910

12345678910

class Controller{ public function action() { $myClass = new MyClass(); $result = $myClass->myMethod();

$this->render($result); }}

class MyClass{ public function myMethod() { $otherClass = new AnotherClass(); x $anyThing = $otherClass->doSomething();

// solves some logic and returns the result }}

Good OO Design

Change , Dependency , Coupling

Page 6: Solid: Good Object Oriented Design

123456789

1234

class AnotherClass{ public function doSomething() { // logic }}

1234567891011

1 class ClassA { // depends AnotherClass }

1 class ClassB { // depends AnotherClass }

class Controller{ public function action() { $myClass = new MyClass(); $otherClass = new AnotherClass();xxx xxxxxx $result = $myClass->myMethod($otherClass);

$this->render($result); }}

class MyClass{ public function myMethod(AnotherClass $class) { $anyThing = $class->doSomething();

// solves some logic and returns the result }}

Good OO Design

Change , Dependency , Coupling

Page 7: Solid: Good Object Oriented Design

123456789

1234

class AnotherClass{ public function doSomething() { // logic }}

1234567891011

1 class ClassA { // depends AnotherClass }

1 class ClassB { // depends AnotherClass }

class Controller{ public function action() { $myClass = new MyClass(); $otherClass = new DerivedClass();xxxxxx xxx $result = $myClass->myMethod($otherClass);

$this->render($result); }}

class MyClass{ public function myMethod(AnotherClass $class) { $anyThing = $class->doSomething();

// solves some logic and returns the result }}

1234

class DerivedClass extends AnotherClass x{ public function doSomething() { // logic }}

Good OO Design

Change , Dependency , Coupling

Page 8: Solid: Good Object Oriented Design

12345678910

12345678

class MyClassTest extends PHPUnit_Framework_TestCase{ public function testMyMethod() { $class = new MyClass(); $this->assertEquals(1, $class->myMethod()); }}

1234

class MyClass{ public function myMethod() { $otherClass = new AnotherClass(); x $anyThing = $otherClass->doSomething();

// solves some logic and returns the result }}

class AnotherClass{ public function doSomething() { // logic }}

what will be the result of this test

?

Good OO Design

Change , Dependency , Coupling

Page 9: Solid: Good Object Oriented Design

12345678910111213141516

class MyClassTest extends PHPUnit_Framework_TestCase{ public function testMyMethod() { // Create a stub for the AnotherClass class. $stub = $this->getMock('AnotherClass'); x

// Configure the stub. $stub->expects($this->any()) ->method('doSomething') ->will($this->returnValue('mon')); x

$class = new MyClass($stub); $this->assertEquals(1, $class->myMethod()); }}

123456789

class MyClass{ public function myMethod(AnotherClass $class) { $anyThing = $class->doSomething();

// solves some logic and returns the result }}

1234

class AnotherClass{ public function doSomething() { // logic }}

Good OO Design

Change , Dependency , Coupling

Page 10: Solid: Good Object Oriented Design

Manifesto for AGILE Software Development

Individuals and interactionsWorking software

Customer collaboration

Responding to change

Good OO Design

Change , Dependency , Coupling, Agile

Page 11: Solid: Good Object Oriented Design

S ingle Responsibility

Open / Closed

L iskov Substitution

I nterface Segregation

Dependency Inversion

The principles of SOLID

Change , Dependency , Coupling, Agile

Page 12: Solid: Good Object Oriented Design

Object Oriented Principles

AbstractionEncapsulationInheritanceCompositionModularityPolymorphism

Principles of Class Design

Design Patterns

Layered Architecture

CohesionLow CouplingOrthogonalityDesign by ContractLaw of Demeter

MVCDDD

Frameworks

General SolutionRecurring problemsProgram to InterfaceFavor Composition

GranularityStabilityMetrics forstability and abstraction

implementation conceptual

Principles of Package and Component Design

Where SOLID “fits”

Change , Dependency , Coupling, Agile , Composition , Interface

Page 13: Solid: Good Object Oriented Design

Object Oriented Principles

AbstractionEncapsulationInheritanceCompositionModularityPolymorphism

Principles of Class Design

Design Patterns

Layered Architecture

CohesionLow CouplingOrthogonalityDesign by ContractLaw of Demeter

MVCDDD

Frameworks

General SolutionRecurring problemsProgram to InterfaceFavor Composition

GranularityStabilityMetrics forstability and abstraction

implementation conceptual

Principles of Package and Component Design

Where SOLID “fits”

Change , Dependency , Coupling, Agile , Composition , Interface

SOLID

Page 14: Solid: Good Object Oriented Design

The Principles by examples S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Single ResponsibilityA class should have only a single responsibility

(only one reason to change)

Page 15: Solid: Good Object Oriented Design

Single Responsibility1234567891011121314151617181920

class Customer{ public function authenticate() { // authenticate user against a database }

public function authorize() { // checks user privileges }

public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234567891011121314

class AccessControlManager{ public function __construct(Customer $customer) { //save reference }

public function login() { if ($this->customer->authenticate() && $this->customer->authorize()) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 16: Solid: Good Object Oriented Design

1234567891011121314

class AccessControlManager{ public function __construct(Customer $customer, Login $login) { //save references }

public function login() { if ($this->login->authenticate($this->customer) && $this->login->authorize($this->customer)) { return true; } return false; }}

Single Responsibility12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

123456789101112

class Login{ public function authenticate(Customer $customer) { // authenticate user against a database }

public function authorize(Customer $customer) { // checks user privileges }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 17: Solid: Good Object Oriented Design

Single Responsibility12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234567

class SignIn{ public function authenticate(Customer $customer) { // authenticate user against a database }}

1234567

class Permission{ public function authorize(Customer $customer) { // checks user privileges }}

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignIn $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 18: Solid: Good Object Oriented Design

Single Responsibility S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Conclusion❖ SRP is the simplest, and the most difficult to get right

Finding and separating those responsibilities is much of whatsoftware design is really about. Indeed, the rest of the principles

we discuss come back to this issue in one way or another.(Robert Martin)

Page 19: Solid: Good Object Oriented Design

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

The Principles by examples

Open / ClosedSoftware entities (classes, modules, functions, etc.)

should be open for extension, but closed for modification

Page 20: Solid: Good Object Oriented Design

12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

Open / Closed

1234567

class SignIn{ public function authenticate(Customer $customer) { // authenticate user against a database }}

1234567

class Permission{ public function authorize(Customer $customer) { // checks user privileges }}

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignIn $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 21: Solid: Good Object Oriented Design

12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

Open / Closed

1234567

class SignIn{ public function authenticate(Customer $customer) { // authenticate user against a database }}

1234567

class SignFacebook extends SignIn x{ public function authenticate(Customer $customer) { // connect to third-party server resource }}

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignIn $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 22: Solid: Good Object Oriented Design

Open / Closed12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234567

class SignIn { public function authenticate(Customer $customer) { // authenticate user against a database }

protected function getRepository(Adapter $db) x { // connect to database }}

1234567

class SignFacebook extends SignIn { public function authenticate(Customer $customer) { // connect to third-party server resource }

protected function getAccessToken(Oauth $client) { // retrieve a valid token }}

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignIn $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 23: Solid: Good Object Oriented Design

Open / Closed12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234567

class SignDatabase implements SignService { x public function authenticate(Customer $customer) { // authenticate user against a database }

protected function getRepository(Adapter $db) { // connect to database }}

1234567

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 }}

1234

interface SignService { public function authenticate(Customer $customer);}

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignService $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 24: Solid: Good Object Oriented Design

Open / Closed S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Conclusion❖ OCP is at the heart of object-oriented design

❖ Flexibility, Reusability and Maintainability

Nor is it a good idea to apply rampant abstractionto every part of the application…

Resisting premature abstraction is as important as abstraction itself.(Robert Martin)

Page 25: Solid: Good Object Oriented Design

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

The Principles by examples

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.

Page 26: Solid: Good Object Oriented Design

Dependency Inversion12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234567

class SignDatabase implements SignService { public function authenticate(Customer $customer) { // authenticate user against a database }

protected function getRepository(Adapter $db) { // connect to database }}

1234

interface SignService{ public function authenticate(Customer $customer);}

1234567

class Permission{ public function authorize(Customer $customer) { // checks user privileges }}

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignService $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 27: Solid: Good Object Oriented Design

Dependency Inversion S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 28: Solid: Good Object Oriented Design

Dependency Inversion

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 29: Solid: Good Object Oriented Design

Dependency InversionPolicy

Mechanism

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

Page 30: Solid: Good Object Oriented Design

Dependency InversionPolicy

Mechanism

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

Page 31: Solid: Good Object Oriented Design

Dependency Inversion

12345678910

class Customer implements UserIdentity{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234

class SignDatabase implements SignService { public function authenticate(Customer $customer) { // authenticate user against a database }}

1234

class Permission implements GrantService { public function authorize(Customer $customer) { // checks user privileges }}

12345678910111213

class AccessControlManager { public function __construct(UserIdentity $user, SignService $sign, GrantService $grant) { //save references }

public function login() { if ($this->sign->authenticate($this->user) && $this->grant->authorize($this->user)) { return true; } return false; }}

1234

interface SignService{ public function authenticate(Customer $customer);}

1234

interface GrantService{ public function authorize(Customer $customer);}

1 interface UserIdentity { }

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 32: Solid: Good Object Oriented Design

Dependency Inversion

12345678910

class Customer implements UserIdentity{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234

class SignDatabase implements SignService { public function authenticate(UserIdentity $user) { // authenticate user against a database }}

1234

class Permission implements GrantService { public function authorize(UserIdentity $user) { // checks user privileges }}

12345678910111213

class AccessControlManager { public function __construct(UserIdentity $user, SignService $sign, GrantService $grant) { //save references }

public function login() { if ($this->sign->authenticate($this->user) && $this->grant->authorize($this->user)) { return true; } return false; }}

1234

interface SignService{ public function authenticate(UserIdentity $user);}

1234

interface GrantService{ public function authorize(UserIdentity $user);}

1 interface UserIdentity { }

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 33: Solid: Good Object Oriented Design

Dependency Inversion

B. Abstractions should not depend upon details. Details should depend upon abstractions.

S.O.L.I.DPolicy

Mechanism

Change , Dependency , Coupling, Agile , Composition , Interface

Page 34: Solid: Good Object Oriented Design

12345678910111213

class AccessControlManager { public function __construct(Customer $customer, SignIn $sign, Permission $perm) { //save references }

public function login() { if ($this->sign->authenticate($this->customer) && $this->perm->authorize($this->customer)) { return true; } return false; }}

Dependency Inversion12345678910

class Customer{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1234567

class SignIn { public function authenticate(Customer $customer) { // authenticate user against a database }

protected function getRepository(Adapter $db) { // connect to database }}

1234567

class Permission{ public function authorize(Customer $customer) { // checks user privileges }}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 35: Solid: Good Object Oriented Design

Dependency Inversion

1234567

class SignDatabase implements SignService { public function authenticate(UserIdentity $user) { // authenticate user against a database }

protected function getRepository(Adapter $db) { // connect to database }}

12345678910

class Customer implements UserIdentity{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1 interface UserIdentity { }

1234

interface SignService { public function authenticate(UserIdentity $user); protected function getRepository(Adapter $db);}

12345678910111213

class AccessControlManager { public function __construct(UserIdentity $user, SignService $sign, GrantService $grant) { //save references }

public function login() { if ($this->sign->authenticate($this->user) && $this->grant->authorize($this->user)) { return true; } return false; }}

1234

class Permission implements GrantService { public function authorize(UserIdentity $user) { // checks user privileges }}

1234

interface GrantService{ public function authorize(UserIdentity $user);}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 36: Solid: Good Object Oriented Design

Dependency Inversion

12345678910

class Customer implements UserIdentity{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1 interface UserIdentity { }

1234567

class SignFacebook implements SignService { public function authenticate(UserIdentity $user) { // connect to third-party server resource }

protected function getAccessToken(Oauth $client) { // retrieve a valid token }}

12345678910111213

class AccessControlManager { public function __construct(UserIdentity $user, SignService $sign, GrantService $grant) { //save references }

public function login() { if ($this->sign->authenticate($this->user) && $this->grant->authorize($this->user)) { return true; } return false; }}

1234567

class SignDatabase implements SignService { public function authenticate(UserIdentity $user) { // authenticate user against a database }

protected function getRepository(Adapter $db) x { // connect to database }}

1234

interface SignService { public function authenticate(UserIdentity $user); protected function getRepository(Adapter $db); x}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 37: Solid: Good Object Oriented Design

Dependency Inversion

12345678910

class Customer implements UserIdentity{ public function setEmail($email) {}

public function getEmail() {}

public function setPassword($password) {}

public function getPassword() {}}

1 interface UserIdentity { }

1234567

class SignFacebook implements SignService { public function authenticate(UserIdentity $user) { // connect to third-party server resource }

protected function getAccessToken(Oauth $client) { // retrieve a valid token }}

12345678910111213

class AccessControlManager { public function __construct(UserIdentity $user, SignService $sign, GrantService $grant) { //save references }

public function login() { if ($this->sign->authenticate($this->user) && $this->grant->authorize($this->user)) { return true; } return false; }}

1234567

class SignDatabase implements SignService { public function authenticate(UserIdentity $user) { // authenticate user against a database }

protected function getRepository(Adapter $db) { // connect to database }}

1234

interface SignService{ public function authenticate(UserIdentity $user);}

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 38: Solid: Good Object Oriented Design

Dependency Inversion S.O.L.I.DPolicy

Mechanism

Change , Dependency , Coupling, Agile , Composition , Interface

B. Abstractions should not depend upon details. Details should depend upon abstractions.

Page 39: Solid: Good Object Oriented Design

Dependency InversionPolicy

Utility

Mechanism

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

Page 40: Solid: Good Object Oriented Design

Dependency Inversion S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

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)

Page 41: Solid: Good Object Oriented Design

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

The Principles by examples

Liskov SubstitutionObjects in a program should be replaceable

with instances of their subtypes without alteringthe correctness of that program

Page 42: Solid: Good Object Oriented Design

Liskov Substitution

1234567891011

class PaymentCalculator{ public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find NEXT work day: 2013-10-07 Monday return new DateTime('2013-10-07'); }}

S.O.L.I.D1234567

class Payment{ private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday;}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

Change , Dependency , Coupling, Agile , Composition , Interface

Page 43: Solid: Good Object Oriented Design

Liskov Substitution

1234567891011

class PaymentCalculator{ public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find NEXT work day: 2013-10-07 Monday return new DateTime('2013-10-07'); }}

S.O.L.I.D1234567

class Payment{ private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday;}

1234567891011

class PaymentCalcBefore extends PaymentCalculator{ public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find PREV work day: 2013-10-04 Friday return date('2013-10-04'); }}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

Change , Dependency , Coupling, Agile , Composition , Interface

Page 44: Solid: Good Object Oriented Design

Liskov Substitution S.O.L.I.D1234567

class Payment{ private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday;}

123456789101112

class PaymentCalcBefore extends PaymentCalculator{ /** @return String */ x public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find PREV work day: 2013-10-04 Friday return date('2013-10-04'); }}

123456789101112

class PaymentCalculator{ /** @return DateTime */ x public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find NEXT work day: 2013-10-07 Monday return new DateTime('2013-10-07'); }}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

Change , Dependency , Coupling, Agile , Composition , Interface

Page 45: Solid: Good Object Oriented Design

Liskov Substitution S.O.L.I.D1234567

class Payment{ private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday;}

123456789101112

class PaymentCalcBefore extends PaymentCalculator{ /** @return DateTime */ x public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find PREV work day: 2013-10-04 Friday return new DateTime('2013-10-04'); }}

123456789101112

class PaymentCalculator{ /** @return DateTime */ x public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); // calculate 5+ days: 2013-10-06 Sunday // find NEXT work day: 2013-10-07 Monday return new DateTime('2013-10-07'); }}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

Change , Dependency , Coupling, Agile , Composition , Interface

Page 46: Solid: Good Object Oriented Design

Liskov Substitution

123456

class PaymentCalcBefore extends PaymentCalculator { protected function resolvePayDay($workDays,$pay) { // calculate D+5 and find PREVIOUS work day return new DateTime('2013-10-04'); // Friday }}

123456789101112

class PaymentCalculator { public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); return $this->resolvePayDay($workDays, $pay); }

protected function resolvePayDay($workDays,$pay) { // calculate D+5 and find NEXT work day return new DateTime('2013-10-07'); // Monday }}

S.O.L.I.D1234567

class Payment{ private $type; //CreditCard, Billet private $amount; private $createdAt; //2013-10-01 Tue private $payday;}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

Change , Dependency , Coupling, Agile , Composition , Interface

Page 47: Solid: Good Object Oriented Design

Liskov Substitution

123456

class BeforeCalculator extends PaymentCalculator{ protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-04'); // Friday }}

1234567891011

abstract class PaymentCalculator{ public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); return $this->resolvePayDay($workDays,$payment); }

abstract protected function resolvePayDay($wd,$p);}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

S.O.L.I.D

123456

class AfterCalculator extends PaymentCalculator{ protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-07'); // Monday }}

123

class CCardPayment implements Payment{ // attributes and methods }

1 interface Payment { }

123

class BilletPayment implements Payment { // attributes and methods }

Change , Dependency , Coupling, Agile , Composition , Interface

Page 48: Solid: Good Object Oriented Design

Liskov Substitution

123456

class CreditCardCalculator extends PaymentCalculator{ protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-04'); // Friday }}

1234567891011

abstract class PaymentCalculator{ public function calculatePayday(Payment $pay) { $calendar = $this->getBrazilianCalendar(); $workDays = $this->getWorkDays($calendar); return $this->resolvePayDay($workDays,$payment); }

abstract protected function resolvePayDay($wd,$p);}

1234567891011

class PaymentManager{ public function __construct(Payment $payment, PaymentCalculator $calc) { // save references }

public function schedulePayment() { $payday = $this->calc->calculatePayday($this->payment); $this->payment->setPayday($payday); // save in database }}

S.O.L.I.D

123456

class BilletCalculator extends PaymentCalculator{ protected function resolvePayDay($workDays,$pay) { return new DateTime('2013-10-07'); // Monday }}

1 interface Payment { }

123

class CCardPayment implements Payment{ // attributes and methods }

123

class BilletPayment implements Payment { // attributes and methods }

Change , Dependency , Coupling, Agile , Composition , Interface

Page 49: Solid: Good Object Oriented Design

Liskov Substitution S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

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)

Page 50: Solid: Good Object Oriented Design

S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

The Principles by examples

Interface SegregationMany client-specific interfaces are better than

one general-purpose interface

Page 51: Solid: Good Object Oriented Design

Interface Segregation S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

AtmUI+ requestDeposit+ requestWithdrawl+ requestTransfer+ informeInsufficientFunds

Page 52: Solid: Good Object Oriented Design

Interface Segregation S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

AtmUI+ requestDeposit+ requestWithdrawl+ requestTransfer+ informeInsufficientFunds

Page 53: Solid: Good Object Oriented Design

Interface Segregation S.O.L.I.D

Change , Dependency , Coupling, Agile , Composition , Interface

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

Page 54: Solid: Good Object Oriented Design

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

Questions

Page 55: Solid: Good Object Oriented Design

Robert Martin

S ingle responsibility

Open/closed

L iskov substitution

I nterface segregation

Dependency inversion

Change , Dependency , Coupling, Agile , Composition , Interface

Page 56: Solid: Good Object Oriented Design

Robert Martin

SOLID

Change , Dependency , Coupling, Agile , Composition , Interface

Page 57: Solid: Good Object Oriented Design

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)

Patterns of Enterprise Applications Architecture (Martin Fowler - 2002)Apps para Android

Change , Dependency , Coupling, Agile , Composition , Interface

Recommended Books

Page 58: Solid: Good Object Oriented Design

Mario Rezende

http://about.me/mariorez

THANKS !!!