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

Don't Be STUPID, Grasp SOLID - ConFoo Edition

on

  • 975 views

When it comes to Object Oriented Programming, there is no shortage of guidelines and principles for how to properly design an OO system. There is also no shortage of acronyms to describe these ...

When it comes to Object Oriented Programming, there is no shortage of guidelines and principles for how to properly design an OO system. There is also no shortage of acronyms to describe these principles: DRY, SRP, LSP, LoD, ISP, OCP, etc. However, there are two acronyms that really shine through to describe how to, and how not to do OOP well. The two acronyms are SOLID and STUPID (respectively).

Statistics

Views

Total Views
975
Views on SlideShare
969
Embed Views
6

Actions

Likes
0
Downloads
3
Comments
0

1 Embed 6

http://confoo.ca 6

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 - ConFoo Edition Don't Be STUPID, Grasp SOLID - ConFoo Edition 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->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 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
  • 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