SlideShare uma empresa Scribd logo
Clean Code e
Object Calisthenics
Aplicados no PHP
<?php
echo ‘Rafael Neris’;
Apaixonado por refactoring
Total Express
Github: @rafaelneris
Linkedin: https://www.linkedin.com/in/rafael-neris-
548402110/
2
Motivação:
▸ Legibilidade
▸ Manutenabilidade
▸ Reusabilidade
▸ Testabilidade
3
Como medir a
qualidade de
seu código?
Método infálivel!
Clean Code
6
Singleton
Tight Coupling
Untestability
Premature Optimization
Indescriptive Naming
Duplication
S T U P I D
7
Single Responsibility
Open/Closed Principle
Liskov Substitution
Interface Segregation
Dependency Inversion
S O L I D
8
Single Responsibility Principle
“Uma classe deve ter um, e somente um, motivo para
ser modificada”
9
class Report {
public function getTitle() {
return 'Report Title';
}
public function getDate() {
return '2018-01-22';
}
pulic function getContents() {
return [ 'title' => $this->getTitle(), 'date' => $this->getDate(), ];
}
public function formatJson() {
return json_encode($this->getContents());
}
}
class Report {
public function getTitle() {
return 'Report Title';
}
public function getDate() {
return '2018-01-22';
}
public function getContents() {
return [ 'title' => $this->getTitle(), 'date' => $this->getDate(), ];
}
}
class JsonReportFormatter {
public function format(Report $report) {
return json_encode($report->getContents());
}
Open Closed Principle
“Entidades de Software devem estar aberta para
expansão, mas fechada para modificação.”
12
class Logger {
public function writeTxt($message)
{
//lógica
}
}
class Logger {
public function writeTxt($message)
{
//lógica
}
public function writeCsv($message)
{
//lógica
}
}
class Logger {
private $writer;
public function __construct(Writer $writer) {
$this->writer = $writer;
}
public function write($message) {
$this->writer->write($message);
}
}
interface Writer {
public function write($message);
}
class Txt implements Writer {
public function write($message) { //lógica }
}
class Csv implements Writer {
public function write($message) { //lógica }
}
Liskov Substitution
16
“
“Se q(x) é uma propriedade
demonstrável dos objetos x de tipo
T. Então q(y) deve ser verdadeiro
para objetos y de tipo S onde S é um
subtipo de T.”
Barbara Liskov
17
“
“Funções que usam ponteiros ou
referências a classes-base devem ser
capazes de usar objetos de classes
derivadas sem o saber.”
Robert C. Martin (Uncle Bob)
18
“
19
class T { … }
class S extends T { … }
$o1 = new T();
$o2 = new S();
function write(T $message) {
return “Ok”;
}
write($o1); // “Ok”
write($o2); // “Ok”
Clean Code
Vamos nos aprofundar mais!
21
Alguns conceitos importantes
▸ Nomes significativos
▸ Funções pequenas
▸ Comentários
22
Nomes significativos
Use nomes que revelam seu propósito
23
class Diretorio {
private $qtd;
public function retornarQtd() {
return $qtd;
}
}
class Diretorio {
private $quantidadeArquivos;
public function getQuantidadeArquivos() {
return $this->quantidadeArquivos;
}
}
Nomes significativos
Nomes devem ser distintos
26
class Aluno {
private $data1; // Data de Nascimento
private $data2; // Data de Matricula
}
class Aluno {
private $nascimentoData;
private $matriculaData;
}
Nomes significativos
Evite mapeamento mental!
29
class File {
private $f;
public function write(array $k) {
foreach ($k as $j) {
fwrite($f, $j);
}
}
}
class File {
private $fileResource;
public function write(array $content) {
foreach ($content as $lineOfContent){
fwrite(
$fileResource,
$lineOfContent
);
}
}
}
Nomes de classes e
Objetos
▸ Devem ter nomes com substantivos
▸ Não deve ser um verbo!
▸ Devem ser buscaveis
32
Nomes de métodos
▸ Devem possuir verbos
▸ Devem ser buscaveis.
33
Evite números mágicos
34
if ($saqueLimite == 1000) {
// Do Something
}
const SAQUE_TETO = 1000;
if ($saqueLimite == self::SAQUE_TETO) {
// Do Something
}
Métodos pequenos
▸ Devem ser pequenos e concisos
▸ “Fazer UMA e APENAS UMA coisa. Eles devem
fazer isso bem e apenas isso.”
▸ “Menor do que pequeno”
37
Comentários
38
Comentários no código é
bom?
39
Não!!!!!!!!
40
Comentários
▸ Envelhecem e mentem
▸ Não comentem código. Deixe que o GIT resolva para você!
▸ O único comentário bom é aquele que você não precisa escrever.
41
// Verifica se o funcionário tem direito a todos
benefícios
if (
($employee->getFlag() && self::HOURLY_FLAG)
&& ($employee->getAge() > 65)
)
if ($employee->isElegibleForFullBenefits())
//$token = token($this->email);
//if (self::where('confirmation_token', $token)->first()) {
// return $this->getUniqueConfirmationToken();
//}
$row = Testimonial::find($id);
$row->list_order = $listOrder;
$row->save();
return $row;
Casos de comentários:
▸ Comentários informativos
▸ Explicar-se no código
▸ Comentários TODO
▸ Comentários Ruidosos
▸ Comentários redundantes
45
Outros conceitos:
▸ Formatação
▸ Objetos e Estrutura de dados
▸ Tratamento de erros
▸ Limites
▸ Testes unitários
▸ Classes
▸ Sistemas
▸ Concorrência
▸ Refinamento sucessivo
46
Outros conceitos:
▸ Formatação
▸ Objetos e Estrutura de dados
▸ Tratamento de erros
▸ Limites
▸ Testes unitários
▸ Classes
▸ Sistemas
▸ Concorrência
▸ Refinamento sucessivo
47
Object Calisthenics
9 regras para manter seu código limpo!
48
CONSELHOS
Termo grego, significa
“Exercício”
Criado por Jeff
Bay
Evitar o código Haddouken
Somente um nível de
indentação por método
Use Extract Method Pattern
51
public function getPromoCode(string $promoName)
{
if ($this->promoCode) {
if (false === $this->promoCodeExpired()) {
if ($this->promoName == $promoname) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
public function getPromoCode(string $promoName)
{
// 1
if ($this->promoCode) {
if (false === $this->promoCodeExpired()) {
if ($this->promoName == $promoname) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
public function getPromoCode(string $promoName)
{
// 1
if ($this->promoCode) {
// 2
if (false === $this->promoCodeExpired()) {
if ($this->promoName == $promoname) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
public function getPromoCode(string $promoName)
{
// 1
if ($this->promoCode) {
// 2
if (false === $this->promoCodeExpired()) {
// 3
if ($this->promoName == $promoname) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
public function getPromoCode(string $promoName)
{
// 1
if ($this->promoCode) {
// 2
if (false === $this->promoCodeExpired()) {
// 3
if ($this->promoName == $promoname) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
public function getPromoCode(string $promoName)
{
// 1
if ($this->promoCode) {
// 2
if (false === $this->promoCodeExpired()) {
$this->getPromoExists($promoName);
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
protected function getPromoExists(string $promoName)
{
if ($this->promoName == $promoName) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
}
public function getPromoCode(string $promoName)
{
// 1
if ($this->promoCode) {
// 2
if (false === $this->promoCodeExpired()) {
$this->getPromoExists($promoName);
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
protected function getPromoExists(string $promoName)
{
if ($this->promoName == $promoName) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
}
public function getPromoCode(string $promoName) {
// 1
if ($this->promoCode) {
$this->getValidPromoCode($promoName)
} else {
throw new Exception('Cliente sem código de promoção');
}
}
protected function getValidPromoCode(string $promoName) {
if (false === $this->promoCodeExpired()) {
return $this->getPromoExists($promoName);
} else {
throw new Exception('Promoção Expirada');
}
}
protected function getPromoExists(string $promoName) {
if ($this->promoName == $promoName) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
}
Benefícios:
▸ S de Single Responsibility Principle
▸ Favorece reusabilidade
60
Não use a palavra “else”
Use early returns!
61
public function getPromoCode(string $promoName) {
if ($this->promoCode) {
$this->getValidPromoCode($promoName)
} else {
throw new Exception('Cliente sem código de promoção');
}
}
protected function getValidPromoCode(string $promoName) {
if (false === $this->promoCodeExpired()) {
return $this->getPromoExists($promoName);
} else {
throw new Exception('Promoção Expirada');
}
}
protected function getPromoExists(string $promoName) {
if ($this->promoName == $promoName) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
}
public function getPromoCode(string $promoName) {
if (!$this->promoCode) {
throw new Exception('Cliente sem código de promoção');
}
return $this->getValidPromoCode($promoName);
}
protected function getValidPromoCode(string $promoName) {
if ($this->promoCodeExpired()) {
throw new Exception('Promoção Expirada');
}
return $this->getPromoExists($promoName);
}
protected function getPromoExists(string $promoName) {
if ($this->promoName != $promoName) {
throw new Exception('Promoção não existe mais');
}
return $this->promoCode;
}
public function getPromoCode(string $promoName)
{
if ($this->promoCode) {
if (false === $this->promoCodeExpired()) {
if ($this->promoName == $promoname) {
return $this->promoCode;
} else {
throw new Exception('Promoção não existe mais');
}
} else {
throw new Exception('Promoção Expirada');
}
} else {
throw new Exception('Cliente sem código de promoção');
}
}
public function getPromoCode(string $promoName) {
if (!$this->promoCode) {
throw new Exception('Cliente sem código de promoção');
}
return $this->getValidPromoCode($promoName);
}
protected function getValidPromoCode(string $promoName) {
if ($this->promoCodeExpired()) {
throw new Exception('Promoção Expirada');
}
return $this->getPromoExists($promoName);
}
protected function getPromoExists(string $promoName) {
if ($this->promoName != $promoName) {
throw new Exception('Promoção não existe mais');
}
return $this->promoCode;
}
Benefícios:
▸ Evita duplicidade de códigos
▸ Aumenta legibilidade
▸ Reduz a complexidade ciclomatica
66
Encapsule TODOS os
tipos primitivos e strings
TODOS que possuem comportamento.
67
class Customer
{
protected $name;
protected $birthday;
public function __construct(string $name, string $birthday)
{
// Validar aqui???
$this->name = $name;
$this->birthday = $birthday;
}
}
// Programador que conhece a classe
$customer = new Customer('John Doe', '1983-02-10');
// Programador que não conhece a classe
// pode gerar um 0000-00-00 no Database
$customer = new Customer('John Doe', '10/02/1983');
class Customer
{
protected $name;
protected $birthday;
public function __construct(
CustomerName $name,
CustomerBirthday $birthday
){
$this->name = $name;
$this->birthday = $birthday;
}
}
// Programador que conhece a classe
$customer = new Customer(
new CustomerName('John Doe'),
new CustomerBirthday('1983-02-10')
);
// A data será formatada internamente
$customer = new Customer(
new CustomerName('John Doe'),
new CustomerBirthday('10/02/1983')
);
Benefícios:
▸ Type hinting
▸ Encapsulamento do código
▸ Auxilia na prevenção de código duplicado
▸ Implementação de Values Object do DDD
72
Envolva suas collections
em Classes
73
class Bucket {
protected $products = [];
// many other things...
}
class Bucket {
/** @var ProductCollection */
protected $products;
// many other things...
}
class ProductCollection implements Iterator { // ... }
Benefícios:
▸ Single Responsible Principle
▸ Usar classes SPL
▸ Facilita agrupar em coleções sem se preocupar com o comportamento
delas
▸ Filtragem, ordenação, mapeamento são exemplos de métodos.
76
Um único operador de
método por linha
Com excessão de interfaces fluentes.
77
$customer->manager->getById(55988)->getPurchase(18376)->getProducts()->filterById(234);
$customer->manager->getById(55988)->getPurchase(18376)->getProducts()->filterById(234);
Propriedades são dificeís de
mockar
$customer->manager->getById(55988)->getPurchase(18376)->getProducts()->filterById(234);
Propriedades são dificeís de
mockar
E se retornar null?
Benefícios:
▸ Lei de Demeter
▸ Legibilidade
▸ Aumenta testabilidade (Mais fácil para mockar)
▸ Facilidade para debugar
81
Lei de Demeter
82
Não quebre a lei de Demeter
83
Não abrevie!
Com excessão de interfaces fluentes.
84
class File {
private $f;
public function write(array $k) {
foreach ($k as $j) {
fwrite($f, $j);
}
}
}
class File {
private $fileResource;
public function write(array $content) {
foreach ($content as $lineOfContent){
fwrite(
$fileResource,
$lineOfContent
);
}
}
}
Benefícios:
▸ Legibilidade
▸ Manutenibilidade
87
Mantenha suas classes
pequenas
▸ Métodos devem possuir até 20 linhas
▸ Não crie namespaces com mais de 15 arquivos
▸ Não crie classe com mais de 200 linhas
88
Benefícios:
▸ Legibilidade
▸ Manutenibilidade
89
Não tenha classes com mais
de duas variáveis de instância
A comunidade PHP adota à CINCO variáveis de
instância por adaptabilidade da linguagem.
90
Benefícios:
▸ Alta coesão
▸ Baixo acoplamento
▸ Encapsulamento
▸ Lista de dependências mais curtas
▸ Manutenabilidade
91
Não use GETTERS/SETTERS
▸ Regra parcialmente relacionada ao DDD
▸ Não aplicável ao PHP devido a natureza da linguagem
92
class ImmutableBankAccount
{
public $currency = 'USD';
private $amount;
public function setAmount(int $amount)
{
$this->amount = $amount;
}
}
class ImmutableBankAccount
{
private $currency = 'USD';
private $amount;
public function withdrawAmount(int $withdrawnAmount)
{
$this->amount -= $withdrawAmount;
}
}
Benefícios:
▸ Open/Close Principle
95
Valide Object Calisthenics no
seu código
https://github.com/object-calisthenics/phpcs-calisthenics-rules
96
97
“Qualquer um pode escrever um código que o
computador entenda.
Bons programadores escrevem códigos que os
humanos entendem”
Perguntas??
▸ @rafaelneris
▸ rafael.neris@totalexpress.com.br

Mais conteúdo relacionado

Mais procurados

Adianti Framework PHPConf 2013
Adianti Framework PHPConf 2013Adianti Framework PHPConf 2013
Adianti Framework PHPConf 2013Pablo Dall'Oglio
 
PHP robusto com Zend Framework
PHP robusto com Zend FrameworkPHP robusto com Zend Framework
PHP robusto com Zend Framework
Jaime Neto
 
Design Patterns com PHP
Design Patterns com PHPDesign Patterns com PHP
Design Patterns com PHP
Pablo Dall'Oglio
 
Vraptor
VraptorVraptor
Vraptor
clauvane1708
 
PHP: Programando com orientação a Objetos
PHP: Programando com orientação a ObjetosPHP: Programando com orientação a Objetos
PHP: Programando com orientação a ObjetosPablo Dall'Oglio
 
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Pablo Dall'Oglio
 
Hiearquia Window
Hiearquia WindowHiearquia Window
Hiearquia Window
Daniel Arndt Alves
 
Codifique melhor
Codifique melhorCodifique melhor
Codifique melhor
Marcos Sousa
 
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven DesignTDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
Alexandre Rodrigues
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um Framework
Pablo Dall'Oglio
 
Design Patterns na Programação de Jogo
Design Patterns na Programação de JogoDesign Patterns na Programação de Jogo
Design Patterns na Programação de Jogo
Bruno Cicanci
 
Acesso a banco de dados com JDBC
Acesso a banco de dados com JDBCAcesso a banco de dados com JDBC
Acesso a banco de dados com JDBCEduardo Mendes
 
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworksDo Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Pablo Dall'Oglio
 
JAVA - ENCAPSULAMENTO
JAVA - ENCAPSULAMENTOJAVA - ENCAPSULAMENTO
JAVA - ENCAPSULAMENTO
André Victor
 
Java script - document object model
Java script - document object modelJava script - document object model
Java script - document object modelGabriel Coelho
 
Criando aplicações com PHP-GTK
Criando aplicações com PHP-GTKCriando aplicações com PHP-GTK
Criando aplicações com PHP-GTKPablo Dall'Oglio
 

Mais procurados (20)

Trabalhando com as views do Web2Py
Trabalhando com as views do Web2PyTrabalhando com as views do Web2Py
Trabalhando com as views do Web2Py
 
Adianti Framework PHPConf 2013
Adianti Framework PHPConf 2013Adianti Framework PHPConf 2013
Adianti Framework PHPConf 2013
 
PHP robusto com Zend Framework
PHP robusto com Zend FrameworkPHP robusto com Zend Framework
PHP robusto com Zend Framework
 
Design Patterns com PHP
Design Patterns com PHPDesign Patterns com PHP
Design Patterns com PHP
 
Vraptor
VraptorVraptor
Vraptor
 
PHP: Programando com orientação a Objetos
PHP: Programando com orientação a ObjetosPHP: Programando com orientação a Objetos
PHP: Programando com orientação a Objetos
 
Poo
PooPoo
Poo
 
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
 
Hiearquia Window
Hiearquia WindowHiearquia Window
Hiearquia Window
 
Codifique melhor
Codifique melhorCodifique melhor
Codifique melhor
 
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven DesignTDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um Framework
 
POO - 09 - Entradas e Saídas em Java
POO - 09 - Entradas e Saídas em JavaPOO - 09 - Entradas e Saídas em Java
POO - 09 - Entradas e Saídas em Java
 
POO - 06 - Encapsulamento
POO - 06 - EncapsulamentoPOO - 06 - Encapsulamento
POO - 06 - Encapsulamento
 
Design Patterns na Programação de Jogo
Design Patterns na Programação de JogoDesign Patterns na Programação de Jogo
Design Patterns na Programação de Jogo
 
Acesso a banco de dados com JDBC
Acesso a banco de dados com JDBCAcesso a banco de dados com JDBC
Acesso a banco de dados com JDBC
 
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworksDo Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
 
JAVA - ENCAPSULAMENTO
JAVA - ENCAPSULAMENTOJAVA - ENCAPSULAMENTO
JAVA - ENCAPSULAMENTO
 
Java script - document object model
Java script - document object modelJava script - document object model
Java script - document object model
 
Criando aplicações com PHP-GTK
Criando aplicações com PHP-GTKCriando aplicações com PHP-GTK
Criando aplicações com PHP-GTK
 

Semelhante a Clean Code e Object Calisthenics - Aplicados no PHP

[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
Jessica Zanelato Soares
 
5 Maneiras de melhorar seu código PHP
5 Maneiras de melhorar seu código PHP5 Maneiras de melhorar seu código PHP
5 Maneiras de melhorar seu código PHP
Augusto das Neves
 
Programação web ii aulas 06 e 07
Programação web ii   aulas 06 e 07Programação web ii   aulas 06 e 07
Programação web ii aulas 06 e 07
Yuri Bispo
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6
Renato Haddad
 
Introducao a orientacao a objetos com PHP
Introducao a orientacao a objetos com PHPIntroducao a orientacao a objetos com PHP
Introducao a orientacao a objetos com PHP
guilhermemar
 
Orientação a Objetos em PHP
Orientação a Objetos em PHPOrientação a Objetos em PHP
Orientação a Objetos em PHP
zehzinho
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
Michael Castillo Granados
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que pareceImpacta Eventos
 
DevTalk Zoox 04/2016
DevTalk Zoox 04/2016DevTalk Zoox 04/2016
DevTalk Zoox 04/2016
Leandro Silva
 
Robustez de Software - Como ouvir menos reclamações dos seus chefes
Robustez de Software - Como ouvir menos reclamações dos seus chefesRobustez de Software - Como ouvir menos reclamações dos seus chefes
Robustez de Software - Como ouvir menos reclamações dos seus chefes
David Robert Camargo de Campos
 
Desenvolvimento ágil com Kohana framework
Desenvolvimento ágil com Kohana frameworkDesenvolvimento ágil com Kohana framework
Desenvolvimento ágil com Kohana framework
Marcelo Rodrigo
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnit
Diego Tremper
 
Rafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em açãoRafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014
Michael Castillo Granados
 
Object Calisthenics: relaxe e escreva códigos simples
Object Calisthenics: relaxe e escreva códigos simplesObject Calisthenics: relaxe e escreva códigos simples
Object Calisthenics: relaxe e escreva códigos simplesOtávio Calaça Xavier
 
Perl Moderno, dia5
Perl Moderno, dia5Perl Moderno, dia5
Perl Moderno, dia5
garux
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dados
Henrique Fernandes
 
Clean code
Clean codeClean code
Clean code
Marcos Brizeno
 

Semelhante a Clean Code e Object Calisthenics - Aplicados no PHP (20)

[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
 
Aula5
Aula5Aula5
Aula5
 
Prog web 06-php-oo
Prog web 06-php-ooProg web 06-php-oo
Prog web 06-php-oo
 
5 Maneiras de melhorar seu código PHP
5 Maneiras de melhorar seu código PHP5 Maneiras de melhorar seu código PHP
5 Maneiras de melhorar seu código PHP
 
Programação web ii aulas 06 e 07
Programação web ii   aulas 06 e 07Programação web ii   aulas 06 e 07
Programação web ii aulas 06 e 07
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6
 
Introducao a orientacao a objetos com PHP
Introducao a orientacao a objetos com PHPIntroducao a orientacao a objetos com PHP
Introducao a orientacao a objetos com PHP
 
Orientação a Objetos em PHP
Orientação a Objetos em PHPOrientação a Objetos em PHP
Orientação a Objetos em PHP
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
 
DevTalk Zoox 04/2016
DevTalk Zoox 04/2016DevTalk Zoox 04/2016
DevTalk Zoox 04/2016
 
Robustez de Software - Como ouvir menos reclamações dos seus chefes
Robustez de Software - Como ouvir menos reclamações dos seus chefesRobustez de Software - Como ouvir menos reclamações dos seus chefes
Robustez de Software - Como ouvir menos reclamações dos seus chefes
 
Desenvolvimento ágil com Kohana framework
Desenvolvimento ágil com Kohana frameworkDesenvolvimento ágil com Kohana framework
Desenvolvimento ágil com Kohana framework
 
Qualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnitQualidade no desenvolvimento de software com PHPUnit
Qualidade no desenvolvimento de software com PHPUnit
 
Rafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em açãoRafael Garcia - Yii Framework, principais características e em ação
Rafael Garcia - Yii Framework, principais características e em ação
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014
 
Object Calisthenics: relaxe e escreva códigos simples
Object Calisthenics: relaxe e escreva códigos simplesObject Calisthenics: relaxe e escreva códigos simples
Object Calisthenics: relaxe e escreva códigos simples
 
Perl Moderno, dia5
Perl Moderno, dia5Perl Moderno, dia5
Perl Moderno, dia5
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dados
 
Clean code
Clean codeClean code
Clean code
 

Clean Code e Object Calisthenics - Aplicados no PHP

  • 1. Clean Code e Object Calisthenics Aplicados no PHP
  • 2. <?php echo ‘Rafael Neris’; Apaixonado por refactoring Total Express Github: @rafaelneris Linkedin: https://www.linkedin.com/in/rafael-neris- 548402110/ 2
  • 3. Motivação: ▸ Legibilidade ▸ Manutenabilidade ▸ Reusabilidade ▸ Testabilidade 3
  • 4. Como medir a qualidade de seu código? Método infálivel!
  • 5.
  • 8. Single Responsibility Open/Closed Principle Liskov Substitution Interface Segregation Dependency Inversion S O L I D 8
  • 9. Single Responsibility Principle “Uma classe deve ter um, e somente um, motivo para ser modificada” 9
  • 10. class Report { public function getTitle() { return 'Report Title'; } public function getDate() { return '2018-01-22'; } pulic function getContents() { return [ 'title' => $this->getTitle(), 'date' => $this->getDate(), ]; } public function formatJson() { return json_encode($this->getContents()); } }
  • 11. class Report { public function getTitle() { return 'Report Title'; } public function getDate() { return '2018-01-22'; } public function getContents() { return [ 'title' => $this->getTitle(), 'date' => $this->getDate(), ]; } } class JsonReportFormatter { public function format(Report $report) { return json_encode($report->getContents()); }
  • 12. Open Closed Principle “Entidades de Software devem estar aberta para expansão, mas fechada para modificação.” 12
  • 13. class Logger { public function writeTxt($message) { //lógica } }
  • 14. class Logger { public function writeTxt($message) { //lógica } public function writeCsv($message) { //lógica } }
  • 15. class Logger { private $writer; public function __construct(Writer $writer) { $this->writer = $writer; } public function write($message) { $this->writer->write($message); } } interface Writer { public function write($message); } class Txt implements Writer { public function write($message) { //lógica } } class Csv implements Writer { public function write($message) { //lógica } }
  • 17. “ “Se q(x) é uma propriedade demonstrável dos objetos x de tipo T. Então q(y) deve ser verdadeiro para objetos y de tipo S onde S é um subtipo de T.” Barbara Liskov 17
  • 18. “ “Funções que usam ponteiros ou referências a classes-base devem ser capazes de usar objetos de classes derivadas sem o saber.” Robert C. Martin (Uncle Bob) 18
  • 20. class T { … } class S extends T { … } $o1 = new T(); $o2 = new S(); function write(T $message) { return “Ok”; } write($o1); // “Ok” write($o2); // “Ok”
  • 21. Clean Code Vamos nos aprofundar mais! 21
  • 22. Alguns conceitos importantes ▸ Nomes significativos ▸ Funções pequenas ▸ Comentários 22
  • 23. Nomes significativos Use nomes que revelam seu propósito 23
  • 24. class Diretorio { private $qtd; public function retornarQtd() { return $qtd; } }
  • 25. class Diretorio { private $quantidadeArquivos; public function getQuantidadeArquivos() { return $this->quantidadeArquivos; } }
  • 27. class Aluno { private $data1; // Data de Nascimento private $data2; // Data de Matricula }
  • 28. class Aluno { private $nascimentoData; private $matriculaData; }
  • 30. class File { private $f; public function write(array $k) { foreach ($k as $j) { fwrite($f, $j); } } }
  • 31. class File { private $fileResource; public function write(array $content) { foreach ($content as $lineOfContent){ fwrite( $fileResource, $lineOfContent ); } } }
  • 32. Nomes de classes e Objetos ▸ Devem ter nomes com substantivos ▸ Não deve ser um verbo! ▸ Devem ser buscaveis 32
  • 33. Nomes de métodos ▸ Devem possuir verbos ▸ Devem ser buscaveis. 33
  • 35. if ($saqueLimite == 1000) { // Do Something }
  • 36. const SAQUE_TETO = 1000; if ($saqueLimite == self::SAQUE_TETO) { // Do Something }
  • 37. Métodos pequenos ▸ Devem ser pequenos e concisos ▸ “Fazer UMA e APENAS UMA coisa. Eles devem fazer isso bem e apenas isso.” ▸ “Menor do que pequeno” 37
  • 41. Comentários ▸ Envelhecem e mentem ▸ Não comentem código. Deixe que o GIT resolva para você! ▸ O único comentário bom é aquele que você não precisa escrever. 41
  • 42. // Verifica se o funcionário tem direito a todos benefícios if ( ($employee->getFlag() && self::HOURLY_FLAG) && ($employee->getAge() > 65) )
  • 44. //$token = token($this->email); //if (self::where('confirmation_token', $token)->first()) { // return $this->getUniqueConfirmationToken(); //} $row = Testimonial::find($id); $row->list_order = $listOrder; $row->save(); return $row;
  • 45. Casos de comentários: ▸ Comentários informativos ▸ Explicar-se no código ▸ Comentários TODO ▸ Comentários Ruidosos ▸ Comentários redundantes 45
  • 46. Outros conceitos: ▸ Formatação ▸ Objetos e Estrutura de dados ▸ Tratamento de erros ▸ Limites ▸ Testes unitários ▸ Classes ▸ Sistemas ▸ Concorrência ▸ Refinamento sucessivo 46
  • 47. Outros conceitos: ▸ Formatação ▸ Objetos e Estrutura de dados ▸ Tratamento de erros ▸ Limites ▸ Testes unitários ▸ Classes ▸ Sistemas ▸ Concorrência ▸ Refinamento sucessivo 47
  • 48. Object Calisthenics 9 regras para manter seu código limpo! 48 CONSELHOS Termo grego, significa “Exercício”
  • 50. Evitar o código Haddouken
  • 51. Somente um nível de indentação por método Use Extract Method Pattern 51
  • 52. public function getPromoCode(string $promoName) { if ($this->promoCode) { if (false === $this->promoCodeExpired()) { if ($this->promoName == $promoname) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } }
  • 53. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { if (false === $this->promoCodeExpired()) { if ($this->promoName == $promoname) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } }
  • 54. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { // 2 if (false === $this->promoCodeExpired()) { if ($this->promoName == $promoname) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } }
  • 55. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { // 2 if (false === $this->promoCodeExpired()) { // 3 if ($this->promoName == $promoname) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } }
  • 56. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { // 2 if (false === $this->promoCodeExpired()) { // 3 if ($this->promoName == $promoname) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } }
  • 57. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { // 2 if (false === $this->promoCodeExpired()) { $this->getPromoExists($promoName); } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } } protected function getPromoExists(string $promoName) { if ($this->promoName == $promoName) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } }
  • 58. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { // 2 if (false === $this->promoCodeExpired()) { $this->getPromoExists($promoName); } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } } protected function getPromoExists(string $promoName) { if ($this->promoName == $promoName) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } }
  • 59. public function getPromoCode(string $promoName) { // 1 if ($this->promoCode) { $this->getValidPromoCode($promoName) } else { throw new Exception('Cliente sem código de promoção'); } } protected function getValidPromoCode(string $promoName) { if (false === $this->promoCodeExpired()) { return $this->getPromoExists($promoName); } else { throw new Exception('Promoção Expirada'); } } protected function getPromoExists(string $promoName) { if ($this->promoName == $promoName) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } }
  • 60. Benefícios: ▸ S de Single Responsibility Principle ▸ Favorece reusabilidade 60
  • 61. Não use a palavra “else” Use early returns! 61
  • 62. public function getPromoCode(string $promoName) { if ($this->promoCode) { $this->getValidPromoCode($promoName) } else { throw new Exception('Cliente sem código de promoção'); } } protected function getValidPromoCode(string $promoName) { if (false === $this->promoCodeExpired()) { return $this->getPromoExists($promoName); } else { throw new Exception('Promoção Expirada'); } } protected function getPromoExists(string $promoName) { if ($this->promoName == $promoName) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } }
  • 63. public function getPromoCode(string $promoName) { if (!$this->promoCode) { throw new Exception('Cliente sem código de promoção'); } return $this->getValidPromoCode($promoName); } protected function getValidPromoCode(string $promoName) { if ($this->promoCodeExpired()) { throw new Exception('Promoção Expirada'); } return $this->getPromoExists($promoName); } protected function getPromoExists(string $promoName) { if ($this->promoName != $promoName) { throw new Exception('Promoção não existe mais'); } return $this->promoCode; }
  • 64. public function getPromoCode(string $promoName) { if ($this->promoCode) { if (false === $this->promoCodeExpired()) { if ($this->promoName == $promoname) { return $this->promoCode; } else { throw new Exception('Promoção não existe mais'); } } else { throw new Exception('Promoção Expirada'); } } else { throw new Exception('Cliente sem código de promoção'); } }
  • 65. public function getPromoCode(string $promoName) { if (!$this->promoCode) { throw new Exception('Cliente sem código de promoção'); } return $this->getValidPromoCode($promoName); } protected function getValidPromoCode(string $promoName) { if ($this->promoCodeExpired()) { throw new Exception('Promoção Expirada'); } return $this->getPromoExists($promoName); } protected function getPromoExists(string $promoName) { if ($this->promoName != $promoName) { throw new Exception('Promoção não existe mais'); } return $this->promoCode; }
  • 66. Benefícios: ▸ Evita duplicidade de códigos ▸ Aumenta legibilidade ▸ Reduz a complexidade ciclomatica 66
  • 67. Encapsule TODOS os tipos primitivos e strings TODOS que possuem comportamento. 67
  • 68. class Customer { protected $name; protected $birthday; public function __construct(string $name, string $birthday) { // Validar aqui??? $this->name = $name; $this->birthday = $birthday; } }
  • 69. // Programador que conhece a classe $customer = new Customer('John Doe', '1983-02-10'); // Programador que não conhece a classe // pode gerar um 0000-00-00 no Database $customer = new Customer('John Doe', '10/02/1983');
  • 70. class Customer { protected $name; protected $birthday; public function __construct( CustomerName $name, CustomerBirthday $birthday ){ $this->name = $name; $this->birthday = $birthday; } }
  • 71. // Programador que conhece a classe $customer = new Customer( new CustomerName('John Doe'), new CustomerBirthday('1983-02-10') ); // A data será formatada internamente $customer = new Customer( new CustomerName('John Doe'), new CustomerBirthday('10/02/1983') );
  • 72. Benefícios: ▸ Type hinting ▸ Encapsulamento do código ▸ Auxilia na prevenção de código duplicado ▸ Implementação de Values Object do DDD 72
  • 74. class Bucket { protected $products = []; // many other things... }
  • 75. class Bucket { /** @var ProductCollection */ protected $products; // many other things... } class ProductCollection implements Iterator { // ... }
  • 76. Benefícios: ▸ Single Responsible Principle ▸ Usar classes SPL ▸ Facilita agrupar em coleções sem se preocupar com o comportamento delas ▸ Filtragem, ordenação, mapeamento são exemplos de métodos. 76
  • 77. Um único operador de método por linha Com excessão de interfaces fluentes. 77
  • 81. Benefícios: ▸ Lei de Demeter ▸ Legibilidade ▸ Aumenta testabilidade (Mais fácil para mockar) ▸ Facilidade para debugar 81
  • 83. Não quebre a lei de Demeter 83
  • 84. Não abrevie! Com excessão de interfaces fluentes. 84
  • 85. class File { private $f; public function write(array $k) { foreach ($k as $j) { fwrite($f, $j); } } }
  • 86. class File { private $fileResource; public function write(array $content) { foreach ($content as $lineOfContent){ fwrite( $fileResource, $lineOfContent ); } } }
  • 88. Mantenha suas classes pequenas ▸ Métodos devem possuir até 20 linhas ▸ Não crie namespaces com mais de 15 arquivos ▸ Não crie classe com mais de 200 linhas 88
  • 90. Não tenha classes com mais de duas variáveis de instância A comunidade PHP adota à CINCO variáveis de instância por adaptabilidade da linguagem. 90
  • 91. Benefícios: ▸ Alta coesão ▸ Baixo acoplamento ▸ Encapsulamento ▸ Lista de dependências mais curtas ▸ Manutenabilidade 91
  • 92. Não use GETTERS/SETTERS ▸ Regra parcialmente relacionada ao DDD ▸ Não aplicável ao PHP devido a natureza da linguagem 92
  • 93. class ImmutableBankAccount { public $currency = 'USD'; private $amount; public function setAmount(int $amount) { $this->amount = $amount; } }
  • 94. class ImmutableBankAccount { private $currency = 'USD'; private $amount; public function withdrawAmount(int $withdrawnAmount) { $this->amount -= $withdrawAmount; } }
  • 96. Valide Object Calisthenics no seu código https://github.com/object-calisthenics/phpcs-calisthenics-rules 96
  • 97. 97 “Qualquer um pode escrever um código que o computador entenda. Bons programadores escrevem códigos que os humanos entendem” Perguntas?? ▸ @rafaelneris ▸ rafael.neris@totalexpress.com.br