• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Don't Be STUPID, Grasp SOLID - DrupalCon Prague
 

Don't Be STUPID, Grasp SOLID - DrupalCon Prague

on

  • 4,021 views

Slides from my talk at DrupalCon Prague 2013: https://prague2013.drupal.org/session/dont-be-stupid-grasp-solid

Slides from my talk at DrupalCon Prague 2013: https://prague2013.drupal.org/session/dont-be-stupid-grasp-solid

Statistics

Views

Total Views
4,021
Views on SlideShare
3,941
Embed Views
80

Actions

Likes
5
Downloads
13
Comments
0

6 Embeds 80

https://twitter.com 47
http://eventifier.co 19
http://librosweb.es 9
http://eventifier.com 3
http://www.eventifier.info 1
http://www.eventifier.org 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Don't Be STUPID, Grasp SOLID - DrupalCon Prague Don't Be STUPID, Grasp SOLID - DrupalCon Prague Presentation Transcript

    • 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 MammalBird Fish CatCow 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();
    • (9 Months Later)
    • Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep();
    • Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep(); Does A Lion Have A Button To Make It Roar?
    • Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep(); Does A Lion Have A Button To Make It Roar?What Does It Mean For An Object To “Hunt”?
    • Classic View $lion = new Lion; $lion->roar(); $lion->walkTo($point); $lion->hunt($zebra); $lion->sleep(); Does A Lion Have A Button To Make It Roar?What Does It Mean For An Object To “Hunt”? What Is A Lion In Relation To Our Application?
    • 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 IntegerFloat Decimal longshort 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 instanceof Long) { return new Long($a->getValue() + 1); } elseif ($a instanceof Float) { return new Float($a->getValue() + 1.0); } elseif ($a instanceof Decimal) { return new Decimal($a->getValue() + 1.0); }
    • Polymorphic Code return $int->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 Method MethodMethod Class
    • APIs Method MethodMethod Class ClassClass Package
    • APIs Method MethodMethod Class ClassClass Package PackagePackage Library
    • APIs Method MethodMethod Class ClassClass Package PackagePackage Library Framework LibraryLibrary
    • 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 O- L - I - D- A Good API Does One Thing
    • S - Single Responsibility Principle O- Open / Closed Principle L - I - D- A Good API Never Changes
    • S - Single Responsibility Principle O- Open / Closed Principle L - Liskov Substitution Principle I - D- A Good API Behaves Like Its Contract
    • S - Single Responsibility Principle O- Open / Closed Principle L - Liskov Substitution Principle I - Interface Segregation Principle D- A Good API Has A Narrow Responsibility
    • S - Single Responsibility Principle O- Open / Closed Principle L - Liskov Substitution Principle I - Interface Segregation Principle D- Dependency Inversion Principle A Good API Depends Upon Abstractions
    • 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 T - U - P - I - D- Global Variables (Spooky Action At A Distance)
    • S - Singletons T - Tight Coupling U - P - I - D- Depending On Specifics Of An Implementation
    • S - Singletons T - Tight Coupling U - Untestable Code P - I - D- Hidden Dependencies
    • S - Singletons T - Tight Coupling U - Untestable Code P - Premature Optimization I - D- Unhealthy Focus On Performance
    • S - Singletons T - Tight Coupling U - Untestable Code P - Premature Optimization I - Indescriptive Naming D- Poorly Named APIs
    • S - Singletons T - Tight Coupling U - Untestable Code P - Premature Optimization I - Indescriptive Naming D- Duplication Duplication Duplication DuplicationDuplication Duplication Duplication Duplication 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 function turnLeft(); public function turnRight(); public function goFaster(); public function goSlower(); public function shiftUp(); public function shiftDown(); public function 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); }
    • 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 Encoding Messages
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Formatting Messages Encoding Messages Assembling Headers
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Formatting Messages Encoding Messages Assembling Headers Calling Sendmail
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Formatting Messages Encoding Messages Assembling Headers Calling Sendmail Setting INI settings…?
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Open For Extension?
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Open For Extension? Edits Require Copy/Paste
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Open For Extension? Liskov Substitution...
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Open For Extension? Liskov Substitution... One Interface... Many Responsibilites
    • interface MailSystemInterface { public function format(array $message); public function mail(array $message); } What Responsibility? Open For Extension? Liskov Substitution... One Interface... 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
    • Anthony Ferrara bit.ly/prague-solid-talk @ircmaxell blog.ircmaxell.com me@ircmaxell.com youtube.com/ircmaxell