A maximização da reutilização tem sempre sido uma importante meta de desenvolvimento de software. É melhor reutilizar o
design e o código existentes do que despender recursos na criação, teste, e primeira liberação de algo novo com o risco
dos problemas ocultos que todos os novos softwares têm. As linguagens, especialmente as orientadas a objetos, foram
desenvolvidas para tornar a reutilização mais fácil. Mas somente a linguagem não é suficiente para fornecer uma
reutilização de custo eficaz. A maior parte do software reutilizável vem de arquitetos e desenvolvedores qualificados
que são capazes de identificar e alavancar oportunidades de reutilização.
Existem três perspectivas a serem consideradas quando da reutilização de software: código (implementação), design e
framework ou arquitetura. Os arquitetos devem buscar a reutilização de significantes frameworks de aplicação, tais como
camadas que pode ser aplicadas a muitos tipos diferentes de aplicações. Os desenvolvedores devem buscar os designs e
padrões que possam ser reutilizados para produzir o comportamento desejado ou estruturas robustas. Eles devem também
procurar uma forma de reduzir a quantidade de código a ser escrito pela alavancagem de código e componentes estáveis
que tenham sido usados com sucesso em ambientes de produção.
Identificando Oportunidades de Reutilização
A melhor forma de permitir que uma equipe encontre oportunidades de reutilização é exercer excelentes práticas de
design e programação. É difícil encontrar código e design que possam ser reutilizados quando se trata de classes
grandes, classes que não possuem um foco bem definido ou classes com relacionamentos que são difíceis de compreender.
As classes devem ser pequenas, de fácil compreensão e altamente coesas para facilitar a identificação de oportunidades
de reutilização. Qualquer funcionalidade que possa ser razoavelmente separada em outra classe, deve ser. Outra forma de
dizer isto é que qualquer conceito que possa ser aplicado a mais de um tipo de classe deve ter a sua própria classe.
Por exemplo, se alguns cálculos são adicionados a uma classe existente, pode fazer sentido a re-fatoração desses
cálculos em uma nova classe auxiliar. Esses cálculos podem então ser reutilizados em qualquer outra classe, sem o ônus
do conhecimento da funcionalidade da classe original.
A forma mais simples, porem menos eficiente para identificar oportunidades de reutilização é "cheirar" código
semelhante. Um desenvolvedor deve recordar de algo que fez semelhante ao que está projetando ou implementado agora. Uma
vez que a implementação anterior tenha sido descoberta ou recordada ela poderá ser reutilizada. Os desenvolvedores
sempre encontrarão oportunidades de reutilização desta forma. Mas a sua natureza não estruturada não maximizará as
áreas potenciais de reutilização.
A colaboração é uma boa técnica para identificar oportunidades de reutilização. Ela fornece uma estrutura onde a
identificação da reutilização - ao invés da escrita de código - seja a meta do exercício. E quanto mais pessoas
estiverem procurando por oportunidades de reutilização, mais provável será que elas sejam encontradas. Um brainstorming
ou uma reunião de revisão, que se concentre na identificação de oportunidades de reutilização, pode ser útil para a
consecução desta meta.
Os padrões são boas formas para encontrar oportunidades de reutilização no design e no framework.
A análise do comportamento é uma outra boa forma para identificar áreas potenciais para reutilização. Analise como as
classes precisam colaborar para fornecer alguma funcionalidade específica, tal como um requisito ou característica.
Esta colaboração pode ser documentada em diagramas de seqüência (comportamento) e classe (estrutura) e podem ser
reutilizadas em circunstâncias semelhantes.
A Refatoração deve sempre ser considerada quando da reutilização de código. O código
(ou o design) muitas vezes não é escrito originalmente para ser reutilizado, ou um código reutilizável pode não se
ajustar perfeitamente a uma nova situação.
Técnicas de Reutilização
A reutilização pode ser executada de formas diferentes, dependendo da capacidade do ambiente de implementação. A
técnica é mais simples é copiar o código de um lugar para outro. Isso não é aconselhável, pois não é realmente
reutilização. Várias cópias de código fonte são difíceis de manter e eventualmente podem divergir umas das outras. A
reutilização significa o uso do mesmo código para executar tarefas semelhantes, como forma de aumentar a qualidade e
reduzir a sobrecarga.
Algumas linguagens, como o C++, suportam templates. Os Templates, às vezes referenciados como código parametrizado, são
precursores dos padrões. Um template é um código com parâmetros que é aplicado apenas quando for necessário, em tempo
de compilação. A Biblioteca Padrão de Templates (STL) do C++ é um exemplo. Ela fornece muitos tipos de contêineres
reutilizáveis (listas, conjuntos, arrays seguros, etc) que não possuem alguns dos inconvenientes da herança. Os
templates, tais como estes, também são úteis como classes de mixagem em linguagens como o C++ que suportam herança
múltipla. Pelo fato das mixagens serem implementadas como templates, elas permitem um tipo de herança múltipla sem a
bagagem.
Herança e Agregação
Herança (também conhecida como generalização) é uma forma fácil de implementar polimorfismo e tem sido usada como o
principal mecanismo de reutilização nas modernas linguagens orientadas a objeto. Isso é lamentável, visto que a herança
impõe uma estrutura rígida no design de software que é difícil de alterar. Qualquer hierarquia de herança que
compartilhe código das classes pai para as classes filho terá problemas quando tiverem três ou mais níveis
hierárquicos. Muitas exceções ocorrer para manter um puro relacionamento "é-um" entre classes pai e filho, onde se
considera que as classes filho tenham sempre todas as propriedades e comportamentos dos pais. A herança deve ser usada
para compartilhar definições (interfaces) e não implementações. Anos de dificuldades com implementações de herdando
tornaram essa prática um princípio primário de design orientado a objeto.
Sempre que a herança for utilizada, é melhor ser instanciada apenas a última classe filho (nó folha) da hierarquia de
herança. Todas as classes pai devem ser abstratas. Isso acontece porque a classe que tenta ser reutilizável e concreta
- para fornecer comportamento específico e reutilizável ao mesmo tempo - quase sempre deixa de cumprir suas metas. Isto
é uma dimensão da coesão. Uma coisa que torna uma classe coesa é que ela seja dedicada a reutilização ou dedicada a uma
implementação específica, mas não a ambas.
A agregação é uma técnica que reúne ou agrega a funcionalidade em elementos maiores de funcionalidade. Ela fornece uma
estrutura que é muito mais flexível e reutilizável do que a herança. É melhor reutilizar a implementação e o design
agregando pequenos pedaços de funcionalidade em conjunto ao invés de tentar herdar a funcionalidade de uma classe pai.
Você também poderá encontrar oportunidades de reutilização, revisando as interfaces. Se as interfaces descreverem
comportamento semelhante, pode ser possível eliminar uma das interfaces, tendo apenas uma implementação que realiza
ambas as interfaces, ou re-fatorando as interfaces para colocar o conteúdo redundante em uma nova interface mais
simples.
Encontrando Código Reutilizável
Existem várias fontes de código reutilizável sem ser o que os desenvolvedores estão escrevendo para um projeto
específico. Outros locais para coleta de código são:
-
Bibliotecas internas (corporativas) de código.
-
Bibliotecas de terceiros
-
Bibliotecas embutidas nas linguagens
-
Exemplos de código extraídos de tutoriais, telas de ajuda, livros, etc.
-
Um guru local ou colega com bastante conhecimento de código
-
Código existente nos sistemas
-
Produtos de código aberto (tenha certeza de estar respeitando os acordos de licenciamento)
Também, muitas ferramentas capazes de gerar código poderão gerar código compreensível baseadas em especificações
mínimas. Por exemplo, uma ferramenta de design poderia gerar um atributo com os métodos get e set assim que o Designer
tivesse especificado-o. Outras ferramentas mais sofisticadas, com conhecimento de um framework específico, poderiam
gerar código volumoso para garantir que a classe esteja em conformidade com o framework. Um exemplo poderia ser uma
ferramenta que gerasse código adicional significante quando uma classe fosse definida como sendo uma entidade Java
Bean. Este tipo de transformação consistente, de uma especificação (o design) para uma implementação (o código), pode
também ser considerado uma forma de reutilização de código.
Não Reutilize Tudo
A reutilização torna o código e o design mais baratos de usar, porém mais caros para construir. Exige experiência e
ponderada consideração para criar uma implementação ou design que seja suficientemente abstrato para que outros possam
reutilizar, mas concretos o suficiente para serem verdadeiramente úteis. O código reutilizável também deve ser mantido.
Muitas organizações terão dificuldade em atribuir responsabilidade para a manutenção de código reutilizável, se não
tiverem um grupo dedicado a reutilização.
Normalmente não é uma boa idéia criar código ou design para reutilização, a menos que você saiba que ele será
reutilizado. É melhor re-fatorar o software para ser mais reutilizável após ter sido descoberto que ele pode ser
reutilizado. Uma regra de ouro é escrever pensando em reutilização só quando você souber que vai reutilizar o código
pelo menos 3 vezes. Caso contrário, o custo de construção e manutenção de parte do software não será recuperado pela
redução da sobrecarga em outras áreas de desenvolvimento.
|