Escolar Documentos
Profissional Documentos
Cultura Documentos
AntiPadrões e Refactorização (Grupo 3)
AntiPadrões e Refactorização (Grupo 3)
Resumo
1. - Introdução
"O que é um Anti-Padrão de Software e Refactorização ?"
Como causa de muitos dos problemas encontrados, estão o que se designa por "7 Pecados
Mortais":
1
- "A Preguiça" - A utilização das soluções mais simples e
menos trabalhosas ao invés das adequadas.
2
para a sua resolução. Alguns autores denominam como Pseudo-Anti-Padrão a todos aqueles
que apenas oferecem estratégias para detecção e não apresentam metodologias para correcção.
A esses processos de correcção é dado o nome de reengenharia ou refactorização (" Software
Refactoring").
1.- Introdução
2.- Anti-Padrão de Desenvolvimento "Lava Flow" - Descrição deste Anti-Padrão
3.- Anti-Padrão de Arquitectura "Jumble" - Descrição deste Anti-Padrão
4.- Padrão de Refactorização "Moving Features Between Objects" - Descrição deste Padrão
5.- Conclusões
Muitas vezes as equipas de desenvolvimento não seguem as regras de boas práticas durante o
processo de programação o que leva a situações de uma quase total incompreensão de
funcionamento do Sistema e do código que o suporta.
Este Anti-Padrão é identificado ao nível aplicacional e é também designado por "Dead Code"
(código morto). É muitas vezes encontrado em Sistemas (ou partes de um Sistema) que são
originalmente desenvolvidos como métodos de investigação mas que acabam em produção.
Caracteriza-se por resultar de fluxos de versões implementadas e ao longo das quais vai ficando
código que não é documentado e que poucos, ou ninguém sabe posteriormente qual a sua
funcionalidade, código que não é utilizado, excertos com comentários não compreensíveis, entre
outras causas. A analogia com a expressão "Fluxo de Lava" resulta do facto de, estes tipos de
incoerências terem um efeito similar ao da lava de um vulcão, ou seja, ao longo do processo de
desenvolvimento, actualização e manutenção de um Sistema vão se criando como que rochas de
código que já ninguém consegue ou quer remover.
3
Este Anti-Padrão é muito encontrado em Sistemas com alguns anos e nos quais, as equipas de
desenvolvimento, estando ainda em fase de pesquisa, procuravam várias soluções para atingir
um determinado objectivo, muitas vezes com o único intento de conseguir protótipos para
realizar uma demonstração descurando aspectos importantes como a documentação. O código
então desenvolvido ia ficando não sendo removido ou sequer documentado... predominava
então a lógica de "Se está a funcionar é melhor deixar ficar como está...".
Destas situações resulta um código fragmentado, classes e procedimentos que não são
imediatamente enquadráveis com o Sistema, variáveis não utilizadas, etc.. Os fluxos de código
que daqui derivam são muitas vezes de uma complexidade tal que dão a ideia de se estar perante
algo realmente importante no Sistema mas que na realidade ninguém sabe explicar o que faz ou
porque existe.
No entanto este tipo de atitude apenas agrava o problema aumentando o "Fluxo de Lava" do
Sistema e é, naturalmente, uma má prática por várias razões:
4
O código que se vai "deixando estar" pode se tornar extremamente pesado em termos de
memória consumida comprometendo o desempenho do Sistema
Ao reutilizar código acabamos por estar a proliferar o "Código Morto" aumentando o
"Fluxo de Lava"
Os "Fluxos de Lava" são difíceis de analisar, verificar e testar consumindo muito tempo
e, consequentemente, recursos financeiros e humanos.
Consequências
Principais Causas
5
Tendo em vista a realização de demonstrações dentro dos prazos existe muitas vezes
uma tendência a efectuar precipitadamente alterações ao código. Este código não é
posteriormente revisto comprometendo a Arquitectura definida não sendo produzida
qualquer documentação que justifique as alterações realizadas.
Falhas na Arquitectura definida. Alguns dos compromissos assumidos durante a fase de
Análise de Requisitos revelam-se ao fim de muito trabalho desenvolvido inviáveis.
Muitas vezes o código produzido até então não é removido
Solução de Refactorização
Durante o processo de eliminação do "Código Morto" surgem muitas vezes "bugs" no Sistema.
Quando tal acontecer, deverá evitar-se ao máximo a correcção desse erro sem antes perceber
totalmente a causa do mesmo. Devemos investigar todas as dependências que o código
removido possuía pois, desta forma, iremos conseguir definir com maior clareza a Arquitectura
que deverá ser implementada.
6
Em todos os Anti-Padrões a prevenção é sempre mais barata do que a correcção. É portanto
fundamental que em qualquer Projecto se faça um forte investimento numa boa Arquitectura e
na formação das equipas de desenvolvimento logo no começo.
Solução de Refactorização
7
Um equilíbrio entre os elementos horizontais, verticais e metadados numa Arquitectura conduz-
nos a um Software bem estruturado, reutilizável e escalável.
São definidos oito processos de quando e como realizar essas operações. A descrição de
quando usar cada um dos processos é a seguir apresentada.
"Move Method"
Quando um método utiliza mais recursos de outra classe do que na que está definido ou,
quando um método será usado mais vezes por outra classe do que na que está definido.
Ao movermos métodos podemos fazer classes mais simples tornando mais nítida a
implementação de responsabilidades de cada uma. No entanto, devemos ponderar sempre se ao
efectuar este processo estamos realmente a obter algum ganho no nosso Sistema.
"Move Field"
Devemos utilizar este processo quando verificamos que um determinado campo é, ou será,
usado mais por outra classe do que na qual está definido.
Criamos um novo campo da segunda classe, alteramos em todos os locais onde era utilizado e
removemo-lo da primeira classe.
8
Deveremos ponderar mover um determinado campo quando constatamos que existem mais
métodos noutra classe a utilizá-lo. Essa utilização pode ser indirecta com o objectivo de obter
ou definir métodos. Se verificarmos que tal movimentação faz sentido então deveremos fazê-la.
"Extract Class"
Verificando que possuímos uma classe que faz o trabalho de duas deveremos utilizar este
processo.
Criamos uma nova classe e movemos os campos e métodos relevantes da primeira para a nova
classe.
Este processo deve ser utilizado quando uma classe tem muitos métodos e muitos dados, ou
seja, quando uma classe se tornou demasiado grande e complexa para ser facilmente
compreendida.
"Inline Class"
Em situações em que existam classes que têm poucas funcionalidades deveremos removê-las.
Este processo é o inverso do "Extract Class" e deve ser utilizado sempre que constatamos que
uma determinada classe contribui pouco para o Sistema. Estas classes resultam muitas vezes do
próprio processo de refactorização que vai movimentando responsabilidades de uma classe para
outras até a deixar praticamente sem funcionalidade. A classe de destino deverá ser aquela que
mais utilizará os recursos da primeira.
9
"Hide Delegate"
Quando existem situações onde estamos a invocar métodos de duas classes distintas de forma a
obter uma determinada informação devemos utilizar este processo.
Com este processo podemos melhorar substancialmente o nosso Sistema tornando-o resistente
a alterações.
Utilizar quando uma classe ("servidor") está a fazer demasiadas delegações para uma terceira.
10
No processo anterior ("Hide Delegate") era mencionadas as vantagens do encapsulamento, no
entanto existem também desvantagens. No exemplo dado, sempre que um "cliente" desejar um
novo recurso da terceira classe teremos que adicionar um novo método ao "servidor". Depois de
adicionar vários métodos podemos atingir uma situação em que não se revela produtivo ter um
intermediário. Neste caso deveremos ponderar invocar o método directamente. Estes dois
processos ("Remove Middle Man" e "Hide Delegate") devem ser usados de forma equilibrada
ao longo do desenvolvimento do Sistema.
Quando necessitamos adicionar um método a uma determinada classe mas não a podemos
alterar deveremos utilizar este processo.
Criamos o método na classe "cliente" com uma instância da classe "servidor" como primeiro
argumento.
Esta situação ocorre muitas vezes. Podem existir momentos em que necessitamos de adicionar
um novo método mas não podemos alterar o código dessa classe. Isto acontece, por exemplo,
em situações onde o código pertence a terceiros estando protegido por direitos de autor. De
forma a contornar esta situação devemos utilizar este processo.
Se chegarmos a um ponto em que tivemos que utilizar muitas vezes este processo devemos
ponderar a utilização do processo "Introduce Local Extension" ou então solicitar a quem detém
os direitos do código que introduza os métodos em questão.
Devemos utilizar este processo quando necessitamos de adicionar vários métodos a uma
determinada classe mas não a podemos alterar.
Criamos uma nova classe que contém os métodos extra. Fazemos desta classe uma subclasse da
primeira.
11
Uma extensão local ("Local Extension") é uma classe separada mas que é um subtipo da classe
que é estendida. Isto significa que ela suporta tudo o que a classe original faz e acrescenta novas
funcionalidades. Em situações em que apenas necessitamos de adicionar 2 ou 3 novos métodos
devemos ponderar a utilização do processo "Introduce Foreign Method".
5. - Conclusões
12
REFERÊNCIAS
[1]
Texto adaptado de http://sourcemaking.com/antipatterns/lava-flow
[2]
Texto adaptado de http://sourcemaking.com/antipatterns/jumble
[3]
Texto adaptado de http://sourcemaking.com/refactoring/moving-features-between-objects
13