A very difficult name which translates to: “object exercises”.
In total there are 9 different exercises which all focus on writing code that is maintainable, readable, testable and comprehensible.
Let’s go over these “exercises”.
This “exercise” states that a method should have a maximum of 1 indentation.
Which means that you are not allowed to nest control structures.
For example:
<?php
namespace App\NotSoCleanCode;
class SomeClass
{
public function __construct($boolean, $array)
{
if ($boolean) {
foreach ($array as $item) {
// do something with item
}
}
}
}
The code above is not allowed according to this rule, the constructor is indented twice. Once for the if structure and once for the foreach structure.
To solve this, we can refactor the class to look like:
<?php
namespace App\CleanCode;
class SomeClass
{
public function __construct($boolean, Array $array)
{
if ($boolean) {
$this->processArray($array);
}
}
private function processArray(Array $array)
{
foreach ($array as $item) {
// do something with item
}
}
}
This exercise states that you should write your code without using the else keyword. It is pretty much always possible to do this, although it usually requires you to think about what exactly you want to do.
For example:
<?php
namespace App\NotSoCleanCode;
class SomeClass
{
public function selectValue($value)
{
if ($value === ‘select’) {
$result = ‘Result123’;
} elseif ($value === ‘update’) {
$result = ‘NoResult’;
} else {
$result = ‘’;
}
return $result;
}
}
The example above can easily be refactored to:
<?php
namespace App\CleanCode;
class SomeClass
{
public function selectValue($value)
{
$result = ‘’;
if ($value === ‘select’) {
$result = ‘Result123’;
} elseif ($value === ‘update’) {
$result = ‘NoResult’;
}
return $result;
}
}
It can also be refactored to use early returns:
<?php
namespace App\CleanCode;
class SomeClass
{
public function selectValue($value)
{
if ($value === ‘select’) {
return ‘Result123’;
} elseif ($value === ‘update) {
return ‘NoResult’;
}
return ‘’;
}
}
Of course there might be more ways to avoid using an else condition.
This exercise states that we should wrap primitive types (int, string, etc..) in an object.
For instance we might use a string variable to represent a message or a float to represent an amount of money.
In these cases we should use objects like Message and Money.
This exercise boils down to the rule that when a class contains a collection it should not have any other member variables.
What this means is that you should wrap collections of a certain type in its own class. That way the methods needed to manipulate the collection data can be placed in the new collection class.
While the name of this exercise is “One Dot Per Line”, for PHP it should actually be “One Arrow Per Line”.
It means that you should avoid chaining methods.
There are exceptions however. Especially when the “Method Chaining Pattern” is implemented it would be strange to try and avoid it.
An example of when you should avoid chaining methods is when you call a method on an object which returns a different object and you want to call a method on the last one.
This violates the “Law of Demeter” which states “only talk to your immediate friends, and don’t talk to strangers.”.
For example:
<?php
namespace App\NotSoCleanCode;
class Plant
{
public function getBranch()
{
return new Branch();
}
<?php
namespace App\NotSoCleanCode;
class Branch
{
public function getLeave()
{
return new Leave();
}
}
<?php
namespace App\NotSoCleanCode;
class Leave
{
public function getColor()
{
return ‘Green’;
}
}
Given the classes above it would be possible to get the color of the leave of a plant in the following way:
<?php
$plant = new Plant;
// incorrect: it uses 3 arrows
$color = $plant->getBranch()->getLeave()->getColor();
The exercise states that you should have only one arrow per line, so instead of the code above you should get the leave color like this:
<?php
$plant = new Plant;
$branch = $plant->getBranch();
$leave = $branch->getLeave();
$color = $leave->getColor();
This is a simple one. All it means is that you should not try and shorten names of classes, methods, parameters and variables.
So just name your variable $category
when it is a category.
Please do not name the variable $cate
it is unclear and unnecessary (most IDEs support auto completion anyway)!
Keep all classes under 50 lines and all packages under 10 files. 50 Lines is not a lot, so it’s recommended to try to keep them at least under 150 lines.
This exercise states that no class should have more than two properties. This is a very hard one to actually implement, but there are definitely cases in which that would work.
The following diagram shows a good example:
This does not mean that you should never have any accessor (get…) and mutator methods (set…). Surely there are cases that require you to have accessors and mutators.
However you should never use an accessor to get the state of an object to make a decision on how to change the state of the object.
In that case you can make the decision inside the object.
For example:
<?php
namespace App\NotSoCleanCode;
class FruitBasket
{
private $fruit;
public function getFruit()
{
return $fruit;
}
public function setFruit($fruit)
{
$this->fruit = $fruit;
}
}
Giving the class above you should never:
<?php
$fruitBasket = new FruitBasket;
$fruitBasket->setFruit($fruitBasket->getFruit() + [‘banana’]);
Instead it would be much better to implement the class like:
<?php
namespace App\CleanCode;
class FruitBasket
{
private $fruit;
public function getFruit()
{
return $fruit;
}
public function addFruit(array $fruit)
{
$this->fruit + $fruit;
}
}