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

PPTX
PDF
Refactoring
PDF
As novidades do PHP5 (2005)
ODP
Php 08 Oo
PDF
PHP ao Extremo
PDF
Qualidade no desenvolvimento de software com PHPUnit
PDF
Web2py: Desenvolvimento Ágil de Aplicações Web com Python
PPTX
Injeção de Dependências com PHP
Refactoring
As novidades do PHP5 (2005)
Php 08 Oo
PHP ao Extremo
Qualidade no desenvolvimento de software com PHPUnit
Web2py: Desenvolvimento Ágil de Aplicações Web com Python
Injeção de Dependências com PHP

Mais procurados (20)

ODP
Trabalhando com as views do Web2Py
PDF
Adianti Framework PHPConf 2013
PPTX
PHP robusto com Zend Framework
PDF
Design Patterns com PHP
PDF
Vraptor
PDF
PHP: Programando com orientação a Objetos
PDF
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
PDF
Hiearquia Window
KEY
Codifique melhor
PPTX
TDC Florianópolis 2018 - Bolovo 2.0: Indo do EJB 2.0 ao Domain Driven Design
PDF
Programando para programadores: Desafios na evolução de um Framework
PDF
POO - 09 - Entradas e Saídas em Java
PDF
POO - 06 - Encapsulamento
PDF
Design Patterns na Programação de Jogo
PDF
Acesso a banco de dados com JDBC
PDF
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
PPTX
JAVA - ENCAPSULAMENTO
PDF
Java script - document object model
PDF
Criando aplicações com PHP-GTK
Trabalhando com as views do Web2Py
Adianti Framework PHPConf 2013
PHP robusto com Zend Framework
Design Patterns com PHP
Vraptor
PHP: Programando com orientação a Objetos
Construindo ERP's com PHP: Desafios em design, manutenção segurança e perf...
Hiearquia Window
Codifique melhor
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
POO - 09 - Entradas e Saídas em Java
POO - 06 - Encapsulamento
Design Patterns na Programação de Jogo
Acesso a banco de dados com JDBC
Do Clipper e Delphi ao Ruby e PHP: Antes e depois dos frameworks
JAVA - ENCAPSULAMENTO
Java script - document object model
Criando aplicações com PHP-GTK
Anúncio

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

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

Último (7)

PDF
Dos requisitos ao código: como criar código rastreável em PHP
PPTX
Curso de Windows 11 resumido na prática.pptx
DOC
CODIGO PARA AUTOMATIZAR A JOGABILIDADE SUPER MARIO
DOC
COMO AUTOMATIZR JOGOS SUPER NINTENDO ATRAVES DA PROGRAMAÇÃO
PPTX
Mapeamento de Objeto para Tabela Relacional
PDF
apresentacao introducao computacao ead.pdf
PDF
Evolução em código: algoritmos genéticos com PHP
Dos requisitos ao código: como criar código rastreável em PHP
Curso de Windows 11 resumido na prática.pptx
CODIGO PARA AUTOMATIZAR A JOGABILIDADE SUPER MARIO
COMO AUTOMATIZR JOGOS SUPER NINTENDO ATRAVES DA PROGRAMAÇÃO
Mapeamento de Objeto para Tabela Relacional
apresentacao introducao computacao ead.pdf
Evolução em código: algoritmos genéticos com PHP

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 ▸ rafael.neris@totalexpress.com.br