Desenho por Contrato: Um Ciclo de Vida
Desenho por Contrato: Um Ciclo de Vida
Xxxxxxx Xxxxx, Xxxxxx Xxxxxx
Resumo — Um dos grandes objectivos da Engenharia de Software é produzir software com qualidade. Significa isto que propriedades como robustez, correcção, reutilização, manutenção, compatibilidade, eficiência, portabilidade e funcionalidade, entre outras, têm que estar presentes num produto de software com qualidade. O Desenho por Contrato (DpC) com Object Constraint Language (OCL) e a Programação por Contrato (PpC) são reconhecidamente instrumentos potenciadores de qualidade que actuam em dois extremos, respectivamente no modelo e no código. Estabelecer a ponte entre estes dois extremos é um passo importante para o aumento da qualidade do produto final. Este artigo pretende constituir uma análise do estado da arte no que respeita às ferramentas que possibilitam modelação em Unified Modelling Language (UML) com OCL e implementação de DpC com a linguagem Java e que possam sustentar essa ponte.
Tópicos — OCL, Desenho por Contrato, UML, Java.
—————————— ◆ ——————————
O
1 Introdução
DpC é uma técnica que permite o dese nvolvimento de software com qualidade à custa da expressão de asserções, basea das na cooperação entre cliente e fo r-
necedor sob a forma de um contr ato.
O UML tem vindo a tornar -se a linguagem de modelação mais utilizada para especificar, visualizar, construir e docume n- tar o desenvolvimento de software. No entanto, para expressar formalmente propriedades, como por exe mplo a unicidade, os métodos de análise e desenho percursores do UML (OMT, Booch e Objetory) não tinham mec anismos que permitissem expressar tais pr opriedades. Perante esta necess idade premente, foi desenvolvida uma linguagem – o OCL, com o intuito de colmatá -la. Com o OCL embebido no UML, aumenta -se o rigor no modelo através da definição formal d e asserções (pré - condições, pós -condições e invariantes ), que poderão ser implementadas sob a forma de cláusulas do co ntrato.
Gerar código automaticamente , incluindo o DpC esp ecifi- cado em OCL , originará uma impl ementação mais rápida e eficiente e a garantia da ra streabil idade entre o mod elo e o código correspondente, assentes nos pri ncípios de qualidade que ambos (DpC e PpC) pretendem acrescentar , da ndo-se desta fo rma um passo importante na direcção da qualidade do pr oduto final . Para suporte deste trabalho, foi seleccion a- da a lingu agem Java dada a sua aceit ação e utiliz ação nos meios acad émicos e comerciais.
A geração automática de código Java a partir do modelo
UML é suportada actualmente por uma série de ferrame ntas. No entan to, no que diz respeito ao modelo UML com expre s- sões OCL, ainda existe um longo caminho a percorrer para que tenhamos ferramentas que, automaticamente consigam gerar código Java para as cláusulas do co ntrato expressas em OCL e deste modo estabelecer a ponte entre estes dois extremos .
O objectivo deste artigo é comprovar em que estágio se encontra a tecnologia através da compar ação de uma série de ferramentas ex istentes, que possam sustentar essa ponte.
————————————————
• Xxxxxxx Xxxxx exerce a sua actividade profissional na multinacional Amco r. E-mail: xxxxxxx.xxxxx@xxxxx-xxxxxxxxx.xxx .
O trabalho subjacente a e ste artigo foi desenvolvido n o âmbito do Mestrado em Engenharia Informática, na cadeira de Qualidade do Produto e do Processo1, sob a orientação do Prof. Xxxxxxxx Xxxxx x Xxxxx.
A esta introdução segue -se uma contextualização ao tema pri ncipal, onde apresentaremos um caso de estudo juntamente com uma pequena introdução aos temas que servem de suporte ao tema principal. Seguidamente, apr e- sentamos o estudo comparativo de algumas das ferrame n- tas existentes. Pross eguimos com a implementação do caso de estudo com a alternativa tecnológica q ue nos ass egure maior qualidade no produto final , apresentando finalmente as nossas concl usões.
2 Contexto
2.1 Caso de Estudo
No sentido de dar apoio às vár ias secções deste artigo desenvolvemos um caso de estudo, inspirado nos transpo r- tes fl uviais de pas sageiros que estabelecem a ligação entre as margens do rio Tejo. A fi gura 1 ilustra o diagrama de classes em UML.
Os cacilheiros são utilizados para o transporte de passa- geiros entre as margens Norte e Sul do rio Tejo. Cada caci- xxxxxx faz várias viagens e cada viagem é efectua da apenas
Fig. 1. Diagrama de Classes do modelo “Viagens de Cacilheiro”.
1 xxxx://xxx.xx.xxx.xxx.xx/xxx/xxx
por um cacilheiro. Cada embarcação destas tem uma cap a- cidade lim itada quanto ao número de passageiros que pode transportar. Em cada viagem é transportado um determ i- nado número de passageiros que não pode exceder o número de lugares disp oníveis do cacilheiro que lhe está associado. Cada cacilheiro tem atribuído um conjunto de identificação único assim como cada viagem é identificada por um número de viagem único . Um passageiro não pode realizar mais do que uma viagem simu ltaneamente .
2.2 Desenho por Contrato
O paradigma do desenvolvimento de software orientado pelos objectos (DSOO) introduziu os conceitos de classes, objectos, abstracção, herança, polimorfismo e genericidade que se traduziram num passo impo rtante na constante pr o- cura da qu alidade do produto na engenharia de software. No entanto, expressar alguns factores de qualidade na pr o- gramação, no sentido de tornar os programas legíveis, bem especificados e validados e ente nder as regras que estão por trás da sua forma de implementação, é algo que a maioria das fe rramentas de apoio ao desenvolvimento orientado pelos objectos não contemplava. Esta necessidade despol e- tou o su rgimento do DpC.
pós -condições e invarian tes permite -nos exprimir de uma maneira formal as especificações do contrato. Falta ainda, obviamente, especificar as consequências e respectivo trat a- mento das excepções às cláusulas co ntratuais.
O DpC no DSOO resume -se à utilização sistemática de pré-con dições, pós -condições e invariantes. As pré -condições são uma obrigação da operação cliente, em benefício da op e- ração fornecedor; as pós -condições são uma obrigação da operação fornecedor, em benefício da operação cliente. Ambas, descrevem as propriedades de cada método indiv i- dualmente. O s invariantes expressam as propriedades gl o- bais das instâncias de uma classe, as quais terão que ser pr e- servadas por todas as operações dessa classe [2]. Mesmo havendo um contrato entre as classes, algo inesperado pode ocorrer que o viole, ou seja, uma excepção. Embora, teoric a- mente, num sistema construído com qualidade nenhum contrato possa ser violado, isso não acontece na realidade.
Nesse sentido, terão que existir mecanismos de tratamento de excepções.
Na figura 2 está ilustrado um exemplo, de como se pode redigir um contrato na fase de implementação, utilizando uma linguagem de programação 2 que suporte a inclusão de cláus ulas contratuais expressas em pré -condições, pós -
TABELA 1 Exemplo de um contrat o
Obrigações | Benefícios | |
Cliente | Tem que assegurar as pré -condições: 1. bilhete comprado. 2. estar no cacilheiro 5 minutos antes da pa rtida. | Da pós-condição: 1. estar no local pretendido às na hor a prevista no horário com atraso mínimo de 10 minutos . |
Fornecedor | Tem que assegurar a pós -condição: 1. transportar o cliente para o local pretendido até 10 minutos depois da hora prevista no horário . | Da pré-condição: 1. não t er prejuízo por transportar clie ntes sem bilhete comprado e não partir com atraso . |
O conceito chave do DpC assenta essencialmente na expre s- são das r elações entre uma classe (fornecedor) e os seus clientes sob os ausp ícios de um acordo formal, contemplando os direitos
e obrigações de ambas as partes. Somente com a definição prec i- sa de todas as reivindicações e responsabilidades re speitantes a cada módu lo pertence ntes a um determinado sistema, se lhe pode depositar um alto grau de confiança [1].
Fazendo um paralelismo com os contratos efectuados, por exemplo entre duas organizações, podemos inferir algumas pr opriedades importantes de um contrato:
1. são firmados entre duas ou mais entidades , em que cada uma assume o papel de clien te ou fornecedor;
2. é explicitamente escrito numa linguagem conhec i- da por ambas as partes;
3. especifica as obrigações e benefícios mútuos;
4. as obrigações de uma das partes são os b enefíc ios da outra e vice -versa;
5. não contem cláusulas escondidas;
6. muitas vezes faz referência, implícita ou explicit a- mente, a regras comuns a todos os contratos (leis vigentes, reg ulamentos oficiais, etc.).
Tomando por exemplo o contrato entre a empresa que assegura as travessias do rio Tejo (fornecedor) e os seus pass a- geiros (cliente) pode mos formalizar alguns dos benefícios e obrigações correspondentes como está expresso na tabela 1.
Como podemos observar a utilização de pré -condições,
condições, invariantes e tratamento de exce pções. Conclui-se, facilmente, que a util ização do DpC elimina, por completo, a necessidade da programação defensiva , na qual as valid a- ções da utilização do serviço estão todas do lado do fornec e- dor não havendo obr igações por parte do cliente .
O conceito de hera nça é largamente utilizado no DSOO. De modo a que a utilização deste conceito não invalide as cláus ulas do DpC, a redefinição de uma operação apenas pode sub stituir a pré -condição original por uma igual ou mais fraca ( exigindo menos do cliente ) e a pós -con dição ori- ginal por uma igual ou mais forte ( oferecendo mais ao clie n- te) [30]. Significa isto, que uma subclasse não é mais do que uma subcontratação da parte da classe pai e, por consegui n- te, tem qu e, obrigatoriamente, satisfazer no mínimo, o me s- mo contra to.
A utilização do conceito de contrato pode ser utilizado em todo o ciclo de vida do processo de DSOO. Assim a utiliz a- ção de pré -condições, pós -condições e invariantes começa na modelação do sistema descrevendo os seus eve ntos. Na fase de análise e na fa se de implementação os contratos def inem as operações, os benefícios e as obrigações de cada comp o- nente do sistema, respectivamente. Finalmente, na fase de testes, os contratos definem a correcta especificação de cada comp onente [3].
2 A linguagem Eiffel tem mecanismos nativos de suporte ao DpC.
O DpC é suportado pelo UML através de uma linguagem, o OCL, que permite es pecificar pré e pós -condições para as operações e invaria ntes para as classes.
Fig. 2. Exemplo de um contrato em Eiffel.
2.3 Object Constraint Language - OCL
O OCL evoluiu de uma linguagem de expressões do mét o- do Syntropy que era uma linguagem de modela ção de pr o- cessos de negócio utilizada na IBM, até ser integr ada, em 1997, no UML [5].
A modelação de sistemas de software é tradicionalmente sinónimo de construção de diagramas. Os diagramas, si m- plesmente, não conseguem expressar toda a informação necessária a uma especificação completa [19]. Por exemplo, no diagrama de cla sses ilustrado na figura 5, podíamos concluir que o número de passageiros de um cacilheiro s e- ria ilimitado. Obviamente que essa conclusão não é verd a- deira, mas não conseguimos expressar n o diagrama que o número de pass ageiros está limitado ao número de lugares disponíveis no cacilheiro. Contudo, tal lim itação pode ser expressa com recurso a uma invariante no contexto da cla s- se Viagem, expresso em OCL da seguinte forma:
Exemplo em OCL para expressar a restrição de multiplicidade da classe Viagem.
Context Viagem
inv:passageiros ->size() <= cacilhero.numeroDeLugares
Em virtude do exposto anteriormente surge a necessid ade da integração do O CL, uma linguagem formal (sem a com-
plexidade das tradicionais linguagens formais), no UML uma linguagem de modelação. Além disso expre ssões for- mais, dada a sua base matemática, não dão azo a inte rpre- tações ambíguas e podem ser verificadas aut omaticamente por ferramentas. Além de utilizar uma notação sim ilar às linguagens de programação orientadas pelos objectos, é uma lingu agem de expressões pura. Mais, as expressões em OCL não têm efeitos colaterais, ou seja, não conseguem alterar o estado do sistema, embora possam referenciá -lo.
O OCL pode ser utilizado para os seguinte propósitos [21]:
1. especificar invariantes em classes e tipos no modelo de classes;
2. d escrever pr é e pós -condições nas operações;
3. especificar a semântica de operações do tipo sel ector .
A utilização de asserções, formalizadas através do OCL, permite -nos expressar os conceitos do DpC na fase de an á- lise e desenho, utilizando ferramentas de modelação em UML que tenham suporte OCL.
3 As Ferramentas : Um Estudo Comparativo
Esta secção consiste na análise de uma série de ferramentas cujas características possam sustentar a ponte entre a mod e- lação com UML e OCL e a correspondente impleme ntação de código Java com PpC, bem como na eleição daqu ela ou daquelas que permitam alcançar esse objecti vo originando um pr oduto final com mais qualidade.
Assim sendo, para estabelecer essa ponte , uma ferrame n- ta ou a util ização conjunta de várias , terão de assegurar três aspectos essenciais:
1. a modelação com UML e OCL ;
2. a geração de código Java a partir de UML com cláus u- las de OCL ;
3. a implementaç ão de Pp C em Java a partir das restr ições definidas com OCL .
As ferramentas foram seleccionadas para análise neste
artigo, com base na possibilidade de, à custa das caracterí s- ticas que apresentam, viabilizarem todos ou ap enas alguns dos aspectos mencionados anteriormente, bem como a sua representatividade no segmento de mercado em que se inserem .
A tabela 2 contém a descrição abreviada de cada uma das ferramentas seleccion adas. Para compa rar as várias ferramentas, foram identificadas e analisadas as caracterí s- ticas que podem conferir sustentabilidade ao processo pr e- tendido. A tabela 3 apresenta para cada uma das ferrame n- tas seleccionadas a presença total (S) ou parcial (P) e ausên- cia (N) d e cada uma de ssas características.
TABELA 2
Descrição Abreviada das ferrame ntas seleccionadas
Ferramentas | Descrição Abreviada |
ArgoUML [6] | Ferramenta de análise e desenho em UML com suporte para OCL e verificação da sintaxe. Gera código Java onde são inseridas etiquetas especiais em Javadoc com as cláusulas de OCL. |
Poseidon [8] | Ferramenta de análise e desenho em UML com suporte para OCL. |
MagicDraw [10] | Ferramenta de análise e desenho em UML com suporte para OCL. |
Sparx Enterpr ise Architect [11] | Ferramenta de análise e desenho em UML com suporte para OCL. |
jmsAssert [12] | Ferramenta de implementação de DpC para Java. O DpC é especificado na fonte, com etiquetas e speciais dentro do Javadoc. O jmsAssert é exec utado com a fonte e são gerados os ficheiros de contrato em jmscript que irão ser chamados durante a ex ecução para implementar as cláusulas. |
iContract3 | Ferramenta de implementação de DpC para Java. A fonte é p rocessada primeiro com o iContract e o resultado é compilado com o compilador de Java tradicional. As directivas de iContract residem em comentários semelha n- tes às directivas de Javadoc [25] [27]. |
Jass [13] | Ferramenta de implementação de DpC para Java. Traduz um ficheiro .jass ou . Java com as asserções especific a- das em Javadoc para um ficheiro . java . Este ficheiro deverá por sua vez ser compilado com o compilador de Java tradicional. |
jContractor [9] | Ferramenta de implementação de DpC para Java. Os contratos são escritos como métodos Java normais segui n- do uma convenção de nomes intuit iva. |
Dresden OCL Toolkit [14] | Compilador de Java com cláusulas de OCL. Partindo da fonte com as cláusulas OCL escritas em Javadoc, produz código Java adequado à sua implementa ção que introduz em cada classe. |
jContract [15] | Ferramenta de implementação de DpC para Java. As asserções são descritas à custas de etiquetas especiais em Java doc e posteriorme nte são pré -processadas e compiladas num processo único. Para a compilação rec orre ao compilador nativo da JVM ( Java Virtual Machine ). |
Octopus [16] | Plugin do Eclipse que permite fazer a análise e o desenho em UML, implementar asserções com OCL, verific ação de sintaxe de OCL e geração automática de código Java com adição de código d e suporte às asserções. |
OCLe [17] | Ferramenta de análise e desenho em UML, com suporte a OCL e verificação de sintaxe e ger ação de código Java com adição de código de suporte às asserções. |
OCL2j [18] | Ferramenta de implementação de DpC com OCL em aspect -oriented programming (AspectJ). Recebe um ficheiro XMI ou a fonte com as cláusulas de OCL implementadas em Javadoc e gera o código Java e os aspectos necess á- rios. |
3 O recurso da web não se encontra disponível.
TABELA 3
Principais características das ferramentas seleccionadas
Ferrame ntas | Características | ||||||||
Modelação com UML | DpC 4 | Verific ação sintaxe OCL | Forward Engineering 5 | PpC6 | Pré-processamento 7 | Compilação | Testes | Observações | |
ArgoUML | S | S | P | S | @precondition @postcondition @invariant | N | N | N | |
Xxxxxxxx | S | S | N | S | S | N | N | N | Não inclui OCL na fonte gerada. |
MagicDraw | S | S | S | S | S | N | N | N | |
Sparx Enterpr i- se Architect | S | S | N | S | S | N | N | N | Não inclui OCL na fonte gerada. |
jmsAssert | N | N | N | N | @inv @post @inv | S | N | N | |
iContract | N | P8 | P | N | @inv @post @inv | S | N | N | |
Jass | N | P9 | P | N | require ensure invariant check | S | N | N | |
jContractor | N | N | N | N | aMethod_Precondition() aMethod_Postcondition() aMethod_Invariant() | N | N | N | |
Dresden OCL Toolkit | N | S | S | N | @precondition @postcon dition, @invariant | S | S | N | |
jContract | N | N | N | N | @inv @post @inv @assert: $forall, $implies, $e xists | S | S | N | |
Octopus | S | S | S | S | S | N | N | N | Características baseadas apenas na inform ação dos autores. |
OCLe | S | S | S | S | S | N | N | N | |
OCL2j | N | S | S | S | S | N | N | N | Protótipo não dispon ível à data de reda cção. |
Do estudo comparativo efectuado, podemos concluir
4 Possibilidade de expressar restrições de OCL no modelo.
5 Possibilidade de gerar código Java a partir do modelo.
6 Possibilidade de implementação de pré -condições, pós -condições e invariantes na fonte.
7 A fonte com as cláusulas de DpC é pré -processada , dando or igem a outra fonte que será posteriormente compilada .
8 Apenas contempla: implies, forAll, exists.
9 Apenas cont empla: forAll, exists.
que as funcionalidades apresentadas pelas ferramentas ana- lisadas podem constituir três grandes grupos. Um primeiro
grupo (Grupo 1) com as funcionalidades relacionadas com
a modela ção UML e espec ificação de cláusulas OCL. Um segundo grupo (Grupo 2) com as funcionalidades relaci o- nadas com a pr odução ou utilização de código fonte Java, com as cláusulas de OCL de algum modo aí introduzidas.
E, finalmente, um terceiro grupo (Grupo 3) co m o conjunto
das funcionalidades relacionadas com a produção do cód i- go Java executável. A tabela 4 apresenta as ferramentas an a- lisadas e os grupos de funcionalidades onde se inserem .
Quanto às ferramentas que implementam funcionalid a- des no âmbito do primei ro grupo, importa referir que as
distinções existem essencialmente entre o suporte de OCL e com que extensão, a verificação da sintaxe de OCL, e a validação das asserções contra o modelo UML existente.
Para implementar as funcionalidades descritas no segun do grupo, as ferramentas adoptam essencialmente três met o- dologias distintas. Existem ferramentas que produzem ou
TABELA 4
Distribuição das FerRamentas pelos Grupos de Fun-
CIONALIDADES DE FINIDOS
Grupo 1 | Grupo 2 | Grupo 3 |
ArgoUML Poseidon | ArgoUML jmsAssert | jmsAssert iContract |
MagicDraw Sparx Entrep ise Architect | iContract jass Dresden OCL Too lkit | jass Dresden OCL Too lkit jContract |
Octopus OCLe | jContract Octopus OCLe | Octopus OCLe OCL2j |
utilizam código Java com as cláusulas de OCL embebidas em Javadoc. Existem outras que produzem ou utilizam cód i- go Java, com as cláusulas de OCL implementadas também em Java, dentro das classes a que dizem respeito. E existem ainda outras ferramentas, que produzem ou utilizam cód i- go Java, sendo as cláusulas de OCL implementadas à parte, sob a forma de scripts ou aspectos.
No que diz respeito às fe rramentas que implementam as funcionalidades do terceiro grupo, estas distinguem -se entre as que recorrem ao compilador tradicional de Java, as que recorrem ao compilador tradicional de Java adiciona n- do-lhe parâmetros de compilação extraordinários, as que recorrem a compiladores próprios e as que recorrem a compiladores de aspectos.
De todas as ferramentas analisadas, poderíamos escolher apenas uma ou a combinação de várias para concretizar os objectivos pretendidos. No entanto, esta última opção levantaria algumas questões de compatibilidade entre as ferramentas a utilizar. Como o OCLe é a única ferramenta disponível que contempla todas as funcionalidades nece s- sárias a este processo, mereceu de imediato a nossa atenção, sendo as restantes relegadas para seg undo plano. Mesmo colocando de lado as questões de compatibilidade menci o- nadas anteriormente, o facto de se trabalhar numa única ferramenta é menos propício a falhas no processo de trans i- ção do desenho para a implementação, para além de impl i- car uma curva de aprendizagem significat ivamente menor. Além disso, o OCLe é a ún ica ferramenta que valida as asserções contra o modelo UML, para além da comum val i- dação sintáctica . Mais, já contempla o OCL 2.0 e gera aut o- maticamente código Java correspondente às asserç ões espe- cificadas, implementado quase na totalidade o OCL . Pelas razões anteriormente indicadas, o OCLe afigura -se como a altern ativa tecnológica que nos assegurará maior qualidade
no produto final, pelo que é a ferramenta eleita para impl e-
mentar o caso de estudo.
4 Caso de Estudo
A demonstração do processo, que nos leva da modelação em UML já com suporte ao DpC com OCL, passou pela utilização do modelo “ Viagem Cacilheiro ” cujo diagrama de classes está representado na figura 6. Para este fim, util i- zámos a ferramenta eleita - OCLe - a partir do estudo co m- parativo efectuado na secção anterior.
4.1 Modelação do Sistema “Viagens Cacilheiro”
O primeiro passo foi desenhar o diagrama de classes utiliza ndo as funcionalidade de modelação disponíveis no OCLe.
4.2 Introdução das Cláusulas do Contrato
Introduzimos no modelo algumas asserções em OCL e val i- dámos a sua sintaxe contra o modelo pr oduzido. Para exempli ficar escolhemos a classe Viagem .
Expressões em OCL implementadas .
context Viagem::novoPassageiro(p:Passageiro)
- - um passageiro só pode fazer uma viagem de cada vez.
pre passageiroNaoExiste:
not( self.passageiro ->includes(p) )
- - o numero de passageiros é incrementado.
post numeroPassageiros:
self.passageiro ->size() = self.passageiro ->size@pre + 1
context Viagem
- - o numero de passageiros de uma viagem não pode ser exceder o numero de lugares disponíveis do cacilheiro.
inv numeroPassageirosPorViagem:
self.passageiro ->size() <= self.cacilheiro.numeroLugares
- - Cada viagem tem um número único.
inv uniqueViagem:
Viagem.allInstances ->forAll( c1,c2:Viagem |
c1<>c2 implies c1.nrViagem<>c2.nrViagem )
No OCLe as expressões for am objecto de verificação de sintaxe e verificadas automaticamente contra o diagrama de classes desenhado para o efeito.
4.3 Geração do Código em Java
Depois do desenho em UML e especificação em OCL das restrições no OCLe, é chegada a fase de gerar o código Java adequado. O OCLe gera código Java que implementa simu l- taneamente a interface das classes e as cláusulas de OCL, dentro de cada classe, no aplic ável.
O processo é muito simples, bastando apenas dar a ind i- cação à ferramenta da acção pretendida. Antes de g erar o código Java, a ferramenta procede sempre à análise da si n- taxe do OCL e à validação das restrições introduzidas, co n- tra o modelo especificado no diagrama de classes. O código Java gerado automaticamente pelo OCLe para impl ementar as asserções corresp ondentes às expressões OCL definidas no ponto anterior encontra -se em apêndice .
O código gerado é claro e bem estruturado, fazendo apenas referência a algumas classes de uma framework desenvolv idas especificamente para esta temática. Apesar
de todas as mai s-valias desta ferramenta, não podemos de i-
xar de realçar a quantidade de código que é acrescentado a cada classe, un icamente para implementar o DpC com OCL. O OCLe não suporta alguns dos mecanismos do DpC, sendo exemplo disso a não implementação de restr ições com carácter temp oral (utilização do xpto@pre ). Além disso, esta implementação de DpC contrasta com a do Eiffel, na qual as asserções podem ser inibidas ao critério do progr a- mador. Na implementação do OCLe passam a fazer parte do código da classe perde ndo essa possibilidade.
5 Conclusões e futuro
Hoje em dia, a maioria das organizações têm como pri n- cipais objectivos alcançar um nível elevado de qualidade nos seus produtos e/ ou serviços. Não é mais ace itável fornecer produtos com má qualidade aos client es e po s- teriormente tentar reparar os probl emas ou defeitos que daí podem ocorrer. Neste aspecto, os produtos de softwa- re têm que ser regidos pelo mesmo padrão de qual idade como quaisquer outros produtos, tais como aut omóveis, computadores, relógios ou cas as. No entanto, assum i- mos que a qualidade no software é sem dúvida um co n- ceito complexo que não se pode definir de uma maneira simplista. De qualquer forma, existem prese ntemente técnicas, como o DpC, que conseguem garantir aos pr o- dutos de software um níve l de qualidade já muito próx i- mo daquele que é vigente a outros pr odutos de áreas da engenharia.
Já existe alguma variedade de ferramentas que supo r- tam o DpC. No entanto, atendendo à importância que o OCL vai assumindo na modelação, aquelas que não o suport am irão previsivelmente começar a ser postas de lado pelos utiliz adores.
Havendo uma série de ferramentas que introduzem
as cláusulas de DpC em etiquetas de Javadoc, lamenta -se a inexistência de uma norma, ou pelo menos de uma prática comum, quanto à sinta xe utilizada na declaração das asserções, constatando -se que cada ferramenta util i- za um formato próprio. Este facto, para além de obr igar a uma aprendizagem das etiquetas específicas da ferr a- menta com que se está a trabalhar, impede a compl e- mentaridade ent re as fe rramentas que abrangem apenas partes do ciclo de vida, pois o resultado de uma não
pode ser reutilizado por outra.
O OCLe mostrou ser uma ferramenta bastante eficaz, não ob stante o facto de se mostrar pouco conforme no que diz respeito às funciona lidades apresentadas, quando comparada com outras ferramentas de model ação com UML, sendo exemplo disso a forma de se desenhar uma relação de composição. Em algumas (poucas) circunstâ n- cias, as mensagens de erro apresentadas resu ltantes da compilação do OCL são pouco elucidativas do problema existente, valendo no entanto ao utilizador o rigor com que o pos icionamento do erro é indicado. Na modelação com o OCLe, os atributos das classes são criados como protected por omissão. Isto levanta problemas ao utiliz ador menos atento dado que, quando implementa as clá usulas de OCL a compilação gera erros de visibilidade. Ju lgamos que os atributos das cla sses deviam ser criados como public por omissão, desde que fosse assegurada o enca p-
sulamento destes aquando do forward engineering .
O código Java gerado pelo OCLe para suportar o DpC é muito extenso, constituindo factor de preocupação quanto
à manutenção. Esta preocupação é devida ao emaranh a-
mento entre o código de suporte às asserções e o código de suporte às funcional idades que é implementado em
conjunto dentro da mesma classe. Actualmente estão a ser
desenvolvidas soluções com aspectos [23], [24], o que previsivelmente mitigar á esta problemática . No entanto, como é sabido, os aspe ctos introduzem actualmente um grande overhead e cons equente perda de desempenho, pelo que a evolução para esta tecnologia não só não reso l- verá todos os pr oblemas existentes, como ainda agravará outros. Apesar de tudo, cremos que as soluções impl e- mentadas com aspectos irão vingar, dada a sua m odul a- ridade, e que pouco a pouco os problemas de desemp e- nho irão sendo atenuados, quer com a evolução do hard- ware, quer com a evol ução desta técnica. Todavia, não se conhecem implementações ou projectos de ferr amentas que recorram ao emprego das asserções nativas da li n- guagem Java, talvez devido ao facto de estas terem sido introduzidas muito recentemente (finais 2003 [32]). Ape- sar de as asserções nativas de Java não implement arem o DpC tal como foi concebido, designadamente os invaria n- tes que são implement ados de forma indirecta (é cham a- do um mét odo no final de todos os métodos da classe) [32]. Estas asserções poderão constituir uma alte rnativa séria à impl ementação de DpC com aspectos.
Como foi já ref erido o OCLe não suporta ainda, na sua totalidade o DpC, sendo exemplo s disso a não compilação de asserções que reco rrem ao estado anterior do objecto (xpto@pre) e não permit ir a inibição das asserções . Além disso o OCLe não faz reverse engineering , pelo que qua l- quer alteração no desenho originará novo código. Ap esar de tudo é uma ferramenta bastante completa e a única capaz de sustentar o desenvolvimento de software com DpC e OCL ao longo de todo o ciclo de vida, bem como,
das ferramentas apreciadas, a única que valida as cláus u-
las de OCL introduzidas contra o mo delo des enhado.
Apesar das vantagens evidentes trazidas pela utiliz a- ção do DpC e do OCL à qualidade do software produz ido, não podemos ignorar o compromisso que lhe está ass o- ciado – o desempenho.
Existem presentemente actividades de investigação no sentid o de implementar DpC à custa de notações gráf icas [28], favorecendo deste modo uma melhor integração com
a habitual representação diagramática do UML.
Seria desejável que as ferramentas que implementam OCL evoluíssem no sentido da geração automática de testes, com base nas asserções.
Em resumo, o DpC com OCL e a sua implementação na linguagem Java com PpC são actualmente uma real i- dade, existindo ferramentas capazes de acompanhar o processo de dese nvolvimento ao longo de todo o ciclo de vida, a inda que com algumas l imitações . No entanto , os desenvo lvimentos verificados nesta área indici am que este será o cam inho certo, estando reunidas mais um co n- junto de cond ições, que permit irão a produção de software com cada vez mais qualidade, nome adamente no que diz respeito ao rigor e robustez daí resu ltantes.
Apêndice
/*
* @(#)Viagem. Java
*Generated by <a href="xxxx://xxx.xx.xxxxxxx.xx/xxxx/>OCLE 2.0</a>
* using <a href="xxxx://xxxxxxx.xxxxxx.xxx/xxxxxxxx/">
* Velocity Template Engine 1.3rc1</a>
*/
import Java .util.Iterator;
import Java .util.LinkedHashSet; import Java .util.Set;
import ro.ubbcluj.lci.codegen.framework.ocl.BasicConstraintChecker; import ro.ubbcluj.lci.codegen.framework.ocl.CollectionUtilities; import ro.ubbcluj.lci.codegen.framework.ocl.Ocl;
import ro.ubbcluj.lci.code gen.framework.ocl.OclType;
/** @author unascribed */ public class Viagem
{
}
public final Cacilheiro getCacilheiro() { return cacilheiro; } public final void setCacilheiro(Cacilheiro arg)
{
if (cacilheiro != arg) { Cacilheiro temp = cacilheiro;
cacilheiro = null;//to avoid infinite recursions if (temp != null) {
temp.removeViagem(this);
}
if (arg != null) { cacilheiro = arg; arg.addViagem(this);
}
}
}
public int lugaresDisponiveis() { return 0; }
public void novoPassageiro(Passageiro p)
{
class ConstraintChecker
{
public void checkPreconditions(Pa ssageiro p) { check_passageiroNaoExiste(p);
}
public void checkPostconditions(Passageiro p) { check_numeroPassageiros(p);
}
public void check_passageiroNaoExiste(Passageiro p)
{
Set setPassag eiro = Viagem.this.getPassageiro();
boolean bIncludes = CollectionUtilities.includes( setPassageiro,
boolean bNot = !bIncludes; if (!bNot) {
System.err.println("precondition 'passageiroNaoExiste'
p);
public final Set getPassageiro()
{
if (passag eiro == null) {
return Java .util.Collections.EMPTY_SET;
}
return Java .util.Collections.unmodifiableSet(passageiro);
}
public final void addPassageiro(Passageiro arg)
{
if (arg != null) {
if (passageiro == null) passageiro = ne w LinkedHashSet(); if (passageiro.add(arg)) {
arg.addViagem(this);
}
}
}
public final void removePassageiro(Passageiro arg)
{
if (passageiro != null && arg != null) {
failed for object "+Viagem.this);
}
}
if (passageiro.remove(arg)) { arg.removeV iagem(this);
}
public void check_numer oPassageiros(Passageiro p) }
{ }
Set setPassageiro = Viagem.this.getPassageiro(); int nSize = CollectionUtilities.size(setPassageiro); Set setPassageiro0 = Viagem.this.getPassageiro();
int nSize0 = Collection Utilities.size(setPassageiro0); int nPlus = nSize0 + 1;
boolean bEquals = nSize == nPlus; if (!bEquals) {
System.err.println("postcondition 'numeroPassageiros' failed
for object "+Viagem.this);
}
}
}
ConstraintChecker checker = new ConstraintChecker(); checker.checkPreconditions(p);
checker.result = internal_novoPassageiro(p); checker.checkPostconditions(p);
return checker.result;
private void internal_novoPassageiro(Passageiro p) { }
public Viagem() { }
public class ConstraintChecker extends BasicConstraintChecker
{
public void checkConstraints()
{
super.checkConstraints(); check_Viagem_numeroPassageirosPorViagem(); check_Viagem_uniqueViagem();
}
public void check_Viagem_numeroPassageirosPorViagem()
{
Set setPassageiro = Viagem.this.getPassageiro();
int nSize = CollectionUtilities.size(setPassa geiro); Cacilheiro cacilheiroCacilheiro = Viagem.this.getCacilheiro(); int nNumeroLugares = cacilheiroCacilheiro.numeroLugares;
boolean bLessOrEqual = nSize <= nNumeroLugares; if (!bLessOrEqual) {
System.err.println("invaria nt 'numeroPassageirosPorViagem'
failed for object "+Viagem.this);
}
}
public void check_Viagem_uniqueViagem()
{
Set setAllInstances = Ocl.getType(
new Class[]{Viagem.class}).allInstances();
//evaluate 'forAll(c1,c2:Viagem| c1<>c2 implies
//c1.nrViagem<>c2.nrViagem)':
boolean bForAll = true;
final Iterator iter = setAllInstances.iterator(); while (bForAll && iter.hasNext()) {
final Viagem c1 = (Viagem)xxxx.xxxx();
final Iterator iter0 = setAllInstances.iterator(); while (bForAll && iter0.hasNext()) {
final Viagem c2 = (Viagem)xxxx0.xxxx(); boolean bNotEquals = !c1.equals(c2); int nNrViagem = c1.nrViagem;
int nNrViagem0 = c2.nrViagem;
boolean bNotEquals0 = nNrViagem != nNrViagem0; boolean bImplies = !bNotEquals || bNotEquals0; bForAll = bImplies;
}
}
if (!bForAll) {
System.err.println("invariant 'uniqueViagem'
failed for object "+Viagem.this);
}
}
}
public int nrViagem;
public Cacilheiro caci xxxxxx;
public Set passageiro;
{
OclType.registerInstance(this, Viagem.class);
}
}
Referências
[1] Xxxxx, Xxxxxxxx, Object -Oriented Software Construction - Second Edition, Prentice Hall PTR, Santa Barbara, California, EUA, (1997).
[2] Xxxxxxxxx, Xxxxx, An Introduction to Eiffel and Design by Contract , Univers i- dade Nova de Lisboa, Faculdade de Ciências e Tecnologia, Bielko -Biala, Poland, (2002).
[3] Xxxxxxxxx, Xxxxxxxx, Xxxxx, Xxxxxx, Design by Contract in Java, InferData Corporation, (1999).
[4] Xxxxxx, Xxx, UML Bible, Wiley Publishing Inc., Indianapolis, Indiana,
EUA, (2003).
[5] Xxxxxx Xxx, Xxxxxx, Anneke, The Object Constraint Language – Second Edition, Addison-Wesley, EUA, (2003).
[6] xxxx://xxxxxxx.xxxxxx.xxx/ .
[7] http:// www.db.informatik.uni -xxxxxx.xx/xxxxxxxx/ .
[8] http:// xxx.xxxxxxxxxx.xxx/ .
[9] http:// jcontractor.fontef xxxx.xxx/ .
[10] http:// xxx.xxxxxxxxx.xxx/ .
[11] http:// xxx.xxxxxxxxxxxx.xxx.xx/ .
[12] http:// xxx.xxxxxxxx.xxx/XXXXxxxxx. html .
[13] xxxx://xxx.xxxxxxxxxx.xxx -xxxxxxxxx.xx/xxxxx/ .
[14] xxxx://xxxxxxx -XXX.xxxxxxxxxx.xxx/ .
[15] http:// xxx.xxxxxxxx.xxx/ jsp/products/home.jsp?product=Jcontract&i temId=28 .
[16] http:// xxx.xxxxxx.xx/XXX/xxxxxxx -intro.html .
[17] xxxx://xxx.xx.xxxxxxx.xx/xxxx/ .
[18] http:// xxx.xxx.xxxxxxxx.xx/Xxxxxx/ pubs/ other/XXXXX0000.pdf .
[19] OMG Unified Modeling Language Specification, “Chapter 6: Object Constraint Language Sp ecification”, OMG, (2001).
[20] OMG, “XML Metadata Interchange (XMI) Specification v1.2 ”, Object Management Group, (2002).
[21] Mage, Kjetil, A Pratical Application of the Object Constraint La nguage OCL, Agder University College, (2002)
[22] Briand, Dr. Xxxxxx, Ensuring the Dependability of Software Systems , CUSEC,
(2004).
[23] Xxxxxxxx, Xxxx, Xxxxxxx, Xxxxxx, Aspect -Oriented Monitoring of UML and OCL Constraints, EADS SPACE Transportation, University of Bremen, Germany.
[24] Xxxxxx, L.C., Xxxxxx, W., Labiche, Y ., Using Aspect -Oriented Programming to Instrument OCL Contracts in Java, Simula Research Laboratory, Norway, Software Quality Engineering Laboratory, Departament of Systems and Computer Engineering, Carleton University, Can ada, (2004).
[25] Xxxxxx, Xxxx, iCont ract - The Java Design by Contract Too, Cambridge Technology Partners.
[26] Xxxxxxxx, Xxxxxx, Xxxxxxxx, Xxxxx, Seese, Detlef, Design by Contract in Java - A Roadmap in Excellence to Trusted Components , University Karlsr u- he, Germany,
[27] Xxxx, Xxxxx, Using iContract and Design by Contract Techniques , Embedded Real-Time Inc., (2000).
[28] Xxxxxxx, Xxxxxxxxx, Xxxxxxxx, Xxxxxxxx, Xxxxxxxxxx, Xxxxxxx, Visual OCL, A Visual Notation of the Object Constraint Language , Fakultät IV - Elektrotec h- nik und Informatik, (2002).
[29] Verheec ke, Bart, From Declarative Constraints in Conceptual Models to Explicit Constraint Classes in Implementation Models , Departement Informatica, Faculteit van de Wetenschappen, Vrije Universiteit Brussel, (2001).
[30] Xxxxxx, B., Xxxx, X., A Behavioural Notion of Subtyping , ACM Transa ctions on Progra mming Languages and Systems, 16(6), pp. 1811 -1841, (1994).
[31] J.S. Bridle, Probabilistic Interpretation of Feedforward Classification Network
Outputs, with Relationships to Statistical Pattern Recognition , Neurocomp u- ting—Algorithms, Architectures and Applications , F. Xxxxxxxx-Xxxxxx and X. Xxxxxxx, eds., NATO ASI Series F68, Berlin: Springer -Verlag, pp. 227-236, 1989. (Book style with paper title and xx xxxx) .