O que é code refactoring?
Refatorar é mudar o código que está feito sem mudar o comportamento. Idealmente, devemos melhorá-lo; porém se fizermos algo errado, ainda sim podemos dizer que fizemos uma refatoração. Obviamente, estamos simplificando ao máximo.
Dicas
- DICA 1: Adicione FIXME e TODOS no seu código;
- DICA 2: Sempre que possível reserve um tempo para melhorar o seu código;
- DICA 3: Extraia métodos para que eles fiquem simples e independentes. Evite a complexidade e DRY (Don’t Repeat Yourself);
- DICA 4: Nomeie corretamente as variáveis. EVITE coisas como $nCli, $imgW, etc.. Hoje você sabe o significado mas e daqui a dois meses? Prefira variáveis como $nome_cliente, $image_width, nomes mais legíveis;
- DICA 5: Procure sempre otimizar o código para que ele tenha uma performance melhor;
- DICA 6: A cada mudança no código, rode os testes para garantir que tudo esteja funcionando. ALWAYS GREEN;
Código de produção
<?php
require_once '../lib/tarefa.class.php'; $tarefa = new Tarefa();
$tarefas = $tarefa->get_all( array("status"=>1) ); $cliente = new Cliente();
$clientes = $cliente->get_all( array("status"=>1) );
foreach( $clientes as $cliente ){
foreach( $tarefas as $tarefa ){
$periodo = $tarefa->get_periodo();
$hoje = time();
$dt_ini = explode("-", $tarefa->get_inicio());
$ano = $dt_ini[0];
$mes = $dt_ini[1];
$dia = $dt_ini[2];
$inicio = mktime( 0, 0, 0, $mes, $dia, $ano ); $dias = 0;
if( $periodo == 2 ){ // SEMANAL
$dias = 7;
} else if( $periodo == 3 ){ // QUINZENAL
$dias = 15;
} else if( $periodo == 4 ){ // MENSAL
$dias = 30;
}
$projetos = json_decode(_access_api('/api/projects', array("client_id"=>$cliente)) );
foreach( $projetos as $projeto ){
$tags = strtolower($projeto->tags);
$_tags = explode(",", $tags);
if(in_array(TAG_ADWORDS, $_tags) ){
if( $inicio <= $hoje){
$today = mktime( 0, 0, 0, $mes, $dia+$dias, $ano );
$tarefa->set_id_projeto($projeto->id);
$tarefa->set_inicio( date("Y-m-d"), $today);
$tarefa->create_task();
}
}
}
}
}Este código tem uma série de problemas, mas ele tem coisas boas também – bem, a única coisa boa é que ele funciona… O seu objetivo é criar cada tarefa para cada projeto que contenha uma tag específica para cada cliente.
Mas tem muita coisa pra arrumar… Veja as linhas 5 e 8, elas, respectivamente, recuperaram a lista de tarefas e a lista de clientes. Até ai está bom. Deveríamos tirar o alto acoplamento, mas, por enquanto, está bom. Vamos ver a lógica deste código comparada ao objetivo deste projeto.
Logo de início vemos que a lógica está errada. Veja na linha 10 que eu percorro um array de clientes quando, na realidade, eu deveria percorrer a lista de tarefas e para cada tarefa percorrer os clientes.
Outra coisa que esse código tem é o fato de usar números fixos no if do $periodo nas linhas 22 à 27. Seria uma boa colocar isso em constantes, para que o código fique mais limpo para manutenção futura. E aproveitando essa modificação, vamos substituir o if por um switch.
Outra melhoria seria alterar o explode da linha 14 até a linha 19, que poderia ser substituído por strtotime. E isso seria totalmente menos custoso para o PHP.
Outra sugestão de melhoria seria a utilização do cache nessa lista de projetos, isso foi fundamental para a melhoria de performance. Veja na linha 30 que, para cada cliente, eu obtenho a lista de projetos daquele cliente. Eu faço isso para cada tarefa, então é desnecessário fazer isso todas as vezes. Veja a solução que pensamos para esse caso:
foreach( $clientes as $client_id ){
if( !isset($projetos_cliente[$client_id]) ){
$projetos_cliente[$client_id] = json_decode(_access_api('/api/projects', array("client_id"=>$client_id)) );
}
foreach( $projetos_cliente[$client_id] as $projeto ){Dessa forma, eu aproveito o cache e, assim, o algoritmo e as requisições da API externa ficam muito mais rápidos, pois somente será uma única vez e executada para cada cliente. Repare que melhorei o nome da variável que antes era $cliente e agora é $client_id.
Outra refatoração que fizemos foi a de somar dias a uma data, ao invés de usar o mktime() na linha 36 , podemos fazer da seguinte forma $today = $inicio+($dias*86400); // 86400 = 1 dia em segundos
Feito isso, refatoramos uma boa parte do código deixando-o muito melhor e mais performático. Veja o resultado final:
<?php
require_once '../lib/tarefa.class.php';
$dt_hoje = date("Y-m-d");
$hoje = strtotime($dt_hoje);
$tarefa = new Tarefa();
$tarefas = $tarefa->get_all( array("status"=>1) );
$projetos_cliente = array();
$cliente = new Cliente();
$clientes = $cliente->get_all( array("status"=>1) );
foreach( $tarefas as $tarefa ){
$inicio = strtotime($tarefa->get_inicio());
switch($periodo){
case PERIDIOCIDADE_SEMANAL:
$dias = 7;
break;
case PERIDIOCIDADE_QUINZENAL:
$dias = 15;
break;
case PERIDIOCIDADE_MENSAL:
$dias = 30;
break;
default:
$dias = 0;
}
foreach( $clientes as $client_id ){
if( !isset($projetos_cliente[$client_id]) ){
$projetos_cliente[$client_id] = json_decode(_access_api('/api/projects', array("client_id"=>$client_id)) );
}
foreach( $projetos_cliente[$client_id] as $projeto ){
$tags = explode(",", strtolower($projeto->tags));
if(in_array(TAG_ADWORDS, $tags) ){
if( $inicio <= $hoje){
$today = $inicio+($dias*86400); // 86400 = 1 dia em segundos
$tarefa->set_id_projeto($projeto->id);
$tarefa->set_inicio( date("Y-m-d"), $today);
$tarefa->create_task();
}
}
}
}
}Avisos e agradecimentos
Essa refatoração faz parte do hangout de Code Refactoring disponível no Youtube, onde diversas pessoas compartilharam conhecimento. O link com as pessoas que participaram está aqui.
Gostaria de agradecer imensamente à Octavarium, empresa especializada em links patrocinados e SEO por ter autorizado o compartilhamento do código fonte que foi disponibilizado acima e desenvolvido pela minha empresa movin’ on. Aproveitando, gostaria de recomendar o mais novo produto da movin’ on o http://esquilo.mobi