Don't Be STUPID =============== Grasp SOLID =========== ##### And Other Principles of ##### Object Oriented Design
# None Of These Principles # Are Limited To OOP ##### They can be applied to any paradigm
# All Of These Principles # Are For Production Code ##### They can be violated while developing
S
ingletons
T
ight Coupling
U
ntestable Code
P
remature Optimization
I
ndescriptive Naming
D
uplication
S
ingle Responsibility Principle
O
pen/Closed Principle
L
iskov Substitution Principle
I
nterface Segregation Principle
D
ependency Inversion Principle
# Leaky # Abstractions
## Leaky Abstractions * They Are Everywhere * Database Connections * File-systems * Floating Point Numbers * Fixed-Size Integers (64 bit) * They Are Impossible To Avoid * All Abstractions Leak * Leaks Are Technical Debt * Fix Leakage When Found * Maintain The Abstraction * Capture Exceptions * Check For Side-effects
## Leaky Abstractions (ctd) * Leaky: try { $mapper->loadPerson(1); } catch (DatabaseQueryException $e) { /* Woah! What Does The DB have to do With Anything??? */ }
## Leaky Abstractions (ctd) * Better: try { $mapper->loadPerson(1); } catch (RecordNotFoundException $e) { /* Eih! A Person May Be A Record But If It's A First-Class Object, Why Leak The Record Part??? */ }
## Leaky Abstractions (ctd) * Better Still: try { $mapper->loadPerson(1); } catch (PersonNotFoundException $e) { /* I Get It! The Person Wasn't Found! It All Makes Sense! */ }
# Law of # Demeter
## Law of Demeter ## Principle of Least Knowledge * Know As Little As Possible * Only Talk To Friends * Objects Closely Related To The Class * Reduces Dependencies * Benefits: * Maintainable Code * Reusable Code * Easy To Understand Code
## Complexity * Abstraction Should Be Fractal * Methods Abstract Operations * Classes Abstract Responsibility * Layers Abstract Functionality * Packages Abstract Concepts * Libraries Abstract Interactions * Frameworks Abstract Communication * By Maintaining The Abstraction * We Can Focus On What Rather Than How
## Crosscutting * "Global" concerns * Logging * Authentication * Caching * Monitoring * Fits Fractal Model!
## Crosscutting class User implements iUser { public function login($u, $p) { if (!is_valid($u, $p)) { log("Password Invalid", $u); return false; } log("Valid User", $u); return true; } }
## Crosscutting Decorator class UserDecorator implements iUser { protected $user; public function __construct(iUser $u) { $this->user = $u; } public function login($u, $p) { if ($this->user->login($u, $p)) { log("Valid User", $u); return true; } log("Password Invalid", $u); return false; } }
## Crosscutting Events $mediator->on( "user.login", function($data) { log("Valid User", $data['user']); } ); $mediator->on( "user.loginFailure", function($data) { log("Password Invalid", $data['user']); } );
## A Tradeoff * What we lose in size * More Classes * More Code * We gain in Flexibility * Less "high level" code * Code is "configuration" * We gain in DRY * Less Repitition * Common Abstractions * We gain in Readability * Only focus on one layer * Only With Clean abstractions
## Compare: * PHPASS: * 1 Class * 2 Hashing Methods * 2 Pseudo-Random Generators * 6 Test Cases (6 assertions) * Class Oriented Programming * PHP-PasswordLib * 38 Classes * 4 Interfaces * 12 Hashing Methods * 1384 Test Cases (743 Unit Tests, 641 Vectors) * 6 Pseudo-Random Generators * Object Oriented Programming
# Real World # Applications ## (And Problems)
## Active Record * Business Objects Are "Active" $obj->save(); * Violates: * Tight Coupling * Single Responsibility Principle * Open Closed Principle * Interface Segregation Principle * Dependency Inversion Principle * Leaky Abstractions
## Active Record (ctd) * ORM Has The Same Problems * Only If Applied To Business Objects * Can Be Used In A Data Mapper * (A Layer Between Business And Persistence)
## Service Locator ## Dependency Injection Container ## Global Registry * A Container Is Injected * Dependencies Are "Pulled" From Container * Violates: * Tight Coupling * Single Responsibility Principle * Dependency Inversion Principle * Law Of Demeter
## Service Locator (ctd) * Better Than Concrete Dependencies * Adds A Place To Inject Mocks * It Is Testable * **NOT** Dependency Injection * Depends On A Concrete Locator * Class Is Not Dependent Upon An Abstraction * Classes Dependencies Are Not Known * Limits Reuse * Can Make Edge Cases Harder To Test
## The `new` Operator * Instantiating Classes Inside Objects * Instead Of Injecting Dependencies * Violates (Problems with): * Tight Coupling * Untestable Code * Single Responsibility Principle * Dependency Inversion Principle * Static Coupling
# Deep # Inheritance
# Deep Inheritance * Adds Unnecessary Complexity * Tightly Couples Trees * A Form Of Static Coupling * Favor Composition Over Inheritance * Relationships Between Classes: * Always "Is A" * Never "Acts As A" * Never "Has A" * Never "Can Be A"
# Traits Are # Inheritance! ##### Use Carefully!
# Good # Is Not # Good Enough
# These Are # Principles
# You Can # Bend Them
# You Can # Break Them
# But # Understand # Them
# Know What # You're # Giving Up
# And Understand # Why You're # Giving It Up
# At The End # Of The Day
# Working # Is Better Than # Perfect
## A Foolish Consistency ## Is The Hobgoblin ## Of Little Minds ##### Ralph Waldo Emerson
1. Questions? 2. Comments? 3. Snide Remarks?
## Anthony Ferrara ## joind.in/7457 ## @ircmaxell ## blog.ircmaxell.com ## me@ircmaxell.com