Reutilização de software
(12/12/01 – Versão 4.0)
Relatório final
Nuno Ferreira – [email protected] João Peixoto – [email protected]
Henri Costa – [email protected] Tiago Silva – [email protected] Miguel David – [email protected] Eduardo Abreu – [email protected]
Prefácio
Este projecto foi um dos raros projectos de investigação que tivemos desde que entrámos na faculdade. Além disso foi um trabalho com princípio, meio e fim, com um plano e datas a sério desde o princípio, coisa que não é muito costume nos outros trabalhos. Por isso mesmo é um trabalho diferente, fundamentalmente um trabalho que serviu para aprendermos algo sobre a reutilização de software.
O trabalho está dividido em 4 partes principais. A reutilização como tópico geral e os três subtópicos dessa que foram tratados pelos vários elementos do grupo da forma como está indicado no nosso sítio web. Começamos, assim, pelo tópico mais geral (a reutilização) passando depois aos subtópicos de uma forma gradativa, do mais geral para o mais particular (frameworks, padrões, componentes).
Tentámos também abordar este relatório de forma a que uma pessoa que nunca tivesse ouvido falar de reutilização passasse a saber algo do assunto de uma forma relativamente simples.
Mantivemos alguma da nomenclatura anglo-saxónica que encontrámos dado o risco de ao traduzirmos para português ficar com um sentido que não o desejado (como costuma acontecer em traduções técnicas).
O que resultou dessa aprendizagem sobre reutilização segue-se ...
Sumário
Prefácio... 2
1. Objectivos... 4
2. Reutilização ... 5
2.1 Introdução... 5
2.2 Os custos da reutilização ... 6
3. Frameworks ... 8
3.1 Introdução... 8
3.2 O que é um framework ? ... 8
3.3 Estrutura de um framework ... 8
3.4 Model framework ... 9
3.4.1 Model frameworks de tipos e atributos ... 10
3.5 Collaboration frameworks ... 13
3.5.1 Aplicação de Collaboration frameworks ... 15
3.6 Refinamento de frameworks... 17
3.7 Conclusões... 19
4. Padrões ... 20
4.1 Introdução... 20
4.2 Objectivos... 20
4.3 Especificação de Padrões de Software... 21
4.4 Aplicações - o padrão de software Iterador ... 22
4.5 Conclusões... 23
5. Componentes ... 24
5.1 Introdução... 24
5.2 Definição ... 24
5.2.1 Em que é que um componente difere de uma aplicação ?... 25
5.3 A evolução dos componentes ... 25
5.4 Vantagens e desvantagens ... 27
5.5 Aplicações reais... 28
6. Conclusões... 29
6. Agradecimentos ... 30
7. Bibliografia... 30
7.1 Livros... 30
7.2 Internet... 30
1. Objectivos
No presente trabalho pretende-se introduzir a reutilização de software nas suas formalizações mais comuns: os frameworks, os padrões de desenho e os componentes.
Além disto pretende-se produzir um documento que seja acessível a uma pessoa que nunca tenha lidado com reutilização antes e até com pouca experiência de reutilização.
Com isto esperamos trazer alguma luz sobre a reutilização de software, assunto tão pouco falado (e ainda menos utilizado) por cá.
2. Reutilização 2.1 Introdução
O desenvolvimento de software pode ser visto como uma actividade de resolução de problemas, sendo os problemas encontrar a implementação que satisfaça os requisitos dos utilizadores. Sabe-se que uma das formas mais importantes de que o Homem dispõe para resolver os seus problemas é a memória que guarda de problemas por que passou anteriormente. Assim, quando alguém se depara com um problema, a primeira coisa que faz para o resolver é verificar se já passou antes pela mesma situação e qual foi a solução então adoptada. Caso nunca tenha passado pela mesma situação, procura situações por que já passou e que sejam análogas àquela com que se depara, adoptando as mesmas soluções, mas adaptadas ao contexto na nova situação.
A Reutilização de Software pretende formalizar a memória dos criadores de software e disponibilizá-la a todos os programadores.
Os problemas por que um criador de software passa podem ser a vários níveis: ao nível de todo o processo e organização do projecto de desenvolvimento de software ao nível conceptual do sistema (estruturas, componentes e organização entre os componentes) ao nível de código a utilizar.
Assim, a reutilização de software consiste, não apenas em pedaços de código catalogados, nem em componentes, mas sim em toda a experiência adquirida a todos os níveis no desenvolvimento de software.
A reutilização de software, mesmo que informalmente, começou praticamente desde que começou o desenvolvimento de software, uma vez que a utilização de bibliotecas de código, ferramentas de software e até linguagens de programação podem ser vistos como reutilização de software. Esta constante reutilização de software permitiu que as práticas de desenvolvimento de software se desenvolvessem e que o software desenvolvido hoje em dia seja cada vez mais complexo e completo e que satisfaça cada vez mais as exigências do mercado. Mas mesmo assim, falta capacidade de resposta da indústria de software às exigências, quer de qualidade, quer de produtividade, impostas pelo mercado.
2.2 Os custos da reutilização
Reutilização de software parece fazer sentido, mas muitas empresas vêm que há tanto trabalho envolvido no assunto que não vale a pena o esforço ! -- John W. Smith
A reutilização de código tem sido o objectivo da maioria das empresas de desenvolvimento de software, mas na realidade a reutilização à grande escala não tem acontecido. Isto porque os gestores de desenvolvimento nem sequer põem essa questão.
O problema é que o esforço de construir uma parte reutilizável é três vezes superior ao de desenvolver uma parte normal. Por isso, a não ser que se planeie usar essa parte repetidamente, não vale mesmo a pena !
A Cutter Information Group, uma empresa de pesquisas sobre tecnologia fez uma sondagem a 120 empresas de software e 80 dessas empresas disseram que apenas adoptaram a programação orientada a objectos porque têm como objectivo final a reutilização de software. Sondagens semelhantes concluíram que as falhas de software diminuem drasticamente com os sucessivos esforços para o desenvolvimento da aplicação. Isto é, na primeira vez que se faz uma aplicação ela aparece cheia de "bugs", enquanto que após um refinamento já aparecem menos "bugs" e assim sucessivamente.
Isto leva a pensar que seria melhor se pudéssemos já pegar em pedaços de código testado exaustivamente e pronto a usar.
A gigante dos filmes 20th Century Fox é um exemplo de um bom resultado de reutilização. Puseram uma equipa a desenvolver um componente reutilizável para reunir informação sobre talentos, agências e organizações - os aspectos mais importantes do dia-a-dia para esta empresa. O resultado foi que essa aplicação demorou muito mais tempo a desenvolver que uma aplicação normal, no entanto, uma vez feita, tem sido utilizada para inúmeras aplicações da empresa, vezes sem conta. Uma aplicação só precisava do endereço de uma pessoa. Outra precisava do endereço e informação sobre as diferentes actividades e contactos com uma determinada pessoa. E por aí fora.
Mas a reutilização nem sempre compensa, tudo depende da natureza da organização, da sua experiência em gerir desenvolvimento de software e o tipo de reutilização que procura.
Por exemplo, a reutilização de componentes gráficos parece uma aposta ganha.
Tomemos o Swing (parte gráfica da linguagem Java): a entidade botão, caixa de diálogo, barra de scroll, etc, são reutilizadas inúmeras vezes, muitas delas num mesmo programa !
O que dá um maior valor de retorno são aplicações com a lógica de negócio. São componentes muito complexos com aspectos que vão desde a estrutura de preços da empresa ao modo de vendas, etc. Apesar de serem componentes de desenvolvimento complicado que muitas vezes necessitam de uma reengenharia da própria empresa antes
de serem desenvolvidos, têm um grau de reutilização muito elevado, uma vez que vão constar de todas as aplicações dessa empresa.
O problema é que poucas pessoas estão dispostas a perder tempo valioso quando estão a trabalhar sob prazos para desenvolver algo que é mais geral e pode vir a ser usado mais tarde.
O ideal da reutilização, se é que existe, só aparecerá quando as empresas tiverem padrões de desenho e uma arquitectura própria. Só aí é que os programadores passarão mais tempo a pensar no negócio do que a lutar com a implementação.
3. Frameworks 3.1 Introdução
Não são apenas as grandes porções de código que podem ser transformados em programas reutilizáveis. Os designs e as especificações, também podem ser separados em partes, que podem ser guardadas numa biblioteca e subsequentemente combinadas em várias configurações diferentes. Chamamos a isto model frameworks.
A ferramenta básica para representar e combinar frameworks é uma forma genérica de packages, chamados framework ou modelo package. Isto é, pedaços de design que se combinam para produzir apenas designs, e continuam a precisar de ser implementados.
Mas temos que concordar que o desenho ou arquitectura de um projecto representam a maior parte das grandes decisões que vão condicionar o código final e assim ser capaz de produzir um design a partir de várias partes pré-fabricadas, é uma vantagem valiosa.
3.2 O que é um framework ?
Um framework é um pacote pré-definido que foi concebido para ser utilizado com alterações (ou “customizações”) de acordo com as necessidades do utilizador.
Um framework pode abstrair a descrição de um tipo genérico, uma família ou tipos mutuamente dependentes, um refinamento de um padrão, ou até um conjunto de propriedades genéricas fundamentais (como a associativa, a comutativa, etc.).
Os Frameworks são, eles próprios, construídos através de outros frameworks.
Mais genericamente, a estrutura de um framework representa a base para a organização de todos os modelos.
3.3 Estrutura de um framework
Um model framework é um pacote genérico que contém definições normais e placeholders. Um placeholder é um nome que pode ser substituído quando os frameworks são usados. Cada uso ou aplicação de um framework possibilita por ele próprio a substituição dos placeholders. Os nomes dos atributos e associações dos placeholders são eles próprios placeholders.
No framework, uma aplicação só tem significado se os requisitos estão de acordo com as substituições possíveis no framework. Uma justificação deve ser aplicada a cada aplicação para documentar como os requisitos são atingidos.
3.4 Model framework
Depois de modelar e desenhar sistemas de objectos durante bastante tempo, começa- se a notar que existe um certo padrão neste tipo de operação. Podemos verificar que existe o mesmo conjunto de relações e restrições, chamamos a este conjunto de relações model framework. Muitos padrões de desenho bastante populares originam model frameworks1.
Uma ferramenta adequada deve possuir a capacidade de suportar a construção de modelos e designs através da aplicação de model frameworks (ou modelos).
Suponhamos, por exemplo, que o nosso modelo de negócio tem um tipo Stock com um atributo numérico Level, ao escolher um pacote constituído por partes de interface de utilizador, encontramos um tipo Meter para mostrar leituras de valores numéricos.
Agora queremos especificar que Meters pode ser usado para mostrar níveis do Stock, usando padrões pré-determinados. Como é normal, podemos concentrar diferentes aspectos de um modelo específico em diagramas diferentes, para que não seja necessário repetir tudo o que já foi dito acerca dos dois tipos. Apenas será necessário definir os atributos extra e as operações necessárias para fazer a ligação entre eles.
É aqui que os model frameworks são muito úteis. Vamos supor que Observation é um padrão bastante conhecido e que o usamos no exemplo dado no parágrafo anterior, então definimos um model framework para Observation e usando este padrão obtemos uma forma abreviada de definir as nossas necessidades (ver figura 1).
1.Exemplo de uma aplicação de um model framework.
O veículo para atingir um framework é uma forma de package genérica ou modelo.
Dentro do modelo podemos definir alguns tipos e funcionalidades através de funções.
Analisando a figura 1 verificamos que o modelo Observation tem duas funções (Subject e Observer). Neste caso importamos esse pacote substituindo Stock e Meter.
A definição substituída torna-se parte integrante do modelo definido. Por outras palavras, quaisquer atributos e operações que são definidas para Subject ficam também definidas para Stock dentro do modelo. Este modelo usa um atributo chamado value
1 Em português seria algo como “caixilhos de modelos”.
para a parte do Subject que nós pretendemos observar, então substituimo-lo pelo nível do Stock.
O que o framework Observation faz é representar um grupo de decisões do design sobre como dois tipos de objectos devem colaborar para que seja atingido o efeito pretendido. Neste framework não é discutido qualquer outro tipo de regras ou interacção entre estes dois objectos. Através deste framework separamos este design de qualquer outro domínio específico. Este é um dos usos mais frequentes dos model frameworks.
Um padrão é um conjunto de ideias que podem ser usadas em muitas situações.
Geralmente no coração de muitos padrões está um framework, mas um padrão também inclui material menos formal acerca de estratégias alternativas, informação sobre quando usá-los e muito mais. Quando se guarda um framework numa biblioteca, ele deve estar empacotado com alguma documentação útil.
Algumas linguagens de programação têm class modelos ou generic classes, o UML também as possui. Apesar de a notação ser um pouco diferente, uma class modelo não passa de um model framework que contém apenas uma classe.
Ferramentas que suportam model frameworks e modelos devem proporcionar ao utilizador a capacidade de desempacotar cada aplicação do model framework de forma a que seja possível visualizar o modelo final com todas as alterações efectuadas.
Idealmente, a ferramenta deve guardar a informação do framework, as definições originais do tipo sobre o qual são aplicadas alterações, e quais os diagramas de cada framework foram aplicados. Se o utilizador alterar algum destes atributos o modelo resultante também deve ser alterado. Além disto a ferramenta deve permitir que o utilizador defina os seus próprios frameworks na mesma notação que os modelos existentes.
Em suma, os modelos fornecem uma maneira poderosa para reutilizar model frameworks, quer num nível mais abstracto quer num detalhe do design. Em particular, os modelos são uma forma bastante eficiente de definir relações entre tipos. É uma forma acessível de representar as relações entre os diferentes tipos num diagrama.
3.4.1 Model frameworks de tipos e atributos
Vamos supor que uma empresa de canalização nos pede para realizar uma análise do seu negócio para obter suporte informático. Depois de um dia ou dois a trabalhar com eles, chega-se ao modelo central que está ilustrado na figura 2.
2. Modelo para alocar canalizadores para realizar trabalhos.
Cada canalizador (Plumber) possui uma agenda para fazer uma lista de tarefas (Job), cada uma destas tarefas é realizada numa determinada data para um determinado cliente (Customer). Há alguns tipos de trabalho distintos, e cada um deles possui uma descrição (Job Description). Entre outras coisas, este modelo indica quais as competências técnicas (Skill) que são necessárias para realizar a tarefa. Cada canalizador está qualificado com uma lista de competências técnicas, portanto não deve ser atribuída uma tarefa a um canalizador que não possui as competências necessárias para a realizar.2
Num outro exemplo temos uma organização de ensino comercial. No decorrer do desenvolvimento deste projecto apercebemo-nos que existem partes dos dois modelos que partilham a mesma lógica de negócio.
Portanto, generalizamos o nosso modelo e transformamo-lo num framework através de um pacote normalizado, como o da figura 3.
Agora, o nosso modelo de canalização pode ser facilmente criado através de uma aplicação de um framework (figura 4).
Podemos verificar que vários nomes pertencentes à definição do framework se encontra entre estes os dois sinais ‘<’ e ’>’. Estes são o que se pode chamar de placeholders e devem ser identificados através de nomes de tipos quando o este modelo for aplicado.
No modelo final, cada tipo possui todas as funções definidas para ele explicitamente (como os Job Customers no nosso exemplo) e também possui as funções definidas pelo framework. A esta tarefa de completar o modelo damos o nome de unfolding.
2 De notar que um modelo possui muito mais informação que a demonstrada no parágrafo anterior, por
isso o desenvolvimento deste modelo não está terminado.
3. Model Framework de alocação de recursos.
4. Aplicação do Model Framework de alocação de recursos à empresa de canalização.
5.Dupla aplicação do framework de alocação de recursos para o escalonamento de seminários.
Vamos supor agora um modelo para escalonar seminários. Produzimos para o efeito o modelo da figura 5.
Este modelo é obtido através da aplicação do mesmo framework duas vezes. Tanto as salas (Rooms) como os instrutores (Instructors) tem restrições como o facto de nenhum dos dois poder ser requisitado duas vezes no mesmo horário.
3.5 Collaboration frameworks
Uma collaboration descreve a interacção entre um grupo de objectos que foram desenhados para trabalhar em cooperação. Eles enviam mensagens uns aos outros de modo a atingir um objectivo que têm de realizar em conjunto. Uma das maiores vantagens dos designs orientados para objectos (OO) é o design das colaborações. A técnica CRT (classes, responsabilidades, colaborações) é basicamente usada em design OO e tem como função principal dividir as responsabilidades para uma tarefa de entre os objectos colaboradores. Estas decisões distinguem um design OO estruturado de um único programa que está incumbido de todo o trabalho. A vantagem da realização de decisões extra é a obtenção de um design separado que é flexível e extensível. O design cuidado de collaborations é de tão grande valor, que quando feito de uma forma correcta, vale a pena guardar as ideias desse design e reutilizá-las. Esta é a motivação de muitos padrões.
Vejamos agora um exemplo da vida real. Se descrevermos o que significa ser pai ou mãe, estamos a falar acerca das interacções entre os pais e os seus filhos e os efeitos que uns têm sobre os outros. Quando descrevemos o que significa ser um empregado, estamos a descrever uma função diferente com um conjunto diferente de interacções com um objecto descrito com outros termos. Embora a colaboração possa ser descrita separadamente, o facto é que cada objecto desempenha um papel em várias colaborações: talvez a pessoa em causa possa ser um pai e um empregado ao mesmo tempo.
Collaborations separadas podem ter efeitos sobre os mesmos atributos de um objecto. O facto de uma pessoa ser pai pode (ou não) ter efeito sobre o balanço da conta bancária, que vai ser o mesmo atributo fornecido pelo emprego. Então quando combinamos funções no mesmo objecto, normalmente temos que levar em conta a interferência entre as duas funções.
A collaboration Subject-Observer é um exemplo mais técnico. Na figura 10, tentamos mostrar o interface externo de cada objecto como separado em diferentes colaborações, nas quais os atributos internos podem ser partilhados. Esta colaboração orienta duas funções: Subject and Observer. Subject tem um tipo de valor enquanto que Observer tem outro completamente diferente. Uma acção de actualização é iniciada por Subject para manter Observer actualizado.
6. Colaborações são acerca de partes de objectos.
Apenas conhecemos informação acerca de parte de cada objecto, a outra parte depende de quem usa o framework. Neste exemplo, não sabemos como ou porque é que o valor de Subject é alterado. Apenas sabemos que esta alteração pode acontecer e quando pode acontecer, Observer tem que ser actualizado.
7. Collaboration modelo
3.5.1 Aplicação de Collaboration frameworks
Vamos observar agora a figura 12. Um dos tipos do modelo é CallQueue: a lista de espera das chamadas para um grupo particular de operadores. Vamos supor que tínhamos este tipo definido num pacote; noutro pacote teríamos um kit de classes GUI uma das quais seria Thermometer – um visualizador de valores numéricos. A figura 12 ilustra parte dos dois modelos.
8. Tipo alvo para usar Observation (figura 7).
9. Aplicação e substituição de um framework.
10. Resultado final da aplicação de um framework.
Neste exemplo, estamos a fazer uma ponte entre a lógica de negócio e GUI,
produzimos um pacote para o qual importamos CallQueue e Thermometer.
Gostaríamos de tornar possível que a “temperatura” de Thermometer fosse usada para mostrar o número de Calls de uma CallQueue em particular. Para o efeito aplicamos o framework Observation como exemplificado na figura 13. O modelo final ficaria qualquer coisa como o modelo apresentado na figura 14 de onde podemos verificar que os nomes de Observer e Subject foram alterados.
Até aqui usamos frameworks para construir modelos. O resultado final desta operação é uma especificação que ainda necessita de ser implementada. Neste exemplo particular algum trabalho é deixado para o utilizador do framework, porque não sabemos como vão ser feitas operações como actualizações e registos bem como operações específicas de um objecto.
3.6 Refinamento de frameworks
Os frameworks são ferramentas abstractas, que servem para a modelação, como um mecanismo do tipo modelo apenas pode ser usado quando o problema em questão pode ser parametrizado e é adequado ao nível de granularidade do framework.
11. Um framework de manutenção de stocks.
Mas os frameworks possuem uma dimensão adicional de flexibilidade: o refinamento. Não há nenhuma restrição que indique que um framework tem que ser definido a um certo nível de detalhe. Os próprios frameworks podem ser alvos de refinamento, abstracção, e composição exactamente como os outros modelos o são.
Alguns destes refinamentos são eles próprios definidos como frameworks.
O framework na figura 15 ilustra uma relação entre Traders (que faz Orders) e um Distributor. Neste framework não é relevante como o Trader se liberta dos stocks, nem como o Distributor os obtém. Estamos perante uma collaboration degenerada, que vai ser refinada.
Este modelo informa-nos que um Trader tem sempre que realizar uma ordem quando o stock é baixo. Os designers podem achar conveniente usar este framework e depois definem por eles próprios como as Orders são realizadas. Ou então podemos definir outro framework que inclua essa informação.
Um comerciante retalhista desempenha muitas funções, participando em muitas colaborações. Uma dessas collaborations mostra a relação entre clientes (Customers) e vendedores (Vendors).
12. Modelo de vendor: retail sales.
13. Regras de junção resultantes da aplicação de dois frameworks.
Uma loja é o exemplo de um objecto que desempenha as funções do Trader e do Vendor ao mesmo tempo. Então agora compomos os dois frameworks num único modelo, com Customers, Shop, e Distributor como os intervenientes principais (figura 17). No Public_Vending, o stock do Vendor é representado como um conjunto de objectos, cada um dos quais é um exemplo de um Product, então este modelo deve ser reequilibrado usando uma invariante, para o stock do Trader que foi modelado como um inteiro para qualquer Product.
O passo final é fazer a implementação de tipos com as classes. Suponhamos que a Shop::sell não será alvo de mais refinamentos mas é implementado como uma única mensagem; o designer tem que observar Trade_Supply::depletion sempre que os stocks desaparecem; então uma chamada à função make_Order tem que fazer parte da
execução de sell. Devido ao facto do design do modelo ter sido tão minuciosamente pensado, a implementação das classes será simples.
3.7 Conclusões
Os model frameworks podem ser usados para expressar relações que ultrapassam as fronteiras dos tipos e para encapsular relações feitas a partir de colecções de tipos, associações e acções. São uma ferramenta muito poderosa para a abstracção e uma unidade de reutilização muito útil.
4. Padrões 4.1 Introdução
Os padrões foram introduzidos por Christopher Alexander no livro “A Pattern Language” onde era especificada uma linguagem que resolvia problemas frequentes na concepção de edifícios. A linguagem criada pelo autor permite a criação de um edifício simplesmente através da aplicação de sequências de padrões. Alexander definiu padrões de arquitectura como uma solução típica para problemas semelhantes, inseridos no mesmo contexto e recorrentes em circunstâncias semelhantes.
De forma análoga, pretende-se que os Padrões de Software resolvam ou ajudem a resolver problemas frequentes que ocorram em circunstâncias semelhantes. Mas, ao contrário dos padrões de arquitectura, a simples aplicação dos padrões de software não resulta por si só na solução do problema. Pretende-se que os padrões de software documentem de forma simples e compreensível as soluções de problemas frequentes no desenvolvimento de software.
4.2 Objectivos
Como já foi dito, os padrões de software têm como objectivo a documentação de soluções para problemas semelhantes que ocorrem frequentemente em circunstâncias semelhantes.
Pretende-se que os padrões de software sejam um meio eficaz de transmissão do conhecimento e experiência dos criadores de software. Assim, os padrões deverão ser documentos escritos com uma linguagem e uma estrutura que sejam comuns e acessíveis por toda a comunidade de criadores de software.
O papel dos padrões no desenvolvimento de software não é apenas resolver problemas. Por estruturarem correctamente as soluções para os diferentes problemas, contribuem para uma boa estruturação dos componentes dos sistemas a desenvolver.
Uma boa estruturação e organização dos componentes do sistema, para além de contribuírem para uma boa e fácil solução dos problemas, contribui ainda para a diminuição das consequências de erros de concepção detectados em estados mais avançados no processo de desenvolvimento do sistema.
4.3 Especificação de Padrões de Software
Atendendo à definição de padrões (solução para problemas semelhantes que ocorrem em circunstâncias semelhantes), podem retirar-se dois dos elementos essenciais que compõem um padrão: a solução e o problema.
Mais dois elementos devem ser considerados: o nome do padrão e as consequências.
• Nome: traduz numa ou mais palavras o problema, a solução e as consequências e é usado para ajudar na abstracção do problema, facilitar a documentação e a comunicação entre os participantes no desenvolvimento do projecto.
• Problema: descreve quando aplicar o padrão. Explica o padrão e o seu contexto, assim como as condições dentro das quais faz sentido aplicar o padrão.
• Solução: descreve os elementos (e relação entre eles) que compõem a resolução adoptada para o padrão. Não descreve a implementação adoptada, mas fornece uma forma onde encaixar a solução.
• Consequências: os resultados a esperar da aplicação do padrão. São muito importantes para a avaliação das alternativas de que se dispõe para resolver um problema.
No livro de referência “Design Patterns” é proposta uma estrutura para documentar os padrões de software que, para além destes quatro elementos essenciais, inclui outros elementos importantes. Os elementos mais relevantes da estrutura proposta é a seguir descrita:
• Nome – deve ser um nome significativo, que traduza bem o que se pretende do padrão, para poder ser usado em qualquer discussão, e de modo a que qualquer pessoa compreenda do que se está a tratar.
• Intuito – descreve o que padrão faz, quais os objectivos e que problemas resolve.
• Motivação – indica as condições quando certo problema ocorre ou quando a solução implementada funciona de acordo com o previsto.
• Aplicabilidade – indica as situações em que o padrão poderá ser aplicado.
• Estrutura – representa graficamente os elementos do problema e da solução e as ligações entre eles.
• Consequências – indica os resultados, vantagens e desvantagens a esperar da aplicação do padrão.
• Implementação – indica pormenores de implementação a que o criador de software que use o padrão deve atender.
4.4 Aplicações - o padrão de software Iterador
Nome – Iterador
Intuito – proporcionar uma forma de acesso a elementos sequencialmente ligados abstraindo a programação de baixo nível.
Motivação – é conveniente permitir a navegação através de variadas estruturas de dados de forma independentemente da organização e pormenores de implementação das estruturas de dados ou objectos.
Aplicabilidade – qualquer entidade que pretenda manipular a informação cuja organização é desconhecida ou de difícil manipulação deverá fazê-lo através de um iterador.
Estrutura – estrutura do iterador na figura 14
14. Padrão Iterador
Consequências – com a aplicação deste padrão, diminui-se a responsabilidade de acesso e navegação, quer da estrutura que agrega os objectos, quer da entidade que pretende aceder aos objectos. Assim, separam-se os algoritmos utilizados na manipulação das estruturas das próprias estruturas.
4.5 Conclusões
Pode-se concluir que os padrões de software são uma excelente forma de comunicação de conhecimentos entre criadores de software. Formalizam, de forma acessível e de fácil utilização, as boas soluções para problemas com que se depara quem desenvolve software.
A identificação de padrões é possível com alguma experiência em desenvolvimento de software. Estes vão tornar problemas de concepção muito mais simples, uma vez que fornecem de forma imediata uma conceptualização do problema e da respectiva solução.
Assim, a passagem para a implementação é quase imediata em programação orientada a objectos.
Caso não se reconheça imediatamente um padrão em determinado problema, a catalogação dos padrões permite encontrar, caso exista, no mínimo, um padrão análogo.
Assim, quem usa padrões terá sempre facilitada a resolução dos problemas que encontra e com o melhor compromisso entre o esforço empreendido e o resultado a esperar.
Para além de ajudarem na conceptualização dos problemas e soluções, os padrões fornecem logo uma organização eficiente entre os componentes de software que, para além de ultrapassar o problema imediato, previne erros em estados mais avançados do desenvolvimento e minimiza as consequências. Deve-se referir, porém, que dos padrões de software resultam soluções comprovadamente boas para problemas comuns e não para problemas específicos em contextos específicos de solução específica.
Pode-se sempre perguntar se há reutilização de software em padrões. De facto, existe pouco ou mesmo nenhum código a reutilizar. Mas o software não deve ser visto apenas como código. O software deve ser visto como um sistema completo com o seu código, as suas estruturas de dados e objectos, os seus algoritmos, os seus componentes e a comunicação entre todos eles. Os padrões podem não fornecer código, nem algoritmos, nem estruturas de dados, mas fornecem indicações sobre alguns dos aspectos mais importantes para o desenvolvimento de qualquer sistema de software.
5. Componentes 5.1 Introdução
Em apenas 30 anos passamos de escrever programas gigantes linha-a-linha para juntar partes já prontas a usar denominadas componentes para construir software.
Começou-se ao mais baixo nível, escrevendo zeros e uns (verdadeira linguagem máquina). De seguida, veio o Assembler onde se podia escrever instruções um pouco mais legíveis do ponto de vista humano, mas ainda muito difíceis de entender na sua forma. Depois apareceram linguagens específicas de mais alto nível como COBOL, FORTRAN entre outras. Mas a maior mudança, para a programação de verdadeiramente alto nível veio no fim dos anos 80/princípios dos 90 com bibliotecas de código já feitas como usavam o Quick Basic ou o Turbo Pascal.
Em 1991, o Visual Basic da Microsoft mudou o mundo da programação. Como o VB corria em Windows, podiam-se chamar as DLLs (Dynamic Link Libraries) os VBX (Visual Basic eXtensions) - os antecessores dos componentes.
Os componentes seguem as mesmas ideias que os Legos, em que há os blocos de construção e com a união deles se pode fazer uma casa ou aplicação.
Desde há 30 anos em que se programava linha-a-linha, para hoje em que se programa com blocos percorreu-se um longo caminho.
Estes blocos são chamados Componentes de Software.
5.2 Definição
Componente - Objecto auto-contido com uma funcionalidade pré-definida acedido via uma interface. Pode correr do lado do cliente (como extensões ou módulos de uma aplicação) ou do lado do servidor (como servidores Web e servidores de aplicações).
Exemplos: Componentes do ActiveX, JavaBeans, Enterprise JavaBeans e VCLs.
Componente reutilizável - Um componente reutilizável é um termo genérico para um bloco de código auto-contido que encapsula lógicas de negócio específicas ou funcionalidades de interface com o utilizador. Pode existir sob a forma de componente
"caixa branca" (vendo-se o código fonte) ou como um componente "caixa preta" (sem o código fonte à vista, apenas como binário).
Um componente só será totalmente reutilizável quando se fizerem duas coisas:
1º) achá-lo
2º) perceber o que fazer com ele
O componente em si tem que ser uma "caixa negra" funcional cujos serviços só podem ser acedidos através de um conjunto de interfaces.
Mas fazer um componente reutilizável necessita de informação adicional ! Para achar componentes é necessário um sítio conhecido onde os ir buscar e um conjunto de informação standard de classificação do componente. Isto inclui características tecnológicas e um conjunto de restrições de compatibilidade. Para perceber o que fazer com um componente e como usá-lo é necessária uma quantidade grande de informação e documentação. Isto inclui uma especificação funcional, instruções de distribuição e instalação, informação comercial e de licenças, exemplos de usos em aplicações e demonstrações, configuração e documentação sobre possíveis extensões, etc.
5.2.1 Em que é que um componente difere de uma aplicação ?
Os componentes são os "tijolos" das aplicações. Estes oferecem um conjunto de operações que podem ser usadas pela aplicação em questão ou por outras, vezes sem conta. Uma aplicação em particular pode conter centenas de componentes, cada qual tratando lógicas de negócio específicas ou funcionalidades GUI.
Consideremos como exemplo uma aplicação de base de dados: o ecrã de entrada de dados pode conter vários componentes de interface com o utilizador: botões, menus, comboboxes, etc. Também haverá componentes de lógica do negócio para fazer a validação e cálculos sobre os dados inseridos, assim como componente para escrever os dados na base de dados. Finalmente, haverá componentes a tratarem dos relatórios gerados na BD para serem vistos num gráfico no ecrã ou serem impressos.
5.3 A evolução dos componentes
Desde que se começaram a construir aplicações de software complexas, a procura tem sido no sentido de passar da "arte de programar" para uma forma de engenharia. As pessoas que lidam com a indústria do desenvolvimento de software sempre que olham para as outras indústrias (como os automóveis ou o hardware) têm-se perguntado
"porque é que o software é tão difícil ?" A questão é que o software ainda hoje é muito uma arte e pouco uma engenharia, algo prático, rápido e eficaz.
A primeira coisa a fazer se se quer reutilizar é decompor o problema em partes, por outras palavras, dividir para conquistar. Isto foi o que levou ao nascimento dos componentes. Por exemplo, se quisermos viajar de uma cidade para outra, primeiro temos que escolher o meio de transporte, depois tratarmos dos preparativos para a viagem (como comprar bilhete se formos num transporte público ou meter gasolina se formos de carro), e por aí adiante. Desde que se mantenha uma interface para o exterior standard e esteja bem definida a arquitectura em que se baseia, cada uma destas tarefas pode ser transformada num componente e trabalhada em paralelo por várias pessoas.
A maior parte do esforço de desenvolvimento de uma aplicação não está no desenvolvimento em si, mas sim na manutenção dele. Uma coisa essencial para facilitar a manutenção é conter os erros. Se os erros estiverem de certeza dentro um pedaço de código em concreto, é muito mais fácil analisar e retirar esses erros, uma vez que não tem que se andar à procura pela aplicação toda, mas sim naquele local, analisando as suas entradas e saídas. Isto só ocorre se minimizarmos as dependências entre os componentes e tornarmos bem claras as interacções que um componente tem com o exterior.
Tudo começou com as linguagens OO. Elas trouxeram consigo princípios como a unificação de dados e funções (a combinação dos dois origina um objecto ou classe), a encapsulação e a identidade. Depois, em meados dos anos 80 vieram os RPCs (Remote Procedure Calls) para sistemas distribuídos de objectos. Daqui vieram os problemas do costume na indústria da informática: as incompatibilidades. De repente há objectos em sistemas distribuídos que querem comunicar entre si, mas não conseguem devido a estarem sobre plataformas diferentes. O que resolveu isto foi a IDL (Interface Definition Language) que foi mais tarde a base do COM (Component Object Model) e do CORBA (Common Object Request Broker Architecture). A ideia da IDL é definir uma linguagem neutra no modo da descrição das funções/operações de um objecto.
Cada vez mais se avançava com uma ideia de objectos que comunicavam entre si através de uma linguagem independente - o início teórico dos componentes.
No princípio dos anos 90 apareceu a Internet e a linguagem de programação Java.
Uma linguagem nova que era totalmente pensada por objectos e que podia (em teoria) correr em qualquer lado. Mas apesar de a Java suportar facilidades do tipo componentes como as interfaces, ainda era uma linguagem e não um modelo de componentes (modelo este que foi aproximado com os Beans).
Em paralelo a Microsoft continuou a desenvolver o ActiveX como uma alternativa ao Java baseada no "velho" COM e a Sun lançou a Java 2 com RMI (Remote Method Invocation - fazendo lembrar os RPCs) e o JDBC (para ligação à Base de Dados).
Entretanto, em 1997, a Microsoft lançou o MTS (Microsoft Transaction Server).
Este fornecia um contentor de transacções onde os componentes podiam correr. Pela primeira vez, código de componentes podia participar numa transacção sem sequer precisar de saber que serviços eram aplicados.
O princípio do contentor levou a novos rumos como a COM+ da Microsoft, os Enterprise JavaBeans (EJB) da Sun, e mais tarde o CORBA Component Model (CCM) da OMG. A COM+ era independente da linguagem, mas só funcionava com Microsoft.
Os EJB podiam funcionar em qualquer lado, mas a linguagem tinha que ser Java. O salvador foi o CCM, que de facto era totalmente independente.
A partir daí, o COM+ foi integrado com o ActiveX e o ASP no Windows DNA que levaria à .NET. E os EJB foram integrados com os JSP e as applets no J2EE.
O que nos traz até hoje...
Como futuro mais provável neste momento, temos os chamados serviços de rede, uma extensão natural dos ambientes de componentes distribuídos, passando a LAN a ser a Internet. Neste aspecto há três propostas presentes: a plataforma .NET da Microsoft, a iniciativa ONE da Sun e o programa Websphere da IBM.
Com os Web Services todo o conceito de aplicação está assim a mudar de programas monolíticos para um conjunto de componentes distribuídos.
5.4 Vantagens e desvantagens
O desenvolvimento de aplicações a partir de componentes reutilizáveis leva a uma economia de tempo e outros custos. É uma extensão da programação OO (orientada a objectos) e assume a filosofia "reutiliza antes de comprares, compra antes de programares".
A utilização de componentes assemelha-se à modularização de um programa em vários procedimentos ou mesmo várias classes. Ao fazê-lo, a aplicação final torna-se muito mais "legível" e fácil de comentar, além de que isola possíveis erros e "bugs"
apenas a uma zona da aplicação, não afectando as outras. Torna também a aplicação final muito mais fácil de expandir ou especializar no caso de aparecerem novas lógicas de negócio ou se aprofundarem outras. Todo este desenvolvimento é modular ou orientado ao componente, logo, se as coisas forem bem feitas, não haverá qualquer alteração à aplicação principal ao acoplar o componente, evitando o que acontece tão frequentemente: o aparecimento de novos "bugs" ao surgirem funcionalidades novas.
Também há a vantagem de se uma funcionalidade sair do espectro do programador, um componente para essa área pode ser feito noutro departamento da empresa ou ser comprado a terceiros.
Outra vantagem da utilização de componentes é que permitem diferentes níveis de granularidade: tanto existem componentes muito específicos que farão as partes cruciais da lógica do negócio (e serão esses sobre os quais o programador da aplicação se deve de facto debruçar e que serão totalmente feitos e controlados pelo programador), como existem componentes com uma granularidade mais grossa que permitem uma variedade de operações a muitos níveis como por exemplo interfaces com o utilizador (controladas pelo programador, mas não feitos por ele).
5.5 Aplicações reais
Os componentes permitem resolver problemas tão reais como criar um sítio Web de comércio electrónico em muito pouco tempo, fazer a validação de endereços de correio electrónico para evitar mensagens devolvidas do tipo ([email protected]), imitar a GUI do Microsoft Outlook ou até evitar dados duplicados numa BD !
As aplicações mais recentes e em moda de componentes são a plataforma .NET da Microsoft e os Beans da Sun.
6. Conclusões
Antes de mais gostávamos de dizer que este trabalho foi muito limitado logo à partida pelo número de páginas que se podia escrever no relatório. 30 páginas é muito pouco para um trabalho de investigação sobre um tema tão vasto como a reutilização, ainda para mais com a incidência não na reutilização, mas nas suas três formas mais comuns: os frameworks, os padrões e os componentes. Por isso incitamos o leitor a seguir a sua pesquisa pelos inúmeros links que temos na bibliografia, assim como os livros que existem no mercado acerca do assunto.
A reutilização de software tem, como quase todas as coisas, dois lados. Um positivo e um negativo. Quando uma pessoa pensa pela primeira vez em reutilização de software antes de ler sobre o assunto, imediatamente pensa que só pode ser algo bom ! Deixarmos de fazer os programas todos que precisamos de raiz e passar a utilizar algo já feito por outros parece ideal, não dá trabalho nenhum. Além disso, o tempo de desenvolvimento é quase nulo, uma vez que é quase só uma instalação do componente reutilizado no nosso sistema e já está ! No entanto, a expressão “pronto a usar” muitas vezes utilizada para este tópico é diferente do “pronto-a-vestir” que nós conhecemos do dia-a-dia. Este pronto a usar necessita de ser identificado no nosso sistema, encontrado o que mais se adeqúe e, se tudo correr bem e for o que estávamos à espera ao ler a especificação dele, introduzi-lo no nosso sistema, o que implica “customizações” e adaptação no caso dos frameworks ou até interacção directa no caso dos componentes.
O objectivo de qualquer boa empresa de desenvolvimento de software deveria ter como objectivo final construir “modelos”, pedaços reutilizáveis de código de modo a diminuírem e facilitarem a criação de novos produtos e a manutenção dos seus produtos correntes.
Existem, no entanto, custos. Estes são, a maior parte das vezes, elevados, o que desencoraja logo à primeira vista e leva a que muitas dessas empresas só falem do assunto sem implementarem nada.
No entanto, o mercado do software nunca evoluiu tão rápido como agora. Saem programas novos todos os dias e há actualizações constantes dos programas que já existem no mercado. Assim cada vez mais é preciso pegar em coisas já feitas e utilizá- las, porque o tempo de desenvolvimento de um produto, dada a concorrência actual, é muito escasso.
Assim a reutilização surge como algo que vai aparecer cada vez mais no futuro, sendo uma ideia forte de plataformas novas como a .NET da Microsoft e a ONE da Sun.
Num planeta em que já há lixo a mais, torna-se necessário reutilizar.
6. Agradecimentos
Agradecemos toda a colaboração do Professor Ademar Aguiar para a elaboração deste trabalho.
7. Bibliografia
7.1 Livros
Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John Design Patterns
Addison-Wesley
D'Souza , Desmond Francis; Willis, Alan Cameron
Objects, Components, and Frameworks With Uml : The Catalysis Approach Addison-Wesley
Sommerville , Ian Software Engineering 6th Edition, 2000 Addison-Wesley
7.2 Internet
http://www.fe.up.pt/~aaguiar/
http://www.componentsource.com/
http://www.cis.ohio-state.edu/rsrg/
http://citeseer.nj.nec.com/merkl98selforganizing.html http://www.informationweek.com/708/08iuhid.htm
http://www-2.cs.cmu.edu/afs/cs/usr/ppinto/www/reuse.html http://www.ddj.com/articles/1998/9875/9875k/9875k.htm
http://www.cms.dmu.ac.uk/~nmsampat/research/subject/reuse/reuse-defn.html
http://www.cms.dmu.ac.uk/~nmsampat/research/subject/reuse/components/index.htm http://ksi.cpsc.ucalgary.ca/KAW/KAW96/gennari/
http://www.reusability.com/home.html http://www.cse.dmu.ac.uk/~aoc/teaching-
notes/SOFT3010/slides/ood7/CoordinationAndReuse_files/frame.htm http://java.sun.com/features/1997/may/reuse.html
http://www.cio.com/archive/030197_intro.html http://www.cetus-links.org/oo_reuse.html