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)
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-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);
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).
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;
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.
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 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() ;
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
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?
}
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
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 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);
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);
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
}
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
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 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
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?)
DRY
Don’t repeat yourself
Razão
● Evitar retrabalho
● Evitar erros (corrigiu uma vez, todos os clientes estão OK)

Boas práticas no desenvolvimento de software

  • 1.
    Boas Práticas no Desenvolvimentode 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 ● Sevocê 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 emvez 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 emvez 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 emvez 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ãofale 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 lugarescertos 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 parafora 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 classesdevem 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 classesdevem 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 “Pensarno 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?)
  • 22.
    DRY Don’t repeat yourself Razão ●Evitar retrabalho ● Evitar erros (corrigiu uma vez, todos os clientes estão OK)