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
360
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
Boost Your Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
1.2k
マルチアカウント環境での、そこまでがんばらない RI/SP 運用設計
wa6sn
0
710
API for docs
soutaro
1
590
英語 × の私が、生成AIの力を借りて、OSSに初コントリビュートした話
personabb
0
180
リストビュー画面UX改善の振り返り
splcywolf
0
130
小田原でみんなで一句詠みたいな #phpcon_odawara
stefafafan
0
320
Building Scalable Mobile Projects: Fast Builds, High Reusability and Clear Ownership
cyrilmottier
2
260
サービスクラスのありがたみを発見したときの思い出 #phpcon_odawara
77web
4
630
地域ITコミュニティの活性化とAWSに移行してみた話
yuukis
0
230
プロダクト横断分析に役立つ、事前集計しないサマリーテーブル設計
hanon52_
2
390
海外のアプリで見かけたかっこいいTransitionを真似てみる
shogotakasaki
1
160
Being an ethical software engineer
xgouchet
PRO
0
210
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
91
6k
Faster Mobile Websites
deanohume
306
31k
Scaling GitHub
holman
459
140k
Optimizing for Happiness
mojombo
377
70k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
34
2.2k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
41
2.2k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.6k
Speed Design
sergeychernyshev
29
880
Designing Experiences People Love
moore
141
24k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.7k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
178
53k
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)