HEURISTICS & CONVENTIONS HEURISTICS & CONVENTIONS Think before coding Keep classes small Extract whenever you detect a new responsibility Don't be lazy
POLYMORPHIC OPEN/CLOSED PRINCIPLE POLYMORPHIC OPEN/CLOSED PRINCIPLE Relies on abstractions Abstracts are closed for modification Implementation can change
HEURISTICS & CONVENTIONS HEURISTICS & CONVENTIONS Work towards closed classes Make functionality private Mark classes & methods as final No RTTI Specify abstractions
BARBARA LISKOV BARBARA LISKOV American Computer Scientist MIT Turing Award winner Fields: Operating systems Programming languages Distributed systems Abstractions & modularity
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
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
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 {} }
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 {} }
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 {} }
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 {} }
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)
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
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
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.
interface ContextBuilderLocator { public function retrieve(string $key) : ContextBuilder; } final class InMemoryRegistry implements ContextBuilderLocator { }
MAKE LOW LEVEL SPECIFIC IMPLEMENTATIONS & MAKE LOW LEVEL SPECIFIC IMPLEMENTATIONS & NAME ACCORDINGLY NAME ACCORDINGLY DbalContactRepository or InMemoryContactRepository
WRAPPIN' IT UP WRAPPIN' IT UP Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle