Upload
luis-cobucci
View
683
Download
0
Embed Size (px)
DESCRIPTION
Sabe aquele arquivo com 5000000 linhas e que você tem que acender umas velas pra abrir ele? Então, aqui te daremos as armas corretas para exterminá-lo e para NUNCA MAIS criar monstros como ele!
Citation preview
Removendo o cheiro ruim do seu código
Removendo o cheiro ruim do seu código
Luís Otávio Cobucci Oblonczyk
19 de Novembro de 2011PHPSC Conference 2011
Luís Otávio Cobucci OblonczykLuís Otávio Cobucci Oblonczyk
● Desenvolvedor PHP na Softnex Tecnologia● Orientador no Senac TI● Doido por PHP desde 2003● Perfeccionista ao extremo● Futuro PHP 5.3 ZCE? (teste em dezembro!)
@lcobucci
http://about.me/lcobucci
PHPPHP
● Linguagem essencialmente server-side● Enorme abrangência na web● Inúmeras extensões● Grande ponto forte: simples e fácil de
aprender.
PHP – (possível) ponto fracoPHP – (possível) ponto fraco
Simples e fácil de aprender
Primeiros passos dados
PHP – primeiros passosPHP – primeiros passos
● All-in-one script (tudo junto misturado: SQL, PHP, HTML, Javascript)
● “Não importa se o pato é macho, eu quero é o ovo... e pra ONTEM!”
● “Função? Claaaro: f(x) = 2x + 5”● “Classe? Sim, sim... frequentei a escola”● “Mensagem de erro do PHP é coisa de
moleque!”
<?php$con = @mysql_connect('localhost', 'root', '*****') or die('Fuuuuuuuuu');@mysql_select_db ('mydb', $con) or die('Fuuuuuuuuu');?><html><head><title>Hello world</title></head><body><ul><?php$query = @mysql_query('SELECT * FROM user', $con) or die('Fuuuuuuuuu');
while ($user = @mysql_fetch_assoc($query)) {?><li><?php echo $user['name']; ?></li><?php}?></ul></body></html>
Novas ideias são encontradas
PHP – novas ideiasPHP – novas ideias
● Reutilização movida à includes● Variáveis globais diretas do inferno● “register_globals? Deixa habilitado senão o
sistema não funciona!”● “Ahhhh tá, isso que são funções!”
<?php$host = 'localhost';$user = 'root';$pass = '*****';include 'db.php';?><html><head><title>Hello world</title></head><body><ul><?php$query = @mysql_query('SELECT * FROM user', $con) or die('Fuuuuuuuuu');
while ($user = @mysql_fetch_assoc($query)) {?><li><?php echo $user['name']; ?></li><?php}?></ul></body></html>
Estruturas diferentes, mesmo pensamento
PHP – estruturas diferentes, mesmo pensamentoPHP – estruturas diferentes, mesmo pensamento● “Ouvi que OOP é muito melhor, então agora
vou escrever um monte de classes”● Um bilhão de métodos estáticos● Nível de abstração nas alturas● Uso absurdo de Design Patterns de forma
equivocada
Sim, pode ser a visão do seu código.Preocupado?
Fique tranquilo, isso tem salvação
Vida do código ruimVida do código ruim
● Nasce difícil de entender● Cada manutenção gera uma (ou mais) falhas● Baixa produtividade devido a confusão absurda
existente● Surgem novos colaboradores na esperança de
que com mais gente tenha mais produtividade● Pressão na equipe● Mais falhas são criadas
Vida do código ruimVida do código ruim
● Equipe revoltada propõe solução: jogar tudo no lixo e começar novamente
● Divisão da equipe, os melhores vão modelar o novo código enquanto os outros sofrem pra manter o antigo
● Muito tempo se passa até que o novo entra no lugar do antigo, muitas pessoas não estão nem mais na empresa.
● Os colaboradores atuais exigem refazer o sistema porque o código está uma porcaria novamente.
Alguém se identificou?
Mandamentos do código limpoMandamentos do código limpo
● Nunca terás ciúmes do código que você criar● Não possuirás misericórdia para com código de
seus colegas● Matarás TODO e QUALQUER princípio de
código sujo
Porque apenas funcionarnão é suficiente!
Blz, como posso melhorar?
Mudanças de conceitosMudanças de conceitos
● Nem tudo que está no projeto é público● Muitas vezes dentro de um projeto temos
vários projetos● Front-controllers são legais● OOP não é a solução pra tudo, mas ajuda em
várias ocasiões● PHP 5.3 or die!
Iniciando a limpeza!
Escolha nomes decentes!
NomenclaturaNomenclatura
● Use nomes que possuem algum sentido● Evite abreviações● Evite passar informações incorretas● Use nomes pronunciáveis● Cuidado ao misturar idiomas● Não dê dois (ou mais) sentidos para a mesma
palavra
Nomenclatura – ClassesNomenclatura – Classes
● Nomes das classes devem ser substantivos, NUNCA verbos (exceto para o design pattern Command, mas ele não conta mesmo =P)
● A classe deve receber o nome do elemento que ela representa na vida real
Nomenclatura – MétodosNomenclatura – Métodos
● Nomes dos métodos devem SEMPRE conter verbos
● Caso programar em português, os verbos devem ser utilizados no modo imperativo (calculaJuros(), cancelaCompra(), ...)
Nomenclatura – InterfacesNomenclatura – Interfaces
● Interfaces adicionam comportamentos aos objetos, portanto normalmente são nomeadas como adjetivos (Clickable, Draggable, Resizeable, …) ou substantivos (Iterator, SplObserver, SplSubject)
● Não há absolutamente NENHUMA necessidade de colocar o prefixo “I” em uma interface
Criando métodos e funções
Métodos e funçõesMétodos e funções
● Devem ser PEQUENOS (no máximo 20 linhas)● Devem fazer apenas UMA tarefa● Cuidado com a complexidade ciclomática dos
métodos e funções (quantidade de caminhos possíveis na execução)
● Caso existam muitos parâmetros, considere agrupar os parâmetros com o mesmo contexto em um objeto
● NÃO REPITA CÓDIGO!!
Lidando com comentários
ComentáriosComentários
● Comentários normalmente compensam um código mal feito
● Evite sempre o comentário que você pode substituir por uma variável ou método/função bem nomeada● if ($item->getStatus() == 3)
ComentáriosComentários
● Comentários normalmente compensam um código mal feito
● Evite sempre o comentário que você pode substituir por uma variável ou método/função bem nomeada● if ($item->getStatus() == 3) // verifica se está
cancelado
ComentáriosComentários
● Comentários normalmente compensam um código mal feito
● Evite sempre o comentário que você pode substituir por uma variável ou método/função bem nomeada● if ($item->getStatus() == 3) // verifica se está
cancelado● if ($item->estahCancelado())
ComentáriosComentários
● Comentários após fechar chaves são ruídos desnecessários
● Código comentado é inútil, portanto deve ser exterminado da face da terra
● Sempre que sentir necessidade de comentar pode ter certeza que algo de errado não está certo!
Utilize coding standards
Code StyleCode Style
● Unifica a forma que o código é escrito na empresa, assim TODOS entendem o código de forma prática e rápida
● Você deve escolher um padrão de formatação de código e combinar com a equipe TODA para adotar este padrão
● Nunca, never, ever, crie padrões... utilize um existente e seja feliz!
Gerenciando erros
Tratamento de errosTratamento de erros
● Prefira exceptions do que retornar mensagens ou códigos de erros
● Crie as exceptions necessárias para o tratamento de erros das suas tarefas
● Evite tratar a classe base de exception● O tratamento de exceptions é uma tarefa,
portanto no método que tratá-las não deve haver nenhuma tarefa após o(s) catch(s)
Classes
Criando classesCriando classes
● Classes devem ser PEQUENAS● Mantenha os atributos encapsulados● Classes devem possuir apenas UMA
responsabilidade, ou seja deve estar inserida em somente um contexto
● Busque sempre a alta coesão, e consequentemente baixo acoplamento
● Utilize injeção de dependências● Crie testes automatizados!
Refatoração é OBRIGAÇÃO!
RefatoraçãoRefatoração
“Refatoração (do inglês Refactoring) é o processo de modificar um sistema de software para melhorar a estrutura interna do código sem alterar seu comportamento externo.(…)Outra consequência é a melhora no entendimento do código, o que facilita a manutenção e evita a inclusão de defeitos.”
http://pt.wikipedia.org/wiki/Refatora%C3%A7%C3%A3o
RefatoraçãoRefatoração
● Devem SEMPRE existir testes de unidade para podermos realizar uma refatoração correta (sem eles não temos como afirmar que o comportamento realmente não foi alterado).
Técnicas de refatoraçãoTécnicas de refatoração
● Extração de método● Extração de classe● Extração de variável local● Renomear classe/método/atributo● Encapsular atributo● Subir nível na hierarquia (para classe pai)● Descer nível na hierarquia (para classe filha)● Mover método/atributo (para outra classe)
Detonando TUDO!
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct() { $this->logger = new FileLogger(); }
public function div($x, $y) { $this->logger->log( 'div', array($x, $y), $y == 0 ? false : $x / $y );
return $y == 0 ? false : $x / $y; }}
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct(FileLogger $logger) { $this->logger = $logger; }
public function div($x, $y) { $this->logger->log( 'div', array($x, $y), $y == 0 ? false : $x / $y );
return $y == 0 ? false : $x / $y; }}
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct(FileLogger $logger) { $this->logger = $logger; }
public function divide($dividend, $divisor) { $this->logger->log( 'divide', array($dividend, $divisor), $divisor == 0 ? false : $dividend / $divisor );
return $divisor == 0 ? false : $dividend / $divisor; }}
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct(FileLogger $logger) { $this->logger = $logger; }
public function divide($dividend, $divisor) { if ($divisor == 0) { throw new \InvalidArgumentException('Divisor can`t be ZERO');
}
$this->logger->log( 'divide', array($dividend, $divisor), $dividend / $divisor );
return $dividend / $divisor; }}
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct(FileLogger $logger) { $this->logger = $logger; }
public function divide($dividend, $divisor) { if ($divisor == 0) { throw new \InvalidArgumentException('Divisor can`t be ZERO');
}
$result = $dividend / $divisor; $this->logger->log('divide', array($dividend, $divisor), $result);
return $result; }}
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct(FileLogger $logger) { $this->logger = $logger; }
public function divide($dividend, $divisor) { if ($divisor == 0) { throw new \InvalidArgumentException('Divisor can`t be ZERO');
}
$result = $dividend / $divisor; $this->logger->log('divide', func_get_args(), $result);
return $result; }}
<?phpnamespace Lcobucci\Utils\Math;
use \Lcobucci\Utils\Log\FileLogger;
class Calculator{ private $logger;
public function __construct(FileLogger $logger) { $this->logger = $logger; }
public function divide($dividend, $divisor) { if ($divisor == 0) { throw new \InvalidArgumentException('Divisor can`t be ZERO');
}
$result = $dividend / $divisor; $this->logger->log(__METHOD__, func_get_args(), $result);
return $result; }}
Dúvidas???Dúvidas???
Obrigado!Obrigado!
Eu por aí: http://about.me/lcobucci
Slides: http://slideshare.net/lcobucci
Avalie essa palestra: http://joind.in/4500