don't be stupid, grasp solid - confoo edition

134
Don’t Be STUPID Grasp SOLID! Anthony Ferrara

Upload: anthony-ferrara

Post on 18-May-2015

1.114 views

Category:

Technology


2 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Don’t Be STUPIDGrasp SOLID!

Anthony Ferrara

Page 2: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Let’s TalkObject

OrientedProgramming

Page 3: Don't Be STUPID, Grasp SOLID - ConFoo Edition

WhatIs An

Object?

Page 4: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View

Object == Physical “Thing”

Page 5: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View

Object == Physical “Thing”

Methods == Actions on “Thing”

Page 6: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View

Object == Physical “Thing”

Methods == Actions on “Thing”

Properties == Description of “Thing”

Page 7: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Animal

MammalBird Fish

CatCow Dog

Lion Feline Cheetah

Page 8: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 9: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View

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

Page 10: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Is This Realistic?

Page 11: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View

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

Page 12: Don't Be STUPID, Grasp SOLID - ConFoo Edition

(9 Months Later)

Page 13: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View

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

Page 14: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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?

Page 15: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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”?

Page 16: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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?

Page 17: Don't Be STUPID, Grasp SOLID - ConFoo Edition

The Classical Model Is Easy To

Understand

Page 18: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 19: Don't Be STUPID, Grasp SOLID - ConFoo Edition

The Classical Model Is

Completely Impractical

Page 20: Don't Be STUPID, Grasp SOLID - ConFoo Edition

“Modern” View

Object == Collection Of (Related) Behaviors

Page 21: Don't Be STUPID, Grasp SOLID - ConFoo Edition

“Modern” View

Object == Collection Of (Related) Behaviors

Methods == Behavior

Page 22: Don't Be STUPID, Grasp SOLID - ConFoo Edition

“Modern” View

Object == Collection Of (Related) Behaviors

Methods == Behavior

Properties == Details Of Behavior

Page 23: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Classic View == “(conceptually) is a”

Modern View == “behaves as a”

Page 24: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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);

}

Page 25: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Number

IntegerFloat Decimal

longshort long long

unsigned signed

Page 26: Don't Be STUPID, Grasp SOLID - ConFoo Edition

But Wait!

Page 27: Don't Be STUPID, Grasp SOLID - ConFoo Edition

We Don’t Even Need Inheritance

Page 28: Don't Be STUPID, Grasp SOLID - ConFoo Edition

All We Need IsPolymorphism

And Encapsulation

Page 29: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 30: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Polymorphism

Behavior Is Determined Dynamically

“Dynamic Dispatch”

Page 31: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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);

}

Page 32: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Polymorphic Code

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

Page 33: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Polymorphic Code

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

Page 34: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Polymorphic Code

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

Page 35: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 36: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Encapsulation

Behavior Is Completely Contained By The Object’s API

(Information Hiding)

Page 37: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Procedural Code

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

Page 38: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Encapsulated Code

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

Page 39: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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

Page 40: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 41: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 42: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Behavior Is Defined By The

API

Page 43: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Two Types Of Primitive APIs

Interfaces (Explicit)

Page 44: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Two Types Of Primitive APIs

Interfaces (Explicit)

Duck Typing (Implicit)

Page 45: Don't Be STUPID, Grasp SOLID - ConFoo Edition

If an Object Is A Collection Of Behaviors...

Page 46: Don't Be STUPID, Grasp SOLID - ConFoo Edition

What Is A Collection Of

Classes/Objects?

Page 47: Don't Be STUPID, Grasp SOLID - ConFoo Edition

APIs

Method

Page 48: Don't Be STUPID, Grasp SOLID - ConFoo Edition

APIs

Method MethodMethod

Class

Page 49: Don't Be STUPID, Grasp SOLID - ConFoo Edition

APIs

Method MethodMethod

Class ClassClass

Package

Page 50: Don't Be STUPID, Grasp SOLID - ConFoo Edition

APIs

Method MethodMethod

Class ClassClass

Package PackagePackage

Library

Page 51: Don't Be STUPID, Grasp SOLID - ConFoo Edition

APIs

Method MethodMethod

Class ClassClass

Package PackagePackage

Library

Framework

LibraryLibrary

Page 52: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 53: Don't Be STUPID, Grasp SOLID - ConFoo Edition

What Makes A Good API?

Page 54: Don't Be STUPID, Grasp SOLID - ConFoo Edition

A Good APIDoes One Thing

Page 55: Don't Be STUPID, Grasp SOLID - ConFoo Edition

A Good APINever Changes

Page 56: Don't Be STUPID, Grasp SOLID - ConFoo Edition

A Good APIBehaves Like Its

Contract

Page 57: Don't Be STUPID, Grasp SOLID - ConFoo Edition

A Good APIHas A Narrow Responsibility

Page 58: Don't Be STUPID, Grasp SOLID - ConFoo Edition

A Good APIDepends Upon Abstractions

Page 59: Don't Be STUPID, Grasp SOLID - ConFoo Edition

And That’sSOLIDCode

Page 60: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Single Responsibility Principle O- L - I - D-

A Good API Does One

Thing

