6. Clean code
Code style: let’s find fails
class FeedParser
{
(...)
private function parse_elem($elem)
{
$name = $this->getElementErrorHandler($elem, "title");
$url = $this->getElementErrorHandler($elem, "link");
//Product not active
return new Product($name, $url, $elem->id, false);
}
private function getElementErrorHandler($elem, $attr) {
$item = (string)$elem->$attr;
if ($item == "") {
throw new Exception("incorrect item");
}
return $item;
}
}
7. ● A repository with n developers should look homogeneous
● Code style (CS) tools
○ Verification
○ Automatic fixer
Clean code
Code style
8. ● Impatient duplication
○ copy it and make a couple of changes
● Inter-developer duplication
○ Make it easy to use/reuse
Clean code
Don’t Repeat Yourself (DRY)
9. ● Imposed duplication (unavoidable case)
○ Multiple representations of information
● Use a copy-paste detector
Clean code
Don’t Repeat Yourself (DRY)
10. ● The less, the better!
● Usually comments are not needed
○ Redundant
○ Outdated
● Or even worse..
○ Commented out code
Clean code
Comments
11. Clean code
Any useful comment here?
class FeedParser
{
public function doParse()
{
$products = array(); //array of products to return
$xml = simplexml_load_file("/tmp/products.xml"); //read xml file
if ($xml === FALSE) {
throw new Exception("feed not found"); //file not found
} else {
if (count($xml) === 0) {
throw new Exception("empty feed");
} else {
foreach($xml as $elem) {
$prod = $this->parse_elem($elem);
array_push($products, $prod); //add Product object
}
}
}
return $products;
}
(...)
12. ● Use the code itself to explain the logic
○ Use a variable instead of a comment
○ Use intention revealing names in vars and functions
Clean code
Comments
13. Clean code
Use a variable instead of a comment
private function parse_elem($elem)
{
$name = $this->getElementErrorHandler($elem, "title");
$url = $this->getElementErrorHandler($elem, "link");
//Product not active
return new Product($name, $url, $elem->id, false);
}
14. Clean code
Use a variable instead of a comment
private function parse_elem($elem)
{
$name = $this->getElementErrorHandler($elem, "title");
$url = $this->getElementErrorHandler($elem, "link");
//Product not active
return new Product($name, $url, $elem->id, false);
}
--------
private function parse_elem($elem)
{
$name = $this->getElementErrorHandler($elem, "title");
$url = $this->getElementErrorHandler($elem, "link");
$isActive = false;
return new Product($name, $url, $elem->id, $isActive);
}
15. ● Intention-revealing names
○ int days; //days since last purchase
○ int daysSinceLastPurchase;
● Shared vocabulary with the team
● Precise vocabulary
○ No “manageUser(...)” but “updateUserContactInfo(...)”
○ No “killUserInDb()” but “deleteUserFromDb()”
Clean code
Naming
16. Clean code
Looking for meaningful names
private function parse_elem($elem)
{
$name = $this->getElementErrorHandler($elem, "title");
$url = $this->getElementErrorHandler($elem, "link");
$isActive = false;
return new Product($name, $url, $elem->id, $isActive);
}
18. ● Small! Really small!
○ 2, 3, 4 lines
● Do ONLY one thing!
Clean code
Easier functions
19. Clean code
Does doParse() do only one thing?
public function doParse()
{
$products = array();
$xml = simplexml_load_file("/tmp/products.xml");
if ($xml === FALSE) {
throw new Exception("feed not found");
} else {
if (count($xml) === 0) {
throw new Exception("empty feed");
} else {
foreach($xml as $elem) {
$prod = $this->createProductFromXmlData($elem);
array_push($products, $prod);
}
}
}
return $products;
}
20. Clean code
public function doParse()
{
$xmlData = $this->readXML("/tmp/products.xml");
$products = $this->extractProductsFromXmlData($xmlData);
return $products;
}
private function readXML($filename)
{
$xmlData = simplexml_load_file($filename);
if ($xmlData === FALSE) {
throw new Exception("feed not found");
} elseif (count($xml) === 0) {
throw new Exception("empty feed");
}
return $xmlData;
}
private function extractProductsFromXmlData($xmlData)
{
$products = array();
foreach($xmlData as $productXml) {
$prod = $this->createProductFromXmlData($productXml);
array_push($products, $prod);
}
return $products;
}
21. ● Keep same level of abstraction
○ From top to bottom, outside in
● Arguments
○ Avoid many arguments: use objects or DTOs instead
○ Caution with flags (bool arguments)
Clean code
Easier functions
22. Clean code
Avoiding flags, and keeping same level
private function createProductFromXmlData($productXmlData)
{
$name = $this->getAttribute($productXmlData, "title");
$url = $this->getAttribute($productXmlData, "link");
$isActive = false;
return new Product($name, $url, $productXmlData->id, $isActive);
}
23. Clean code
Avoiding flags, and keeping same level
private function createProductFromXmlData($productXmlData)
{
$name = $this->getAttribute($productXmlData, "title");
$url = $this->getAttribute($productXmlData, "link");
$isActive = false;
return new Product($name, $url, $productXmlData->id, $isActive);
}
private function createProductFromXmlData($productXmlData)
{
$name = $this->getAttribute($productXmlData, "title");
$url = $this->getAttribute($productXmlData, "link");
$id = $this->getAttribute($productXmlData, "id");
return new Product::createInactive($name, $url, $id);
}