Back-End

12 jul, 2012

Code Refactoring – 6 dicas que vão facilitar o processo de refatoração

Publicidade

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