Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Design Principles - A SOLID Introduction

Design Principles - A SOLID Introduction

This presentation gives an overview of the SOLID principles. What they are and what they mean. With examples in PHP.

Tom Van Herreweghe

September 04, 2018
Tweet

More Decks by Tom Van Herreweghe

Other Decks in Programming

Transcript

  1. Set of 5 Design Principles Robert C. Martin - "Uncle

    Bob" Agile methodology Design Principles and Design Patterns (2000)
  2. QUIZ TIME! QUIZ TIME! Single Responsibility Principle Open/Closed Principle Liskov

    Substitution Principle Interface Segregation Principle Dependency Inversion Principle
  3. class PostalCodeHelper { /* ... */ public function getCity(string $zip)

    : string { return $this->map[$zip] ?? 'Black Hole'; } public function format(string $zip) : string { $city = $this->mapCodeToCity($zip); return sprintf( '%1$s %2$s', $zip, $city
  4. HOW TO FIX? HOW TO FIX? Extract Postal Code Mapper

    Extract Postal Code Repository Extract Postal Code Formatter Extract Postal Code Importer ...
  5. SO WHAT IS THE BENEFIT? SO WHAT IS THE BENEFIT?

    Clear & concise classes, which are easier to grasp and therefore easier to maintain.
  6. HEURISTICS & CONVENTIONS HEURISTICS & CONVENTIONS Think before coding Keep

    classes small Extract whenever you detect a new responsibility Don't be lazy
  7. class ShapeDrawer { public function draw(array $shapes) : void {

    foreach ($shapes as $shape) { if ($shape instanceof Circle) { // ... } if ($shape instanceof Rectangle) { // ... } } } }
  8. HOW TO FIX? HOW TO FIX? Define an abstraction Depend

    on abstraction (see later on) Implement different behaviors (polymorphism)
  9. interface Shape { public function draw(): void; } class Circle

    implements Shape { /* ... */ } class Rectangle implements Shape { /* ... */ }
  10. class ShapeDrawer { public function draw(array $shapes) : void {

    foreach ($shapes as $shape) { if (! $shape instanceof Shape) { continue; } $shape->draw(); } } }
  11. HEURISTICS & CONVENTIONS HEURISTICS & CONVENTIONS Work towards closed classes

    Make functionality private Mark classes & methods as final No RTTI Specify abstractions
  12. BARBARA LISKOV BARBARA LISKOV American Computer Scientist MIT Turing Award

    winner Fields: Operating systems Programming languages Distributed systems Abstractions & modularity
  13. LSP LSP When B is a subtype of A, Then

    objects of type A may be replaced By objects of type B, Without altering the desirable properties Of the program
  14. LSP LSP When B is a child of parent A,

    Then objects of parent A may be replaced By objects of child B, Without altering the desirable properties Of the program
  15. class Rectangle { // ... public function setWidth(int $width) :

    void { $this->width = $width; } // ... }
  16. class Square extends Rectangle { // ... public function setWidth(int

    $width) : void { $this->width = $width; $this->height = $height; } // ... }
  17. function specifyDimensions(Rectangle $rectangle) { $rectangle->setWidth(100); $rectangle->setHeight(200); } $square = new

    Square; specifyDimensions($square); assert($square->getWidth() === 100); // fail? assert($square->getHeight() === 200); // fail?
  18. INFLUENCE OF LSP INFLUENCE OF LSP Contravariance of method arguments

    in subtype Covariance of return types in subtype
  19. QUIZ! - WILL THIS WORK? (1/4) QUIZ! - WILL THIS

    WORK? (1/4) class Foo { public function bar() {} } class Woo extends Foo { public function bar() : int {} }
  20. QUIZ! - WILL THIS WORK? (2/4) QUIZ! - WILL THIS

    WORK? (2/4) class Foo { public function bar() : Rectangle {} } class Woo extends Foo { public function bar() : Square {} }
  21. PHP IS "1-LEVEL" COVARIANT PHP IS "1-LEVEL" COVARIANT Only works

    from "mixed" to "something else" Not from Supertype to Subtype
  22. QUIZ! - WILL THIS WORK? (3/4) QUIZ! - WILL THIS

    WORK? (3/4) class Foo { public function bar(string $baz) : int {} } class Woo extends Foo { public function bar($baz) : int {} }
  23. QUIZ! - WILL THIS WORK? (4/4) QUIZ! - WILL THIS

    WORK? (4/4) class Foo { public function bar(Square $baz) : int {} } class Woo extends Foo { public function bar(Rectangle $baz) : int {} }
  24. PHP IS "1-LEVEL" CONTRAVARIANT PHP IS "1-LEVEL" CONTRAVARIANT Only works

    from "something" to "mixed" (omitting) Not from Subtype to Supertype (scope widening) (only in PHP >= 7.2)
  25. HEURISTICS & CONVENTIONS HEURISTICS & CONVENTIONS LSP is about behavior.

    Think carefully when replaceing with a subtype PHP is Invariant Typehints can be omitted in subtypes Mixed return types can be specified in subtypes
  26. HEURISTICS & CONVENTIONS HEURISTICS & CONVENTIONS When you need to

    implement more than you'd like, split the interface Implementation class Foo implements A, B, C interface Bar extends A, C
  27. Abstractions should not depend on details. Details should depend on

    abstractions. High-level modules should not depend on low-level modules. Both should depend on abstractions.
  28. interface ContextBuilderLocator { public function retrieve(string $key) : ContextBuilder; }

    final class InMemoryRegistry implements ContextBuilderLocator { }
  29. HIGH-LEVEL MODULES SHOULD NOT HIGH-LEVEL MODULES SHOULD NOT DEPEND ON

    LOW-LEVEL MODULES DEPEND ON LOW-LEVEL MODULES
  30. MAKE LOW LEVEL SPECIFIC IMPLEMENTATIONS & MAKE LOW LEVEL SPECIFIC

    IMPLEMENTATIONS & NAME ACCORDINGLY NAME ACCORDINGLY DbalContactRepository or InMemoryContactRepository
  31. IT CAN HELP TO "PHYSICALLY" SPLIT FILES BETWEEN IT CAN

    HELP TO "PHYSICALLY" SPLIT FILES BETWEEN HIGH & LOW LEVEL HIGH & LOW LEVEL
  32. WRAPPIN' IT UP WRAPPIN' IT UP Single Responsibility Principle Open/Closed

    Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle