your code sucks, let's fix it - php master series 2012
DESCRIPTION
Performance and testing are just one aspect of code, to really be successful your code needs to be readable, maintainable and generally easier to comprehend and work with. This talk draws from my own experience in applying the techniques of object calisthenics and code readability, within an existing team. It will help you identify trouble areas, learn how to refactor them and train you to write better code in future projects avoiding common pitfalls.TRANSCRIPT
![Page 1: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/1.jpg)
Your code sucks, let’s !x it!
Object Calisthenics and Code readability
Rafael Dohms@rdohms
![Page 2: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/2.jpg)
phot
o cr
edit:
Eli W
hite
Evangelist, Speaker and Contributor.
Developer at WEBclusive.
Enabler at AmsterdamPHP.
Rafael Dohms@rdohms
![Page 3: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/3.jpg)
Why does mycode suck?
![Page 4: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/4.jpg)
Why does mycode suck?
Is it Readable?
![Page 5: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/5.jpg)
Why does mycode suck?
Is it Readable?
Is it Testable?
![Page 6: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/6.jpg)
Why does mycode suck?
Is it Readable?
Is it Testable?
Is it Maintainable?
![Page 7: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/7.jpg)
Why does mycode suck?
Is it Readable?
Is it Testable?
Is it Maintainable?
Is it Reusable?
![Page 8: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/8.jpg)
Does it look like this?<?php $list=mysql_connect("******","*******","*****"); if(!$list)echo 'Cannot login.'; else{ mysql_select_db("******", $list); $best=array("0","0","0","0","0","0"); $id=mysql_num_rows(mysql_query("SELECT * FROM allnews")); $count=0; for($i=0;$i<6;$i++){ while(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")!="he")$count++; $best[$i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");} $id=$id-$count; $maxdate=mktime(0,0,0,date('m'),date('d')-7,date('Y')); while(mysql_query("SELECT date FROM allnews WHERE id=$id-$count")>=$maxdate){ if(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")=="he"){ $small=$best[0]; while($i=0;$i<6;$i++){ if(mysql_query("SELECT score FROM allnews WHERE id=$small)"<mysql_query("SELECT score FROM allnews WHERE id=$best[i+1]")) $small=$best[i+1];} if(mysql_query("SELECT score FROM allnews WHERE id=$small")<mysql_query("SELECT score FROM allnews WHERE id=$id-$count")){ while($i=0;$i<6;$i++){ if($small==$best[i])$best[i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");}}}} while($i=0;$i<6;$i++) echo '<a href="news-page.php?id='.$best[i].'"><div class="box '.mysql_query("SELECT type FROM allnews WHERE id=$best[i]").'">'.mysql_query("SELECT title FROM allnews WHERE id=$best[i]").'<div class="img" style="background-image:url(images/'.mysql_query("SELECT image1 FROM allnews WHERE id=$best[i]").');"></div></div></a>'; mysql_close($list); } ?>
![Page 9: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/9.jpg)
Does it look like this?<?php $list=mysql_connect("******","*******","*****"); if(!$list)echo 'Cannot login.'; else{ mysql_select_db("******", $list); $best=array("0","0","0","0","0","0"); $id=mysql_num_rows(mysql_query("SELECT * FROM allnews")); $count=0; for($i=0;$i<6;$i++){ while(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")!="he")$count++; $best[$i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");} $id=$id-$count; $maxdate=mktime(0,0,0,date('m'),date('d')-7,date('Y')); while(mysql_query("SELECT date FROM allnews WHERE id=$id-$count")>=$maxdate){ if(mysql_query("SELECT language FROM allnews WHERE id=$id-$count")=="he"){ $small=$best[0]; while($i=0;$i<6;$i++){ if(mysql_query("SELECT score FROM allnews WHERE id=$small)"<mysql_query("SELECT score FROM allnews WHERE id=$best[i+1]")) $small=$best[i+1];} if(mysql_query("SELECT score FROM allnews WHERE id=$small")<mysql_query("SELECT score FROM allnews WHERE id=$id-$count")){ while($i=0;$i<6;$i++){ if($small==$best[i])$best[i]=mysql_query("SELECT id FROM allnews WHERE id=$id-$count");}}}} while($i=0;$i<6;$i++) echo '<a href="news-page.php?id='.$best[i].'"><div class="box '.mysql_query("SELECT type FROM allnews WHERE id=$best[i]").'">'.mysql_query("SELECT title FROM allnews WHERE id=$best[i]").'<div class="img" style="background-image:url(images/'.mysql_query("SELECT image1 FROM allnews WHERE id=$best[i]").');"></div></div></a>'; mysql_close($list); } ?>
If Rebecca Black was a developer
![Page 10: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/10.jpg)
How do we fix it?
![Page 11: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/11.jpg)
Object Calisthenics
![Page 12: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/12.jpg)
Object Calisthenics
cal·is·then·ics - noun - /ˌkaləsˈTHeniks/
Calisthenics are a form of dynamic exercise consisting of a variety of
simple, often rhythmical, movements, generally using minimal equipment or
apparatus.
![Page 13: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/13.jpg)
Object Calisthenics
cal·is·then·ics - noun - /ˌkaləsˈTHeniks/
Calisthenics are a form of dynamic exercise consisting of a variety of
simple, often rhythmical, movements, generally using minimal equipment or
apparatus.
A variety of simple, often rhythmical, exercises to achieve better OO and code quality
![Page 14: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/14.jpg)
Object Calisthenics
“So here’s an exercise that can help you to internalize principles of good object-oriented design and actually
use them in real life.”
-- Jeff Bay
![Page 15: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/15.jpg)
Object Calisthenics
“So here’s an exercise that can help you to internalize principles of good object-oriented design and actually
use them in real life.”
-- Jeff Bay
Important:
PHP != JAVA
Adaptations will be done
![Page 16: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/16.jpg)
Object Calisthenics+
Readability Tips
![Page 17: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/17.jpg)
Object Calisthenics+
Readability Tips
“You need to write code that minimizes the time it would take someone else to understand it—even if that
someone else is you.”
-- Dustin Boswell and Trevor Foucher
![Page 18: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/18.jpg)
Object Calisthenics+
Readability Tips
“You need to write code that minimizes the time it would take someone else to understand it—even if that
someone else is you.”
-- Dustin Boswell and Trevor Foucher
I’m a tip
![Page 19: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/19.jpg)
Disclaimer:“These are guidelines, not rules”
![Page 20: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/20.jpg)
OC #1“Only one indentation
level per method”
![Page 21: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/21.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } } return $valid; }
![Page 22: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/22.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } } return $valid; }
01
23
![Page 23: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/23.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } } return $valid; }
01
23
![Page 24: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/24.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $validationResult = validateSingleProduct($rawProduct, $requiredFields); if ( ! $validationResult){ $valid = false; } } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } return $valid; }
![Page 25: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/25.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $validationResult = validateSingleProduct($rawProduct, $requiredFields); if ( ! $validationResult){ $valid = false; } } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } return $valid; }
whitespace
![Page 26: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/26.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $validationResult = validateSingleProduct($rawProduct, $requiredFields); if ( ! $validationResult){ $valid = false; } } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } return $valid; }
whitespace
duplicated logic
![Page 27: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/27.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $validationResult = validateSingleProduct($rawProduct, $requiredFields); if ( ! $validationResult){ $valid = false; } } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } return $valid; }
whitespace
duplicated logic
01
2
01 2
![Page 28: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/28.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $validationResult = validateSingleProduct($rawProduct, $requiredFields); if ( ! $validationResult){ $valid = false; } } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } return $valid; }
01
2
01 2
![Page 29: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/29.jpg)
function validateProducts($products) { // Check to make sure that our valid fields are in there $requiredFields = array( 'price', 'name', 'description', 'type', ); $valid = true; foreach ($products as $rawProduct) { $validationResult = validateSingleProduct($rawProduct, $requiredFields); if ( ! $validationResult){ $valid = false; } } return $valid; } function validateSingleProduct($product, $requiredFields) { $valid = true; $fields = array_keys($rawProduct); foreach ($requiredFields as $requiredField) { if (!in_array($requiredField, $fields)) { $valid = false; } } return $valid; }
01
2
01 2
![Page 30: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/30.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
![Page 31: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/31.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
I see cheating!
![Page 32: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/32.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
I see cheating!
Single line IF, simple operations
![Page 33: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/33.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
I see cheating!
Single line IF, simple operations
![Page 34: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/34.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
return earlySingle line IF, simple operations
![Page 35: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/35.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
return earlySingle line IF, simple operations
C (native) functions are faster then PHP
![Page 36: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/36.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
![Page 37: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/37.jpg)
function validateProducts($storeData) { $requiredFields = array('price','name','description','type'); foreach ($storeData['products'] as $rawProduct) { if ( ! validateSingleProduct($rawProduct, $requiredFields)) return false; } return true; } function validateSingleProduct($product, $requiredFields) { $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
![Page 38: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/38.jpg)
function validateProductList($products) { $validProducts = array_filter($products, 'isValidProduct'); return (count($products) == count($validProducts)); }
function isValidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
![Page 39: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/39.jpg)
function validateProductList($products) { $validProducts = array_filter($products, 'isValidProduct'); return (count($products) == count($validProducts)); }
function isValidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
faster iteration
![Page 40: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/40.jpg)
function validateProductList($products) { $validProducts = array_filter($products, 'isValidProduct'); return (count($products) == count($validProducts)); }
function isValidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
faster iteration
reusable method
![Page 41: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/41.jpg)
function validateProductList($products) { $validProducts = array_filter($products, 'isValidProduct'); return (count($products) == count($validProducts)); }
function isValidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
faster iteration
reusable method
method name matches “true” result
![Page 42: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/42.jpg)
function validateProductList($products) { $validProducts = array_filter($products, 'isValidProduct'); return (count($products) == count($validProducts)); }
function isValidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
faster iteration
reusable method
method name matches “true” result
assertable return: expected/returned
![Page 43: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/43.jpg)
function validateProductList($products) { $validProducts = array_filter($products, 'isValidProduct'); return (count($products) == count($validProducts)); }
function isValidProduct($rawProduct) { $requiredFields = array('price', 'name', 'description', 'type'); $fields = array_keys($rawProduct); $missingFields = array_diff($requiredFields, $fields); return (count($missingFields) == 0); }
faster iteration
reusable method
method name matches “true” result
assertable return: expected/returned
List is more readable the plural
![Page 44: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/44.jpg)
Key Benefits
• Single Responsibility Principle (S in SOLID)
• Increases re-use
![Page 45: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/45.jpg)
OC #2“Do not use the ‘else’
keyword”
![Page 46: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/46.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 47: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/47.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 48: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/48.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 49: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/49.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 50: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/50.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 51: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/51.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 52: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/52.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
![Page 53: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/53.jpg)
public function createPost($request) { $entity = new Post(); $form = new MyForm($entity); $form->bind($request); if ($form->isValid()){ $repository = $this->getRepository('MyBundle:Post'); if (!$repository->exists($entity) ) { $repository->save($entity); return $this->redirect('create_ok'); } else { $error = "Post Title already exists"; return array('form' => $form, 'error' => $error); } } else { $error = "Invalid fields"; return array('form' => $form, 'error' => $error); } }
intermediate variable
intermediate variable
![Page 54: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/54.jpg)
public function createPost($request) { $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); $form = new MyForm($entity); $form->bind($request); if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
![Page 55: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/55.jpg)
public function createPost($request) { $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); $form = new MyForm($entity); $form->bind($request); if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
![Page 56: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/56.jpg)
public function createPost($request) { $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); $form = new MyForm($entity); $form->bind($request); if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
removed intermediates
![Page 57: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/57.jpg)
public function createPost($request) { $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); $form = new MyForm($entity); $form->bind($request); if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
removed intermediates
early return
![Page 58: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/58.jpg)
public function createPost($request) { $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); $form = new MyForm($entity); $form->bind($request); if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
removed intermediates
early return
Alternate solution:Use Exceptions
![Page 59: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/59.jpg)
public function createPost($request) { $entity = new Post(); $repository = $this->getRepository('MyBundle:Post'); $form = new MyForm($entity); $form->bind($request); if ( ! $form->isValid()){ return array('form' => $form, 'error' => 'Invalid fields'); } if ($repository->exists($entity)){ return array('form' => $form, 'error' => 'Duplicate post title'); } $repository->save($entity); return $this->redirect('create_ok'); }
Separate code into blocks.
Its like using Paragraphs.
removed intermediates
early return
Alternate solution:Use Exceptions
![Page 60: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/60.jpg)
Key Benefits
• Helps avoid code duplication
• Easier to read (single true path)
• Reduces cyclomatic complexity
![Page 61: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/61.jpg)
OC #3“Wrap primitive types
and strings”
Ada p t e d
* if there is behavior
![Page 62: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/62.jpg)
//... $component->repaint(false);
![Page 63: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/63.jpg)
//... $component->repaint(false);
![Page 64: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/64.jpg)
unclear operation
//... $component->repaint(false);
![Page 65: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/65.jpg)
class UIComponent { //... public function repaint($animate = true){ //... } }
unclear operation
//... $component->repaint(false);
![Page 66: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/66.jpg)
class UIComponent { //... public function repaint( Animate $animate ){ //... } } class Animate { public $animate; public function __construct( $animate = true ) { $this->animate = $animate;} } //... $component->repaint( new Animate(false) );
![Page 67: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/67.jpg)
class UIComponent { //... public function repaint( Animate $animate ){ //... } } class Animate { public $animate; public function __construct( $animate = true ) { $this->animate = $animate;} } //... $component->repaint( new Animate(false) );
This can now encapsulate all animation related operations
![Page 68: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/68.jpg)
Key Benefits
• Helps identify what should be an Object
• Type Hinting
• Encapsulation of operations
![Page 69: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/69.jpg)
OC #4“Only one -> per line”
Ada p t e d
* getter chain or a fluent interface
![Page 70: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/70.jpg)
$this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'both');
$this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading');
Source: CodeIgniter
![Page 71: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/71.jpg)
$this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'both');
$this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading');
properties are harder to mock
Source: CodeIgniter
![Page 72: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/72.jpg)
$this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'both');
$this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading');
properties are harder to mock
no whitespace
Source: CodeIgniter
![Page 73: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/73.jpg)
- Underlying encapsulation problem- Hard to debug and test- Hard to read and understand
$this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'both');
$this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading');
properties are harder to mock
no whitespace
Source: CodeIgniter
![Page 74: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/74.jpg)
- Underlying encapsulation problem- Hard to debug and test- Hard to read and understand
$this->base_url = $this->CI->config->site_url().'/'.$this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'both');
$this->base_uri = $this->CI->uri->segment(1).$this->CI->uri->slash_segment(2, 'leading');
properties are harder to mock
no whitespace
move everything to uri object
$this->getCI()->getUriBuilder()->getBaseUri(‘leading’);
Source: CodeIgniter
![Page 75: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/75.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 76: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/76.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
fluent interface
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 77: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/77.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
operator alignment
fluent interface
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 78: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/78.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
operator alignment
fluent interface
$user = $this->get('security.context')->getToken()->getUser();
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 79: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/79.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
operator alignment
fluent interface
$user = $this->get('security.context')->getToken()->getUser();
only getters (no operations)
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 80: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/80.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
operator alignment
fluent interface
$user = $this->get('security.context')->getToken()->getUser();
only getters (no operations)
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 81: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/81.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
operator alignment
fluent interface
$user = $this->get('security.context')->getToken()->getUser();
only getters (no operations)
where did my autocomplete go?
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 82: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/82.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
operator alignment
fluent interface
$user = $this->get('security.context')->getToken()->getUser();
only getters (no operations)
return null?where did my autocomplete go?
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 83: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/83.jpg)
Key Benefits
• Readability
• Easier Mocking (Testing)
• Easier to Debug
• Demeter’s Law
![Page 84: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/84.jpg)
OC #5“Do not Abbreviate”
![Page 85: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/85.jpg)
if($sx >= $sy) { if ($sx > $strSysMatImgW) { $ny = $strSysMatImgW * $sy / $sx; $nx = $strSysMatImgW; } if ($ny > $strSysMatImgH) { $nx = $strSysMatImgH * $sx / $sy; $ny = $strSysMatImgH; }
} else {
if ($sy > $strSysMatImgH) { $nx = $strSysMatImgH * $sx / $sy; $ny = $strSysMatImgH; } if($nx > $strSysMatImgW) { $ny = $strSysMatImgW * $sy / $sx; $nx = $strSysMatImgW; } }
![Page 86: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/86.jpg)
if($sx >= $sy) { if ($sx > $strSysMatImgW) { $ny = $strSysMatImgW * $sy / $sx; $nx = $strSysMatImgW; } if ($ny > $strSysMatImgH) { $nx = $strSysMatImgH * $sx / $sy; $ny = $strSysMatImgH; }
} else {
if ($sy > $strSysMatImgH) { $nx = $strSysMatImgH * $sx / $sy; $ny = $strSysMatImgH; } if($nx > $strSysMatImgW) { $ny = $strSysMatImgW * $sy / $sx; $nx = $strSysMatImgW; } }
??
?
?
?
![Page 87: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/87.jpg)
Why do you abbreviate?
![Page 88: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/88.jpg)
Why do you abbreviate?
Its repeated many times, and i’m lazy.
![Page 89: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/89.jpg)
Why do you abbreviate?
Its repeated many times, and i’m lazy.
Underlying Problem!
You need to transfer those operations into a separate class.
![Page 90: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/90.jpg)
function processResponseHeadersAndDefineOutput($response) { ... }
Why do you abbreviate?
![Page 91: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/91.jpg)
This method name is too long to type, and i’m lazy.
function processResponseHeadersAndDefineOutput($response) { ... }
Why do you abbreviate?
![Page 92: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/92.jpg)
This method name is too long to type, and i’m lazy.
function processResponseHeadersAndDefineOutput($response) { ... }
more than one responsibility?
Why do you abbreviate?
![Page 93: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/93.jpg)
function getPage($data) { ... }
function startProcess() { ... }
$tr->process(“site.login”);
![Page 94: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/94.jpg)
function getPage($data) { ... }
get from where?
function startProcess() { ... }
$tr->process(“site.login”);
![Page 95: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/95.jpg)
Use clearer names:fetchPage()downloadPage()
function getPage($data) { ... }
get from where?
function startProcess() { ... }
$tr->process(“site.login”);
![Page 96: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/96.jpg)
Use clearer names:fetchPage()downloadPage()
function getPage($data) { ... }
get from where?
function startProcess() { ... }Use a thesaurus:fork, create, begin, open
$tr->process(“site.login”);
![Page 97: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/97.jpg)
Use clearer names:fetchPage()downloadPage()
function getPage($data) { ... }
get from where?
function startProcess() { ... }Use a thesaurus:fork, create, begin, open
$tr->process(“site.login”);
Table row?
![Page 98: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/98.jpg)
Use clearer names:fetchPage()downloadPage()
function getPage($data) { ... }
get from where?
function startProcess() { ... }Use a thesaurus:fork, create, begin, open
$tr->process(“site.login”);Easy understanding, complete scope:$translatorService
Table row?
![Page 99: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/99.jpg)
Key Benefits
• Clearer communication and maintainability
• Indicates underlying problems
![Page 100: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/100.jpg)
OC #6“Keep your classes
small”
Ada p t e d
![Page 101: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/101.jpg)
200 lines per class10 methods per class
15 classes per package
![Page 102: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/102.jpg)
200 lines per class10 methods per class
15 classes per package
Increased to include docblocks
![Page 103: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/103.jpg)
200 lines per class10 methods per class
15 classes per package
15-20 lines per methodIncreased to include
docblocks
![Page 104: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/104.jpg)
200 lines per class10 methods per class
15 classes per package
15-20 lines per methodIncreased to include
docblocks
read this as namespace or folder
![Page 105: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/105.jpg)
Key Benefits
• Single Responsibility
• Objective and clear methods
• Slimmer namespaces
• Avoids clunky folders
![Page 106: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/106.jpg)
OC #7“Limit the number of
instance variables in a class (2 to 5)”
Ada p t e d
![Page 107: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/107.jpg)
class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; protected $translator; protected $entityManager; protected $imageCropper; // ... }
![Page 108: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/108.jpg)
class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; protected $translator; protected $entityManager; protected $imageCropper; // ... }
Limit: 5
![Page 109: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/109.jpg)
class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; protected $translator; protected $entityManager; protected $imageCropper; // ... }
Limit: 5
Use an event based system and move this
to listener
All DB interaction should be in userService
![Page 110: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/110.jpg)
Key Benefits
• Shorter dependency list
• Easier Mocking for unit test
![Page 111: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/111.jpg)
OC #8“Use first class
collections”
![Page 112: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/112.jpg)
$collection->getIterator(); $collection->filter(...);
$collection->append(...);
$collection->map(...);
Doctrine: ArrayCollection
![Page 113: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/113.jpg)
Key Benefits
• Implements collection operations
• Uses SPL interfaces
• Easier to merge collections and not worry about member behavior in them
![Page 114: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/114.jpg)
OC #9“Do not use getters/
setters”
Dr o p p e d
* Use them if you code PHP
![Page 115: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/115.jpg)
/** * THIS CLASS WAS GENERATED BY THE DOCTRINE ORM. DO NOT EDIT THIS FILE. */ class DoctrineTestsModelsCMSCmsUserProxy
extends \Doctrine\Tests\Models\CMS\CmsUser implements \Doctrine\ORM\Proxy\Proxy
{ public function getId() { $this->__load(); return parent::getId(); } public function getStatus() { $this->__load(); return parent::getStatus(); }
Property accessor (get/set) syntax RFC may change the game.
![Page 116: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/116.jpg)
/** * THIS CLASS WAS GENERATED BY THE DOCTRINE ORM. DO NOT EDIT THIS FILE. */ class DoctrineTestsModelsCMSCmsUserProxy
extends \Doctrine\Tests\Models\CMS\CmsUser implements \Doctrine\ORM\Proxy\Proxy
{ public function getId() { $this->__load(); return parent::getId(); } public function getStatus() { $this->__load(); return parent::getStatus(); }
Example: Doctrine uses getters to inject lazy loading operations
Property accessor (get/set) syntax RFC may change the game.
![Page 117: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/117.jpg)
Key Benefits
• Injector operations
• Encapsulation of transformations
![Page 118: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/118.jpg)
OC #10 (bonus!)“Document your code!”
C r e a t e d !
![Page 119: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/119.jpg)
//check to see if the section above set the $overall_pref variable to void if ($overall_pref == 'void')
// implode the revised array of selections in group three into a string// variable so that it can be transferred to the database at the end of the // page $groupthree = implode($groupthree_array, "\n\r");
![Page 120: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/120.jpg)
//check to see if the section above set the $overall_pref variable to void if ($overall_pref == 'void')
really?
// implode the revised array of selections in group three into a string// variable so that it can be transferred to the database at the end of the // page $groupthree = implode($groupthree_array, "\n\r");
![Page 121: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/121.jpg)
//check to see if the section above set the $overall_pref variable to void if ($overall_pref == 'void')
really?
// implode the revised array of selections in group three into a string// variable so that it can be transferred to the database at the end of the // page $groupthree = implode($groupthree_array, "\n\r");
Documenting because i’m doing it wrong in an unusual way
![Page 122: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/122.jpg)
$priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(...)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace(array( '/(?<=\b)[a-z]/ie', '/[^a-z0-9]/i' ), array('strtoupper("\\0")', ''), $event['event']); } $definition->addMethodCall(
'addListenerService', array($event['event'], array($listenerId, $event['method']), $priority
));
Source: Symfony2
![Page 123: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/123.jpg)
$priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(...)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace(array( '/(?<=\b)[a-z]/ie', '/[^a-z0-9]/i' ), array('strtoupper("\\0")', ''), $event['event']); } $definition->addMethodCall(
'addListenerService', array($event['event'], array($listenerId, $event['method']), $priority
));
What does this do?
Source: Symfony2
![Page 124: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/124.jpg)
$priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(...)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace(array( '/(?<=\b)[a-z]/ie', '/[^a-z0-9]/i' ), array('strtoupper("\\0")', ''), $event['event']); } $definition->addMethodCall(
'addListenerService', array($event['event'], array($listenerId, $event['method']), $priority
));
What does this do?
Add a simple comment://Strips special chars and camel cases to onXxx
Source: Symfony2
![Page 125: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/125.jpg)
$priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(...)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace(array( '/(?<=\b)[a-z]/ie', '/[^a-z0-9]/i' ), array('strtoupper("\\0")', ''), $event['event']); } $definition->addMethodCall(
'addListenerService', array($event['event'], array($listenerId, $event['method']), $priority
));
What does this do?
Add a simple comment://Strips special chars and camel cases to onXxx
Source: Symfony2
Don’t explain bad code, fix it!
![Page 126: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/126.jpg)
/** * Checks whether an element is contained in the collection. * This is an O(n) operation, where n is the size of the collection. * * @todo implement caching for better performance* @param mixed $element The element to search for. * @return boolean TRUE if the collection contains the element, or FALSE. */ function contains($element);
![Page 127: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/127.jpg)
/** * Checks whether an element is contained in the collection. * This is an O(n) operation, where n is the size of the collection. * * @todo implement caching for better performance* @param mixed $element The element to search for. * @return boolean TRUE if the collection contains the element, or FALSE. */ function contains($element);
mark todo items so the changes don’t get lost
![Page 128: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/128.jpg)
/** * Checks whether an element is contained in the collection. * This is an O(n) operation, where n is the size of the collection. * * @todo implement caching for better performance* @param mixed $element The element to search for. * @return boolean TRUE if the collection contains the element, or FALSE. */ function contains($element);
mark todo items so the changes don’t get lost
A note on cost of running function
![Page 129: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/129.jpg)
/** * Checks whether an element is contained in the collection. * This is an O(n) operation, where n is the size of the collection. * * @todo implement caching for better performance* @param mixed $element The element to search for. * @return boolean TRUE if the collection contains the element, or FALSE. */ function contains($element);
mark todo items so the changes don’t get lost
A note on cost of running function
Do a mind dump, then clean it up.
![Page 130: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/130.jpg)
/** * Checks whether an element is contained in the collection. * This is an O(n) operation, where n is the size of the collection. * * @todo implement caching for better performance* @param mixed $element The element to search for. * @return boolean TRUE if the collection contains the element, or FALSE. */ function contains($element);
mark todo items so the changes don’t get lost
A note on cost of running function
Do a mind dump, then clean it up.
Generate API docswith phpDocumentor
![Page 131: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/131.jpg)
Key Benefits
• Automatic API documentation
• Transmission of “line of thought”
• Avoids confusion
![Page 132: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/132.jpg)
Recap• #1 - Only one indentation level per method.
• #2 - Do not use the ‘else’ keyword.
• #3 - Wrap primitive types and string, if it has behavior.
• #4 - Only one -> per line, if not getter or fluent.
• #5 - Do not Abbreviate.
• #6 - Keep your classes small
• #7 - Limit the number of instance variables in a class (max: 5)
• #8 - Use first class collections
• #9 - Use getter/setter
• #10 - Document your code!
![Page 133: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/133.jpg)
Questions?
http://slides.doh.ms
http://doh.ms
@rdohms
http://fixthatcode.com
http://joind.in/7941
![Page 134: Your code sucks, let's fix it - PHP Master Series 2012](https://reader033.vdocuments.net/reader033/viewer/2022052822/554f3d19b4c90572088b5089/html5/thumbnails/134.jpg)
Recommended Links:
http://goo.gl/OcSNx
http://goo.gl/unrij
DISCLAIMER: This talk re-uses some of the examples used by Guilherme Blanco in his original Object Calisthenic talk. These principles were studied and applied by us while we worked together in previous jobs. The result taught us all a lesson we really want to spread to other developers.
The ThoughtWorks Anthology
The Art of Readable Code