Don't Be STUPID, Grasp SOLID - DrupalCon Prague
Upcoming SlideShare
Loading in...5
×
 

Don't Be STUPID, Grasp SOLID - DrupalCon Prague

on

  • 4,342 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,342
Views on SlideShare
4,257
Embed Views
85

Actions

Likes
5
Downloads
13
Comments
0

6 Embeds 85

https://twitter.com 49
http://eventifier.co 19
http://librosweb.es 11
http://eventifier.com 4
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