Download PDF
ads:
UNIVERSIDADE FEDERAL DE SANTA CATARINA
PROGRAMA DE PÓS-GRADUAÇÃO EM CIÊNCIA DA
COMPUTAÇÃO
Claumir Claudino dos Santos
GERAÇÃO AUTOMÁTICA DE DIAGRAMAS DE
COMUNICAÇÃO A PARTIR DE CONTRATOS OCL
Dissertação submetida à Universidade Federal de Santa Catarina como parte dos
requisitos para a obtenção do grau de Mestre em Ciência da Computação.
Orientador
Raul Sidnei Wazlawick
Florianópolis, maio de 2007.
ads:
Livros Grátis
http://www.livrosgratis.com.br
Milhares de livros grátis para download.
ii
GERAÇÃO AUTOMÁTICA DE DIAGRAMAS DE
COMUNICAÇÃO A PARTIR DE CONTRATOS OCL
Claumir Claudino dos Santos
Esta Dissertação foi julgada adequada para a obtenção do tulo de Mestre em Ciência
da Computação - Área de Sistemas de Computação e aprovada em sua forma final pelo
Programa de Pós-Graduação em Ciência da Computação.
Coordenador do Curso
________________________________
Prof. Rogério Cid Bastos, Dr.
Orientador
________________________________
Prof. Raul Sidnei Wazlawick, Dr.
Banca Examinadora
_________________________________
Prof. Frank Augusto Siqueira, Dr.
________________________________
Prof. Ricardo Pereira e Silva, Dr.
________________________________
Prof. Paulo César Masiero, Dr.
ads:
iii
“Diagrams don’t crash”
(Bertrand Meyer)
iv
Agradecimentos
À Dynamix Software, empresa onde eu pude aplicar os conhecimentos adquiridos
durante meu mestrado, a todos os colaboradores e em especial ao Charles Trevizan
pelas revisões e criticas construtivas ao meu trabalho.
Ao colega Fabiano Beppler que sempre me auxiliou e incentivou.
Ao colega Dr. Paulo Luna, pelo apoio e por sempre ter apostado em mim.
Ao meu orientador e grande mestre Dr. Raul S. Wazlawick.
À minha mãe Elvira, amiga e eterna incentivadora.
Aos membros da banca examinadora, Dr. Frank, Dr. Ricardo e Dr. Masiero, que com
suas críticas e sugestões melhoraram infinitamente a qualidade final deste trabalho.
E por fim, à minha esposa Anabela, sem a qual minha vida não faria sentido.
v
Sumário
Lista de Figuras ................................................................................................................ 7
Resumo............................................................................................................................. 9
Abstract........................................................................................................................... 10
1. Introdução............................................................................................................... 11
1.1. Motivação....................................................................................................... 11
1.2. Objetivos......................................................................................................... 12
1.3. Justificativa..................................................................................................... 13
1.4. Resultados Esperados..................................................................................... 14
1.5. Organização da Dissertação............................................................................ 15
2. Conceitos................................................................................................................ 16
2.1. Automação do Desenvolvimento de Software ............................................... 16
2.2. Vantagens da Automação............................................................................... 16
2.3. Desvantagens da Automação.......................................................................... 17
2.4. Diagramas de Comunicação........................................................................... 18
2.5. Aplicações dos Diagramas de Comunicação.................................................. 21
2.6. Contratos......................................................................................................... 23
2.7. OCL - Linguagem para Escrita de Contratos ................................................. 26
2.7.1 Expressões OCL............................................................................................. 27
2.7.2 Tipos de Aplicação de Expressões OCL........................................................ 28
2.7.3 Símbolos e palavras-reservadas...................................................................... 28
2.7.4 Tipos de Dados............................................................................................... 30
2.7.5 Tipos Herdados de Modelos UML................................................................. 30
2.7.6 Collections...................................................................................................... 30
2.7.6.1 Set................................................................................................................... 31
2.7.6.1 Bag.................................................................................................................. 31
2.7.6.1 Sequence......................................................................................................... 31
vi
2.7.8 Operações sobre Collection............................................................................ 31
2.7.9 Contexto de uma Expressão OCL .................................................................. 33
2.7.9 Invariantes ...................................................................................................... 33
2.7.10 Pré-condições .................................................................................................. 33
2.7.11 Pós-condições.................................................................................................. 34
2.8. Adaptações à OCL.......................................................................................... 35
2.9. Padrões ........................................................................................................... 36
2.7.7 Especialista..................................................................................................... 37
2.7.8 Criador............................................................................................................ 37
2.7.9 Acoplamento Fraco......................................................................................... 38
2.7.10Coesão Alta ...................................................................................................... 39
2.7.11Controlador....................................................................................................... 39
2.10. Trabalhos correlatos ....................................................................................... 40
3. O Método de Geração de Diagramas Comunicação............................................... 45
3.1. Regras para Criação de Diagramas de Comunicação..................................... 46
3.2. O Algoritmo de Busca.................................................................................... 48
4. Resultados............................................................................................................... 53
4.2. Estudo de Caso ............................................................................................... 53
4.2.1 Exemplo Detalhado ........................................................................................ 54
4.2.2 Demais Exemplos........................................................................................... 58
4.3. Vantagens do Método Proposto...................................................................... 59
4.4. Limitações e Sugestões para Trabalhos Futuros ............................................ 59
5. Conclusões.............................................................................................................. 62
Anexo I........................................................................................................................... 71
7
Lista de Figuras
FIGURA 1 - Esquematização do mecanismo gerador de diagramas de comunicação
.........................................................................................................................................12
FIGURA 2 - Diagrama de seqüência...............................................................................19
FIGURA 3 - Diagrama de comunicação.........................................................................20
FIGURA 4 - Contra-exemplo de diagrama de comunicação..........................................21
FIGURA 5 - Exemplo de contrato de operação de sistema em linguagem natural.........24
FIGURA 6 - Exemplo de contrato de operação de sistema em de OCL.........................24
FIGURA 7 - Diagrama de classe para exemplificação da OCL......................................27
FIGURA 8 - Operações e propriedades suportadas pelas coleções OCL........................30
FIGURA 9 - Representação visual do algoritmo usando busca em profundidade..........46
FIGURA 10 - Modelo conceitual utilizado no exemplo.................................................49
FIGURA 11 - Contrato da operação de sistema InsereClausula.....................................49
FIGURA 12 - Estado inicial............................................................................................50
FIGURA 13 - Estado após a regra 3 para adquirir visibilidade para contratoAtual........50
FIGURA 14 - Estado após a regra 2 para delegar a criação de Clausula........................51
FIGURA 15 - Estado após a regra 1 para criar uma instância de Clausula.....................51
FIGURA 16 - Estado após a regra 1 para associar novaClausula a contratoAtual.........52
FIGURA 17 - Estado após a regra 1 para modificar o atributo Texto de Clausula.........52
FIGURA 18 - Resumo das regras aplicadas na criação dos diagramas de comunicação
.........................................................................................................................................53
FIGURA 19 - Modelo conceitual - 1ª parte.....................................................................71
FIGURA 20 - Modelo conceitual - 2ª parte.....................................................................72
FIGURA 21 - Modelo conceitual - 3ª parte.....................................................................72
FIGURA 22 - Modelo conceitual - 4ª parte.....................................................................73
FIGURA 23 - Contrato da operação de login..................................................................73
FIGURA 24 - Diagrama de Comunicação para operação de login.................................74
FIGURA 25 - Contrato da operação de definirPessoaCorrente......................................74
FIGURA 26 - Diagrama de Comunicação para operação definirPessoaCorrente...........75
8
FIGURA 27 - Contrato da operação de inserirCasamento..............................................75
FIGURA 28 - Diagrama de Comunicação para operação inserirCasamento..................76
FIGURA 29 - Contrato da operação de alterarCasamento..............................................77
FIGURA 30 - Diagrama de Comunicação para operação alterarCasamento..................77
FIGURA 31 - Contrato da operação de inserirEstangeiro...............................................78
FIGURA 32 - Diagrama de Comunicação para operação inserirEstangeiro...................78
FIGURA 33 - Contrato da operação de alterarEstangeiro...............................................79
FIGURA 34 - Diagrama de Comunicação para operação alterarEstangeiro...................79
FIGURA 35 - Contrato da operação de inserirVinculoProfissional................................80
FIGURA 36 - Diagrama de Comunicação para operação inserirVinculoProfissional....80
FIGURA 39 - Contrato da operação de removerVinculoProfissional.............................81
FIGURA 40 - Diagrama de Comunicação para operação removerVinculoProfissional
.........................................................................................................................................81
9
Resumo
Este trabalho apresenta um conjunto de princípios que, se aplicados para a
definição de contratos de operações de sistema, possibilitam a geração automática de
diagramas de comunicação (UML). Os diagramas assim gerados podem ser usados
também para geração automática de código.
O mecanismo que gera os diagramas de comunicação é um sistema de busca, o
qual foi projetado para encontrar diagramas que realizam um contrato de acordo com os
padrões de projeto GRASP General Responsibility Assignment Software Patterns. Os
contratos são escritos em uma linguagem que consiste em uma variação da OCL (Object
Constraint Language) adaptada para representar explicitamente os cinco tipos de pós-
condições semânticas possíveis em modelos orientados a objetos. Apesar de seu
considerável poder de geração, o mecanismo de busca resume-se a um conjunto de
apenas quatro regras.
O sistema foi implementado e testado em diversos contratos típicos de sistemas
de informação, produzindo em todos os casos os resultados almejados. Estes resultados
podem ser generalizados também para contratos mais complexos.
10
Abstract
This work presents a set of rules that can be applied to contracts for system
operations in order to allow automatic generation of UML (Unified Modeling
Language) communication diagrams. Those diagrams may be used afterwards for
automatic code generation.
A blind search algorithm was defined and implemented to find diagrams that
implement a contract in accordance to four basic GRASP design patterns (General
Responsibility Assignment Patterns Software). The contracts are written in a language
that consists in an OCL (Object Constraint Language) adaptation to represent each of
the five types of semantic post-conditions. The blind search algorithm is defined by a
set of four rules that allows generating communication diagrams for a large number of
contracts.
The system was implemented and tested for several typical information system
contracts taken from actual projects. In every test it produced the expected results. Due
to the structure of that kind of contracts, the results can be generalized to arbitrarily
complex systems.
11
1. Introdução
Muitos desenvolvedores de software aprenderam que desenvolver um sistema
a partir “do zero” é, quase sempre, mais difícil do que quando existe alguma coisa
pronta para ser usada como base.
Todavia, existem desenvolvedores que se restringem ao reaproveitamento de
código-fonte, usando apenas funções e rotinas programadas durante a construção de
outros sistemas.
Em um nível mais avançado de reaproveitamento encontram-se aqueles que
reutilizam também as “lições aprendidas” nos projetos anteriores. Lições estas
codificadas em “padrões de projetos” que são aplicados na resolução de problemas que
se repetem em novos sistemas.
Na tentativa de melhorar o desempenho dos construtores de software, muitos
estudos têm buscado formas de automatizar as atividades de desenvolvimento de
sistemas. Porém, ainda são bem vindos estudos que busquem automatizar a aplicação
dos padrões de projeto, focando a reutilização de idéias e princípios para a construção
de sistemas com melhor qualidade técnica a custos mais baixos.
Sob a óptica do processo de desenvolvimento proposto por Larman [Larman, 07]
este trabalho trata da automação da etapa de projeto da camada de domínio por meio de
um conjunto de princípios que, se aplicados para a definição de contratos de operações
de sistema, possibilitam a geração automática dos diagramas de comunicação (UML).
1.1. Motivação
As idéias de Larman [Larman, 07] mostram que um problema comum nos
projetos que empregam a orientação a objetos é a ausência de um projeto que utilize
corretamente os diagramas de comunicação. Na maioria dos projetos, o que se são
diagramas vagos, que mostram mensagens abstratas, que ainda exigem muita elaboração
antes de sua programação. Por exemplo, um diagrama que envia uma mensagem
“fazer_locação” a um objeto “Locação”, sem mostrar os detalhes da interação entre os
12
objetos, necessita de muita elaboração para seja possível compreendê-lo e implementá-
lo de forma correta.
Também, a literatura tem relegado os diagramas de comunicação a meros
coadjuvantes no processo de análise e projeto de software. Para muitos autores
[Rational, 03] [OMG, 06] [Booch, 00] [Fowler 03] [Furlan, 98] [Scott, 04] estes
diagramas não são considerados como especificação precisa do código que deve ser
gerado, e dificilmente eles são mostrados como a realização dimica do modelo
funcional (contratos) do sistema, servindo freqüentemente apenas como documentação
ou explanação sobre os processos de colaboração entre objetos.
Todavia, fazer diagramas de comunicação é decidir os detalhes do projeto da
interação dinâmica entre os objetos, e é na construção destes diagramas que deve
ocorrer a atribuição de responsabilidades e a aplicação de padrões de projetos, como os
padrões GRASP (General Responsibility Assignment Software Patterns). Seguindo
estes padrões, a escolha das interações entre objetos e, portanto, a construção dos
diagramas de comunicação, pode ser feita com decisões justificadas a partir dos
princípios adotados.
1.2. Objetivos
O objetivo deste trabalho é sistematizar a criação de diagramas de comunicação
através dos contratos de operações de sistema e do modelo conceitual, baseando-se nos
padrões de projeto GRASP, de forma a possibilitar a automatização deste processo.
13
FIGURA 1 – Esquematização do mecanismo gerador de diagramas de comunicação.
A figura 1 ilustra, de forma simplificada, o mecanismo que foi criado. São utilizados
como entrada do mecanismo dois artefatos de software: o modelo conceitual e o
contrato OCL (Object Constraint Language) da operação de sistema. Após o
processamento seapresentado como saída um conjunto de possíveis diagramas de
comunicação que realizam a operação de sistema descrita pelas pré e pós-condições do
contrato.
1.3. Justificativa
A partir da pesquisa de alguns trabalhos, [Larman, 07] [Wazlawick, 04] [Porres,
01] [Heckel, 00] [Bezerra, 02] foram coletadas as seguintes informações:
Um diagrama de comunicação é a realização de cada uma das pós-condições de
um contrato de operação de sistema;
Para realizar uma pós-condição irá existir uma ou mais mensagens enviadas
entre os objetos do diagrama de comunicação;
A aplicação de padrões de projetos, como os padrões GRASP, podem definir
como devem ser as trocas de mensagens entre os objetos;
14
Respaldado por estas afirmações, este trabalho quer demonstrar que é possível
sistematizar e automatizar a criação dos diagramas de comunicação através da aplicação
sucessiva de padrões de projetos, justificando as decisões de projeto a partir dos
próprios padrões adotados.
Diferentemente de trabalhos que utilizam contratos OCL para validar os
modelos e diagramas produzidos manualmente [Kyas, 04] [Richters, 00] [Richters, 02]
[Gogolla, 01], o que se deseja não é corrigir modelos incorretos, e sim produzir uma
solução adequada na primeira vez.
Outras abordagens de automação de software [Engels, 99] [Enseling, 06]
[Sjögren, 02] [Kiniry, 98] [Engels, 99] [Barstow, 85] [Bottoni, 01] produzem código-
fonte diretamente da especificação, eliminando etapas do processo de desenvolvimento
e produzindo soluções nas quais pode ser difícil avaliar a qualidade ou mesmo fazer
manutenção diretamente no código produzido.
A abordagem deste trabalho pode trazer vantagens pelo uso de diagramas ao
invés de código porque de acordo com Larman [Larman, 07], na etapa de criação dos
diagramas de comunicação é que são tomadas as decisões de atribuição de
responsabilidades das classes. Além disso, o uso dos diagramas permite ao projetista
avaliar a qualidade da solução gerada automaticamente, especialmente no que tange à
utilização dos padrões de projeto GRASP. Tal característica é interessante tanto para
os projetistas experientes, que podem ajustar ou alterar os diagramas gerados, como
para os projetistas iniciantes, que podem aprender novas habilidades visualizando os
diagramas gerados.
1.4. Resultados Esperados
Este trabalho pretende atingir os seguintes resultados:
a) Preservação do conhecimento e da experiência adquirida em projetos anteriores por
meio da sistematização do processo de criação de diagramas de comunicação,
refinando e melhorando o processo e a utilização dos padrões de projeto.
15
b) Aplicação do método por ferramentas CASE. A idéia de transformar o modelo
conceitual e funcional (contrato) em modelo dinâmico (diagrama de comunicação)
pode ser utilizada em ferramentas CASE para acelerar o processo de
desenvolvimento do software, visto que, esta transformação é aplicada logo após o
final da fase de análise e produz a base para a camada de domínio na fase de projeto.
c) Melhorar a qualidade das soluções geradas pela garantia de aplicação dos padrões de
projeto. A sistematização do processo de criação de diagramas de comunicação pode
ser feita pela aplicação sucessiva de padrões de projeto, o que garante, pelo menos, a
aplicação dos padrões GRASP (General Responsibility Assignment Software
Patterns).
1.5. Organização da Dissertação
Este trabalho está organizado como segue. No capítulo 2 são apresentados os
conceitos, as vantagens e desvantagens da automação no desenvolvimento de software,
os conceitos básicos sobre diagramas de comunicação, contratos, linguagem para
criação de contratos, padrões de projeto e sobre outros trabalhos relacionados.
O capítulo 3 é a maior contribuição desta pesquisa. está descrito em detalhes
o método de geração dos diagramas de comunicação e também como aplicá-lo.
Abordando os resultados obtidos na aplicação do método em contratos e
operações típicas de sistemas de informação têm-se o capítulo 4.
Por fim, o capítulo 5 descreve as principais conclusões, ressaltando as principais
contribuições, limitações e sugerindo futuras pesquisas que podem complementar o
trabalho aqui apresentado.
16
2. Conceitos
2.1. Automação do Desenvolvimento de Software
Desenvolvedores de software vêm reconhecendo a importância de reaproveitar o
esforço empregado no desenvolvimento de sistemas anteriores para reduzir prazos e
custos de novos sistemas.
Além de compreender os conceitos do domínio do sistema a ser produzido, a
equipe de desenvolvimento consome um grande tempo reescrevendo código idêntico ou
similar àquele que já foi produzido em sistemas anteriores. Isto literalmente é uma perda
de tempo e aos desenvolvedores a oportunidade de cometer os mesmo erros
novamente.
Vários pesquisadores [Far, 94] [Barstow, 85] [Gómez, 89] [Nishida, 91] [Chen,
97] [Blaine, 91] [Dietz, 98] têm proposto abordagens para automatizar o
desenvolvimento de software, tentando gerar programas completos a partir de
especificações ou tentando automatizar alguma parte do processo de desenvolvimento.
Neste sentido, as técnicas de automação utilizadas têm sido as mais diversas
possíveis. os que têm tentado desenvolver abordagens de automação a partir das
atividades dos profissionais humanos e há os que desenvolvem técnicas diferenciadas de
automação. Ainda, devido à dificuldade que evolve este tema, muitos trabalhos têm
aplicado a inteligência artificial para prover alguma forma de automação às fases do
desenvolvimento de sistemas [Zang 00] [Far, 93] [Chen, 97].
2.2. Vantagens da Automação
Utilizar métodos automatizados para a produção de software traz muitas vantagens:
a) A automação garante o rigor no desenvolvimento, estabelecendo restrições e
premissas para que os projetistas não produzam erros ou esqueçam detalhes a
respeito do projeto.
17
b) O ganho de tempo oferecido pelos métodos automatizados possibilita ao
projetista produzir e testar soluções alternativas para o mesmo problema.
c) A automação diminui a variedade de tipos de projetos, evitando com que os
projetistas “re-inventem a roda”, facilitando a compreensão dos projetos para
todos os envolvidos.
d) Incrementa a qualidade das soluções produzidas, pois a automatização é uma
forma de garantir a aplicação dos padrões de projetos.
e) Auxilia os projetistas novatos a produzir bons projetos, pois os ensina através
dos exemplos produzidos.
2.3. Desvantagens da Automação
Embora existam vantagens na automação da produção de software, existem também
algumas desvantagens que devem ser analisadas:
a) As ferramentas de automação que se comportam como black-boxes
dificultam ou impedem a compreensão da solução produzida.
b) Muitas vezes as ferramentas de automação não estão aptas a tratar algoritmos
complexos e não usuais. Esta situação faz com que os desenvolvedores
tenham que produzir partes do sistema de forma manual, o que incrementa
consideravelmente a complexidade da manutenção do sistema.
c) O tempo ganho na automação de uma tarefa pode ser transferido para outra
etapa do processo de desenvolvimento, o que, na prática, não representa um
aumento real de produtividade. Frequentemente existe a necessidade de
especialização técnica para aquisição de novas habilidades para o uso das
ferramentas de automação.
18
d) O rigor imposto pelas ferramentas de automação pode dificultar a inovação e
o emprego de novas tecnologias.
No geral, a automação de software envolve diversas disciplinas da ciência da
computação. Isto que têm contribuindo para o surgimento de diversas abordagens de
automação, algumas mais vantajosas de que outras, mas todas ajudando a traçar um
futuro proeminente para o desenvolvimento de software.
2.4. Diagramas de Comunicação
A literatura tem relegado os diagramas de comunicação a meros coadjuvantes no
processo de análise e projeto de software. Ela se restringe, muitas vezes a apenas
apresentar a sintaxe dos diagramas de comunicação [Rational, 03] [OMG, 06] [Booch,
00] [Fowler 03] [Furlan, 98] [Scott, 04], e em poucos casos [Larman, 07] [Wazlawick,
04] [Porres, 01] [Heckel, 00] [Bezerra, 02] mostra que eles podem ser considerados
como uma realização dinâmica do modelo funcional (contratos) mostrando o
comportamento de uma operação de sistema. Dificilmente estes diagramas são
considerados como uma especificação precisa do código que deve ser gerado, servindo
mais freqüentemente apenas como documentação ou explanação sobre os processos de
colaboração e interação entre objetos.
Segundo Bezerra [Bezerra, 02], um caso de uso descreve quais são os requisitos
funcionais do sistema e quais são as entidades (atores) que interagem com o sistema.
Este modelo informa também quais as ações e as respostas o sistema deve realizar ou
produzir para os atores. Ou seja, para que um caso de uso seja satisfeito, é necessário
realizar um conjunto de operações de sistema. No entanto, um caso de uso não deve
conter informações sobre como o sistema deverá funcionar internamente para realizar
estas operações.
Larman [Larman, 07] e Wazlawick [Wazlawick, 04] nomeiam as ações e repostas
que o sistema deve realizar e produzir como “eventos” e “respostas” de sistema. Cada
evento ou resposta de sistema iativar um processamento interno, ao qual eles dão o
nome de operação de sistema. Estas operações iniciam na camada de interface com o
usuário e devem ser realizadas pela camada de domínio. Estes autores descrevem
19
também o uso de contratos para a especificação das operações de sistema, entretanto
este assunto será aprofundado em uma seção posterior.
Também de acordo com Bezerra [Bezerra, 02], o modelo de classes de domínio
fornece uma visão estática do sistema, definindo as classes, as suas associações e as
suas responsabilidades. Este modelo também não descreve de que forma os objetos
devem interagir para realizar as operações expressas nos casos de uso.
O objetivo destes modelos é dar um entendimento do problema a ser resolvido. Para
mostrar “como” os objetos do modelo de domínio irão interagir e colaborar para realizar
as operações de sistema é necessário criar o modelo dinâmico do sistema. Ou seja, os
diagramas de interação.
De acordo com o OMG [OMG, 06], a descrição da cooperação entre as
instâncias envolve dois aspectos: 1) a descrição estrutural dos participantes; 2) a
descrição dos padrões de comunicação.
A estrutura dos participantes que “interpretam os papéis” para executar uma
tarefa é chamada de colaboração. O padrão de comunicação executado pelas instâncias
para executar a tarefa é chamado de interação. Para compreender o mecanismo usado
em um projeto, é importante visualizar as instâncias e as interações envolvidas no
cumprimento de um propósito (ou conjunto de propósitos).
Uma colaboração inclui um conjunto de instâncias e associações que definem os
participantes necessários para a realização de uma determinada operação. As instâncias
e as associações são definidas, respectivamente, pelas classes e associações do modelo
conceitual e pelas pré-condições do contrato da operação de sistema.
uma interação é definida no contexto de uma colaboração para especificar o
padrão de comunicação entre os objetos. De forma mais precisa, uma interação é um
conjunto ordenado de mensagens que sinaliza as operações que devem ser invocadas e
os papéis que devem ser interpretados pelo emissor e pelo receptor da mensagem.
Neste trabalho as colaborações serão utilizadas para definir operações de
sistema, embora seja possível definir colaborações em diferentes níveis de
granularidade.
A UML 2.0 [UML2, 02] define quatro tipos diagrama que podem ser utilizados
para exibir as interações entre os objetos:
20
1. Diagrama de seqüência – é o mais comum deles é o que foca a troca de
mensagens entre os objetos sob a óptica do "tempo de vida" dos objetos.
2. Diagrama de comunicação - mostra as interações em uma visão arquitetural,
onde são exibidas as linhas de visibilidade entre os objetos e a seqüência das
mensagens é marcada utilizando-se uma numeração.
3. Diagrama de visão geral da interação (Interaction Overview Diagrams) - é uma
variação do diagrama de atividades que define interações de uma maneira que
possibilita uma visão geral do fluxo do controle.
4. Timing Diagrams que são usados para mostrar as interações quando o
propósito primário do diagrama é raciocinar sobre o tempo. Estes diagramas
focam as mudanças que ocorrem nos objetos ao longo de seu tempo de vida.
Eles podem descrever o comportamento de um classificador individual (uma
instância de uma classe) e também as interações dos classificadores ao longo do
tempo.
Conforme Larman [Larman, 07] para a descrição de interações entre objetos no
nível de operações de sistema são utilizados os dois primeiros tipos de diagramas. O
diagrama de seqüência, exemplificado na Figura 2, mostra a seqüência das mensagens
enviadas, mas omite a visibilidade entre os objetos.
21
FIGURA 2 – Diagrama de seqüência.
FIGURA 3 – Diagrama de comunicação.
o diagrama de comunicação exibe claramente a visibilidades entre os objetos
usando linhas de ligações pelas quais é possível visualizar os diferentes tipos de
visibilidades entre as instâncias visibilidade por associação, visibilidade por
parâmetro, visibilidade por declaração local. Como será visto mais adiante, esta
possibilidade auxilia na aplicação de design patterns.
2.5. Aplicações dos Diagramas de Comunicação
De acordo com Hamilton e Miles [Hamilton, 06], o propósito principal dos
digramas de seqüência é mostrar a ordem dos eventos entre as partes de um sistema
22
envolvidas em uma operação. Diagramas de comunicação estabelecem uma outra
perspectiva para a operação focando nas ligações entre os objetos.
Além de vários exemplos de utilização de diagramas de comunicação na
especificação de sistemas de informação [Larman, 07] [Wazlawick, 04] [Porres, 01]
[Russel, 03] [Grand, 99] [Fowler 03] [Fulan, 98] [Fowler 03] [Heckel, 00] [Engels, 99],
muitos outros trabalhos têm utilizado diagramas de comunicação para expressar as
interações entre os objetos, destacando-se:
1) Capturing Dynamic Program Behaviour with UML Collaboration Diagrams
[Kollmann, 01] neste trabalho os autores utilizam diagramas de comunicação para
expressar o comportamento dinâmico de código executável Java, extraído por uma
abordagem própria.
2) A visualization of OCL using Collaborations [Bottoni, 01] este artigo sugere a
introdução de novos elementos gráficos aos diagramas de comunicação para que seja
possível visualizar restrições definidas em OCL de forma mais conveniente e embutidas
nos próprios diagramas.
3) UML Collaboration Diagrams and their Transformation to Java [Engels, 99] os
autores apresentação um algoritmo para transformação de diagramas de comunicação
em código Java.
4) Strengthening the Semantics of UML Collaboration Diagrams [Heckel, 00] – o
trabalho sugere um “alongamento” da semântica dos diagramas de comunicação para
suportar especificações formalmente precisas que possam ser verificadas por métodos
formais.
Em contrapartida aos trabalhos acima, pode-se citar algumas aplicações dos
diagramas de comunicação que são verdadeiros maus exemplos de utilização [Rational,
03] [OMG, 06] [Booch, 00] [Furlan, 98] [Fowler 03] [Scott, 04].
23
A figura a seguir é um destes exemplos do uso dos diagramas de comunicação
de forma ineficiente. O exemplo, retirado de Furlan [Furlan, 98], apresenta um diagrama
onde as mensagens são vagas e imprecisas.
FIGURA 4 – Um exemplo de diagrama de comunicação vago [Furlan, 98].
Este é um exemplo de utilização vaga do diagrama de comunicação porque a
partir deste diagrama não é possível produzir uma implementação em código executável
para realizar a operação descrita. As mensagens do diagrama necessitam ainda de muito
trabalho de projeto para que se possa considerá-las como uma especificação de uma
operação. Por exemplo, a mensagem “preparar”, vem da interface, e não passa
parâmetro algum. Então, como o receptor “pedido” saberá o que preparar? Além disso,
o diagrama não permite saber o que é “preparar”. Seria uma associação a ser criada
entre pedido e item para incluir um novo item no pedido? Seria a crião de uma nova
instância? Seria o preenchimento de um atributo de item? Também o é possível saber
o que deve ser atualizado em “item de entrega”. Estas perguntas não são respondidas no
diagrama. Por isso ele é vago e pouco útil como documentação de projeto.
2.6. Contratos
De acordo com [Larman, 07] [Wazlawick, 04], durante a expansão dos casos de
uso, são identificadas entradas e saídas de informações no sistema. Estas entradas e
24
saídas, chamadas de operações de sistema, correspondem a uma intenção por parte do
usuário.
Normalmente os casos de uso são suficientes para descrever as mudanças de
estados que as entradas e saídas provocam nos objetos do modelo de domínio.
Entretanto, casos em que é necessária uma descrição detalhada e formal de como
estas operações deve funcionar. No contexto do método de analise seguido por este
trabalho, é assumido que para cada operação de sistema identificada deverá ser criado
um contrato para especificá-la.
Em UML, as operações são definidas formalmente: “uma operação é uma
especificação de uma transformação ou consulta que um objeto pode ser chamado para
executar” [Booch, 00]. Uma operação tem uma assinatura (nome e parâmetros) e uma
especificação que descreve os efeitos provocados pela sua execução. O formato para
especificação de operações pode ser variado. Todavia, uma forma muito conveniente de
definir operações é através do uso de contratos com pré-condições e pós-condições. As
pré-condições são assertivas sobre o estado do sistema no instante anterior à execução
da operação. Elas estabelecem o que deve ser verdadeiro quando uma operação de
sistema for executada [Wazlawick, 04].
Pré-condições dos contratos podem ser interpretadas como uma extensão
temporária do modelo conceitual. Por exemplo, se o modelo conceitual especificar que
uma determinada associação tem multiplicidade de papel 0..1, uma pré-condição poderá
garantir que, antes da execução de uma determinada operação o papel esteja
necessariamente preenchido (1) ou não preenchido (0). As pré-condições nunca podem
contradizer o modelo conceitual, apenas estender o conjunto de restrições que ele
apresenta.
Ao contrário das pré-condições, que descrevem o estado do sistema antes da
execução da operação, as pós-condições identificam as mudanças que terão ocorrido no
sistema logo após a execução da operação. As pós-condições não são ações a serem
executadas e sim declarações sobre o estado do sistema que se tornam verdadeiras ao
término da execução da operação. Elas são semânticas no sentido de que se referem
apenas aos elementos do modelo conceitual e não a aspectos tecnológicos como
interface, banco de dados, comunicação, etc.
25
O formato de contrato com pré e pós-condições (Design by Contracts) foi
incluído pela primeira vez em uma linguagem de programação por Bertrand Meyer
[Meyer, 88]. Nesta abordagem, além dos contratos para operações de sistema (pré e pós-
condições e exceções), são criados contratos para classes (invariantes de classe) e
estruturas de repetição (invariantes e variantes de loop).
Algumas linguagens, como Eiffel [Meyer, 92], dão suporte nativo à
programação por contratos. Todavia, usando pré-processadores é possível prover um
suporte similar em outras linguagens, como Java [Enseling, 06] [Kiniry, 98]
[Karaorman, 99] [Man, 06] [Duncan, 98] ou .NET [Sjögren, 02].
Contratos podem ser escritos em linguagem natural ou em uma linguagem
formal. Associada à UML existe uma linguagem formal para a escrita de contratos
conhecida como OCL (Object Constraint Language) [Warner, 98] [OCL, 06]. A seção
“Linguagem para escrita de contratos” descreve em detalhes a OCL.
Na figura 5 é apresentado um típico contrato de operação de sistema escrita em
linguagem natural. Já na figura 6 é apresentado o mesmo contrato transcrito para OCL.
FIGURA 5 – Exemplo de contrato de operação de sistema em linguagem natural.
Contrato da operação
: InsereClausu
la( numero_contrato:inteiro, texto_clausula:string)
Pré-condições
Existe uma instancia de Contrato com o atributo numero igual ao parâmetro
numero_contrato.
Pós-condições
Foi criada uma nova instância de Clausula
A nova instância de Clausula foi associada ao Contrato
O atributo texto da nova Clausula foi alterado para o valor de texto_clausula.
InsereClausula( numero_contrato:integer, texto_clausula:string)
Pre
contrato = self.cadastro select(numero== numero_contrato)
contrato size() == 1
Post
novaClausula = Clausula.new()
contrato.associaClausula(novaClausula)
novaClausula.texto = texto_clausula
26
FIGURA 6 - Exemplo de contrato de operação de sistema em OCL.
Conforme se pode notar, a OCL, apesar de apresentar leitura mais árdua, é mais
precisa. A primeira linha da seção “pré” apresenta um alias (abreviação da notação “let
... in ...”, da OCL, apresentada mais adiante) que define que o “contrato” com o qual a
operação vai trabalhar é uma entidade ligada ao controlador de sistema (self) cujo
atributo “numero” é igual ao parâmetro numero_contrato passado para a operação.
A segunda linha especifica a pré-condição em si, ou seja, que este contrato existe
e é único.
A primeira linha da seção “pós” representa a criação da instância de “clausula”.
A segunda linha indica que esta instância recém criada é associada ao contrato
em questão.
A terceira linha mostra a definição do atributo “texto” dessa clausula como o
valor do parâmetro “texto_clausula” passado para a operação.
Apesar de ser mais precisa do que a linguagem natural, o uso da OCL muitas
vezes é desencorajado, inclusive por autores como Larman [Larman, 07], visto que as
especificações podem se tornar difíceis de ler por parte dos interessados pelo sistema.
2.7. OCL - Linguagem para Escrita de Contratos
A primeira versão da UML submetida ao OMG (Object Management Group)
mostrou uma grande deficiência na clareza e consistência. Particularmente porque a
semântica das definições feitas em UML poderia ser interpretada de forma ambígua. Em
1997, para minimizar este problema, a UML foi incrementada a com a OCL.
O objetivo da OCL é ser uma linguagem de expressões para especificar
restrições sobre modelos orientados a objetos e descritos em UML. É uma linguagem
textual, precisa e formal.
A estrutura da OCL está ligada aos modelos da UML, como por exemplo, o
diagrama de classes. É uma linguagem textual que possui expressões escritas na forma
de afirmações, com tipos de dados pré-definidos e algumas palavras reservadas.
O artigo XOCL An XML language for specifying logical constraints in object
oriented models [Ramalho, 03] propõe uma integração da OCL com os modelos UML
27
pela fusão da OCL com o XMI (XML Metadata Interchange). Desta forma os modelos
UML teriam as suas restrições embutidas, podendo ser facilmente interoperabilizadas,
entre ferramentas CASE, bem como facilitariam a geração automática de código ou
testes de modelos.
2.7.1 Expressões OCL
As expressões OCL são utilizadas para definir condições invariáveis nas classes
de um modelo e também para especificar as pré e pós-condições das operações
aplicadas a classes deste modelo.
Expressões OCL podem ser utilizadas ainda para fazer consultas a um modelo
de classes da UML. Essas consultas podem ser úteis para validar modelos de classes na
fase de projeto.
Nesta seção, a título de exemplificação da OCL, adotamos o diagrama de classes
de uma locadora de veículos, apresentado na figura a seguir.
FIGURA 7 – Diagrama de classe para exemplificação da OCL.
Os exemplos seguintes, sobre a escrita de contratos, utilizam as classes e
associações do modelo conceitual da figura acima. Este diagrama seque o padrão
Controlador-Fachada descrito por Larman [Larman, 07] .
28
2.7.2 Tipos de Aplicação de Expressões OCL
São usados três tipos de aplicação para as expressões em OCL:
a) Invariantes: expressões que representam condições invariáveis do modelo;
b) Pré-condições: representam condições verdadeiras antes da execão de uma
operação;
c) Pós-condições: expressões que indicam o estado do sistema após a execução de
uma operação;
2.7.3 mbolos e palavras-reservadas
A exemplo de outras linguagens formais, a OCL também utiliza símbolos e
palavras-reservadas para a construção de suas expressões. Abaixo segue a explanação
dos símbolos e palavras-reservadas mais comuns:
a) Self - Numa expressão em OCL, a palavra reservada self é usada para
referenciar uma instância do contexto, de forma equivalente à palavra this do
Java.
b) Ponto “.” – Como nas linguagens de programação este operador é utilizado
para acessar as propriedades dos objetos.
post:
self.locacao.valorTotal = 8.50
c) Arrow-operator ->“ – O chamado de operador se a, permite acessar
as propriedades de uma coleção. Fazendo um paralelo com as linguagens de
programação este operador atua como o “.” utilizado para acessar as
propriedades dos objetos.
pre:
self.cadastro -> size() > 1
29
A linha acima permite acessar a propriedade size da coleção Cadastro para
testar se ele é maior do que 1.
d) @pre - É utilizado em prós-condições para referenciar o valor de um
atributo antes da execução da operação.
post:
self.locacao.valorTotal = valorTotal@pre * 2
Assim, o atributo valorTotal irá receber o seu valor anterior à execução da
operação multiplicado por 2.
e) OclIsTypeOf - É o operador utilizado para verificar se um objeto é de um
determinado tipo. Retorna verdadeiro se o objeto for do tipo especificado na
expressão.
Object -> oclIsTypeOf (type: OclType): boolean
f) OclIsNew - O operador OclIsNew retorna verdadeiro se o objeto informado
é um instancia nova, recém criada. Este operador somente pode ser utilizado
em pós-condições.
Object -> oclIsNew: boolean
g) Ifthen... else... end if Algumas vezes as expressões OCL (invariantes,
pré-condições e pós-condições) são condicionadas a determinadas situações.
Para expressar essas condições pode-se utilizar as palavras
if...then...else...end if.
context Sistema inv:
if
self.cadastro -> select(cpf=cpf_cli).size==0.
then
self.cadastro -> including(Cliente.new).
self.cadastro -> select(cpf=cpf_cli).debito=0.
else
self.cadastro -> select(cpf=cpf_cli).debito=0.
end if
30
2.7.4 Tipos de Dados
A OCL possui uma classificação hierárquica para os tipos de dados. Todas as
informações manipuladas nas expressões OCL, devem pertencer a um dos seguintes
grupos de variáveis:
Tipos básicos: Integer, Real, Boolean e String;
Coleções: Collection, Set, Sequence e Bag;
Tipos Especiais: OclAny, OclType e OclExpression;
Tipos dos modelos UML: todas as classes, interfaces, associações e
enumerações definidas no diagrama de classes.
2.7.5 Tipos Herdados de Modelos UML
Nas expressões OCL é possível utilizar os tipos de dados da própria UML:
a) Classifiers: são atributos da UML que servem para designar tipos de dados.
Classes de objetos é a ocorrência mais comum de classificadores encontrados
em expressões OCL;
b) Attributes: são as propriedades estruturais que caracterizam os classifier.
c) Associations: são as conexões entre 2 ou mais classifiers;
d) Operations: todas as operações definidas em um modelo podem fazer parte das
expressões OCL.
e) Enumerations: são conjuntos de tipos básicos de dados definidos nos classifiers.
2.7.6 Collections
Collection é o tipo abstrato de todas as coleções OCL. Ou seja, todos os tipos de
coleções estendem o tipo collection. Os objetos que pertencem a uma coleção são
chamados de elementos.
Quando se têm associações com um relacionamento “um-para-muitos” ou
“muitos-para-muitos”, a parte da associação que aparece multivalorada é considerada
uma coleção.
31
2.7.6.1 Set
Set representa um tipo de dado similar ao conjunto matemático. Os elementos
contidos em um set não podem aparecer duplicados. Outro detalhe é que não existe
ordem entre os elementos.
2.7.6.1 Bag
Bag é uma coleção de elementos que permite elementos duplicados, isto é, um
objeto pode ser um elemento na bag mais de uma vez. Como nos sets, na bag também
não existe ordem entre os elementos.
2.7.6.1 Sequence
A criação de coleções com elementos ordenados sob algum tipo de critério é
feita usando uma sequence. Diferentemente dos sets, os elementos podem aparecer
duplicados.
2.7.8 Operações sobre Collection
As coleções em OCL podem ser manipuladas por de diversas operações. A
tabela da Figura 8 descreve estas operações.
Propriedade Descrição
Size Retorna o número de elementos da coleção
count(objeto) Retorna o número de ocorrências do objeto na coleção.
includes(objeto) Inclui o objeto na coleção. Retorna verdadeiro se o objeto está
coleção.
includesAll(coleção) Inclui a coleção em outra coleção. Retorna verdadeiro se
coleção já estiver inserida.
isEmpty Retorna verdadeiro se a coleção estiver vazia.
notEmpty Retorna verdadeiro se a coleção não estiver vazia.
iterate(expressão) Avalia a expressão para cada um dos elementos da coleção.
sum(coleção) Soma uma coleção com outra.
32
exists(expressão) Retorna verdadeiro se existir um objeto na coleção que satisfaça
à expressão.
forAll(expressão) Retorna verdadeiro se todos os objetos na coleção satisfazem à
expressão.
select(expressão) Retorna o subconjunto de objetos da coleção que satisfazem à
expressão.
reject(expressão) Retorna o subconjunto de objetos da coleção que não satisfazem
à expressão.
collect(expressão) Transfere todos os elementos dados pela expressão em uma
nova coleção.
one(expressão) Retorna verdadeiro se somente um objeto satisfizer a expressão.
sortedBy(expressão) Retorna uma sequence de objetos que satisfazem a expressão.
FIGURA 8 – Operações e propriedades suportadas pelas coleções OCL.
33
2.7.9 Contexto de uma Expressão OCL
As expressões OCL necessitam estar ligadas a um contexto. O contexto de uma
expressão pode variar, sendo aplicável a uma classe ou a uma operação. Para expressar
o contexto em OCL utilizamos a palavra reservada context.
2.7.9 Invariantes
Invariantes são condições que os objetos do modelo devem respeitar durante
toda sua existência. Em OCL, para indicar que uma expressão é uma invariante,
utilizamos a palavra reservada inv após a declaração do contexto. Uma expressão pica
de invariante tem o seguinte formato:
context <contexto> inv: <expressão>
Utilizando o diagrama de classes da Figura 8, podemos definir uma invariante da
seguinte forma: “Todo veículo tem o valor da placa informado”.
context Veiculo inv: self.placa != ””
2.7.10 Pré-condições
Pré-condições são expressões que descrevem o estado do sistema antes da
execução de uma operação. A palavra pre após a declaração do contexto seguido do
símbolo “:” (dois-pontos) define uma pré-condição.
Em OCL representamos uma pré-condição da seguinte forma:
context <contexto> pre: <expressão>
Usando o diagrama de classes da Figura 8, pode-se mostrar um exemplo de pré-
condição com uma operação de sistema para efetuar a locação de um veículo. Uma
operação que recebe o CPF do cliente e a placa do veículo - registrarLocacao(cpf_cli:
34
int, placa_vei: String). Nessa operação teríamos duas pré-condições: “Existe um cliente
com o CPF igual ao parâmetro cpf_cli” e “Existe um veículo com a placa igual ao
parâmetro placa_vei”. Assim, em OCL tem-se:
context Sistema::registrarLocacao (cpf_cli: int, placa_vei:
String)
pre:
self.cadastro -> select(cpf=cpf_cli)-> size=1.
self.frota -> select(placa=placa_vei)-> size=1.
2.7.11 Pós-condições
Pós-condições apresentam o estado do sistema logo após a execução de uma
determinada operação. Na OCL, uma expressão deste tipo é declarada com a palavra
reservada post, logo após a definição do contexto seguido do símbolo “:” (dois-pontos).
context <contexto> post:<expressao>
Para exemplificar as pós-condições pode-se definir que a operação citada
anteriormente, registrarLocacao(cpf_cli: int, placa_vei: String), tem 4 pós-condições:
(1) “Foi criada uma instância de Locação”, (2) “A nova instância foi associada como a
locaçãoCorrente”, (3) “A nova instância foi associada ao veículo cuja placa é igual ao
parâmetro placa_vei” e (4) “A nova instância foi associada ao cliente cujo CPF é igual
ao parâmetro cpf_cli”. Em OCL:
context Sistema::registrarLocacao (cpf_cli: int, placa_vei:
String)
post:
self.locacaoCorrente -> including(Locacao.new).
self.locacaoCorrente.locado= self.frota -> select (placa =
placa_vei).
self.locacaoCorrente.locatario=self.cadastro -> select( cpf
= cpf_cli).
35
2.8. Adaptações à OCL
Neste trabalho são introduzidas duas adaptações à OCL: a primeira é a
possibilidade de fazer a especificação de aliases para objetos nas pré-condições, e a
segunda, é a inclusão de propriedades (métodos) para que os objetos e classes possam
expressar diretamente as pós-condições.
Context InsereClausula(numero_contrato: integer;
texto_clausula: String)
pre:
contratoAtual= self.contratos ->
select(contrato|contrato.numero == numero_contrato).
contratoAtual -> size() == 1.
post:
novaClausula = Clausula.criar().
contratoAtual.associa_clausula(novaClausula).
novaClausula.texto = texto_clausula.
No exemplo acima, a primeira expressão das pré-condições define um alias
“contratoAtual” para o objeto e a segunda expressão usa este alias. As duas expressões
em conjunto representam a pré-condição que, em linguagem natural, poderia ser
descrita como existe uma instância de Contrato cujo número é igual a
‘número_contrato’”. Esta expressão corresponde à definição de um let clienteCorrente
= ... in ...”, onde a parte após o “in” estende-se tanto à parte “pré” quanto à parte “post”
do contrato.
Considerando-se que o modelo conceitual, descrito por um diagrama de classes
UML, tem basicamente três elementos: classe, associação e atributo, as mudanças
possíveis no estado dos objetos de um sistema, que as pós-condições descrevem, são
necessariamente de cinco tipos: (1) criação de objetos, (2) destruição de objetos, (3)
criação de associações, (4) destruição de associações e (5) modificação do valor de
atributos. Então, a segunda adaptação à OCL utilizada introduz novas propriedades
36
métodos) para objetos e classes que permitem expressar diretamente esses cinco tipos de
pós-condição, respectivamente:
a) classe.criar(): indica que foi criada uma nova instância de Classe.
b) objeto.destruir(): indica que o objeto foi destruído.
c) objeto1.set_papel(objeto2) ou objeto1.add_papel(objeto2): no primeiro caso,
indica a criação de uma associação para 1, no segundo caso a criação de uma
associação para muitos.
d) objeto1.remove_papel(objeto2): indica a destruição de uma associação.
e) objeto.set_atributo(valor): indica que o atributo do objeto foi alterado para
“valor”.
Para efeito de contrato, as propriedades set_papel, add_papel e remove_papel são
consideradas simétricas, ou seja, escrever objeto1.remove_papel(objeto2) equivale a
escrever objeto2.remove_papel(objeto1). O sentido real da criação da associação será
definido pelo mecanismo de busca.
2.9. Padrões
Projetistas experientes, sejam eles de diferentes áreas do conhecimento, buscam
resolver os problemas de projeto utilizando soluções de sucesso comprovado em
projetos anteriores. Esta afirmação introduz a idéia de padrões de problema-solução
que se originou dos padrões arquitetônicos de Chistopher Alexander.
De acordo com Gamma [Gamma, 94], um padrão de projeto é descrito como as
interações entre classes e objetos que podem ser adaptadas para resolver um problema
de projeto em um domínio específico. Outra definição diz que um padrão de projeto é
um par problema/solução que pode ser aplicado a um projeto de software para a
atribuição de responsabilidades às classes [Larman, 07].
Este trabalho foca um conjunto de padrões de projeto conhecidos como GRASP
(General Responsibility Assignment Software Patterns) [Larman, 07] [Wazlawick, 04].
Estes padrões definem princípios que devem ser seguidos para a atribuição de
responsabilidades aos objetos da camada de domínio.
Dominar e ser capaz de aplicar
estes padrões é a base para a criação de um bom projeto de objetos.
37
Embora existam outros padrões de projetos, como sugere Gamma [Gamma, 94],
primeiramente deve-se dominar estes cinco, pois tratam de questões comuns e
problemas fundamentais de projeto.
2.7.7 Especialista
Em termos de orientação a objetos, este é o princípio mais básico de todos. Ele
prega que o responsável por conhecer ou modificar uma informação seja a classe que
tem a informação necessária para satisfazer a responsabilidade. Ou seja, o especialista
na informação.
Wazlawick [Wazlawick, 04] diz que a aplicação mais óbvia deste padrão é
quando um objeto armazena um valor como atributo e oferece métodos (get/set) para
acesso a esta informação. Já uma aplicação não tão óbvia é quando a informação não é
apenas um simples atributo e precisa ser calculada através do acesso a outros objetos.
Neste caso o especialista na informação será a classe que tiver o acesso mais direto à
informação.
Este padrão é mais utilizado que qualquer outro na atribuição de
responsabilidades [Larman, 07]. O especialista conduz a projetos em que um objeto faz
as operações que normalmente são executadas pela coisa do mundo real que ele
representa.
Os benefícios de utilização deste padrão são, principalmente, a manutenção do
encapsulamento, favorecendo o acoplamento fraco (que será visto mais adiante) e a
distribuição do comportamento entre as classes do sistema, estimulando a definição de
classes leves e obtendo-se uma coesão mais alta.
2.7.8 Criador
Este padrão descreve princípios para determinar quem deve ser responsável pela
criação de instâncias de uma classe.
De acordo com Larman [Larman, 07], deve-se atribuir à classe X a
responsabilidade de criar uma instância da classe Y se pelo menos uma das seguintes
condições for satisfeita:
a) X agrega objetos de Y;
38
b) X contém objetos de Y;
c) X registra instâncias de objetos de Y;
d) X usa de maneira muito próxima objetos de Y;
e) X tem os dados de inicialização que serão passados no método construtor de Y.
Wazlawick [Wazlawick, 04] acrescenta ainda que outro princípio que deve ser
aplicado é que como uma instância somente pode ser criada por outra instância
existente pode-se usar a multiplicidade das associações para decidir qual a a classe que
será a criadora. Uma associação com multiplicidade de papel igual a 1 do lado X e 0..1
ou * do lado Y é uma associação onde a instância do lado X deve ser criada antes da
instância ou instâncias do lado Y. Desta forma, é muito provável que o criador de Y seja
X. Também faz mais sentido ter um único criador de várias instâncias do que rios
criadores de uma única instância.
Ainda e de acordo com Wazlawick, deve-se considerar também que quando
houver apenas um único caminho (de associações) da classe X até a classe controladora,
então o criador de X deverá estar neste caminho. Deverá estar porque a criação de uma
instância acontecerá em conseqüência do fluxo de execução de uma operação de sistema
iniciada no controlador. O fluxo de execução inicia no controlador e as mensagens são
delegadas até a classe que irá efetivamente fazer a instanciação do objeto.
A utilização deste padrão produz um projeto de objetos com um acoplamento
fraco, com uma menor dependência entre os objetos e favorecendo a reutilização e a
clareza do projeto.
2.7.9 Acoplamento Fraco
Acoplamento é uma palavra que significa a ligação entre dois ou mais elementos. No
contexto do projeto de software o acoplamento indica o quanto um elemento do sistema
está conectado ou dependente de outros elementos. Um elemento com acoplamento
fraco é dependente de poucos elementos. Aqui, a palavra elemento inclui classes,
subsistemas, sistemas, componentes etc. A correta aplicação dos padrões Especialista e
Criador favorecem um projeto com acoplamento fraco. Os tipos comuns de
acoplamento são:
39
a) O TipoX possui um atributo que referencia uma instância do TipoY ou o próprio
TipoY;
b) Um Objeto do TipoX chama serviços de um objeto do TipoY;
c) O TipoX recebe o TipoY como parâmetro de um método;
d) O TipoX retorna o TipoY como retorno de um método;
e) O TipoX é uma subclasse do TipoY;
f) O TipoX é uma interface e o TipoY é a implementação da interface.
Acoplamento fraco é um padrão de avaliação que prega a redução das ligações entre
em os objetos e o projetista precisa sempre ter esse padrão em mente durante a
confecção do projeto.
2.7.10 Coesão Alta
A coesão alta estabelece que o projetista deva sempre avaliar as decisões de
projeto para evitar que as classes se tornem complexas demais por assumirem
responsabilidades em excesso.
Booch [Booch, 94] descreve a coesão alta como algo existente quando os
elementos de um sistema (por exemplos as classes) trabalham todos em conjunto para
fornecer um comportamento bem delimitado.
Uma classe com coesão alta tem um número pequeno de métodos, com
funcionalidades relativas a si, e não executa todo o trabalho sozinha, colaborando com
os demais objetos para realizar o trabalho.
Mais clareza e facilidade de compreensão no projeto, simplificação da
manutenção e do acréscimo de melhorias e o favorecimento do acoplamento fraco são
alguns benefícios que, segundo por Larman [Larman, 07], a coesão alta proporciona.
2.7.11 Controlador
Durante a análise é normal definir uma única classe controladora para atribuir a
ela as operações de sistema. Entretanto, durante o projeto essas responsabilidades
poderão ser atribuídas a um conjunto de classes controladoras. O padrão de projeto
40
Controlador diz respeito à atribuição de responsabilidades a quem deve receber e tratar
os eventos de sistemas.
Um controlador é uma classe que faz uma ponte entre a interface com o usuário
e a camada de domínio, sendo responsável por receber ou tratar os eventos e repostas do
sistema. O controlador define o método para a operação de sistema, delegando para os
outros objetos o trabalho que precisa ser feito enquanto ele coordena ou controla a
atividade. Ele próprio não executa muito trabalho [Larman, 07] .
As grandes vantagens em se utilizar este padrão de projeto são o incremento da
reutilização das interfaces com o usuário, por garantir que a interface não execute lógica
da aplicação e, a possibilidade de conhecer o estado do caso de uso, ajudando a garantir
que as operações de sistemas executem numa seqüência válida.
2.10. Trabalhos correlatos
Após a realização da pesquisa bibliográfica, não se encontrou estudos que
tratassem exatamente do tema desta dissertação. Entretanto, identificou-se que o tema
da dissertação tem basicamente dois grupos de trabalhos correlatos. O primeiro grupo
diz respeitos aos trabalhos que utilizam contratos como uma fonte de informação para
testes ou verificações em modelos UML. O segundo grupo trata dos trabalhos que
fazem a automação de etapas do desenvolvimento de software, como a geração
diagramas, geração de casos de testes ou até a geração de programas completos.
Embora os trabalhos citados não sejam exatamente centrados no tema da
dissertação, a sua análise é relevante porque a abordagem proposta aqui, ou seja, a
geração automática de diagramas de comunicação a partir dos contratos é a
automatização de uma etapa do processo de desenvolvimento de software pelo uso de
contratos, assunto tratado diretamente pelos trabalhos citados.
No primeiro grupo destacam-se trabalhos como:
a) From Contracts to Aspects in UML Designs [Jézéquel, 02] - separar
preocupações é um princípio básico da engenharia e também é aplicado na
engenharia de software através da programação orientada a aspectos. Neste
41
trabalho é apresentada uma abordagem para modelar e organizar o projeto de
software usando a noção de serviços (geridos por contratos) e de aspectos. O
modelo UML produzido serve como base para a geração de código orientado a
aspectos.
b) A Precise Approach to Validating UML Models and OCL Constraints
[Richters, 02] - neste trabalho os autores criam um meta-modelo para a OCL,
definindo formalmente todos os elementos possíveis - tipos, operações,
expressões, invariantes, pré e pós condições. Eles propõem que este meta-
modelo pode ser usado para estender o meta-modelo da UML, introduzindo a ele
a precisão da OCL. Para demonstrar a aplicação pratica do trabalho é
apresentada uma ferramenta CASE, a USE, a qual faz a validação de modelos
UML.
c) XOCL An XML language for specifying logical constraints in object
oriented models [Ramalho, 03] - os autores desde trabalho sugerem uma
linguagem para embutir a OCL nos arquivos XMI (XML Metadata Interchange)
a fim de possibilitar o transporte e a interoperabilidade das constraints OCL
através de ferramentas CASE.
d) Formalizing UML Models and OCL Constraints in PVS [Kyas, 04] - de
acordo com os autores, uma das razões para a OCL não ser amplamente
difundida é falta de ferramentas que a suportem. Por isso, apresentam um
protótipo de ferramenta que analisa a sintaxe e a semântica de expressões OCL
em modelo UML traduzindo-os para uma linguagem de prova de teoremas
(PVS) fazendo uma verificação forma da OCL e dos modelos UML.
e) Transformation of UML Design Model into Performance Model: A Model-
Driven Framework [Wang, 06] - através de transformação de modelo, o trabalho
propõe um framework para fazer estimativas de performance de sistema
baseando-se em modelos UML.
42
De uma forma geral, os trabalhos analisados neste grupo apresentam
basicamente as mesmas vantagens e desvantagens.
Principais vantagens:
Possibilitam a aplicação de métodos formais no desenvolvimento de
software.
Pela transformação de modelos, em alguns casos, possibilita o reuso dos
artefatos já produzidos.
Principais desvantagens:
Focam na validação dos modelos produzidos manualmente.
São aplicáveis a situações muito especificas o que reduz a sua
empregabilidade no desenvolvimento de sistemas de informações típicos.
A abordagem de validar modelos anteriormente criados, apresentada na maioria
dos trabalhos correlatos deste grupo, “coloca a carroça na frente dos bois”. Em um
processo de desenvolvimento de software faz mais sentido produzir soluções corretas do
que corrigir modelos produzidos manualmente. Ao contrario das propostas analisadas,
nesta dissertação buscou-se encontrar um mecanismo que produza, de forma
automática, soluções corretas na primeira vez. A intenção não é corrigir modelos
prontos ou criados manualmente, mas sim produzir modelos corretos e validados
conforme os padrões de projeto aplicados.
Outro aspecto diferenciador é que o método de geração de diagramas de
comunicação produz diagramas para as situações típicas dos sistemas de informação, o
que amplia considerável o espectro de aplicação do método proposto neste trabalho.
Nos trabalhos do segundo grupo, focados na automação de software, sobressaem
as pesquisas citadas a seguir.
a) Knowledge-Based Automation of a Design Method for Concurrent Systems
[Mills, 02] - este artigo descreve uma abordagem para a automação do projeto de
softwares para sistemas concorrentes utilizando-se o conhecimento embutido nas
43
técnicas de projeto. Fluxogramas e um meta-modelo são utilizados para
representar este conhecimento e para a Concurrent Object-Based Real-time
Analysis (COBRA).
b) Automated Prototyping of User Interfaces Based on UML Scenarios
[Elkoutbi, 06] - o trabalho sugere um processo de levantamento de requisitos que
produz um protótipo de interface com usuário descrito por diagramas de
seqüência da UML. Estes diagramas são transformados em Petri nets e
utilizados para gerar interfaces automaticamente.
c) Approaches to Automatic Programming [Rich, 93] - este paper é uma visão
geral de várias abordagens de automação de programação, organizado sob a
ótica de três questões fundamentais: O que o usuário vê? Como o sistema
funciona? O que o sistema sabe?
d) Automating Software Design [Lowry, 91] - neste trabalho o autor organiza e
resume técnicas de automação de software que vão desde a inteligência artificial
até a automatização da programação.
e) A Semi-Automatic Program Development System [Smith, 89] - é apresentado
um algoritmo KIDS (Kestrel Interactive Development System) para a criação de
programas a partir de uma especificação formal. Nos testes, em cerca da uma
hora, o algoritmo produziu 92 possíveis soluções para o problemas das 8 rainhas.
Na seqüência são apresentadas a principais vantagens e desvantagens dos
trabalhos analisados na área de automação de software.
Principais vantagens:
Incrementam a produtividade dos desenvolvedores.
Com base nos modelos formais, produzem soluções teoricamente já testadas.
44
Principais desvantagens:
Pouco ou nenhum uso de padrões de projeto nas soluções geradas.
Soluções obscuras de difícil compreensão.
Produzem código-fonte o que limita o método a apenas uma linguagem de
programação.
Os trabalhos analisados, destacando-se A Semi-Automatic Program Development
System [Smith, 89], produzem quase sempre código executável obscuro para o
desenvolvedor. Este tipo de automação de software não é desejável nessa dissertação,
pois traz consigo a desvantagem de dificultar ou impedir a compreensão da solução
produzida. Com a geração de diagramas de comunicação ao invés de código-fonte
diretamente, elimina se essa desvantagem fornecendo uma clara compreensão da
solução produzida.
Também, nos trabalhos analisados, praticamente não há utilização de padrões de
projeto para automatizar a geração de software. Este fato faz com as decisões de projeto
das soluções geradas sejam baseadas em princípios pouco comprovados. Situação que
não ocorre no método proposto neste trabalho.
Ainda, a utilização de diagramas possibilita que a etapa posterior, a de geração
de código-fonte, utilize os diagramas de comunicação produzidos como entrada para
gerar código-fonte em mais de uma linguagem de programação.
45
3. O Método de Geração de Diagramas Comunicação
Este método utiliza os conceitos do processo de desenvolvimento de software
proposto por Larman [Larman, 07] e Wazlawick [Wazlawick, 04] . Neste processo
iterativo e incremental o ciclo de vida é baseado em refinamentos e incrementos do
sistema por meio de múltiplas iterações, com realimentação e adaptação cíclica como
propulsores para convergir para um sistema adequado. Neste processo, após a fase de
análise, na qual é realizado o trabalho de investigação e levantamento de requisitos,
têm-se a fase de projeto, que enfatiza a busca por uma solução que satisfaça os
requisitos apurados.
Dentro da fase de projeto, existe uma etapa do processo denominada de Projeto da
Camada de Domínio. Nesta etapa é definida a camada de domínio do sistema, de onde
as demais camadas (interface, persistência, segurança etc) irão derivar. Esta camada
corresponde ao conjunto de classes que irão realizar a gica do sistema, realizando os
casos de uso descritos na análise.
De acordo com [Larman, 07] [Wazlawick, 04], nesta etapa o trabalho do projetista
consiste em duas atividades principais: (1) construir um diagrama de comunicação para
cada operação de sistema e (2) construir o diagrama de classes de projeto. Para realizar
este trabalho, o projetista precisa levar em consideração dois artefatos: o modelo
conceitual e os contratos das operações de sistema.
Para que o projeto esteja completo, deverá existir um diagrama de comunicação para
cada contrato de operação de sistema definido na fase de análise do sistema e, um
diagrama de classes que contemple detalhes que não eram possíveis de obter na fase de
análise, como, por exemplo, a direção das associações. Entretanto, a elaboração
detalhada do diagrama de classes somente pode ser concluída de forma efetiva após a
criação dos diagramas de comunicação, pois é nesta etapa que são tomadas as decisões
de projeto e nela é feita a aplicação dos padrões de projeto.
Os diagramas de comunicação, quando são criados corretamente, mostram as
decisões de atribuição de responsabilidades a objetos. Estas decisões são tomadas para
refletir as mensagens enviadas para diferentes classes de objetos e são baseadas em
princípios fundamentais do projeto de sistema expressos nos padrões de projeto. Desta
forma, seguindo estes padrões, as decisões de projeto, e conseqüentemente os diagramas
46
gerados, podem ser justificados a partir dos próprios princípios adotados nos padrões de
projeto.
3.1. Regras para Criação de Diagramas de Comunicação
O método de busca que permite encontrar diagramas de comunicação a partir
dos contratos considera que cada uma das pós-condições especificadas no contrato deve
ser executada por exatamente uma operação básica.
Conforme a adaptação sugerida para a OCL, toda pós-condição define uma das
cinco possíveis mudanças no estado dos objetos de um sistema: (1) criação de objetos,
(2) destruição de objetos, (3) criação de associações, (4) destruição de associações e (5)
modificação do valor de atributos. Considera-se que toda pós-condição tem um objeto-
alvo que é um objeto capaz de executar a operação básica que realiza a pós-condição.
Em conformidade como o padrão de projeto Especialista, o responsável por
conhecer ou modificar uma informação deve ser a classe que tem a informação
necessária para satisfazer esta responsabilidade. Assim, se um determinado objeto
detém o controle da execução em um diagrama de comunicação, deve-se verificar se ele
é o objeto-alvo podendo realizar a operação básica que satisfaz a pós-condição.
O padrão Especialista pode ser aplicado na criação e destruição de associações,
onde qualquer um dos objetos ligados pela associação pode executar a operação básica
e, na modificação do valor de um atributo, onde o objeto-alvo é objeto que contém o
atributo em questão.
Caso a pós-condição seja a criação de uma instância, além do padrão
Especialista, pode-se empregar também o padrão Criador, que define qual objeto deverá
executar o comando de criação de nova instância.
Para pós-condições de destruição de objeto, a operação básica de destruição é
executada pelo próprio objeto que vai ser destruído. De acordo com Wazlawick
[Wazlawick, 04], em algumas linguagens de programação que possuem coletores de
lixo, como Java e Smalltalk, a destruição de todas as associações com um objeto
implica na destruição automática da instância. Destra forma, nessas linguagens não a
necessidade de uma mensagem explicita para destruição de instâncias.
Seguindo os princípios do padrão Acoplamento Fraco, se o objeto que detém o
controle da execução não pode realizar a operação básica que satisfaz a pós-condição,
47
ou seja, não é o “especialista na informação” ou não pode exercer a função de “criador”,
somente resta a ele delegar o controle para outro objeto para o qual ele tenha
visibilidade. Ainda, na hipótese de que o objeto-controle não tenha visibilidade para
nenhum outro objeto, ele pode primeiro adquirir visibilidade para um outro objeto e
então delegar o controle a esse objeto ou, pode adquirir visibilidade e usá-lo como
parâmetro em uma operação básica ou delegada.
Os parágrafos anteriores descrevem os princípios para a troca de mensagens
entre os objetos de um modelo e consequentemente para a criação de diagramas de
comunicação. Esses princípios podem ser expressões na forma de regras da seguinte
forma:
a) SE
o objeto com o controle da execução tem visibilidade para o objeto-alvo,
ENTÃO
o objeto com o controle da execução envia mensagem básica para o
objeto-alvo que realiza a pós-condição.
b) SE
o objeto com o controle da execução tem visibilidade para um outro objeto,
ENTÃO
o objeto com o controle da execução delega o controle a este outro objeto.
c) SE o objeto com o controle da execução tem visibilidade para uma coleção de
objetos e pode recuperar um objeto individual da coleção, ENTÃO
o objeto com o
controle da execução recupera o objeto da coleção colocando-o na lista de objetos
visíveis.
d) SE
o objeto com o controle da execução tem visibilidade para um outro objeto,
ENTÃO
inclui o objeto na lista de parâmetros que podem ser usados pelas
operações básicas ou delegadas.
Essas quatro regras possibilitam a criação de um algoritmo de busca que funciona da
seguinte maneira:
a) O algoritmo recebe uma lista de pós-condições que precisam ser realizadas.
b) Ele faz a busca no espaço de estados que consiste em diagramas de comunicação
buscando por algum estado que atenda às restrições impostas pelo modelo
48
conceitual, pelas pré-condições e pela dinâmica do próprio diagrama de
comunicação.
c) O algoritmo aplica as quatro regras acima para expandir estados sucessores até
encontrar um estado no qual todas as pós-condições tenham sido realizadas.
Apesar da simplicidade, este algoritmo permite encontrar diagramas de
comunicação para uma vasta gana de contrato de operações de sistema. Nas seções
seguintes são apresentados os detalhes do funcionamento deste algoritmo.
3.2. O Algoritmo de Busca
O algoritmo produz como saída um conjunto de diagramas de comunicação que
são possíveis soluções de implementação para o contrato apresentado. Aplica-se ao
algoritmo as técnicas de busca cega [Russel, 03], sendo que a forma mais eficiente, caso
se deseje encontrar uma solução de menor custo, é a busca de aprofundamento iterativo.
No exemplo abaixo, porém, para efeito de simplificação da apresentação usa-se busca
em profundidade.
O espaço de busca do algoritmo é definido por um conjunto de estados no qual cada
estado é representado por uma tupla <controle, objsVis, colsVis, args, pósconds, DC>
onde:
a) controle é o objeto com o controle de execução no DC;
b) objsVis é o conjunto de objetos para os quais controle tem associação para 1
pelo modelo conceitual ou de acordo com as pré-condições do contrato ainda
não descartadas;
c) colsVis é o conjunto de coleções para as quais o controle tem associações pelo
modelo conceitual ainda não descartadas;
d) args é o conjunto de argumentos da operação sendo executada por controle;
e) pósconds é a lista de pós-condições do contrato da operação de sistema ainda
não descartadas;
f) DC é um Diagrama de Comunicação.
No estado inicial da busca, o objeto no controle é definido como uma instância do
controlador do sistema, sendo as demais variáveis definidas em função desta instância.
49
DC é inicializado com a instância do controlador recebendo a mensagem
correspondente à operação de sistema.
Seja <controle, objsVis, colsVis, args, pósconds, DC> o estado atual, então a
lista de estados sucessores é definida da seguinte forma:
Função estados-sucessores(e) = regra1 (e) regra2(e) regra3(e) regra4(e)
Sendo a função regra1 definida da seguinte forma:
regra1 (<controle, objsVis, colsVis, args, pósconds, DC>) = e’ |
Se first(posconds) for “criação de instância” da classe X e classe(controle) tem
associação com X, então e’ = { <controle, objsVis
{ X.criar() }, colsVis, args),
tail(pósConds), DC + mensagem de controle para X.criar() “criar()”> }
Se first(posconds) for “criação de associação” de x com y e xobjsVis e
yobjsVis então e’ = { <controle, objsVis, colsVis, args{y}, tail(pósConds), DC
+ mensagem de controle para x “setY(y)” ou “addY(y)”, dependendo se a
associação é para 1 ou *, respectivamente> }
Se first(posconds) for a “modificação de atributo” x.at para o valor arg e
xobjsVis e argargs então e’ = { <controle, objsVis, colsVis, args{arg},
tail(pósConds), DC + mensagem de controle para x “setAt(arg)” > }
Se first(posconds) for a “destruição de uma instância” x e xobjsVis então e’ =
{ <controle, objsVis-{x}, colsVis, args, tail(pósConds), DC + mensagem de
controle para x “destroi()” > }
Se first(posconds) for a “destruição de uma associação” para 0..1 entre x e y, e
xobjsVis então e’ = { <controle, objsVis, colsVis, args, tail(pósConds), DC +
mensagem de controle para x “removeY()” > }
50
Se first(posconds) for a “destruição de uma associação” para * entre x e y, e
xobjsVis e y objsVis então e = {<controle, objsVis, colsVis, args-{y},
tail(pósConds), DC + mensagem de controle para x “removeY(y)” >}
Senão e’ = {}
As demais regras são definidas assim:
regra2 (<controle, objsVis, colsVis, args, pósconds, DC>) = { e’ | para todo objeto em
objsVis e’ = < objeto, objsVis(objeto), colsVis(objeto), args, pósconds, DC + mensagem
de delegação de controle para objeto com args > }
regra3 (<controle, objsVis, colsVis, args, pósconds, DC>) = { e’ | para toda coleção em
colsVis e’= < controle, objsVis
{ objeto | objeto pode ser recuperado de coleção com
uma chave | chave
args }, colsVis, args chave, pósconds, DC + mensagem get de
controle para para coleção com chave >}
regra4 (<controle, objsVis, colsVis, args, pósconds, DC>) = { e’ | para todo objeto
objsVis e’= < controle, objsVis, colsVis, args
{objeto}, pósconds, DC> }
Formalmente, um algoritmo de busca em profundidade realiza uma busca não-
informada que progride através da expansão do primeiro filho da árvore de busca, e
se aprofunda cada vez mais, até que o alvo da busca seja encontrado ou até que ele se
depare com um que não possui filhos (nó folha). Então a busca retrocede
(backtracking) e começa no próximo nó.
Conforme é apresentado na Figura 9, o algoritmo inicia aplicando a função
geradora de estados sucessores ao estado inicial (E0) a fim de realizar a primeira pós-
condição do contrato. Cada um dos estados subseqüentes gerados (E2, E3) consiste na
aplicação de uma das regras da função estados-sucessores. O número de estados gerados
irá variar conforme o número de associações da classe do objeto-controle que aumentam
as possibilidades de aplicação das regras. Se a primeira pós-condição pode ser
realizada, o algoritmo descarta esta pós-condição e reinicia tentando satisfazer a
51
segunda pós-condição. Caso contrário ele continua buscando satisfazer a primeira. O
algoritmo reinicia o seu trabalho aplicando novamente a função estados-sucessores
sobre o estado mais à esquerda da árvore de busca (E3).
O processo é repetido até que o algoritmo encontre um estado em que todas as
pós-condições foram satisfeitas ou em que não é mais possível expandir estados
sucessores. Quando esta situação ocorre, se o estado é um estado final (E5), onde todas
as pós-condições são satisfeitas, o algoritmo armazena este estado sendo uma possível
solução de implementação do contrato em questão. Caso o estado não seja final, e não é
possível gerar novos estados a partir dele (E6), o algoritmo retorna ao nível anterior e
inicia o processo de expansão dos estados sucessores novamente.
Ao final do processamento o algoritmo apresenta um conjunto de estados que
são as possíveis soluções para a implementação do contrato em questão.
O exemplo que será apresentado na seção Resultados mostra o funcionamento
do algoritmo ao expandir os estados de um ramo da árvore de busca até atingir um o
estado final. Na figura abaixo, este ramo é representado pelos estados (quadrados) em
tom de cinza escuro. As setas azuis indicam o caminho percorrido pelo algoritmo.
FIGURA 9 - Representação visual do algoritmo usando busca em profundidade.
52
Com as definições citadas anteriormente pode-se afirmar que este algoritmo de
busca constrói diagramas de comunicação que seguem os padrões GRASP [Gamma, 94]
[Russel, 03] pelos seguintes motivos:
a) O estado inicial segue o padrão controlador-fachada, pois inicia sempre o
diagrama com o controle da execução na classe que representa o sistema.
b) As diferentes formas da regra 1 garantem o padrão especialista, pois apenas o
objeto que contém o atributo ou que faz parte da associação ou que é o alvo da
destruição executará a ação básica.
c) A regra 1 também garante o padrão criador, pois apenas um objeto cuja classe se
associa com o objeto a ser criado executará o comando de criação de nova
instância.
d) Se os estados sucessores forem ordenados de acordo com as 4 regras,
preferência por executar a pós-condição (regra 1), se possível, e depois tentar
delegar para objetos para os quais se tem visibilidade (regra 2), e no final
tentar produzir visibilidade localmente declarada (regra 3) ou por parâmetro
(regra 4), minimizam o acoplamento entre objetos (padrão acoplamento fraco).
Deve-se observar, porém, que por ser um mecanismo de busca, o algoritmo será
capaz de gerar todos os possíveis diagramas de comunicação quando houver mais de
uma possibilidade de realizar o contrato.
53
4. Resultados
O algoritmo de busca foi implementado em Java e atua sobre contratos escritos
em OCL adaptada e modelos conceituais em formato XMI, gerados pela ferramenta
CASE Enterprise Architect.
Foram realizados testes com contratos representativos de diferentes situações de
análise. Foram utilizados contratos reais de aplicações desenvolvidas comercialmente.
Foram utilizados contratos para situações padrão como inserir, alterar e remover
informação de um sistema, bem como outros tipos de operações mais complexas. Em
todas as situações testadas o algoritmo encontrou rapidamente pelo menos um diagrama
de comunicação que satisfazia os padrões GRASP e permitia a geração automática de
código.
Na próxima seção será apresentada em detalhes a aplicação do algoritmo. No
Anexo I são mostrados outros contratos e os diagramas gerados com a aplicação do
algoritmo.
4.1. Estudo de Caso
Para ilustrar na pratica as idéias apresentadas na seção anterior, é apresentado o
resultado da aplicação do método proposto na geração de diagramas de um sistema
simples de manutenção de contratos. O modelo conceitual deste sistema é definido na
Figura 10. Em detalhes é apresentada uma operação típica de sistema de informação em
que é inserida uma cláusula em um contrato cujo número é dado. O resultado da
aplicação do método em mais algumas operações de sistema é apresentado na tabela da
Figura 18 ao final desta seção.
54
FIGURA 10 - Modelo conceitual utilizado no exemplo.
A operação de sistema definida no contrato da Figura 11 foi escolhida para ser
apresentada em detalhes porque é uma operação significativa como exemplo, pois seu
contrato apresenta criação de instância, criação de associação e modificação de atributo,
ou seja, trabalha com três das cinco pós-condições possíveis. Nesta operação o
controlador do sistema cria uma nova instância da classe Clausula, associa-a com uma
instância de Contrato, cujo número é informado pelo parâmetro “numero_contrato” e,
por fim, altera o atributo “texto” da nova instância de Clausula para o valor do
parâmetro “texto_clausula”.
4.1.1 Exemplo Detalhado
Para gerar o diagrama de comunicação o mecanismo de busca expandiu os
estados que são mostrados através das figuras subseqüentes. O objeto no controle da
execução é denotado através da cor cinza. O conteúdo das demais variáveis utilizadas
no mecanismo de busca é apresentado textualmente na própria figura.
FIGURA 11 - Contrato da operação de sistema InsereClausula.
InsereClausula (numero_contrato: int; texto_clausula: String)
Pré:
contratoAtual= self.contratosselect(contrato|contrato.numero==numero_contrato)
contratoAtualsize() == 1
Pós:
novaClausula = Clausula.new();
contratoAtual.associa_clausula(novaClausula)
novaClausula.texto = texto_clausula;
55
ObjsVis ColsVis Args Posconds
{ } {this.Contratos,
this.Clientes}
{texto_clausula,
numero_contrato)
{novaClausula = Clausula.new(),
self.contratoAtual.associa_clausula(novaClausula),
novaClausula.texto = texto_clausula}
FIGURA 12 - Estado inicial.
Na Figura 12 o objeto no controle (Sistema) não tem visibilidade individual para
nenhum outro objeto, mas apenas para uma coleção de contratos e clientes. Nas pós-
condições, observa-se que contratoAtual foi definido como alias na pré-condição, e
representa a instância de Contrato cujo número é numero_contrato.
ObjsVis ColsVis Args Posconds
{contratoAtual }
{this.contratos,
this.clientes}
{texto_clausula} {novaClausula = Clausula.new(),
contratoAtual.adiciona_clausula(novaClausula),
novaClausula.texto = texto_clausula}
FIGURA 13 - Estado após a regra 3 para adquirir visibilidade para contratoAtual.
Na Figura 13, como não era possível aplicar a regra 1, pois a classe do objeto no
controle (Sistema) não tinha visibilidade para a classe alvo (Clausula), nem a regra 2,
pois não havia objeto visível para delegar, aplicou-se a regra 3. Neste caso, o sistema
executou uma operação “get” básica sobre sua associação com Contrato (getContrato) e
obteve visibilidade local para “contratoAtual”. Para que o sistema de busca saiba que o
parâmetro numero_contrato refere-se a um atributo da classe Contrato, usa-se uma
convenção de nomenclatura onde sempre que um parâmetro passado por uma operação
de sistema corresponde a algum atributo x de uma classe y do modelo conceitual,
56
escreve-se o nome do parâmetro como x_y. Sem esta convenção ainda seria possível
executar o método, mas seria menos eficiente, pois teria que testar todas as combinações
de parâmetros, atributos e classes.
ObjsVis ColsVis Args Posconds
{contratoAtual.
cliente}
{contratoAtual.clau
sulas}
{texto_claus
ula}
{novaClausula = Clausula.new(),
contratoAtual.adiciona_clausula(novaClausula)
novaClausula.texto = texto_clausula}
FIGURA 14 - Estado após a regra 2 para delegar a criação de Clausula.
No estado representado na Figura 14 novamente não era possível aplicar a regra
1, mas como havia um objeto visível para delegar a operação, a regra 2 pôde ser
aplicada. Foi repassado apenas o argumento texto_clausula, pois o argumento
numero_contrato já foi descartado na operação getContrato no estado anterior.
ObjsVis ColsVis Args Posconds
{contratoAtual
.cliente,
novaClausula
}
{contratoAtual.clau
sulas }
{texto_claus
ula}
{contratoAtual.adiciona_clausula(novaClausula),
novaClausula.texto = texto_clausula}
FIGURA 15 - Estado após a regra 1 para criar uma instância de Clausula.
Na Figura 15 foi possível aplicar a regra 1, que a classe Contrato tem
visibilidade para uma classe da instância a ser criada na primeira pós-condição. Assim,
57
a primeira pós-condição pode ser descartada e a operação básica de criação de instância
de Clausula inserida no diagrama.
Na Figura 16 foi possível aplicar a regra 1 novamente, mas desta vez para
descartar a segunda pós-condição: criação de associação entre o contrato atual e a nova
cláusula.
ObjsVis ColsVis Args Posconds
{contratoAtual.cliente,
novaClausula }
{contratoAtual.clausulas } {texto_clausula} {novaClausula.texto
= texto_clausula}
FIGURA 16 - Estado após a regra 1 para associar novaClausula a contratoAtual.
ObjsVis ColsVis Args Posconds
{contratoAtual.cliente,
novaClausula }
{contratoAtual.clausulas } { } { }
FIGURA 17 - Estado após a regra 1 para modificar o atributo Texto de Clausula.
Na Figura 17 o diagrama final é obtido após a execução da regra 1 para alterar o
atributo texto da novaClausula, o que descarta a última pós-condição.
58
4.1.2 Demais Exemplos
Na tabela a seguir é apresentado um resumo das demais operações de sistema
definidas para o sistema de manutenção de contratos. Nela é possível visualizar as pré-
condições e as pós-condições das operações e também a seqüência de regras aplicadas
pelo algoritmo de busca para atingir um estado final.
Operação Pré-condições Pós-condições Seqüência de regras aplicadas
insereClausula
(num_contrato : int;
txClausula: String)
- Existe um contrato com
número igual ao
num_contrato.
- Criada uma instancia de
clausula.
- Clausula foi associada com o
ContratoAtual.
- O atribulo texto de Clausula
recebe txClausula.
Regra 3 - recuperou o contrato.
Regra 2 – delegou para contrato.
Regra 1 – criou clausula.
Regra 1 – associou clausula.
Regra 1 – modificou texto
removeClausula(num_co
ntrato :int,
num_clausula:int)
- Existem um contrato com
número igual ao parâmetro
num_contrato.
- Existe uma clausula com
número igual ao parâmetro
num_clausula.
- A instancia de clausula cujo
número é igual ao parâmetro
num_clausula foi destruída..
Regra 3 – recuperou o contrato.
Regra 2 – delegou para contrato.
Regra 3 – recuperou clausula.
Regra 1 – destruiu clausula.
removeContrato
(num_contrato :int)
- Existe um Contrato cujo
número é igual ao
num_contrato.
- A instância de Contrato é
destruída.
Regra 3 – recuperou o contrato.
Regra 1 – destruiu contrato.
insereCliente (cpf_cli: int,
nome_cli: String, rua_cli:
String, num_cli:String,
cid_cli:String)
- Não existe um cliente com
CPF igual a cpf_cli.
- Criada uma nova instância de
Cliente.
- Criada uma nova instancia de
endereço.
Regra 1 – criou cliente.
Regra 1 – modificou cpf.
Regra 1 – modificou nome.
Regra 2 – delegou para cliente.
Regra 1 – criou endereço.
Regra 1 – modificou rua.
Regra 1 – modificou numero.
Regra 1 – modificou cidade.
removeCliente (cpf_cli:
int)
- Existe um cliente cujo
CPF é igual ao parâmetro
cpf_cli.
- A instância de Cliente foi
destruída.
Regra 3 – recuperou cliente.
Regra 1 – destruiu cliente.
atualizaEndereco(cpf_cli:
int, nova_rua: String,
novo_num: String,
nova_cidade: String)
- Existe um cliente cujo
CPF é igual ao parâmetro
cpf_cli.
- O cliente possui um
endereço associado.
- O atributo rua de endereço
recebeu o parâmetro nova_rua.
- O atributo numero recebeu o
parâmetro novo_num.
- O atributo cidade recebeu o
parâmetro nova_cidade.
Regra 3 – recuperou cliente.
Regra 2 – delegou para cliente.
Regra 1 – modificou rua.
Regra 1 – modificou numero.
Regra 1 – modificou cidade.
FIGURA 18 – Resumo das regras aplicadas na criação dos diagramas de comunicação.
Embora o mecanismo ainda apresente algumas limitações, que são discutidas
mais adiante, a aplicação do método a este conjunto de operações/contratos mostra que
ele é capaz de produzir diagramas para situações reais encontradas no desenvolvimento
de sistemas de informação.
59
4.2. Vantagens do Método Proposto
Diferente das abordagens de automação de projetos de software, que geram
código fonte diretamente, o método apresentado neste trabalho incorpora idéias de
trabalhos anteriores para a geração de modelos (diagramas de comunicação), que
representam graficamente a colaboração entre os objetos para a realização das
operações de sistema. Como resultado, esta abordagem conduz a vantagens pelo uso de
diagramas ao invés de código-fonte, pois permite ao projetista avaliar a qualidade de
cada operação de sistema gerada automaticamente.
Além disso, um método que utiliza modelos permite rastrear explicitamente e
automaticamente os elementos do modelo conceitual e os elementos que realizam uma
operação. Embora outras abordagens também permitam alguma rastreabilidade, o
método apresentado permite uma rastreabilidade bi-direcional, em um vel mais fino
de granularidade, incluindo as pré e pós-condições que podem ser utilizadas na
validação dos diagramas do projeto.
Finalmente, a geração de diagramas permite identificar mais facilmente se os
design patterns que foram aplicados. Tal característica é interessante tanto para os
projetistas experientes, que podem ajustar ou alterar os diagramas gerados, como para
os projetistas iniciantes, que podem aprender novas habilidades visualizando os
diagramas gerados.
4.3. Limitações e Sugestões para Trabalhos Futuros
As limitações do sistema atualmente implementado são as seguintes:
a) Não considera associações de agregação, qualificadas ou ordenadas.
b) Não considera pós-condições condicionais.
c) Não gera nomes significativos para as operações delegadas.
As duas primeiras limitações podem ser incorporadas ao algoritmo sem maiores
dificuldades. As associações de agregação, por exemplo, deveriam ser colocadas em um
conjunto distinto de colsVis, e deveriam ser utilizadas antes de colsVis para atender ao
padrão de projeto criador, que exige que um objeto deve ser criado preferencialmente
60
por outro que o contenha em uma agregação e somente se não existir essa possibilidade
por um objeto apenas associado. No caso de associações qualificadas, mudaria apenas a
forma de recuperar o objeto da coleção (busca direta ao invés de busca iterativa), mas
isso não traria diferença no diagrama de comunicação, pois a recuperação do objeto é
feita por um método get_associação que não varia se a associação é ou não qualificada.
No caso de associações ordenadas deveria ser colocada no algoritmo a possibilidade
de recuperar um objeto da coleção pela sua posição e não apenas por uma chave, como
nesta versão.
As pós-condições condicionais do tipo “this.clientessize() == 0 IMPLIES
this.add_cliente(cliente_novo)” devem gerar uma mensagem delegada que é
condicionada pela expressão à esquerda do IMPLIES. Após a inserção da mensagem
delegada no diagrama a pós-condição (lado direito do IMPLIES) deve ser tratada como
seqüente da mensagem delegada.
Para as pós-condições que operam sobre coleções, usando por exemplos os
operadores forAll e iterate, os diagramas de comunicação gerados pelo algoritmo
produzem mensagens diretamente para as coleções, não incluindo possíveis mensagens
de controle de loops ou iterações necessárias à geração de código.
Isto é feito por dois motivos. Primeiro, porque na OCL não existe o conceito de
loops ou estruturas de repetição. A OCL é uma linguagem declarativa, sendo que, nestes
casos as suas declarações trabalham sobre coleções (conjuntos). Segundo, porque
estruturas de repetição são características típicas de linguagens de programação
imperativas, sendo que a forma de controlar os loops e as iterações varia de linguagem
para linguagem. Desta forma, o controle “fino” dessas estruturas é deixado para uma
futura etapa de geração de código-fonte.
Já a geração automática de nomes significativos para as mensagens delegadas é uma
questão de pesquisa em aberto. Uma sugestão é procurar nomear as mensagens como
nomes que expressem a intenção da delegação, indicando, por exemplo, que a
mensagem delegada tem a intenção de passa a responsabilidade de criação de uma
instância da classe X.
Outro caminho para continuação deste trabalho seria a geração de código-fonte a
partir dos diagramas produzidos.
61
Ampliando-se ainda mais a pesquisa poder-se-ia buscar um mecanismo para
automatizar a criação da interface com o usuário, talvez utilizando o fluxo de “eventos”
e “respostas de sistema” descrito nos casos de uso. Com essa automação e com o uso de
uma camada de persistência, o Hibernate [Hibernate, 07] por exemplo, poderia ser
elaborado um método de automação que gerasse aplicações completas, produzindo a
camada de interface com o usuário e a camada de domínio conectada à camada de
persistência. Esse método poderia ser a base para a criação uma ferramenta CASE que
utilizaria poucos artefatos para produzir um sistema o modelo conceitual, os contratos
das operações de sistema e os casos de uso.
62
5. Conclusões
O algoritmo apresentado neste trabalho produz de forma automática diagramas
de comunicação que satisfazem o modelo conceitual e os contratos de operação de
sistema obedecendo aos padrões GRASP.
Esta abordagem de transformação do modelo conceitual e funcional (contrato)
em modelo dinâmico (diagrama de comunicação) pode ser utilizada em ferramentas
CASE para acelerar o projeto do software, visto que, esta transformação é aplicada logo
após o final da fase de análise e produz a base para a camada de domínio na fase de
projeto.
Embora o algoritmo seja de fácil implementação, existe certa dificuldade de
utilização prática porque não existem linguagens para escrita de contratos que
expressem diretamente as pós-condições. Para reduzir esta dificuldade, é necessária a
utilização de uma adaptação à linguagem de contratos, como a sugerida neste trabalho.
Com os testes realizados e com o estudo de caso apresentado foi possível
comprovar que o mecanismo pode gerar diagramas para diversas situações encontradas
no desenvolvimento de sistemas de informação. Em comparação com diagramas
produzidos por projetistas humanos, pode-se afirmar que este método automático traz
um incremento de qualidade ao projeto por garantir, pelo menos, a aplicação dos
padrões de projeto GRASP. Além disso, a abordagem utilizada conduz a vantagens pelo
uso de diagramas ao invés de código-fonte, não eliminando etapas do processo de
desenvolvimento e permitindo ao projetista avaliar a qualidade da solução gerada
automaticamente, sendo uma característica interessante tanto para os projetistas
experientes, que podem ajustar ou alterar os diagramas gerados, como para os
projetistas iniciantes, que podem aprender novas habilidades visualizando os diagramas
produzidos automaticamente.
Uma última contribuição deste trabalho foi a própria sistematização do processo
de construção de diagramas de comunicação. Já que as operações básicas têm seu
código gerado de forma predeterminada (getters, setters, constructors e destructors) e
as operações delegadas são implementadas como sendo a seqüência direta das
63
mensagens incluídas, então os diagramas gerados com esta técnica podem ser usados
para gerar código executável para a camada de domínio automaticamente.
64
Referências
[Larman, 07] LARMAN, C. Utilizando UML e Padrões. Porto Alegre: Bookman,
2007.
[Wazlawick, 04] WAZLAWICK, R. S. Análise e Projeto de Sistemas de Informação
Orientados a Objetos. Rio de Janeiro: Elsevier, 2004.
[Porres, 01] PORRES, I. Modeling and Analyzing Software Behavior in UML. PhD
Thesis. TUCS. Turku Centre for Computer Science, Turku, Finland:
2001.
[Rational, 03] The Rational Unified Process Product. Documentação on-line baseada
em hipertexto comercializada pela Rational Corp. Armonk, NY: IBM,
2003.
[OMG, 06] OMG - Unified Modeling Language Specification. Disponível em:
<http://www.omg.org>. Acesso em 01/01/2006.
[Booch, 00] BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: Guia do usuário.
Rio de Janeiro: Campus, 2000.
[Gamma, 94] GAMMA, E. et. al. Design Patterns: Elements of reusable object-oriented
software. Massachusetts: Addison-Wesley, 1994.
[Russel, 03] RUSSELL, S.; NORVIG, P. Inteligência Artificial. Englewood Cliffs, NJ:
Prentice-Hall, 2003.
[Grand, 99] GRAND, M. Patterns in Java, V. 2. New York, NY: John Wiley & Sons,
1999.
[Furlan, 98] FURLAN, J. D. Modelagem de Objetos através da UML-The Unifield
Modeling Language, São Paulo: Makron Books do Brasil, 1998.
65
[Fowler 03] FOWLER, M.; SCOTT, K. UML Distilled: A Brief Guide to the Standard
Object Modeling Language. New York, NY: Addison-Wesley, 2003.
[Opdyke, 92] OPDYKE, W. F. Refactoring Object-Oriented Frameworks. PhD Thesis,
University of Illinois, 1992.
[Roberts, 99] ROBERTS, D. B. Practical Analysis for Refactoring. Technical Report
UIUCDCS-R-99-2092, University of Illinois at Urbana-Champaign,
April 1999.
[Gogolla, 98] GOGOLLA, M.; RICHTERS, M. Equivalence Rules for UML Class
Diagrams. First International Workshop, Mulhouse, França, Junho de
1998, Lecture Notes in Computer Science (1618): 87-96. Springer, 1998.
[Blaha, 96] BLAHA, M.; PREMERLANI, W. A Catalog of Object Model
Transformation. Working Conference on Reverse Engineering,
November 1996.
[Schönberger, 99] SCHÖNBERGER, S.; KELLER, R. K.; KHRISS, I. Algorithmic
Support for Model Transformation in Object Oriented Software
Development. Theory And Practice of Object Systems, 1999.
[Lano, 98] LANO, K; BICARREGUI, J. Formalising the UML in Structured Temporal
Theories. Proceedings Second ECOOP Workshop on Precise Behavioral
Semantics (with an Emphasis on OO Business Specifications), pages
105-121. Technische Universität München, TUM-I9813, 1998
[Engels, 99] G. ENGELS, R. HUCKING, ST. SAUER, A. WAGNER. UML
collaboration diagrams and their transformation to Java. In France and
Rumpe. 1999.
[Actions, 05] Action semantics for the UML - request for proposals. Disponível em:
<http://www.omg.org/pub/docs/ad/98-11-01.pdf.>. Acesso em
01/03/2005.
66
[Scott, 04] SCOTT, K.; FOWLER, M;. UML Distilled - Applying the Standard Object
Modeling Language. Addison-Wesley 2004.
[Heckel, 00] HECKEL, R.; SAUER, S. Strengthening the Semantics of UML
Collaboration Diagrams. University of Paderborn, 2000.
[Meyer, 88] MEYER, Bertrand. Design by Contracts. Prentice-Hall:1988.
[Enseling, 06] ENSELING, Oliver. iContract: Design by Contract in Java. Disponível
em:<http://www.javaworld.com/javaworld/jw-02-2001/jw-0216-
cooltools.html.> Acesso em 11/07/2006.
[Sjögren, 02] SJÖGREN, Andreas. A Method for Support for Design By Contract on the
.NET platform. Mälardalen University, Västerås, Sweden: 2002.
[Warner, 98] WARNER, J. B.; KLEPPE, A. G. The Object Constraint Language:
Precise Modeling with UML. Addison-Wesley:1998.
[OCL, 06] OCL - Object Constraint Language Specification, version 2.0. Disponível
em: <http://www.omg.org/cgi-bin/apps/doc?formal/06-05-01.pdf>.
Acesso em 01/07/2006.
[Meyer, 92] MEYER, Bertrand. Eiffel: The Language. Prentice Hall, 1992.
[Kiniry, 98] KINIRY, J. R.; CHEONG. E. JPP: A Java pre-processor. Technical Report
CS-TR-98-15, Department of Computer Science, California Institute of
Technology, 1998.
[Karaorman, 99] KARAORMAN, M.; U. HÖLZLE; J. BRUNO. jContractor: A
reflective Java library to support design by contract. Proceedings of
Meta-Level Architectures and Reflection:1999.
[Man, 06] Man Machine Systems. Design by contract for Java using JMSAssert.
Disponível em: <http://www.mmsindia.com/DBCForJava.html>. Acesso
maio 2006.
67
[Duncan, 98] DUNCAN, A.; U. HÖLZLE. Adding contracts to Java with handshake.
Technical Report TRCS98-32, The University of California at Santa
Barbara: 1998.
[UML1,02] UML 2.0 Infrastruture Specification. Disponível em
http://www.omg.org/cgi-bin/doc?ptc/2003-08-02.
[UML2,02] UML 2.0 Superstruture Specification. Disponível em
http://www.omg.org/cgi-bin/doc?ptc/2003-08-02.
[UML3, 02] UML 2.0 Diagrams Interchage. Disponível em http://www.omg.org/cgi-
bin/doc?ptc/2003-07-03
[Bezerra, 02] BEZERRA, Eduardo; Princípios de Análise e Projeto de Sistemas com
UML. Rio de Janeiro : Campus, 2002.
[Hamilton, 06] HAMILTON K; M. RUSSELL. Learning UML 2.0. O'Reilly. Abril,
2006.
[Engels, 99] ENGELS, R. HUCKING; ST. SAUER, A. WAGNER: UML collaboration
diagrams and their transformation to Java. Springer Berlin/Heidelberg:
1999.
[Ramalho, 03] RAMALHO, F.; ROBIN, J.; BARROS, R. S. M.: XOCL An XML
language for specifying logical constraints in object oriented models.
Journal of Universal Computer Science, 2003.
[Booch,94] BOOCH, Grady Object-Oriented Analysis and Design. Bejamin/Cumming,
1994.
[Zang 00] ZHANG, D.: Applying Machine Learning Algorithms in Software
Development, Proceedings of the 2000.
[Far, 93] FAR, B. H.: Reproducing Human Cognitive Processes in Automatic Software
Design. JCSE '93: Joint Conference on Software Engineering Fukuoka,
Japan November 1993.
68
[Far, 94] FAR, B. H.; TANAKA, T.; SUGIMOTO, T.; KOONO, Z. A Systematic
approach for implementation of human design knowledge in automatic
software desing. JCKBSE´94. 1994.
[Wang, 06] WAGH, R.; MENEZES, B.; BELLUR, U. Transformation of UML Design
Model into Performance Model: A Model-Driven Framework. European
Conference on Object-Oriented Programming, 20th edition, Nantes,
França, 2006.
[Barstow, 85] BARSTOW, D. Domain-Specific Automatic Programming, IEEE
Transactions on Software Engineering. Nov. 1985.
[Gómez, 89] GOMEZ, F.; WINGATE, V. Automatic Programming for End Users: The
TOAD System, IEEE Transactions on Knowledge and Data Engineering,
Setembro 1989.
[Nishida, 91] NISHIDA, F.; TAKAMATSU, S.; FUJITA, Y.; TANI, T. Semi-
Automatic Program Construction from Specifications Using Library
Modules, IEEE Transactions on Software Engineering, Setembro 1991.
[Chen, 97] CHEN, Y.; CHENG B. Formalizing and Automating Component Reuse, 9th
International Conference on Tools with Artificial Intelligence, 1997.
[Blaine, 91] BLAINE, L.; GOLDBERG A. DTRE—a semi-automatic transformation
system, Constructing Programs from Specifications: 165-204, North-
Holland, 1991.
[Dietz, 98] DIETZ, P.; WEIGERT, T.; WEIL, F. Formal techniques for automatically
generating marshalling code from high-level specifications. Workshop
on Industrial-Strength Formal Specification Techniques, Boca Raton,
EUA, 1998.
[Kyas, 04] KYAS, M.; FECHER, H.; BOER, F. S. de; JACOB, J.; HOOMAN, J.; VAN
DER ZWAA, M.; ARONS, T.; KUGLER, H. Formalizing UML Models
and OCL Constraints in PVS. Elsevier, 2004.
69
[Richters, 00] RICHTERS, M.; GOGOLLA, M. Validating UML Models and OCL
Constraints. Proceedings UML 2000, 2000.
[Richters, 02] RICHTERS, M; A Precise Approach to Validating UML Models and
OCL Constraints, Phd thesis. Universitaet Bremen. Logos Verlag,
Berlin, 2002.
[Gogolla, 01] GOGOLLA, M. Using OCL for Defining Precise,Domain-Specific UML
Stereotypes, Proceedings 6th Australian Workshop on Requirement
Engineering (AWRE'2001), 2001.
[Kollmann, 01] KOLLMANN, R.; GOGOLLA, M.: Capturing Dynamic Program
Behaviour with UML Collaboration Diagrams. Fifth European
Conference on Software Maintenance and Reengineering, 2001.
[Bottoni, 01] BOTTONI, P.; KOCH, M.; PARISI-PRESICCE, F.; TAENTZER, G. A
Visualization of OCL using Collaborations. Proceedings of UML 2001,
2001.
[Jézéquel, 02] JÉZÉQUEL J.; PLOUZEAU, N.; WEIS, T.; GEIHS, K. From Contracts
to Aspects in UML Designs. AOSD Workshop on AOP in UML.
Enschede, Niederlande, 2002.
[Mills, 02] MILLS, K. L.; GOMAA, H. Knowledge-Based Automation of a Design
Method for Concurrent Systems. IEEE Transactions on Software
Engineering 28, 2002.
[Elkoutbi, 06] ELKOUTBI., M.; KHRISS, I; KELLER, R. K. Automated Prototyping of
User Interfaces Based on UML Scenarios. ACM Automated Software
Engineering, Volume 13, Issue 1, January 2006.
[Rich, 93] RICH, C.; WATER, R. C. Approaches to Automatic Programming.
Advances in Computers, Volume 37, M. C. Yovits, ed., Academic Press,
1993
70
[Kaiser, 89] KAISER, G.; Rule-Based Modelling of the Software Development Process.
Proceedings of the 4th International Software Process Workshop:
Representing and Enacting the Software Process, Moretonhampstead,
Devon, United Kingdom, 1988, publicado em ACM Sigsoft Software
Engineering Notes, 1989.
[Lowry, 91] LOWRY, M; MCCARTNEY, R. Automating Software Design. AAAI
Press, 1991.
[Smith, 89] D. R. SMITH, D. R. A Semi-Automatic Program Development System,
Special Issue on Formal Methods, IEEE Transactions on Software
Engineering, Kestrel Institute, Palo Alto, Califórnia, 1989.
[Hibernate, 07] Hibernate, An object/relational persistence and query service for Java.
<http://www.hibernate.org.> Acesso em 11/04/2007.
71
Anexo I – Exemplos de diagramas de comunicação gerados
Neste anexo são apresentados alguns exemplos da aplicação do algoritmo de
geração de diagramas de comunicação. São apresentados o modelo conceitual do
sistema base, os contratos e os diagramas de comunicação resultados da aplicação o
algoritmo a cada um dos contratos. Também são apresentadas, todos os diagramas e as
regras utilizadas para gerá-lo.
Devido ao tamanho do modelo conceitual, o diagrama é apresentado em partes,
divido nas Figuras 19, 20, 21 e 22. Para uma melhor visualização, este diagrama e dos
demais diagramas deste anexo, pode-se acessar
http://www.dynamix.com.br/claumir/mestrado/ e recuperar arquivos com maior
definição.
FIGURA 19 – Modelo conceitual – 1ª parte.
72
FIGURA 20 – Modelo conceitual – 2ª parte.
FIGURA 21 – Modelo conceitual – 3ª parte.
73
FIGURA 22 – Modelo conceitual – 4ª parte.
A seguir são apresentados os pares: contrato-diagrama de comunicação. Cada
par trás o contrato escrito em OCL adaptada, o diagrama final produzido e as regras
usadas na sua geração.
A primeira operação apresentada é a operação para definirUsuario, utilizado no
login do sistema para definir a pessoa que é o usuário atual do sistema.
FIGURA 23 – Contrato da operação de login.
Context
definirUsuario (login, senha : String)
Pre:
usuario = self.usuarios -> select(usuario|usuario.login==login && usuario.senha==senha)
usuario->size()==1
Post:
self.associa_usuario(usuario)
74
Este contrato produziu o diagrama de comunicação da Figura 24.
Regras utilizadas na geração
Primeiramente o algoritmo aplicou a regra 3 sobre a coleção “usuários” para obter usuário cujo
login e senha são iguais aos parâmetros passados.
Depois aplicou a regra 1 para criar a associação entre a instância de Usuário recuperado e Sistema.
FIGURA 24 – Diagrama de Comunicação para operação de login.
A segunda operação é utilizada para recuperar uma pessoa do cadastro e defini-
la como pessoa atualmente manipulada pelo sistema. Esta operação é semelhante a
anterior, mas apresenta um número diferente de parâmetros.
FIGURA 25 – Contrato da operação de definirPessoaCorrente.
Context
definirPessoaCorrente (oid : int)
Pre:
pessoa_corr = self.pessoas -> select(pessoa|pessoa.oid ==oid)
pessoa_corr->size() == 1
Post:
self.associa_pessoa(pessoa_corr)
75
O processamento deste contrato resultou no diagrama de comunicação da Figura 26.
Regras utilizadas na geração
O algoritmo aplicou a regra 3 sobre a coleção “pessoas” para obter a pessoa cujo oid é igual ao
parâmetro oid_pessoa.
Após, aplicou a regra 1 para criar a associação entre a instância recuperada e Sistema.
FIGURA 26 – Diagrama de Comunicação para operação definirPessoaCorrente.
A terceira operação é a operação para de inserirCasamento. Esta operação
associa duas pessoas (marido e esposa) e atribuiu valores a alguns atributos do
casamento.
FIGURA 27 – Contrato da operação de inserirCasamento.
Context
inserirCasamento(marido_oid,esposa_oid: integer, dataCasamento:Date ; situacaoCasamento :
String)
Pre:
marido = self.pessoas -> select(pessoa|pessoa.oid == marido_oid)
marido ->size() == 1
esposa = self.pessoas -> select(pessoa|pessoa.oid == esposa_oid)
esposa ->size() == 1
Post:
casamento = Casamento.new()
casamento.data = dataCasamento
casamento.situacao = situacaoCasamento
self.marido.associa_casamento (casamento)
self.esposa.associa_casamento (casamento)
76
A Figura 28 é o diagrama de comunicação resultante.
Regras utilizadas na geração
Sistema não tem visibilidade para Casamento. Então ele não pôde aplicar a regra 1 para
criar casamento. Aplicou então a regra 3 para recuperar um objeto usando os seus
parâmetros. Recuperou então uma instancia de pessoa (marido) usando o marido_oid.
Aplicou a regra 2 para delegar para a instância de Pessoa.
A instancia de pessoa (marido) tem visibilidade para Casamento, então foi aplicada a regra
1 para a criação da instância de Casamento.
Foi usada novamente a regra 1 para associar marido ao casamento.
Na seqüência foi aplicado duas vezes a regra 1 para modificação dos atributos data e
situação do casamento.
Pela regra 3 recuperou-se uma instância de pessoa que é esposa no casamento (esposa_oid).
Com a regra 1 criou-se a associação entre esposa e casamento.
FIGURA 28 – Diagrama de Comunicação para operação inserirCasamento.
77
A quarta operação é a operação para alteração da situação do casamento da pessoa
corrente - alterarCasamento.
FIGURA 29 – Contrato da operação de alterarCasamento.
Este contrato produziu o diagrama de comunicação abaixo:
Regras utilizadas na geração
Primeiramente Sistema delega para Pessoa (pessoa corrente) usando a regra 2. Pessoa corrente
recupera o casamento utilizando o parâmetro oidCasamento através da regra 3. Por fim, pela
regra 1, altera o atributo situacao da instância de Casamento.
FIGURA 30 – Diagrama de Comunicação para operação alterarCasamento.
A quinta operação testada é a inserção de informações do cadastro de um estrangeiro
para a pessoa corrente.
Context alterarCasamento(oidCasamento: int; situacaoCasamento : String)
Pre:
self.pessoa -> size() == 1
casamento = self.pessoa.casamentos -> select(casamento|casamento.oid = oidCasamento)
casamento->size() == 1
Post:
casamento.situacao = situacaoCasamento
78
FIGURA 31 – Contrato da operação de inserirEstangeiro.
A saída do processamento deste contrato pelo algoritmo de geração de diagramas foi a
Figura 32.
Regras utilizadas na geração
Conforme a regra 3, o controle é delegado para a pessoa corrente. Pessoa corrente usa a regra 1
para criar uma instância de estrangeiro.
A regra 1 é aplicada novamente 3 vezes para satisfazer as pós-condições de modificação dos
atributos dataChagadaAoPais, nacionalidadeOrigem e dataNaturalizacao.
A regra 1 é mais uma vez utilizada para associar a instância de Estrangeiro com a pessoa corrente.
FIGURA 32 – Diagrama de Comunicação para operação inserirEstangeiro.
Context inserirEstangeiro(dataChegadaAoPais:Date; nacionalidadeOrigem: String;
dataNaturalizacao:Date)
Pre:
self.pessoa->size() == 1
self.pessoa.estrangeiro->size() == 0
Post:
estrangeiro = Estrangeiro.new()
estrangeiro.dataChagadaAoPais = dataChegadaAoPais
estrangeiro.nacionalidadeOrigem = nacionalidadeOrigem
estrangeiro.dataNaturalizacao = dataNaturalizacao
self.pessoa.associa_estrangeiro(estrangeiro)
79
A sexta operação é a atualização da data de naturalização do estrangeiro.
FIGURA 33 – Contrato da operação de alterarEstangeiro.
Este contrato produziu o diagrama de comunicação da Figura 34.
Regras utilizadas na geração
A pré-condição garante que a instância de “pessoa corrente” possui uma instância de Estrangeiro
associada. Então pela regra 2 o controle é delegado para “pessoa corrente” e a pós-condição é
satisfeita usando-se a regra 1.
FIGURA 34 – Diagrama de Comunicação para operação alterarEstangeiro.
Context alterarEstangeiro(estrang_oid: int, dataNaturalizacao:Date)
Pre:
self.pessoa.estrangeiro->size() == 1
Post:
estrangeiro.dataNaturalizacao = dataNaturalizacao
80
A sétima operação é a inserção de um vinculo profissional para a pessoa corrente.
FIGURA 35 – Contrato da operação de inserirVinculoProfissional.
O processamento do contrato da Figura 35 produziu o seguinte diagrama de
comunicação:
Regras utilizadas na geração
O controle é delegado para “pessoa_corrente” (regra 2). Pessoa corrente aplica a regra 1 e cria
uma instância de Vinculo profissional. Pessoa Corrente aplica novamente a regra 1 para adicionar
vinculo.
A regra 1 é aplicada 6 vezes sucessivas para alterar os atributos de vinculo e satisfazer as pós-
condições.
FIGURA 36 – Diagrama de Comunicação para operação inserirVinculoProfissional.
Context inserirVinculoProfissional(atividade, cargo, email, empresa, homePage, fone: String;
dataInicio:Date)
Pre:
self.pessoa->size() == 1
Post:
vinculo = VinculoProfisional.new()
self.pessoa.associa_vinculosProfissionais(vinculo)
vinculo.atividadeProfisional = atividade
vinculo.cargoFuncao = cargo
vinculo.dataInicio = dataInicio
vinculo.email = email
vinculo.empresa = empresa
vinculo.telefone = fone
81
A oitava operação é a remoção de vinculo profissional. Em algumas linguagens
de programação, como Java e Smalltalk, a destruição de instâncias não necessita de uma
mensagem explicita, pois a destruição de todas as associações com um objeto implica
na destruição automática da instância. Destra forma, muitas vezes não são criados
diagramas para este tipo de contrato, mas esta operação é apresentada aqui com a
finalidade de mostrar o funcionamento do algoritmo na busca de diagramas de
comunicação que incluam também mensagens de destruição de instâncias.
FIGURA 39 – Contrato da operação de removerVinculoProfissional.
A operação de destruição removerVinculoProfissional produziu o diagrama da Figura
40.
Regras utilizadas na geração
De acordo com a regra 2, a mensagem é delegada para “pessoa corrente”. Pessoa corrente usada a
regra 2 e o parêmtro oidVinculo para recuperar a instância de vinculo profissional desejada e por fim
aplica a regra 1 para destrói a instância de vinculo.
FIGURA 40 – Diagrama de Comunicação para operação removerVinculoProfissional.
Como é possível visualizar nos exemplos mostrados neste anexo, o algoritmo foi
aplicado em diversas situações padrão como inserir, alterar e remover informação de um
Context
removerVinculoProfissional (oidVinculo: int)
Pre:
self.pessoa->size() == vinculo->size == 1
Post:
vinculo.destroy();
82
sistema de informação típico. Em todas as situações testadas o algoritmo encontrou
rapidamente pelo menos um diagrama de comunicação que satisfazia os padrões
GRASP e permitia a geração automática de código a partir do diagrama de comunicação
produzido.
Livros Grátis
( http://www.livrosgratis.com.br )
Milhares de Livros para Download:
Baixar livros de Administração
Baixar livros de Agronomia
Baixar livros de Arquitetura
Baixar livros de Artes
Baixar livros de Astronomia
Baixar livros de Biologia Geral
Baixar livros de Ciência da Computação
Baixar livros de Ciência da Informação
Baixar livros de Ciência Política
Baixar livros de Ciências da Saúde
Baixar livros de Comunicação
Baixar livros do Conselho Nacional de Educação - CNE
Baixar livros de Defesa civil
Baixar livros de Direito
Baixar livros de Direitos humanos
Baixar livros de Economia
Baixar livros de Economia Doméstica
Baixar livros de Educação
Baixar livros de Educação - Trânsito
Baixar livros de Educação Física
Baixar livros de Engenharia Aeroespacial
Baixar livros de Farmácia
Baixar livros de Filosofia
Baixar livros de Física
Baixar livros de Geociências
Baixar livros de Geografia
Baixar livros de História
Baixar livros de Línguas
Baixar livros de Literatura
Baixar livros de Literatura de Cordel
Baixar livros de Literatura Infantil
Baixar livros de Matemática
Baixar livros de Medicina
Baixar livros de Medicina Veterinária
Baixar livros de Meio Ambiente
Baixar livros de Meteorologia
Baixar Monografias e TCC
Baixar livros Multidisciplinar
Baixar livros de Música
Baixar livros de Psicologia
Baixar livros de Química
Baixar livros de Saúde Coletiva
Baixar livros de Serviço Social
Baixar livros de Sociologia
Baixar livros de Teologia
Baixar livros de Trabalho
Baixar livros de Turismo