Um pequeno conjunto de boas práticas para o desenvolvimento de software. O conteúdo é recomendado para desenvolvedores iniciantes ou intermediários. O foco é em desenvolvimento Web, baseado em Sistemas de Informação, com uma linguagem fracamente tipada. Os exemplos são dados na linguagem PHP.
1. Boas Práticas no
Desenvolvimento de
Software
60 - 90 minutos
Atualizado: Julho 2015 falmeida1988@gmail.com
Com foco especial em aplicativos Web, tipagem fraca,
sistemas de informação. (Exemplos em PHP)
2. 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
3. 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?”
4. 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.
5. Nomes auto-explicativos
Razã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);
6. Coisas explícitas em vez de implícitas
Razã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).
7. Coisas explícitas em vez de implícitas
Anti-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;
8. Coisas explícitas em vez de implícitas
Exemplo
// 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.
9. 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();
10. Lei de Demeter
Exemplo
// 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() ;
11. Asserts nos lugares certos
Razã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
12. Edge cases (casos-limite)
Razão
● Nós só costumamos pensar nos casos comuns que uma função deve
atender
Anti-exemplo
function avg(array $arr){
$sum = 0;
$size = count($arr);
foreach($arr as $num){
$sum += $num;
}
return $sum/$size; //quando isso pode dar errado?
}
13. Escolheu um jeito, fique com ele
Razã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
14. 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
15. Value Objects
Quando você tem muitos pequenos dados que precisam ser manipulados
juntos
Razã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);
16. Value Objects
Exemplo
$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);
17. Métodos e classes devem devem
fazer poucas coisas
Razã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
}
18. Métodos e classes devem devem
fazer poucas coisas
Extra
● Classes que representam entidades e tabelas do Banco (modelos) vs o
resto
● Não helperizar seus modelos nem controllers
19. 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.
20. Programação Top down
Anti-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
21. Programação Top down
Exemplo
● Preciso criar um sistema para gerar relatórios.
● Vou criar a estrutura principal “fingindo” que as partes já foram criadas
(exemplo?)