Page 61: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 62: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 63: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Single Responsibility Principle O- Open / Closed Principle

L - I - D-

A Good API Never Changes

Page 64: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 65: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 66: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 67: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 68: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 69: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Single Responsibility Principle O- Open / Closed Principle

L - Liskov Substitution Principle

I - D-

A Good API Behaves Like Its Contract

Page 70: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 71: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 72: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 73: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Single Responsibility Principle O- Open / Closed Principle

L - Liskov Substitution Principle

I - Interface Segregation Principle

D-

A Good API Has A Narrow Responsibility

Page 74: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 75: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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

Page 76: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 77: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 78: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Single Responsibility Principle O- Open / Closed Principle

L - Liskov Substitution Principle

I - Interface Segregation Principle

D- Dependency Inversion Principle

Page 79: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Note That SOLID Does Not Dictate

What Is Good OOP

Page 80: Don't Be STUPID, Grasp SOLID - ConFoo Edition

SOLID Emerges From Good OOP

Page 81: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 82: Don't Be STUPID, Grasp SOLID - ConFoo Edition

So, What Makes A Bad API?

Page 83: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Global Variables(Spooky Action At A Distance)

Page 84: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Depending OnSpecifics Of An Implementation

Page 85: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Hidden Dependencies

Page 86: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Unhealthy Focus On Performance

Page 87: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Poorly Named APIs

Page 88: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Duplication

Page 89: Don't Be STUPID, Grasp SOLID - ConFoo Edition

And That’sSTUPID

Code

Page 90: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T -U -P -I -D-

Global Variables(Spooky ActionAt A Distance)

Page 91: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 92: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T - Tight Coupling

U -P -I -D-

Depending On Specifics Of An

Implementation

Page 93: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 94: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T - Tight Coupling

U - Untestable Code

P -I -D-

Hidden Dependencies

Page 95: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 96: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T - Tight Coupling

U - Untestable Code

P - Premature Optimization

I -D-

Unhealthy Focus On Performance

Page 97: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 98: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T - Tight Coupling

U - Untestable Code

P - Premature Optimization

I - Indescriptive Naming

D-

Poorly Named APIs

Page 99: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 100: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T - Tight Coupling

U - Untestable Code

P - Premature Optimization

I - Indescriptive Naming

D- Duplication

Duplication

Duplication

DuplicationDuplication

Duplication

DuplicationDuplication

Duplication

Page 101: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 102: Don't Be STUPID, Grasp SOLID - ConFoo Edition

S - Singletons

T - Tight Coupling

U - Untestable Code

P - Premature Optimization

I - Indescriptive Naming

D- Duplication

Page 103: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 104: Don't Be STUPID, Grasp SOLID - ConFoo Edition

STUPID Embodies

Lessons Learned From Bad OOP

Page 105: Don't Be STUPID, Grasp SOLID - ConFoo Edition

What Good OOP Gives You

Modular CodeReusable CodeExtendable CodeEasy To Read CodeMaintainable CodeEasy To Change CodeEasy To Understand CodeClean Abstractions (mostly)

Page 106: Don't Be STUPID, Grasp SOLID - ConFoo Edition

What Good OOP Costs You

Tends To Have More “Layers”Tends To Be Slower At RuntimeTends To Have Larger CodebasesTends To Result In Over-AbstractionTends To Require More Effort To WriteTends To Require More Tacit Knowledge

Page 107: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Let’s Look At Some Code!

Page 108: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface Car {

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

}

Page 109: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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

Page 110: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Let’s Look At Drupal Code!

Page 111: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

Page 112: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Page 113: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Formatting Messages

Page 114: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Formatting Messages

Encoding Messages

Page 115: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Formatting Messages

Encoding Messages

Assembling Headers

Page 116: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Formatting Messages

Encoding Messages

Assembling Headers

Calling Sendmail

Page 117: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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…?

Page 118: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Open For Extension?

Page 119: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Open For Extension?

Edits Require Copy/Paste

Page 120: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Open For Extension?

Liskov Substitution...

Page 121: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Open For Extension?

Liskov Substitution...

One Interface...

Many Responsibilites

Page 122: Don't Be STUPID, Grasp SOLID - ConFoo Edition

interface MailSystemInterface {

public function format(array $message);

public function mail(array $message);

}

What Responsibility?

Open For Extension?

Liskov Substitution...

One Interface...

What Dependencies?

Page 123: Don't Be STUPID, Grasp SOLID - ConFoo Edition

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

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

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

}

Page 124: Don't Be STUPID, Grasp SOLID - ConFoo Edition

class MailSystem { public function __construct( MessageFormatter $messageFormatter, MessageEncoder $messageEncoder, MessageTransport $messageTransport

) {} public function mail(Message $message);

}

Page 125: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Principle Of

GoodEnough

Page 126: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 127: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 128: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 129: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 130: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 131: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 132: Don't Be STUPID, Grasp SOLID - ConFoo Edition
Page 133: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Know the rules wellso you can break them

effectively...Dalai Lama XIV

Page 134: Don't Be STUPID, Grasp SOLID - ConFoo Edition

Anthony Ferrara@ircmaxell

[email protected]/ircmaxell