your code sucks, let's fix it
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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/1.jpg)
Your code sucks, let’s !x it!
Object Calisthenics and Code readability
Rafael Dohms
![Page 2: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/3.jpg)
Why does mycode suck?
![Page 4: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/4.jpg)
Why does mycode suck?
Is it Readable?
![Page 5: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/5.jpg)
Why does mycode suck?
Is it Readable?
Is it Testable?
![Page 6: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/10.jpg)
How do we fix it?
![Page 11: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/11.jpg)
Object Calisthenics
![Page 12: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/16.jpg)
Object Calisthenics+
Readability Tips
![Page 17: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/19.jpg)
Disclaimer:“These are guidelines, not rules”
![Page 20: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/20.jpg)
OC #1“Only one indentation
level per method”
![Page 21: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/44.jpg)
Key Benefits
• Single Responsibility Principle (S in SOLID)
• Increases re-use
![Page 45: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/45.jpg)
OC #2“Do not use the ‘else’
keyword”
![Page 46: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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'); }
Separate code into blocks.
Its like using Paragraphs.
removed intermediates
early return
![Page 59: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/59.jpg)
Key Benefits
• Helps avoid code duplication
• Easier to read (single path)
• Reduces cyclomatic complexity
![Page 60: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/60.jpg)
OC #3“Wrap primitive types and strings, if there is
behaviour”
Ada p t e d
![Page 61: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/61.jpg)
class UIComponent { //... public function repaint($animate = true){ //... } } //... $component->repaint(false);
![Page 62: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/62.jpg)
class UIComponent { //... public function repaint($animate = true){ //... } } //... $component->repaint(false);
![Page 63: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/63.jpg)
class UIComponent { //... public function repaint($animate = true){ //... } } //... $component->repaint(false);
unclear operation
![Page 64: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/64.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 65: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/65.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 66: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/66.jpg)
Key Benefits
• Type Hinting
• Encapsulation of operations
![Page 67: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/67.jpg)
OC #4“Only one -> per line, unless its getter or a
fluent interface”
Ada p t e d
![Page 68: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/68.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 69: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/69.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 70: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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');
properties are harder to mock
no whitespace
Source: CodeIgniter
![Page 71: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/71.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 72: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/72.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 73: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/73.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 74: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/74.jpg)
$filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower());
fluent interface
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 75: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/75.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 76: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/76.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 77: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/77.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 78: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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();
only getters (no operations)
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 79: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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)
where did my autocomplete go?
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 80: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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)
return null?where did my autocomplete go?
Source: Zend Framework App
Source: Symfony 2 Docs.
![Page 81: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/81.jpg)
Key Benefits
• Readability
• Easier Mocking (Testing)
• Easier to Debug
• Demeter’s Law
![Page 82: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/82.jpg)
OC #5“Do not Abbreviate”
![Page 83: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/83.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 84: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/84.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 85: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/85.jpg)
Why do you abbreviate?
![Page 86: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/86.jpg)
Why do you abbreviate?
Its repeated many times, and i’m lazy.
![Page 87: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/87.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 88: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/88.jpg)
function processResponseHeadersAndDefineOutput($response) { ... }
Why do you abbreviate?
![Page 89: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/89.jpg)
This method name is too long to type, and i’m lazy.
function processResponseHeadersAndDefineOutput($response) { ... }
Why do you abbreviate?
![Page 90: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/90.jpg)
This method name is too long to type, and i’m lazy.
function processResponseHeadersAndDefineOutput($response) { ... }
more then one responsibility?
Why do you abbreviate?
![Page 91: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/91.jpg)
function getPage($data) { ... }
function startProcess() { ... }
$tr->process(“site.login”);
![Page 92: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/92.jpg)
function getPage($data) { ... }
get from where?
function startProcess() { ... }
$tr->process(“site.login”);
![Page 93: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/93.jpg)
Use clearer names:fetchPage()downloadPage()
function getPage($data) { ... }
get from where?
function startProcess() { ... }
$tr->process(“site.login”);
![Page 94: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/94.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 95: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/95.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 96: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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”);Easy understanding, complete scope:$translatorService
Table row?
![Page 97: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/97.jpg)
Key Benefits
• Clearer communication and maintainability
• Indicates underlying problems
![Page 98: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/98.jpg)
OC #6“Keep your classes
small”
Ada p t e d
![Page 99: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/99.jpg)
200 lines per class10 methods per class
15 classes per package
![Page 100: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/100.jpg)
200 lines per class10 methods per class
15 classes per package
Increased to include docblocks
![Page 101: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/101.jpg)
200 lines per class10 methods per class
15 classes per package
15-20 lines per methodIncreased to include
docblocks
![Page 102: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/102.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 103: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/103.jpg)
Key Benefits
• Single Responsibility
• Objective and clear methods
• Slimmer namespaces
• Avoids clunky folders
![Page 104: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/104.jpg)
OC #7“Limit the number of
instance variables in a class (max: 5)”
Ada p t e d
![Page 105: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/105.jpg)
class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; protected $translator; protected $entityManager; protected $imageCropper; // ... }
![Page 106: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/106.jpg)
class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; protected $translator; protected $entityManager; protected $imageCropper; // ... }
Limit: 5
![Page 107: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/107.jpg)
class MyRegistrationService { protected $userService; protected $passwordService; protected $logger; protected $translator; protected $entityManager; protected $imageCropper; // ... }
Limit: 5
Use and event based system and move this
to listener
All DB interaction should be in userService
![Page 108: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/108.jpg)
Key Benefits
• Shorter dependency list
• Easier Mocking for unit test
![Page 109: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/109.jpg)
OC #8“Use first class
collections”
![Page 110: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/110.jpg)
$collection->getIterator(); $collection->filter(...);
$collection->append(...);
$collection->map(...);
Doctrine: ArrayCollection
![Page 111: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/111.jpg)
Key Benefits
• Implements collection operations
• Uses SPL interfaces
![Page 112: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/112.jpg)
OC #9“Do use accessors
(getter/setter)”
Dr o p p e d
![Page 113: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/113.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 get/set syntax RFC may change the game.
![Page 114: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/114.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 get/set syntax RFC may change the game.
![Page 115: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/115.jpg)
Key Benefits
• Injector operations
• Encapsulation of transformations
![Page 116: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/116.jpg)
OC #10 (bonus!)“Document your code!”
C r e a t e d !
![Page 117: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/117.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 118: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/118.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 119: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/119.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 anusual way
![Page 120: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/120.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 121: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/121.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 122: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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
));
What does this do?
Add a simple comment://Strips special chars and camel cases to onXxx
Source: Symfony2
![Page 123: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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?
Add a simple comment://Strips special chars and camel cases to onXxx
Source: Symfony2
Don’t explain bad code, fix it!
![Page 124: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/124.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 125: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/125.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 126: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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);
mark todo items so the changes don’t get lost
A note on cost of running function
![Page 127: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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
A note on cost of running function
Do a mind dump, then clean it up.
![Page 128: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/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
Do a mind dump, then clean it up.
Generate API docswith phpDocumentor
![Page 129: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/129.jpg)
Key Benefits
• Automatic API documentation
• Transmission of “line of thought”
• Avoids confusion
![Page 130: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/130.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 accessors (getter/setter)
• #10 - Document your code!
![Page 131: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/131.jpg)
Questions?
http://slides.doh.ms
http://doh.ms
@rdohms
http://fixthatcode.com
http://joind.in/7404
![Page 132: Your code sucks, let's fix it](https://reader030.vdocuments.mx/reader030/viewer/2022013101/554f3c5fb4c905cd048b514a/html5/thumbnails/132.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