Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP For Grown Ups
Search
linden3
April 14, 2015
Programming
3
390
PHP For Grown Ups
Slides of the talk as given at the PHPAmersfoort Meetup on April 14, 2015
linden3
April 14, 2015
Tweet
Share
Other Decks in Programming
See All in Programming
API Platformを活用したPHPによる本格的なWeb API開発 / api-platform-book-intro
ttskch
1
150
メタプログラミングで実現する「コードを仕様にする」仕組み/nikkei-tech-talk43
nikkei_engineer_recruiting
0
210
Linux Kernelの1文字のミスで 権限昇格ができた話
rqda
0
2.1k
Goの型安全性で実現する複数プロダクトの権限管理
ishikawa_pro
2
1.2k
Ruby and LLM Ecosystem 2nd
koic
1
1.3k
AI時代のシステム設計:ドメインモデルで変更しやすさを守る設計戦略
masuda220
PRO
6
1.1k
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
7
3k
Rで始めるML・LLM活用入門
wakamatsu_takumu
0
200
Symfony + NelmioApiDocBundle を使った スキーマ駆動開発 / Schema Driven Development with NelmioApiDocBundle
okashoi
0
210
Claude Code Skill入門
mayahoney
0
420
今からFlash開発できるわけないじゃん、ムリムリ! (※ムリじゃなかった!?)
arkw
0
140
Codexに役割を持たせる 他のAIエージェントと組み合わせる実務Tips
o8n
4
1.4k
Featured
See All Featured
Making Projects Easy
brettharned
120
6.6k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
220
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
210
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
490
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
110
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
240
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
580
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
410
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
980
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
89
Transcript
PHP FOR GROWN-UPS
ANDREAS PHP DEVELOPER @ MIJNDOMEIN.NL
PHP HAS A BAD RAP (WHICH IT PARTLY DESERVES)
BUT YOU CAN STILL USE IT TO BUILD SOLID STUFF
(IF YOU KNOW HOW)
SO LET’S TALK ABOUT THE HOW
QUALITIES OF GOOD CODE
EASY TO CHANGE EASY TO UNDERSTAND EASY TO (RE)USE ~
HARD TO BREAK
“Always code as if the guy who ends up maintaining
your code will be a violent psychopath who knows where you live” - probably John Woods
SHY CODE
“Shy code - modules that don’t reveal anything unnecessary to
other modules and that don’t rely on other modules’ implementations” - The Pragmatic Programmer
ENCAPSULATION “MODULES THAT DON’T REVEAL ANYTHING UNNECESSARY TO OTHER MODULES”
$totalPrice = 0; foreach ($order->getItems() as $item) { $amount =
$item->getAmount(); $price = $item->getPrice(); $totalPrice += $amount * $price; } $totalPrice += $order->getShippingCosts();
$totalPrice = $order->getTotalPrice();
TELL, DON’T ASK
$order->applyDiscount($discountPercentage);
“[...] modules that don’t rely on other modules’ implementations”
interface EventDispatcher { public function dispatch(Event $event); }
public function __construct(EventDispatcher $eventDispatcher) { $this->eventDispatcher = $eventDispatcher }
class SymfonyEventDispatcher implements EventDispatcher { public function dispatch(Event $event) {
// Symfony implementation here } }
public function __construct(EventDispatcher $eventDispatcher) { $this->eventDispatcher = $eventDispatcher }
FROM THE PERSPECTIVE OF THE CONSUMER THE INTERFACE IS THE
REAL THING
“MATHEMATICS ABSTRACTION IS THE ART OF GIVING THE SAME NAME
TO DIFFERENT THINGS.” ~ HENRI POINCARÉ’S PROGRAMMER COUSIN
/** * before: */ public function search($searchTerm, $productCategory, $make, $color)
{ switch ($productType) { case ‘car’: // search cars case ‘boat’: // search boat // etc. } }
/** * after: */ public function search(SearchQuery $query) { $worker
= $this->getWorkerForQuery($query); /** @var SearchResults $results */ $results = $worker->process($query); return $results; }
”BUT... YOU JUST INTRODUCED COUPLING!”
“Figuring out if two people are married is easy. Figuring
out if they should be is hard.” - Michael Feathers
LEVELS OF ABSTRACTION
LOW LEVEL OF ABSTRACTION $statement = $database->prepare( “INSERT INTO `fish`(‘name’,
‘species’, ‘gender’, ‘tankId’) ” . “VALUES(?, ?, ?, ?)” ); $statement->execute(array(‘Nemo’, $speciesId, ‘M’, $tankId));
HIGH LEVEL OF ABSTRACTION $command = new IntroduceFishCommand($fish, $tank); $this->commandBus->execute($command);
LAYERED ARCHITECTURE
DATABASE QUERIES IN CONTROLLER CODE BUSINESS LOGIC IN VIEWS VIEW
LOGIC IN DOMAIN OBJECTS
MIXING LEVELS OF ABSTRACTION MAKES CODE HARDER TO UNDERSTAND
“THE RATIO OF TIME SPENT READING CODE VERSUS WRITING IS
WELL OVER 10 TO 1” ~ UNCLE BOB
“THERE ARE ONLY TWO HARD THINGS IN COMPUTER SCIENCE: CACHE
INVALIDATION AND NAMING THINGS” ~ PHIL KARLTON
// not: $light->setStatus(true); // but: $light->switchOn();
NAMES THAT LIE // neither of these is actually a
locale $this->locale = $locale->locale; // does more than it says public function getItem() { // write to disk }
EXTRACT METHOD // before: if (is_numeric($amount) && $amount > 0)
// after: if ($this->isValidAmount($amount))
VALUE OBJECTS $amount = new Amount($amount); // throws exception if
amount is invalid
CODE SAYS WHAT COMMENTS SAY WHY
// set the patient’s clinic $patient->setClinic($clinic); // to register a
patient, set the patient’s clinic $patient->setClinic($clinic);
GOOD NAMING AND GOOD ABSTRACTIONS BEAT GOOD COMMENTS
$clinic->registerPatient($patient);
PRINCIPLE OF LEAST ASTONISHMENT (MINIMIZE THE NUMBER OF WTFS PER
MINUTE)
“I REUSE CODE IF, AND ONLY IF, I NEVER NEED
TO LOOK AT THE SOURCE CODE” ~ UNCLE BOB
WELL-ABSTRACTED GOOD OUTWARD-FACING API DECOUPLED
NAMESPACES PREVENTING NAMING COLLISIONS SINCE PHP 5.3
COMPOSER
OPEN SOURCE VIA GITHUB/PACKAGIST PRIVATE REPOSITORIES IN COMPOSER.JSON TORAN PROXY
ADDED BONUS AUTOLOADING FOR INTERNAL CLASSES (THIS ALONE MAKES COMPOSER
WORTH USING)
PHPDOC DOCBLOCKS IDE USERS LOVE THIS
”SIMPLICITY IS PREREQUISITE FOR RELIABILITY.” ~ EDSGER DIJKSTRA
”Rely only on reliable things” - The Pragmatic Programmer
NOT A RELIABLE THING: THE PHP TYPE SYSTEM
if (! $amount) { // do something } // $amount
can actually be 0, “0”, “”, null or false for this to be true
if ($amount == 0) { // do something } //
$amount can now still be 0, “0” or false for this to be true
if ($amount === 0) { // do something } //
this will only evaluate to true when $amount is actually the number 0
“CRASH, DON’T TRASH” ~ THE PRAGMATIC PROGRAMMER
DO NOT PROGRAM BY COINCIDENCE
”TEST YOUR SOFTWARE, OR YOUR USERS WILL” ~ THE PRAGMATIC
PROGRAMMER
PHPUNIT PHPSPEC CODECEPTION BEHAT
“WHEN YOU AREN’T AFRAID TO CHANGE YOUR CODE, YOU WILL
CLEAN IT” ~ UNCLE BOB
LANGUAGE FEATURES TYPEHINTING VISIBILITY (PRIVATE BY DEFAULT) EXCEPTIONS
CLOSING NOTES
LEARNING ABOUT THIS STUFF IS EASY DOING IT RIGHT IS
HARD
“TO A MAN WITH A HAMMER, EVERYTHING LOOKS LIKE A
NAIL.” ~ ABRAHAM MASLOW
NONE OF THESE IDEAS ARE NEW (IN FACT, MOST ARE
PRETTY OLD)
“THE MORE I LEARN, THE MORE I REALIZE HOW MUCH
I DON’T KNOW” ~ ALBERT EINSTEIN
BOOKS Growing Object-Oriented Software, Guided By Tests The Pragmatic Programmer
Domain-Driven Design Patterns of Enterprise Application Architecture Clean Code
VIDEOS Models and Service Layers; Hemoglobin and Hobgoblins (https://www.youtube.com/watch?v=3uV3ngl1Z8g) Unbreakable
Domain Models (https://www.youtube.com/watch?v=ZJ63ltuwMaE) The Framework As An Implementation Detail (https://www.youtube.com/watch?v=0L_9NutiJlc)
PODCASTS Elephant in the Room (http://elephantintheroom.io)
QUESTIONS?
PLUG TIME WERKENBIJMIJNDOMEIN.NL
BONUS STAGE SOLID PRINCIPLES
“A CLASS SHOULD HAVE ONE, AND ONLY ONE, REASON TO
CHANGE.” ~ SOLID PRINCIPLE #1 (SINGLE RESPONSIBILITY PRINCIPLE)
“A CLASS SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR
MODIFICATION” ~ SOLID PRINCIPLE #2 (OPEN-CLOSED PRINCIPLE)
”CHANGE WHAT A CLASS DOES, BUT NOT WHAT IT IS”
~ KONSTANTIN KUDRYASHOV
“SUBCLASSES MUST BE SUBSTITUTABLE FOR THEIR BASE CLASSES” ~ SOLID
PRINCIPLE #3 (LISKOV SUBSTITUTION PRINCIPLE)
”NEVER FORCE CLASSES TO IMPLEMENT METHODS THAT THEY DO NOT
USE” ~ SOLID PRINCIPLE #4 (INTERFACE SEGREGATION PRINCIPLE)
interface DoesAllTheThings { public function save(Soul $soul); public function addOneAndOne(One
$one, One $one); public function shave(Yak $yak); }
class DefaultCalculator implements Calculator { public function addOneAndOne(One $one, One
$one) { return new Two; } }
class DoesAllTheThings implements SoulSaver, Calculator, YakShaver { // can still
do all the things }
“DEPEND ON ABSTRACTIONS, NOT ON CONCRETIONS” ~ SOLID PRINCIPLE #5
(DEPENDENCY INVERSION PRINCIPLE)