Vinícius B. Alonso
vba321@hotmail.com
"Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions and straightforward lines of control."
Grady Booch, autor do livro Object Oriented Analysis and Design with Applications
"You know you are working on clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem."
Ward Cunningham, co-inventor do eXtreme programming
Livro Clean Code
Robert C. Martin
"Uncle Bob"
$d = 10;
$cust_n = "Juca";
$brt = "1990-03-30 18:00:38";
Nomes abreviados e difíceis de pronunciar!
$workedDays = 10;
$customerName = "Juca";
$birthday = "1990-03-30 18:00:38";
function calc(x, y) {
return x / y;
}
O nome da função não expressa sua intenção!
function division(dividend, divider) {
return dividend / divider;
}
class ProgrammerFL {
private $h;
private $v;
public function __construct($h, $v) {
$this->h = $h;
$this->v = $v;
}
public function pay() {
return $this->h * $this->v;
}
}
A classe não expressa sua intenção e tem muita abreviação!
class ProgrammerFreeLancerPayment {
private $hoursWorked;
private $valuePerHour;
public function __construct($hoursWorked, $valuePerHour)
{
$this->hoursWorked = $hoursWorked;
$this->valuePerHour = $valuePerHour;
}
public function calculateTotalValueOfWork()
{
return $this->hoursWorked * $this->valuePerHour;
}
}
À seguir um exemplo da fórmula Bhaskara
function quadratic_equation($a,$b,$c) {
if($a === 0) {
echo "Para o cálculo de uma equação quadrática,
\"a\" não pode ser igual a zero.";
} else {
$delta = pow($b,2) - ((4*$a)*$c);
if($delta === 0) {
$raiz = -($b)/(2*$a);
echo "Delta igual a zero. A equação tem 1 raiz.
<br>Raiz da equação: ".$raiz;
} elseif($delta > 0) {
$x1 = (-$b + sqrt($delta))/(2*$a);
$x2 = (-$b - sqrt($delta))/(2*$a);
$raiz = array($x1, $x2);
echo "Delta maior que zero. A equação tem 2 raizes.
<br>Raizes da equação: " .$raiz[0]. "," .$raiz[1];
} else {
echo "Delta menor que zero: equação sem solução.";
}
}
}
Fonte: http://codetalkbr.blogspot.com.br/2014/10/formula-de-bhaskara-em-php.html
function calculate_bhaskara($a,$b,$c) {
if(not_is_zero($a)) {
$delta = calculate_delta($a, $b, $c);
return calculate_root($a, $b, $delta);
}
}
function not_is_zero($param) {
return $param !== 0;
}
function calculate_delta($a, $b, $c) {
return pow($b,2) - ((4*$a)*$c);
}
function calculate_root($a, $b, $delta) {
if(is_zero($delta))
return calculate_simple_root($b, $a);
if(is_greater_than_zero($delta))
return calculate_double_root($b, $a, $delta);
return null;
}
Continuação: https://gist.github.com/viniciusalonso/dceaace37d95481bcdbb87f75f283ffa#file-clean_code_refactored_function-php
# Primeira opção
if ($delta === 0)
return -($b)/(2*$a);
# Segunda opção
if(is_zero($a))
return calculate_simple_root($b, $a);
Use suas funções para tentar formar uma narrativa
function checkPassword($email, $password) {
$credentials = ['email' => $email,
'password' => $password];
$userExists = User::check($credentials);
if ($userExists) {
session_start();
}
return $userExists;
}
O que há de errado com esse código ?
function checkPassword($email, $password) {
$credentials = ['email' => $email,
'password' => $password];
$userExists = User::check($credentials);
if ($userExists) {
session_start();
}
return $userExists;
}
Cuidado com funções que fazem mais do que se propõe a fazer!
O código deve ser auto explicativo
# Não pode ser vazio e nem nulo
if (!is_empty($name) && !is_null($name))
function notIsEmptyOrNull($param) {
return !is_empty($name) && !is_null($name);
}
if (notIsEmptyOrNull($name))
Lembre-se, não deixe trechos de código comentados em sua aplicação
O Git nos permite consultar versões antigas do sistema
class UserRepository extends BaseRepository
{
public function getUsersWithAdresses(){}
public function countCollaborators(){}
public function getCollaborators(){}
public function update($id, $data){}
public function delete($id){}
public function paginate($value, $field = '',
$order = '', $keyword = null){}
public function create($data){}
public function findByAdmin(){}
public function filterManagers(){}
}
Problema também conhecido como Bad Smell Code God Class
class UserRepository extends BaseRepository
{
public function getUsersWithAdresses(){}
public function countCollaborators(){}
public function getCollaborators(){}
public function update($id, $data){}
public function delete($id){}
public function create($data){}
public function paginate($value, $field = '',
$order = '', $keyword = null){}
public function findByAdmin(){}
public function filterManagers(){}
}
Inicialmente, podemos dividir em 5 responsabilidades distintas
1
2
3
4
5
trait UserRelationships {
public function getUsersWithAdresses(){}
}
trait UserCollaborators {
public function countCollaborators(){}
public function getCollaborators(){}
}
trait UserCRUDOperations {
public function update($id, $data){}
public function delete($id){}
public function create($data){}
}
trait UserPagination {
public function paginate($field = '',
$order = '',
$keyword = null){}
}
trait UserHighLevel {
public function findByAdmin(){}
public function filterManagers(){}
}
class UserRepository extends BaseRepository {
use UserRelationships,
UserCollaborators,
UserCRUDOperations,
UserPagination,
UserHighLevel;
}
Cada trait faz uma coisa e a classe ficou mais simples
$hoursWorked = 30;
$valuePerHour = 50;
$programmerFreeLancer =
new ProgrammerFreeLancerPayment($hoursWorked, $valuePerHour);
$programmerFreeLancer->calculateTotalValueOfWork();
Cuidado para não deixar a linha muito grande
# ...
public function buildJson()
{
$this->getUsersData();
return $this->build();
}
private function getUsersData() {
# ...
}
private function build() {
# ...
}
O métodos públicos devem ser quebrados em métodos privados