Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PHP For Grown Ups
Search
linden3
April 14, 2015
Programming
410
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHP For Grown Ups
Slides of the talk as given at the PHPAmersfoort Meetup on April 14, 2015
linden3
April 14, 2015
Other Decks in Programming
See All in Programming
Java 27新機能 / Java 27 new features
kishida
2
200
R8 の設定見直しでアプリサイズ削減
andpad
0
120
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
FreeBSDでZabbixを動かす
kenkino
0
350
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
340
速習iPhone Duo対応
yuukiw00w
2
960
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
340
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
360
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1.3k
Ghostty + Neovimで作る 透明でカッコ良い開発環境
j341nono
0
150
Rでドレミ/Do-Re-Mi_with_R
florets1
0
120
AWSに止められる覚悟してますか?
morizo_1984
2
510
Featured
See All Featured
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
450
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
66k
A better future with KSS
kneath
240
18k
My Coaching Mixtape
mlcsv
0
340
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
900
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
350
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
310
We Have a Design System, Now What?
morganepeng
55
8.4k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
560
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
GraphQLとの向き合い方2022年版
quramy
50
15k
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)