A Importância do Reuso em Software


 

É muito comum acharmos nos livros de desenvolvimento de sistemas e de engenharia artesanato de software a defesa de que devemos preparar o software para reuso. No entanto, muitas vezes não fica claro como realizar isso na prática. É preciso entender que existem diferentes níveis de reuso, e mesmo copiar o código feito anteriormente e colar em um novo programa é um tipo de reuso (incipiente.)

A principal causa da incapacidade para desenvolver módulos reutilizáveis está na dificuldade de pensar antes de escrever o código o que acarreta em soluções específicas na maior parte das vezes. Com a entrada em produção, a cada manutenção o sistema vai ficando cada vez mais específico até que chega ao ponto de não ser mais possível modificá-lo e um novo sistema torna-se necessário.

Então antes de explorar possíveis soluções para o reuso, é interessante conhecer os níveis, em ordem crescente de qualidade, de reuso que podem ser considerados para uma aplicação:

  1. Diferentes implementações de um algoritmo – independente de serem feitas em linguagens iguais ou diferentes, existir mais de uma implementação de um algoritmo exige controlar em um nível mais abstrato as correções que podem ser feitas em uma das implementações. Além disso temos que identificar se uma correção que acontece uma versão refere-se a um erro no algoritmo ou especificamente daquela implementação.
  2. Cópia de código – uma vez dada a solução para um problema ela é copiada do código fonte do programa original e colada no programa novo. O primeiro problema está no fato de que passam a existir duas versões da solução que precisam ser mantidas, eventualmente essa manutenção acaba por não ser mais controlada e alterações podem ser feitas em apenas uma das várias cópias possíveis, além disso as novas versões ganham vida própria e vão sendo adaptadas até que se tornam soluções completamente diferentes da versão original.
  3. Uso de herança ou composição – isso está relacionado ao uso de linguagens orientadas a objetos uma vez que essas linguagens têm a capacidade de organizar e agrupar as funcionalidades. O problema dessa técnica é que muitas vezes acabamos por querer utilizar as classes em outros sistemas e acabamos por copiar as classes, voltando para o nível 2. As duas técnicas promovem efeitos semelhantes, mas são semanticamente diferentes:
    1. Herança – uma nova classe é desenvolvida e considerada como uma especialização da classe superior na hierarquia, assim, todo o código disponível para a super classe está disponível para a subclasse (mesmo que não esteja diretamente acessível.) Dessa maneira nos concentramos em fazer as partes novas do código ter que copiar o código feito anteriormente, a infraestrutura da linguagem se encarrega de fornecer os meios para tornar o código acessível. O conceito chave aqui é a relação “é-um,” ou seja, a subclasse é do mesmo tipo que a superclasse.
    2. Composição – uma nova classe é desenvolvida e considerada como cliente da classe anterior, não existe a visão hierárquica, mas através de um atributo a classe anterior pode ser utilizada evitando que tenhamos que copiar o código que já foi criado. O conceito chave aqui é a relação “tem-um,” ou seja, a nova classe tem um objeto da classe anterior e por isso pode usar seus serviços a seu favor compondo novos métodos.
  4. Gerar bibliotecas – para evitar de copiar as classes de um sistema para outro, podemos isolar o código em bibliotecas mais genéricas e usar essas bibliotecas, já compiladas, em mais de um projeto. Essa abordagem tem a vantagem de manter uma única versão de código em desenvolvimento, mas traz a questão de gerenciar as diferentes versões que foram instaladas em cada um dos sistemas que utilizam a biblioteca. Isso fica claro quando aparecem conflitos entre versões diferentes de DLLs no Windows.
  5. Uso de frameworks – essa abordagem se baseia em usar bibliotecas que fornecem um conjunto de funcionalidades básicas para um certo tipo de sistema de forma que seja possível incluir apenas a lógica da aplicação que está sendo desenvolvida. No entanto é necessário aprender a usar todos os detalhes do framework.
  6. Uso de componentes – essa técnica depende de mais apoio da infraestrutura de software, isto porque componentes são artefatos auto-contidos, com uma função e interface bem definidas, porém que dependem de um contêiner para executar, ou seja, não são partes de sistema completas, precisam de serviços base para executar e assim, oferecer seus serviços. A vantagem de usar componentes é que permitem seu uso de forma remota, isto porque não são instalados junto com a aplicação, ao invés disso a aplicação acessa o contêiner onde os componentes estão instalados e requisita seus serviços. A maior desvantagem é o aumento na complexidade para o desenvolvimento e manter mais de uma versão, isso porque se mudarmos uma versão de componente no servidor, forçamos que todas as aplicações sejam atualizadas. No entanto nem sempre a atualização de uma aplicação cliente é possível ou desejável.
  7. Uso de serviços – expor componentes na forma de serviços permite criar funcionalidades maiores a partir da composição dos diversos componentes com uma visão maior em termos de objetivos de negócio. Pode-se até mesmo utilizar webservices para expor via internet os serviços permitindo a interconexão de sistemas de organizações diferentes a fim de construir um sistema maior.

Conhecendo as possibilidades e níveis de abstração, o problema de reuso torna-se uma questão de escolha, mas porque alguém iria querer reusar software? A resposta é muito simples, conforme os sistemas vão sendo desenvolvidos e colocados em produção vão sendo testados na prática e depois de um tempo a melhor opção para realizar uma tarefa é usar o mesmo código já pronto simplesmente porque ele funciona!

Como o desenvolvimento de sistemas é uma atividade cara quanto mais partes de código tivermos, já testadas, maiores as chances de terminar o projeto no prazo e com sucesso. A medida que são criados mais e mais sistemas, maior será a quantidade de código já testado pronto para usar e isso se transforma em uma vantagem competitiva para a própria empresa.

One comments

  1. Excelente artigo Paulo. Gostei de como voce descreveu e comentou sobre varias formas de reuso de codigo.

    E engracado como tantos desenvolvedores tem verdadeira aversao a usar codigo “velho” e acabam por reinventar a roda todos os dias.

    Outro comentario, esse meio off-topic: seria legal se alguns dos seus posts, como esse, fossem traduzidos para o Ingles (infelizmente para nos tupiniquins, A lingua franca em TI) para aumentar a sua audiencia. Mas, se para manter um blog ja da trabalho, dois entao fica dificil!

    Um abraco!

Leave a Reply