Boas Práticas no Desenvolvimento de Software60 - 90 minutosAtualizado: Julho 2015 [email protected]
Com foco especial em aplicativos Web, tipagem fraca, sistemas de informação. (Exemplos em PHP)
Princípios gerais● Consistência
○ Senão fica muito trabalhoso entender o sistema
● Cérebro humano é limitado○ 7 ± 2 coisas ao mesmo tempo é o limite
■ métodos em uma classe, classes em um módulo, etc
● Comentários○ São para dizer o porquê e não o como. O como é o próprio código
que diz (se for bem-feito, com componentes auto-explicativos)
● Legibilidade○ O código é, em geral, lido mais frequentemente do que escrito
Princípios gerais● Testes
○ Sem testes você não tem como saber se alguma parte da sua aplicação deixou de funcionar depois de uma modificação
● Objetivos eternos:○ Baixo acoplamento○ Reduzir complexidade
■ Usando abstrações (exemplo?)
● A característica mais importante do código é “quão fácil é modificá-lo?”
Princípios gerais● Se você não tomar medidas para manter a estrutura do seu projeto, ele irá
acabar uma massa amorfa impossível de entender ou de mudar
● “Privado até prova em contrário” (por que?)
● Vai haver casos em que você vai precisar quebrar um desses princípios para resolver algum problema urgente, mas saiba que isso tem um custo, que vai aumentando com o tempo. Isso é uma dívida técnica (technical debt) que você vai ter que pagar mais cedo ou mais tarde.
Nomes auto-explicativosRazão● Dá pra entender o que está sendo feito só de se ver o nome das coisas● Não precisa tanto de comentários
Anti-exemplo// fazendo a média de todas as idades recebidas
$a = func2($b);
Exemplo$mediaIdades = calculaMedia($idades);
Coisas explícitas em vez de implícitasRazão● Mais fácil de entender o código depois
○ Mesmo por você
● Mais fácil de reusar e refatorar (por que?)
● Mesmo em um método de instância (em um objeto), às vezes é melhor passar os parâmetros explicitamente (como argumentos) em vez de pegar tudo do $this ou de alguma coisa implícita (como variáveis globais).
Coisas explícitas em vez de implícitasAnti-exemplo
class User{
//não tem como saber (de fora) o que esta função usa sem olhar seu código
public function calculaPontos(){
$data = $this->foo-> getData();
//linhas de código
$empresa = $this-> getEmpresa();
// mais linhas de código
$historicoDeCompras = Helper::getHistoricoDeCompras ($usuario,$data);
// mais linhas de código
return $resultado;
Coisas explícitas em vez de implícitasExemplo // está óbvio que este método calcula pontos para um usuário levando em // consideração a data, sua empresa e seu histórico de compras
class User{
public function calculaPontos($data,$empresa,$historicoDeCompras){
// corpo do método
}
Note que, no anti-exemplo, um potencial usuário precisa saber, de antemão, que um User precisa ter uma Empresa definida pois caso contrário o método getEmpresa() pode gerar um erro. Isto é mais uma coisa implícita que, no exemplo dado, torna-se explícita, impedindo possíveis erros.
Lei de Demeter“Não fale com o vizinho do seu vizinho”
Razão● Aumenta complexidade● Aumenta acoplamento
Anti-exemplo // uma mudança em qualquer dos componentes da cadeia vai quebrar esse código
$anoDeFundacao = $user
->getEmpresa()
->getMatriz()
->getDataDeFundacao()
->getAno();
Lei de DemeterExemplo// comportamento delegado para a classe User
// o código atual não é afetado por mudanças na obtenção do ano de fundação
$anoDeFundacao = $user-> getAnoDeFundacao() ;
Asserts nos lugares certosRazão● Garantir que, de um ponto em diante, uma certa condição é verdadeira
○ Só para coisas que nunca devem ser false● Dar “pistas”, para quem está lendo, do que você está fazendo
Exemplo$pessoas = Pessoa::getAll(); //do banco de dados
$pontuacoes = funcaoComplicadaQueCalculaPontosParaPessoas ($pessoas);
$cores = funcaoComplicadaQuePegaACorPreferidaDeCadaPessoa ($pessoa);
assert( count($pontuacoes) === count($cores) );
//se esse assert falhar, há algo errado
//melhor descobrir agora do que mais à frente
Edge cases (casos-limite)Razão● Nós só costumamos pensar nos casos comuns que uma função deve
atenderAnti-exemplofunction avg(array $arr){
$sum = 0;
$size = count($arr);
foreach($arr as $num){
$sum += $num;
}
return $sum/$size; //quando isso pode dar errado?
}
Escolheu um jeito, fique com eleRazão● Pessoas não conseguem criar um modelo mental do seu projeto se ele
não for consistente
Exemplos● Nomenclatura de variáveis● Estrutura de classes, arquivos
Passar operações para fora dos loops sempre que possível
Razão● Às vezes a gente pode criar um problema sem perceber● Muitas vezes uma informação é constante para todas as execuções de um
loop
Exemplos● Operações no banco de dados● Outros tipos de operações pesadas
Value ObjectsQuando você tem muitos pequenos dados que precisam ser manipulados juntosRazão● Evitar ter que definir uma função que recebe 15 parâmetros● Podemos capturar erros mais cedo (vai dar erro se o VO passado não for
do tipo correto)
Anti-exemplo $relatorio = geraRelatorio($itens,$dataInicio,$dataFim,
$secoes,$incluirGraficos,$incluirInformacoesGerais,$estilo,$nome);
Value ObjectsExemplo $opcoesVO = new OpcoesDoRelatorioVO($itens,$dataInicio,
$dataFim,$incluirGraficos,$incluirInformacoesGerais,$estilo,$nome);
// código mais simples, mais fácil entender e mais fácil de mudar
$relatorio = geraRelatorio($opcoesVO);
Métodos e classes devem devem fazer poucas coisasRazão● 7 ± 2● Facilidade de reuso, manutenção
Anti-Exemplo // um nome vago assim já é um sintoma sério
public function getResultadoCorreto ($params){
// 600 linhas de código
}
Métodos e classes devem devem fazer poucas coisasExtra● Classes que representam entidades e tabelas do Banco (modelos) vs o
resto ● Não helperizar seus modelos nem controllers
Programação Top down“Pensar no todo antes de criar as partes”
Razão● Se você cria as partes (funções e classes individuais) que você acha que
serão necessárias antes de pensar a estrutura do projeto, você pode acabar tendo que “entortar” a estrutura para que consiga usar as partes que você já criou.
Programação Top downAnti-Exemplo
● Preciso criar um sistema para gerar relatórios.● “Vou criar logo a parte das consultas de banco de dados pois já sei
que serão necessárias.”● Com essas partes prontas, vou começar a fazer o loop principal do
sistema (exemplo?)○ Agora vi que vou precisar consultar um CSV também. Vou
adicionar um parâmetro às funções do banco para resolver isso.○ Agora vi que vou precisar gerar resultados em PDF também
então vou adicionar um parâmetro a todas as funções de consulta a dados que foram feitas para que modifiquem o output.
● 9 meses depois o sistema está desorganizado e sem estrutura
Programação Top downExemplo
● Preciso criar um sistema para gerar relatórios.● Vou criar a estrutura principal “fingindo” que as partes já foram criadas
(exemplo?)
DRYDon’t repeat yourself
Razão● Evitar retrabalho● Evitar erros (corrigiu uma vez, todos os clientes estão OK)
Top Related