2. Antes de começarmos
• Use sempre o bom senso! Nem tudo que
cheira mal é podre e nem tudo que cheira
bem é bom.
• Algumas siglas essenciais pro programador:
– KISS
– DRY
– OOP
– MVC
– ACID
3. KISS
• KISS – Keep It Simple, Stupid!
• Mantenha as coisas simples!
• Soluções mais legíveis e reaproveitáveis.
• Um código mais reaproveitável precisa ser
consistente e isso é sempre difícil.
• Pode até resultar em mais código, só que
resolvendo o problema de uma forma fácil.
4. DRY
• DRY – Don’t Repeat Yourself!
• Não se repita!
• Código duplicado é retrabalho.
• Código duplicado é mais difícil de manter
(experimente corrigir um erro de um código
que foi duplicado em cinco, vinte, cem
arquivos...)
5. OOP
• OOP = Programação orientada a objetos.
• Dividir código em classes que agrupam funções
relacionadas não é o suficiente.
• O objeto também pode ser um formulário, um
controlador, um helper, um comando ou qualquer
outro tipo de objeto que não represente uma linha de
uma tabela do banco de dados.
• Assim como decorar a gramática não faz de alguém um
bom escritor, saber declarar uma classe no PHP não
significa que pensamos orientado a objeto.
6. MVC
• M de Modelo (model)
– Classes que trabalham diretamente com os dados do banco e
digitados pelo usuário.
– Não necessariamente representa uma tabela.
– Modelo gordo, controlador magrinho.
• V de Visão (view)
– HTML quase puro.
– Sem lógica, exceto para exibir (loops, condições, que podem ser
extraídos em helpers e partials)
• C de Controlador (controller)
– Faz o controle de acesso.
– Carrega e alimenta os modelos corretos.
– Carrega as visões e injeta os modelos.
7. ACID
• Atomicidade: ou todo o trabalho é feito, ou nada
é feito.
• Consistência: a integridade dos dados deve estar
assegurada. Não deve quebrar as regras do banco
de dados.
• Isolamento: duas transações diferentes não
deveriam utilizar o mesmo objeto em estados
diferentes. Só devem ser simultâneas se não
afetarem os mesmos dados.
• Durabilidade: os efeitos de uma transação com
sucesso devem persistir no banco de dados.
8. O que são Code Smells?
• São sintomas de código mal pensado.
• Podem indicar problemas mais profundos.
• Não são necessariamente o problema em si. Um
método muito longo pode ser um sintoma de que
as responsabilidades do objeto não estão bem
divididas. Quebrá-lo em métodos menores
provavelmente não é o jeito certo de corrigir.
• O programador precisa pensar num nível mais
abstrato sobre o que o sintoma realmente
representa.
9. Sintomas de código ruim dentro de uma única classe.
CODE SMELLS DENTRO DE CLASSES
10. Comentários (desodorante)
• Os comentários são necessários? Eles
explicam “por que” e não “o que”?
• Você pode refatorar o código para que ele seja
mais legível e os comentários não sejam
necessários?
• Você está escrevendo comentários para
pessoas, não para máquinas.
11. Métodos longos
• Um método mais curto é mais fácil de ler, mais
fácil de entender, e mais fácil de debugar.
• Refatore métodos longos em métodos
menores. Muitas vezes eles serão
reaproveitados.
• Verifique também se o método não é muito
longo por causa de uma lógica complexa.
12. Muitos parâmetros no método
• Quanto mais parâmetros um método
tem, mais complexo ele é.
• Limite o número de parâmetros que você
precisa em um determinado método, ou use
um objeto para combinar os parâmetros.
• Cuidado com métodos onde a maioria dos
parâmetros é opcional.
13. Código duplicado
• Código duplicado é a ruína do
desenvolvimento de software.
• Acabe com a duplicação sempre que possível.
• Você deve estar sempre à procura de casos
menos óbvios de duplicação (código
levemente diferente).
• DRY – não se repita!
14. Complexidade condicional
• Cuidado com os grandes blocos de
if/else/switch, especialmente blocos que
tendem a crescer ou mudar bastante ao longo
do tempo.
• Soluções (patterns):
– Implemente preocupando-se que o objeto tenha o
método necessário, e não o tipo necessário.
– O método do objeto responde de forma diferente
de acordo com o estado dele.
15. Explosão combinatória
• Você tem um monte de código que faz quase
a mesma coisa, mas com pequenas variações
de dados ou de comportamento.
• Isso pode ser difícil de refatorar. Considere
responder e chamar métodos independente
do seu tipo.
16. Classe grande
• Classes grandes, como métodos longos, são
difíceis de ler, compreender e debugar.
• Será que a classe tem responsabilidades
demais?
• A classe grande pode ser reestruturada ou
dividida em classes menores?
17. Tipo incorporado nos nomes
• Evite colocar os nomes dos tipos e classes nos
nomes dos métodos.
• Não é apenas redundante, também nos obriga
a mudar o método e as chamadas se o nome
do tipo ou da classe mudar.
18. Nome não-explicativo
• O nome do método, do atributo, da
variável, da classe, etc., descreve
sucintamente o que ele faz?
• Se você lesse em voz alta o nome do método
para outro desenvolvedor, ele saberia explicar
o que isso faz? Se você acha que ele não
saberia, renomeie ou reescreva.
19. Nomes inconsistentes
• Escolha uma terminologia padrão e siga ela no
código todo.
• Por exemplo, se você tem open(), você
provavelmente deve ter close().
• Se você usa $row->ativo, não misture com
$row->excluido.
20. Código morto
• Apague sem dó o código que não está mais
sendo usado, como por exemplo código
comentado.
• É por isso que temos Git, Subversion, etc.!
• Cuidado ao excluir métodos ou classes que
você criou e acha que não estão sendo usados
em mais nenhum lugar. Sempre faça uma
busca.
21. Código de vidente
• Escreva código para resolver os problemas de
hoje, e se preocupe com os problemas de
amanhã quando eles realmente se
concretizarem.
• Você (provavelmente) não vão precisar disso.
• Só se preocupe se as chances forem muito
concretas de que o problema aconteça.
22. Soluções estranhas
• Deve haver apenas uma forma de resolver o
mesmo problema em seu código.
• Se você encontrar uma solução estranha, que
poderia ser um caso de código mal duplicado
– ou poderia ser um argumento para o
modelo adaptador, se você realmente precisa
de múltiplas soluções para o mesmo
problema.
23. Campo temporário
• Cuidado com objetos que contêm uma grande
quantidade de campos opcionais ou
desnecessários.
• Se você está passando um objeto como um
parâmetro para um método, certifique-se de
que você está usando tudo isso e não está
fazendo uma seleção de uns poucos campos.
24. Sintomas de código ruim no relacionamento entre várias classes.
CODE SMELLS ENTRE AS CLASSES
25. Classes parecidas com APIs diferentes
• Se duas classes são semelhantes no
interior, mas diferentes do lado de fora (API
pública), talvez elas possam ser modificadas
para compartilhar uma interface comum.
26. Obsessão com tipos primitivos
• Não use um bando de variáveis de tipo
primitivo como um substituto pobre de uma
classe.
• Se o tipo de dados é complexo o
suficiente, escreva uma classe para
representá-lo.
• Datas são suficientemente complexas para
serem um objeto ao invés de uma string.
• As vezes é melhor usar novas classes do que
exagerar nos arrays.
27. Classes de dados
• Por outro lado, evite classes que só
armazenam dados.
• As classes devem conter dados e métodos que
operam sobre esses dados também.
28. Tufos de dados
• Se você sempre vê os mesmos dados por aí
reunidos, talvez eles sejam um grupo.
• Considere juntar os dados relacionados em
uma classe maior.
29. Legado renegado
• Se você herda de uma classe, mas nunca
utiliza qualquer uma das funcionalidades
herdadas, você realmente deveria estar
usando herança?
30. Intimidade inapropriada
• Cuidado com as classes que passam muito
tempo juntas, ou classes que interagem de
modo inadequado.
• Uma classe deve saber o mínimo possível
sobre as outras.
31. Inveja de características
• Métodos que fazem uso extensivo de outra
classe podem pertencer à essa outra classe.
• Considere mover este método para a classe da
qual ele tem tanta inveja.
32. Exposição indecente
• Cuidado com as classes que desnecessariamente
expõem seu interior.
• Refatore agressivamente as classes para diminuir
sua interface pública.
• Você deve ter um motivo convincente para cada
item que você torna público. Se você não
tem, esconda.
• Private = esconde das classes que herdam de si.
• Protected = esconde das outras classes.
33. Corrente de mensagens
• Cuidado com as longas sequências de
chamadas de métodos ou
variáveis temporárias para obter dados
rotineiros.
• Intermediários são dependências disfarçadas.
34. Garoto de recados
• Se uma classe está delegando todo o seu
trabalho, por que ela existe?
• Corte o intermediário.
• Cuidado com classes que são apenas
invólucros para outras classes ou
funcionalidades já existentes no framework.
35. Mudanças divergentes
• Se, ao longo do tempo, você faz alterações em
uma classe que toca partes completamente
diferentes da mesma, ela pode conter muita
funcionalidade não relacionada.
• Considere isolar em outra classe as partes que
mudaram.
36. Tiro de espingarda
• Se uma alteração em uma classe requer
mudanças em cascata em várias classes
relacionadas, considere uma refatoração de
modo que as alterações sejam limitadas a uma
única classe, ou use herança.
37. Heranças paralelas
• Sempre que você faz uma subclasse de uma
classe e também precisa fazer uma subclasse
de outra. Considere juntar a hierarquia em
uma única classe.
38. Biblioteca incompleta
• Precisamos de um método que está faltando em
uma biblioteca, mas estamos relutantes ou
somos incapazes de mudar a biblioteca para
incluir o método.
• O método acaba sendo anexado a uma outra
classe. Se você não pode modificar a
biblioteca, considere isolar o método ou
aproveitar a flexibilidade do Yii de usar classes
personalizadas que estendem seus componentes
padrão.
39. Solução esparramada
• Se é preciso cinco classes para fazer algo
útil, você pode ter uma solução esparramada.
• Considere simplificar e consolidar o seu
projeto.
40. Gostamos de controladores magrinhos e modelos gordinhos – mas
cuidado se estes ficarem obesos!
DICAS PARA REFATORAR OS
MODELOS OBESOS
41. Extraia Value Objects do modelo
• Value Object é um objeto pequeno que representa
uma entidade simples, geralmente com um único
valor, que deveria ser imutável.
• São úteis quando há um atributo ou pequeno grupo de
atributos que tem alguma lógica associada com eles.
• Exemplos:
– Uma classe CNPJ que se valida e retorna seu valor
numérico ou formatado.
– Uma classe Avaliacao para ratings, que retorna a
média, descrição legível da nota, etc.
– Qualquer sub-regra dentro de um modelo maior.
42. Extraia objetos de serviço
• Quando uma ação é muito complexa (como o envio de um pedido).
• A ação consulta muitos modelos diferentes ao mesmo tempo.
• A ação interage com um serviço externo (conexão com uma rede
social, uma API de outro sistema, etc.)
• A ação não é uma das preocupações principais do modelo principal
(por exemplo, escrever num arquivo de log poderia ser delegado a
uma classe de log).
• Quando existem muitas formas de fazer a ação (como a
autenticação de um usuário, uma checagem de uma regra de
acesso, etc.)
• Se a ação poderia ser reutilizada sempre (exemplo: cálculos que
podem ser refeitos e retornar o mesmo número).
43. Extraia objetos de formulários
• Quando há uma busca ou filtro complexo.
• Quando mais de um modelo é atualizado pelo
mesmo formulário você poderia encapsular a
submissão em um CFormModel.
• Mais fácil de manejar os erros e uma
transação do banco de dados.
44. Extraia objetos de queries
• Para queries SQL muito complexas que estão
inundando o modelo, considere extrair em
uma classe que a represente.
• Útil para relatórios que cruzam muitos
modelos, mas não pode-se dizer que é
baseado em um deles.
• Casos em que cada objeto de query retorna
dados baseados em determinadas regras de
negócio.
45. Extraia helpers
• Quando alguns métodos só existem para não incluir código
na view.
• Quando um bloco de HTML é reutilizado em mais de uma
view.
• Pode ser associado com uma partial:
– Layout – topo, logo, menu, rodapé, toda a parte “repetidas” que
envolve o “miolo” da aplicação.
– View – visão, o “miolo”, chamada por um controller e exibindo
dados de um ou mais modelos.
– Helper – uma classe de código que encapsula views com muitas
condições em PHP ou que são usadas em muitos lugares.
– Partial – um pedaço de view que pode ser reaproveitado. Por
exemplo, a partial _form é usada nas views editar e cadastrar.