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 e Object Calisthenics - Aplicados no PHP
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 (20)

ODP
Trabalhando com as views do Web2Py
Hugo Leonardo Costa e Silva
 
PDF
Adianti Framework PHPConf 2013
Pablo Dall'Oglio
 
PPTX
PHP robusto com Zend Framework
Jaime Neto
 
PDF
Design Patterns com PHP
Pablo Dall'Oglio
 
PDF
Vraptor
clauvane1708
 
PDF
PHP: Programando com orientação a Objetos
Pablo Dall'Oglio
 
PDF
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Pablo Dall'Oglio
 
PDF
Hiearquia Window
Daniel Arndt Alves
 
KEY
Codifique melhor
Marcos Sousa
 
PPTX
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
Alexandre Rodrigues
 
PDF
Programando para programadores: Desafios na evolução de um Framework
Pablo Dall'Oglio
 
PDF
POO - 09 - Entradas e Saídas em Java
Ludimila Monjardim Casagrande
 
PDF
POO - 06 - Encapsulamento
Ludimila Monjardim Casagrande
 
PDF
Design Patterns na Programação de Jogo
Bruno Cicanci
 
PDF
Acesso a banco de dados com JDBC
Eduardo Mendes
 
PDF
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Pablo Dall'Oglio
 
PPTX
JAVA - ENCAPSULAMENTO
André Victor
 
PDF
Java script - document object model
Gabriel Coelho
 
PDF
Criando aplicações com PHP-GTK
Pablo Dall'Oglio
 
Trabalhando com as views do Web2Py
Hugo Leonardo Costa e Silva
 
Adianti Framework PHPConf 2013
Pablo Dall'Oglio
 
PHP robusto com Zend Framework
Jaime Neto
 
Design Patterns com PHP
Pablo Dall'Oglio
 
Vraptor
clauvane1708
 
PHP: Programando com orientação a Objetos
Pablo Dall'Oglio
 
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Pablo Dall'Oglio
 
Hiearquia Window
Daniel Arndt Alves
 
Codifique melhor
Marcos Sousa
 
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
Pablo Dall'Oglio
 
POO - 09 - Entradas e Saídas em Java
Ludimila Monjardim Casagrande
 
POO - 06 - Encapsulamento
Ludimila Monjardim Casagrande
 
Design Patterns na Programação de Jogo
Bruno Cicanci
 
Acesso a banco de dados com JDBC
Eduardo Mendes
 
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
Pablo Dall'Oglio
 
JAVA - ENCAPSULAMENTO
André Victor
 
Java script - document object model
Gabriel Coelho
 
Criando aplicações com PHP-GTK
Pablo Dall'Oglio
 

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

PDF
[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
Jessica Zanelato Soares
 
PDF
Boas práticas no desenvolvimento de software
Felipe
 
PDF
Clean code v3
Jean Carlo Machado
 
PPTX
Clean Coder
Camilo de Melo
 
PDF
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Luís Cobucci
 
PDF
Programando Melhor - Flisol
Leonn Leite
 
PPTX
Clean Code - Fork In Tuba
Rafael Paz
 
PPTX
Clean code - Qualidade em desenvolvimento de Software
Gabriel Felipe Soares
 
PPTX
DevTalk Zoox 04/2016
Leandro Silva
 
PPTX
ZeroBugsProject - Técnicas de programação efetivas
Rafael Chinelato Del Nero
 
PDF
Refatoração - aquela caprichada no código
Juciellen Cabrera
 
PPTX
Code Smells
Alan Willms
 
PDF
Código legado - PHP Conference Brasil - 2014
Michael Castillo Granados
 
PDF
Clean Code na Prática
Douglas Siviotti
 
PDF
Php Conf08 Refactoring
Wildtech
 
PDF
Clean Code
Daniel Tamiosso
 
PDF
Codigo limpo
diegomcunha
 
PDF
clean code
Douglas Siviotti
 
PDF
Objects calisthenics - Os 10 mandamentos do rei do código
BonoBee
 
[TDC 2019] - Object Calisthenics: 9 regras para melhorar seu código
Jessica Zanelato Soares
 
Boas práticas no desenvolvimento de software
Felipe
 
Clean code v3
Jean Carlo Machado
 
Clean Coder
Camilo de Melo
 
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Luís Cobucci
 
Programando Melhor - Flisol
Leonn Leite
 
Clean Code - Fork In Tuba
Rafael Paz
 
Clean code - Qualidade em desenvolvimento de Software
Gabriel Felipe Soares
 
DevTalk Zoox 04/2016
Leandro Silva
 
ZeroBugsProject - Técnicas de programação efetivas
Rafael Chinelato Del Nero
 
Refatoração - aquela caprichada no código
Juciellen Cabrera
 
Code Smells
Alan Willms
 
Código legado - PHP Conference Brasil - 2014
Michael Castillo Granados
 
Clean Code na Prática
Douglas Siviotti
 
Php Conf08 Refactoring
Wildtech
 
Clean Code
Daniel Tamiosso
 
Codigo limpo
diegomcunha
 
clean code
Douglas Siviotti
 
Objects calisthenics - Os 10 mandamentos do rei do código
BonoBee
 
Anúncio

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!
  • 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 ▸ [email protected]