Page 1

Don’t Be STUPID Grasp SOLID!

Anthony Ferrara


Let’s Talk Object Oriented Programming


What Is An Object?


Classic View Object == Physical “Thing”


Classic View Object == Physical “Thing” Methods == Actions on “Thing”


Classic View Object == Physical “Thing” Methods == Actions on “Thing” Properties == Description of “Thing”


Animal Bird

Mammal

Fish

Cow

Cat

Dog

Lion

Feline

Cheetah


Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep();


Is This Realistic?


Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep();


) r te

a L s

(

o M 9

h t n


Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep();


Classic View Does A Lion Have A Button To Make newIt Roar? Lion;

$lion = $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep();


Classic View Does A Lion Have A Button To Make $lion Lion; What Does=It newIt Roar? Mean For An $lion->roar(); Object To “Hunt”?

$lion->walkTo($point); $lion->hunt($zebra); $lion->sleep();


Classic View Does A Lion Have A Button To Make $lion Lion; What Does=It newIt Roar? Mean For An $lion->roar(); Object To “Hunt”? $lion->walkTo($point); What Is A Lion In Relation To Our $lion->hunt($zebra); Application?

$lion->sleep();


The Classical Model Is Easy To Understand


The Classical Model Is Completely Impractical


“Modern” View Object == Collection Of (Related) Behaviors


“Modern” View Object == Collection Of (Related) Behaviors Methods == Behavior


“Modern� View Object == Collection Of (Related) Behaviors Methods == Behavior Properties == Details Of Behavior


Classic View == “(conceptually) is a” Modern View == “behaves as a”


interface Number { function getValue(); function __toString(); function add(Number $n); function subtract(Number $n); function equals(Number $n); function isLessThan(Number $n); function isGreaterThan(Number $n); }


Number Float

Integer

Decimal

short

long

long long

unsigned

signed


But Wait!


We Don’t Even Need Inheritance


All We Need Is Polymorphism And Encapsulation


Polymorphism Behavior Is Determined Dynamically “Dynamic Dispatch”


Procedural Code if ($a->isLong()) { return new Long($a->getValue() + 1); } elseif ($a->isFloat()) { return new Float($a->getValue() + 1.0); } elseif ($a->isDecimal()) { return new Decimal($a->getValue() + 1.0); }


Polymorphic Code return $number->add(new Integer(1));


Polymorphic Code class Integer implements Number { public function add(Number $a) { return new Integer( $this->getValue() + (int) $a->getValue() ); } }


Polymorphic Code class Float implements Number { public function add(Number $a) { return new Float( $this->getValue() + (float) $a->getValue() ); } }


Encapsulation Behavior Is Completely Contained By The Object’s API (Information Hiding)


Procedural Code if (5 == $number->value) { print “Number Is 5”; } else { print “Number Is Not 5”; }


Encapsulated Code if ($number->equals(new Integer(5))) { print “Number Is 5”; } else { print “Number Is Not 5”; }


Encapsulated Code class Decimal implements Number { protected $intValue; protected $exponent; public function equals(Number $a) { if ($a instanceof Decimal) { // Compare Directly } else { // Cast } }


Behavior Is Defined By The API


Two Types Of Primitive APIs

Interfaces (Explicit)


Two Types Of Primitive APIs

Interfaces (Explicit) Duck Typing (Implicit)


If an Object Is A Collection Of Behaviors...


What Is A Collection Of Classes/Objects?


APIs

Method


APIs

Class Method

Method

Method


APIs

Package Class

Class

Class

Method

Method

Method


APIs Library Package

Package

Package

Class

Class

Class

Method

Method

Method


APIs Framework Library

Library

Library

Package

Package

Package

Class

Class

Class

Method

Method

Method


What Makes A Good API?


A Good API Does One Thing


A Good API Never Changes


A Good API Behaves Like Its Contract


A Good API Has A Narrow Responsibility


A Good API Depends Upon Abstractions


And That’s SOLID Code


S - Single Responsibility Principle OL - A Good API Does One I Thing D-


S - Single Responsibility Principle O- Open / Closed Principle LA Good API I Never Changes D-


S - Single Responsibility Principle O- Open / Closed Principle L - Liskov Substitution Principle I - A Good API D- Behaves Like Its Contract


S - Single Responsibility Principle A Good API O- Open / Has Closed Principle A Narrow L - LiskovResponsibility Substitution Principle I - Interface Segregation Principle D-


S - Single Responsibility Principle A Good O- Open / Closed Principle API Depends Upon L - Liskov Substitution Principle Abstractions I - Interface Segregation Principle D- Dependency Inversion Principle


S - Single Responsibility Principle O- Open / Closed Principle L - Liskov Substitution Principle I - Interface Segregation Principle D- Dependency Inversion Principle


Note That SOLID Does Not Dictate What Is Good OOP


SOLID Emerges From Good OOP


So, What Makes A Bad API?


Global Variables (Spooky Action At A Distance)


Depending On Specifics Of An Implementation


Hidden Dependencies


Unhealthy Focus On Performance


Poorly Named APIs


Duplication


And That’s STUPID Code


S - Singletons TGlobal Variables U(Spooky Action PAt A Distance) I D-


S - Singletons T - Tight Coupling UDepending On PSpecifics Of An I Implementation D-


S - Singletons T - Tight Coupling U - Untestable Code PHidden I - Dependencies D-


S - Singletons T - TightUnhealthy Coupling Focus U - Untestable Code On Performance P - Premature Optimization I D-


S - Singletons T - Tight Coupling Poorly U - Untestable CodeNamed APIs P - Premature Optimization I - Indescriptive Naming D-


S - Singletons Duplication Duplication T - Tight Coupling Duplication Duplication U - Untestable Code Duplication P - Premature Optimization Duplication Duplication Duplication I - Indescriptive Naming D- Duplication


S - Singletons T - Tight Coupling U - Untestable Code P - Premature Optimization I - Indescriptive Naming D- Duplication


STUPID Embodies Lessons Learned From Bad OOP


What Good OOP Gives You Modular Code Reusable Code Extendable Code Easy To Read Code Maintainable Code Easy To Change Code Easy To Understand Code Clean Abstractions (mostly)


What Good OOP Costs You Tends To Have More “Layers” Tends To Be Slower At Runtime Tends To Have Larger Codebases Tends To Result In Over-Abstraction Tends To Require More Effort To Write Tends To Require More Tacit Knowledge


Let’s Look At Some Code!


interface Car { public public public public public public public }

function function function function function function function

turnLeft(); turnRight(); goFaster(); goSlower(); shiftUp(); shiftDown(); start();


interface Steerable { public function steer($angle); } interface Acceleratable { public function accelerate($amt); } interface Shiftable { public function shiftDown(); public function shiftUp(); }


Let’s Look At Drupal Code!


interface MailSystemInterface { public function format(array $message); public function mail(array $message);

}


What Responsibility? interface MailSystemInterface { public function format(array $message); public function mail(array $message);

}


What Responsibility? Formatting Messages interface MailSystemInterface { public function format(array $message); public function mail(array $message);

}


What Responsibility? Formatting Messages interface MailSystemInterface { Encoding Messages public function format(array $message); public function mail(array $message);

}


What Responsibility? Formatting Messages interface MailSystemInterface { Encoding Messages public function format(array $message);

Assembling Headers

public function mail(array $message);

}


What Responsibility? Formatting Messages interface MailSystemInterface { Encoding Messages public function format(array $message);

Assembling Headers

public function mail(array $message); Calling Sendmail

}


What Responsibility? Formatting Messages interface MailSystemInterface { Encoding Messages public function format(array $message);

Assembling Headers

public function mail(array $message); Calling Sendmail

}

Setting INI settings‌?


What Responsibility? Open For Extension? interface MailSystemInterface { public function format(array $message); public function mail(array $message);

}


What Responsibility? Open For Extension? interface MailSystemInterface { Edits Require Copy/Paste public function format(array $message); public function mail(array $message);

}


What Responsibility? Open For Extension? interface MailSystemInterface { Liskov Substitution... public function format(array $message); public function mail(array $message);

}


What Responsibility? Open For Extension? interface MailSystemInterface { Liskov Substitution... public function format(array $message);

One Interface...

public mail(array $message); Manyfunction Responsibilites

}


What Responsibility? Open For Extension? interface MailSystemInterface { Liskov Substitution... public function format(array $message);

One Interface...

public function mail(array $message); What Dependencies?

}


interface MessageFormatter { public function format(Message $message);

} interface MessageEncoder { public function encode(Message $message);

} interface MessageTransport { public function send(Message $message);

}


class MailSystem { public function __construct( MessageFormatter $messageFormatter, MessageEncoder $messageEncoder, MessageTransport $messageTransport ) {} public function mail(Message $message);

}


Principle Of

Good Enough


Know the rules well so you can break them effectively... Dalai Lama XIV


Anthony Ferrara @ircmaxell blog.ircmaxell.com me@ircmaxell.com youtube.com/ircmaxell

Don't be stupid, grasp solid v4 confoo  
Read more
Read more
Similar to
Popular now
Just for you