drawcode: um plugin do eclipse para a geraÇÃo...
TRANSCRIPT
UNIVERSIDADE REGIONAL DE BLUMENAU
CENTRO DE CIÊNCIAS EXATAS E NATURAIS
CURSO DE CIÊNCIAS DA COMPUTAÇÃO – BACHARELADO
DRAWCODE: UM PLUGIN DO ECLIPSE PARA A GERAÇÃO
DE CÓDIGO A PARTIR DE DIAGRAMAS DE CLASSE E
DIAGRAMAS N-S
ANDRÉ HENKELS
BLUMENAU 2007
2007/2-04
ANDRÉ HENKELS
DRAWCODE: UM PLUGIN DO ECLIPSE PARA A GERAÇÃO
DE CÓDIGO A PARTIR DE DIAGRAMAS DE CLASSE E
DIAGRAMAS N-S
Trabalho de Conclusão de Curso submetido à Universidade Regional de Blumenau para a obtenção dos créditos na disciplina Trabalho de Conclusão de Curso II do curso de Ciências da Computação — Bacharelado.
Prof. Maurício Capobianco Lopes, MEng - Orientador.
BLUMENAU 2007
2007/2-04
DRAWCODE: UM PLUGIN DO ECLIPSE PARA A GERAÇÃO
DE CÓDIGO A PARTIR DE DIAGRAMAS DE CLASSE E
DIAGRAMAS N-S
Por
ANDRÉ HENKELS
Trabalho aprovado para obtenção dos créditos na disciplina de Trabalho de Conclusão de Curso II, pela banca examinadora formada por:
______________________________________________________ Presidente: Prof. Mauricio Capobianco Lopes, MEng – Orientador, FURB
______________________________________________________ Membro: Prof. Everaldo Artur Grahl, MEng – FURB
______________________________________________________ Membro: Prof. José Roque Voltolini da Silva – FURB
Blumenau, 07 de dezembro de 2007
Dedico este trabalho a toda minha família, em especial a dona Maurina que infelizmente pode acompanhar apenas o começo desta caminhada. Dedico também aos meus amigos, especialmente aqueles que me ajudaram diretamente na realização deste.
AGRADECIMENTOS
A minha noiva Luciane, pelo apoio que recebi durante toda a graduação. A sua
compreensão, principalmente durante a realização deste onde não lhe dei toda a atenção que
desejava.
Ao meu pai Floriano, pelo seu apoio e incentivo, indispensáveis durante toda esta
caminhada.
Ao meu irmão e herói Tarcisio, pelo apoio e companheirismo, principalmente pelas
madrugadas sem dormir, abrindo mão da sua família para me ajudar.
Aos irmãos Juliano e Susane e demais familiares, muito obrigado pelo carinho e apoio.
A todos os meus amigos da graduação, em especial Gustavo e Fabio, pelo
companheirismo durante toda esta caminhada.
Ao meu orientador Mauricio, que embora tivesse ficado com receio sobre o tema no
início, acreditou na conclusão deste trabalho. Obrigado pelo apoio, conhecimento e
experiência, compartilhados durante o andamento deste.
Ao professor Roque, pela idéia sobre o tema do trabalho e ajuda durante o andamento
do mesmo.
A professora Joyce pelas dicas sobre o motor de template e o analisador léxico.
A todos os demais professores, muito obrigado por todo o conhecimento que adquiri
com vocês durante todos estes anos da graduação.
Aos meus amigos de trabalho da Benner que seguraram as pontas para mim quando eu
desapareci da empresa para garantir o termino deste trabalho.
A todos os demais que eu possa ter esquecido, meu muito obrigado.
O valor das coisas não está no tempo que duram, mas na intensidade com que acontecem. Por isso existem momentos inesquecíveis, coisas inexplicáveis e pessoas incomparáveis.
Fernando Pessoa
RESUMO
Este trabalho apresenta o Drawcode, um plugin para o ambiente de desenvolvimento Eclipse cujo objetivo é a edição de diagramas de classe, diagramas N-S e geração de código a partir da associação destes dois tipos de diagramas. Depois de criados os diagramas é possível associar um método de uma classe a um diagrama N-S e gerar código para a linguagem Java das classes definidas, incluindo os atributos e corpo dos métodos associados a um diagrama N-S. Em ambos os diagramas a representação visual é atualizada a cada alteração para ajustar o tamanho dos elementos visuais dinamicamente conforme a necessidade. Para a geração dos gráficos e interatividade do usuário foi utilizado o Graphical Editing Framework (GEF), um subprojeto da Eclipse Foundation para facilitar a criação de plugins para o ambiente com interfaces visuais mais amigáveis. Para a geração de código foi utilizado o motor de templates Velocity.
Palavras-chave: Geração de código. Algoritmos. Diagramas N-S. Orientação a objetos. Diagramas de classe. Eclipse.
ABSTRACT
This work presents the Drawcode, a plug-in for Eclipse development environment. It’s purpose is to allow editing of the class diagrams, N-S diagrams and code generation from the association of these two types of diagrams. After the creation of diagrams, it’s possible to associate a method from a class to one N-S diagram and generate code to the Java language of the defined classes, including attributes, methods and body method when associated with one N-S diagram. In both diagrams, the visual representation is updated for every change to adjust the size of the visual elements. For the generation of graphics and user control was used Graphical Editing Framework (GEF), a subproject of the Eclipse Foundation to facilitate the creation of plug-in for the environment with more friendly visual interfaces. For code generation was used engine templates Velocity.
Key-words: Code generation. Algorithms. N-S diagrams. Object orientation. Class diagrams. Eclipse
LISTA DE ILUSTRAÇÕES
Figura 1- Exemplo de diagrama de classes simples .................................................................21
Figura 2 – Exemplos de representação de algoritmos ..............................................................23
Figura 3 - Exemplo de um comando de atribuição...................................................................25
Figura 4 - Exemplo de um comando de decisão.......................................................................25
Figura 5 - Exemplo de uma estrutura de seleção......................................................................25
Figura 6 - Exemplo de um comando de repetição ....................................................................26
Figura 7 - Exemplo de um bloco de comandos ........................................................................26
Figura 8 - Exemplo de uma estrutura de paralelismo...............................................................26
Figura 9 – Componentes de um compilador.............................................................................28
Figura 10 – Representação do funcionamento de um motor de templates ...............................31
Figura 11 – Diagrama de seqüência da ativação do plugin ......................................................33
Figura 12 – Visão geral do GEF...............................................................................................35
Figura 13 – Tela do aplicativo NSD Editor..............................................................................36
Figura 14 – Tela do aplicativo Structorizer ..............................................................................37
Figura 15 – Tela principal do plugin Jupe................................................................................39
Figura 16 – Editor de diagrama de classe do plugin TOPCASED...........................................40
Figura 17 - Requisitos funcionais do plugin.............................................................................41
Figura 18 - Requisitos não funcionais do plugin ......................................................................42
Figura 19 - Diagrama de casos de uso do plugin......................................................................42
Figura 20 - Classe principal do Drawcode ...............................................................................45
Figura 21 - Diagrama de classe do editor de diagramas de classe ...........................................46
Figura 22 - Diagrama de classes do editor de diagramas N-S..................................................49
Figura 23 - Diagrama de classe da manutenção do modelo e representação gráfica ...............52
Figura 24 – Diagrama de classe da geração de código.............................................................55
Figura 25 – Diagrama de seqüência da inclusão de um elemento no diagrama N-S ...............60
Figura 26 – Seqüência de inicialização da classe NSDiagramEditor.......................................61
Figura 27 – Diagrama de atividades do processo de inserção de elementos no modelo..........63
Figura 28 – Exemplo de representação gráfica de uma instrução simples...............................64
Figura 29 – Exemplo de representação gráfica de uma instrução de decisão ..........................64
Figura 30 – Exemplo de representação gráfica de uma instrução “for”...................................64
Figura 31 – Exemplo de representação gráfica de uma instrução “while”...............................65
Figura 32 – Exemplo de representação gráfica de uma instrução “repeat-until” .....................65
Figura 33 – Exemplo de representação gráfica de uma instrução de seleção...........................65
Figura 34 – Exemplo de representação gráfica de um diagrama N-S e sua lista de comandos66
Figura 35 – Diagrama de seqüência do processo de atualização gráfica do modelo................67
Figura 36 – Diagrama de atividades do processo de cálculo dos elementos visuais................69
Figura 37 – Seqüência para a geração de código do diagrama N-S .........................................70
Figura 38 – Seqüência de geração de código para o diagrama de classe .................................71
Figura 39 – Exemplo de template VTL de decisão com anotações..........................................72
Figura 40 – Iniciando o ambiente Eclipse: definir pasta de trabalho .......................................77
Figura 41 – Informações sobre os plugins instalados no ambiente ..........................................77
Figura 42 – Tela principal do ambiente Eclipse .......................................................................78
Figura 43 – Edição do diagrama de classe: incluindo uma classe com atributos e métodos....79
Figura 44 – Edição do diagrama N-S: definindo o algoritmo ..................................................80
Figura 45 – Associar um algoritmo representado por diagrama N-S para o método da classe 81
LISTA DE QUADROS
Quadro 1 – Exemplo de utilização da VTL..............................................................................32
Quadro 2 – Estrutura do arquivo plugin.xml .....................................................................34
Quadro 3 – Detalhes do caso de uso: editar diagrama de classe ..............................................44
Quadro 4 – Detalhes do caso de uso: editar diagrama N-S ......................................................44
Quadro 5 – Código completo da classe IfCommand..............................................................57
Quadro 6 – Conteúdo da interface ICommandVisitable ..................................................58
Quadro 7 – Conteúdo da interface ICommandVisitor .......................................................58
Quadro 8 – Parte da classe NSDiagramHandler ................................................................62
Quadro 9 – Método responsável por retornar a posição do elemento ......................................68
Quadro 10 – Template escrito na VTL para elemento de decisão gerando código Java..........71
Quadro 11 - Esquema representando o resultado do processamento de um elemento de decisão
...............................................................................................................................72
Quadro 12 – Implementação do método processChilds ..................................................73
Quadro 13 – Implementação do método processSingleCommand .................................74
Quadro 14 – Template criado com a tabela de tradução para a condição dos elementos.........75
Quadro 15 – Definições regulares criadas na ferramenta GALS .............................................76
Quadro 16 – Definições de tokens criados na ferramenta GALS.............................................76
Quadro 17 – Resultado da geração de código a partir do diagrama de classe..........................82
Quadro 18 – Comparativo entre Drawcode e seus correlatos ..................................................83
Quadro 19 - Template para a lista principal do diagrama N-S .................................................91
Quadro 20 - Template para os comandos simples, atribuições e chamadas de sub-rotinas .....91
Quadro 21 - Template para o comando de seleção...................................................................91
Quadro 22 - Template para as opções do comando de seleção ................................................91
Quadro 23 - Template para o comando de repetição com condição no final do laço de
repetição.................................................................................................................91
Quadro 24 - Template para o comando de repetição com número de repetições definido.......91
Quadro 25 - Template para o comando de repetição com condição no inicio do laço de
repetição.................................................................................................................92
Quadro 26 - Template para o comando de decisão...................................................................92
Quadro 27 - Template para a lista de comandos verdadeiros e falsos do comando de decisão92
Quadro 28 - Template para o lista de classes do diagrama de classes......................................93
Quadro 29 - Template criado para o elemento classe...............................................................93
Quadro 30 - Template criado para a lista de atributos da classe...............................................93
Quadro 31 - Template criado para o elemento atributo ............................................................93
Quadro 32 - Template criado para o elemento método ............................................................93
Quadro 33 - Template criado para lista de métodos da classe..................................................93
Quadro 34 - Template contendo a tabela de mapeamento para os comandos do tipo instrução
...............................................................................................................................94
Quadro 35 - Template com a tabela de mapeamento para as condições dos elementos do
diagrama N-S .........................................................................................................94
Quadro 36 – Operações das classes apresentadas na Figura 23 .............................................101
LISTA DE SIGLAS
DAS – Departamento de Automação e Sistemas
EA – Enterprise Architect
ECF – Ecole Centrale Paris
GALS – Gerador de Analisadores Léxicos e Sintáticos
GEF – Graphical Editing Framework
IBM – International Business Machines
MVC – Model View Controller
UML – Unified Modeling Language
VTL – Velocity Template Language
XML - eXtensible Markup Language
SUMÁRIO
1 INTRODUÇÃO..................................................................................................................15
1.1 OBJETIVOS DO TRABALHO ........................................................................................17
1.2 ESTRUTURA DO TRABALHO ......................................................................................18
2 FUNDAMENTAÇÃO TEÓRICA....................................................................................19
2.1 ORIENTAÇÃO A OBJETOS ...........................................................................................19
2.2 DIAGRAMA DE CLASSES.............................................................................................20
2.3 ALGORITMOS.................................................................................................................22
2.4 DIAGRAMAS N-S ...........................................................................................................24
2.5 GERADORES DE CÓDIGO ............................................................................................27
2.6 MOTORES DE TEMPLATES ...........................................................................................30
2.7 AMBIENTE DE DESENVOLVIMENTO ECLIPSE.......................................................32
2.7.1 Estendendo o ambiente de desenvolvimento ..................................................................32
2.7.2 Editores gráficos no ambiente Eclipse ............................................................................34
2.8 TRABALHOS CORRELATOS........................................................................................35
2.8.1 NSD Editor......................................................................................................................36
2.8.2 Structorizer......................................................................................................................37
2.8.3 Jupe .................................................................................................................................38
2.8.4 Topcased .........................................................................................................................39
3 DESENVOLVIMENTO DO PLUGIN.............................................................................41
3.1 REQUISITOS PRINCIPAIS DO PROBLEMA A SER TRABALHADO.......................41
3.2 ESPECIFICAÇÃO ............................................................................................................42
3.2.1 Diagrama de casos de uso ...............................................................................................42
3.2.2 Diagrama de classes do Drawcode..................................................................................45
3.2.2.1 Diagrama da principal classe do plugin ........................................................................45
3.2.2.2 Diagrama de classe do editor de diagrama de classes ..................................................46
3.2.2.3 Diagrama de classe do editor de diagrama N-S............................................................48
3.2.2.4 Diagrama de classes do gerador de código...................................................................54
3.3 IMPLEMENTAÇÃO ........................................................................................................55
3.3.1 Técnicas e ferramentas utilizadas....................................................................................56
3.3.1.1 Entendendo o modelo criado ........................................................................................56
3.3.1.2 Manutenção dos modelos de dados ..............................................................................59
3.3.1.3 Representação gráfica do diagrama N-S.......................................................................63
3.3.1.4 Geração de código ........................................................................................................69
3.3.2 Operacionalidade da implementação ..............................................................................76
3.4 RESULTADOS E DISCUSSÃO ......................................................................................82
4 CONCLUSÕES..................................................................................................................85
4.1 EXTENSÕES ....................................................................................................................86
REFERÊNCIAS BIBLIOGRÁFICAS .................................................................................88
APÊNDICE A – Templates criados na linguagem VTL para o diagrama N-S.................91
APÊNDICE B – Templates criados na linguagem VTL para o diagrama de classes .......93
APÊNDICE C – Relação dos templates da tabela de tradução...........................................94
APÊNDICE D – Relação de métodos das classes apresentadas na Figura 23 ..................95
15
1 INTRODUÇÃO
Os computadores vêm evoluindo constantemente desde a sua concepção: maior poder
de processamento e maior capacidade de armazenamento são apenas alguns exemplos na
parte de hardware. Porém, isto não vem ocorrendo apenas com hardware, pois aliado ao
aumento da capacidade computacional, os softwares vêm crescendo tanto em quantidade
como em complexidade, para os mais variados fins.
Basicamente um computador é uma máquina que executa instruções previamente
definidas, ou seja, apenas executa o que foi previamente programado para fazer, sendo que
assim é necessário organizar quais são e em que ordem o computador deve executar essas
instruções. Para atingir esta organização de instruções é necessário entender o problema e
organizá-lo de maneira que o computador possa executar sua resolução. Este processo é
dividido em várias etapas: analisar e entender o problema, criar a solução do problema em
uma determinada linguagem e transformar esta linguagem em instruções para o computador.
Este processo de transformação vem evoluindo constantemente, sendo que várias
linguagens e ferramentas estão sendo criadas com o objetivo de facilitar e ajudar a mapear o
conteúdo sobre determinada área do conhecimento de forma que o computador possa executar
instruções onde o resultado seja usado de alguma maneira pelo usuário do recurso
computacional, seja ele um humano, ou ainda outro computador.
O que motiva a construção de um programa é a necessidade do cliente. Para se
desenvolver um programa, o cliente indica o que o programa deve contemplar e executar por
meio de especificações chamadas de requisitos. No desenvolvimento, os requisitos do cliente
são traduzidos em especificações técnicas de software pelos analistas de sistema ou
engenheiros de software (SOUZA et al., 2005, p. 2).
Uma das preocupações da indústria de software é a necessidade de criar software e sistemas corporativos muito mais rapidamente e a um custo mais baixo. Para fazer bom uso da crescente potência dos computadores, precisamos de um software de maior complexidade. Ainda que mais complexo, esse software também precisa ser mais confiável. A alta qualidade é fundamental no desenvolvimento de software. (MARTIN; ODELL; 1996, p. 3).
Martin e Odell (1996, p. 5) afirmam que para atingir tal qualidade e rapidez é
necessária uma combinação de técnicas e ferramentas. Uma das técnicas mais utilizadas
atualmente é a orientação a objetos, que permite ter uma visão mais natural do problema nas
fases de análise e programação da solução. Tal técnica agrupa as informações conforme suas
características e comportamentos, possibilitando uma visão mais parecida com o mundo real
16
onde todas as coisas podem ser consideradas objetos, podendo ser formados por outros
objetos menores, distribuindo a responsabilidade da resolução do problema.
O software construído no estilo Orientado a Objetos (OO) pode ser descrito com a
ajuda da Unified Modeling Language (UML), que segundo Fowler (2005, p. 25) é uma
família de notações gráficas que ajudam na descrição e no projeto de sistemas de software. A
UML é formada por diversos diagramas, dentre os quais o diagrama de classes que descreve
os tipos de objetos presentes no software e os relacionamentos entre eles. Um dos elementos
presentes no diagrama de classes são as operações que a classe possui, ou seja, são os
problemas que a classe sabe resolver (FOWLER, 2005, p. 33).
Para determinar como a operação de uma classe chega à solução do problema é
possível construir um algoritmo. Um algoritmo é um conjunto de regras finito, numa
determinada ordem de execução, onde cada regra tem determinado significado segundo
alguma convenção (uma linguagem de programação, por exemplo). A associação destas
regras permite a solução de um problema computacional qualquer (SOUZA et al. 2005, p. 4).
É possível representar algoritmos de várias maneiras. Souza (2000, p. 21) cita:
fluxogramas, português estruturado, pseudocódigo, diagrama de Nassi-Shneiderman (N-S) e
diagrama de ações. Alguns são representações textuais e outras gráficas. A representação
visual facilita a estruturação do raciocínio e, consequentemente, minimiza o esforço para
obtenção da solução do problema (SOUZA, 2000, p. 9).
Uma das notações para representação gráfica do algoritmo é o diagrama N-S, que
apresenta como vantagens domínio funcional bem definido e claramente visível,
impossibilidade de transferência de controle arbitrária, escopo dos dados facilmente
determinado e a recursividade é bem representada.
Definido o algoritmo para a solução do problema e representado através do diagrama
(N-S), é preciso codificar a solução de maneira que o computador possa tratar os dados e
processar a solução, escrevendo a solução em alguma linguagem de programação para
posterior compilação e geração de instruções que o computador possa executar. Geralmente
esta etapa é feita manualmente, entretanto, Martin e Odell (1996, p. 7) afirmam que sempre
que possível, os programas devem ser gerados utilizando técnicas de geração de código que
permitem produzir código sem nenhum erro de sintaxe a partir do projeto.
Herrington (2003, p. 15) afirma que técnicas de geração de código podem trazer
benefícios como: consistência ao definir um padrão para nomes de variáveis, produtividade
para o desenvolvimento de programas onde classes são geradas rapidamente e qualidade, pois
o código gerado é uniforme e superior ao criado numa codificação manual. Tal técnica
17
também possibilita abstração em nível de linguagem, sendo possível gerar programas em
outras linguagens de programação utilizando templates, sem comprometer a lógica envolvida.
Assim, este trabalho propõe a criação de uma ferramenta que possibilite a edição de
diagramas de classes, permitindo definir um algoritmo para as operações das classes criadas
usando diagramas N-S e possibilitando ainda gerar código para a linguagem Java, utilizando
para isso a técnica de templates1. No diagrama de classes serão editados apenas o nome da
classe, os atributos e métodos, não sendo tratados as demais representações deste tipo de
diagrama como associações, agregação, herança, entre outros, que serão tratados como
extensões do mesmo.
1.1 OBJETIVOS DO TRABALHO
O objetivo deste trabalho é desenvolver uma ferramenta gráfica e interativa que
possibilite a edição de atributos e métodos em diagramas de classe, permitindo criar para cada
método/operação das classes do diagrama de classes, um diagrama N-S, que vai representar o
algoritmo para alcançar o resultado planejado para este método. A partir desta associação de
um diagrama N-S para cada o método da classe, será gerado o código para a classe, incluindo
a assinatura, os atributos e o corpo do método.
Os objetivos específicos do trabalho são:
a) permitir que o usuário possa criar diagramas de classe;
b) permitir que o usuário possa criar diagramas N-S;
c) gerar código na linguagem Java para o corpo dos métodos utilizando templates;
d) utilizar a técnica de plugins2 para o ambiente Eclipse3.
1 Template é uma técnica que consiste em montar um texto com algumas anotações especiais, onde determinado programa vai processar este texto, substituindo tais anotações por outra informação. 2 Plugin é um programa de computador que serve normalmente para adicionar funções a outros programas maiores, provendo alguma funcionalidade especial ou muito específica (PLUGIN, 2007). 3 Eclipse é um ambiente de desenvolvimento de código aberto para a construção de programas de computador (ECLIPSE FOUNDATION, 2007a).
18
1.2 ESTRUTURA DO TRABALHO
Este trabalho está divido em quatro capítulos. O primeiro capítulo apresenta uma
introdução sobre o contexto que o plugin está envolvido. Já no segundo capítulo é apresentada
a fundamentação teórica envolvida na idealização do mesmo, assim como algumas
ferramentas correlatas. O terceiro capítulo apresenta detalhes sobre o desenvolvimento,
informações sobre como o problema foi modelado e dividido e quais técnicas foram utilizadas
na sua construção. No quarto capítulo são apresentadas algumas discussões sobre os
resultados, comparações com seus correlatos, limitações existentes e extensões futuras.
19
2 FUNDAMENTAÇÃO TEÓRICA
Neste capítulo são apresentados os principais assuntos relacionados ao
desenvolvimento deste projeto, sendo: orientação a objetos, diagramas de classe, algoritmos,
diagramas N-S, geração de código, motores de templates, ambiente de desenvolvimento
Eclipse e alguns trabalhos correlatos.
2.1 ORIENTAÇÃO A OBJETOS
A orientação a objetos é um paradigma4 de análise, projeto e programação de sistemas
baseado na composição e interação entre diversas unidades de software chamadas de objetos
(ORIENTAÇÃO A OBJETO, 2007).
Em outras palavras, o objetivo é identificar e classificar as informações que fazem
parte do software e organizá-las em grupos, conforme suas características e comportamentos,
apresentando quais objetos fazem parte do software. Neste modelo um software pode ser
descrito como vários objetos distintos que interagem entre si. A interação entre estes objetos
será o resultado final do software.
Mas, o que é um objeto? Tonsig (2003, p. 166) apresenta a seguinte definição de
objeto: “Objeto é a representação de elementos físicos do mundo real, que sob o ponto de
vista do problema a ser resolvido, possuem atributos e métodos comuns”. Portanto, um objeto
é composto por atributos que representam suas características e métodos que são suas
atividades. Normalmente um software é composto por uma grande quantidade de objetos, que
são agrupados em classes de objetos. Uma classe representa um conjunto de objetos com as
mesmas características e comportamentos (TONSIG, 2003, p. 167).
Para ajudar a entender estas classes de objetos e como elas se relacionam no contexto
do software a UML prevê alguns diagramas (PILONE, PITMAN, 2006, p. 5), os quais são
exemplos:
a) diagramas de classes: apresentam as classes existentes no software e de que
maneira elas se relacionam;
20
b) diagrama de componentes: mostram a organização e as dependências envolvidas
na implementação do sistema. Agrupam elementos menores como as classes em
elementos maiores;
c) diagrama de estruturas compostas: demonstram a ligação entre os diagramas de
classe e os diagramas de componentes;
d) diagramas de pacote: são tipos especiais de diagramas de classe, utilizando a
mesma notação, porém com foco em como classes e interfaces estão agrupadas;
e) diagramas de objetos: utilizam a mesma sintaxe do diagrama de classe e tem como
objetivo demonstrar o relacionamento entre elementos em determinado momento
da execução do software;
f) diagrama de atividade: demonstram o fluxo de comportamento de determinada
classe de objetos;
g) diagrama de comunicação: demonstram as mensagens trocadas entre os objetos
que compõem o software;
h) diagrama de seqüência: apresentam os elementos envolvidos, o tipo e a ordem das
mensagens enviadas entre os elementos durante a execução do software.
Neste trabalho será dada ênfase ao Diagrama de Classes.
2.2 DIAGRAMA DE CLASSES
O diagrama de classes representa os objetos presentes no sistema, seus
atributos/propriedades, suas operações e os relacionamentos existentes entre os objetos
utilizados na construção do software. Ele demonstra atributos e operações, apresentando sua
visibilidade, indicando se podem ser acessados de fora da classe ou apenas internamente. Um
exemplo de diagrama de classes pode ser visto na Figura 1, onde também é apresentado o
significado das notações utilizadas no diagrama.
4 Um paradigma de programação fornece e determina a visão que o programador possui sobre determinado software e mostra como este software está dividido (PARADIGMA DE PROGRAMAÇÃO, 2007).
21
Fonte: adaptado de Fowler (2005, p. 53).
Figura 1- Exemplo de diagrama de classes simples
No diagrama apresentado na Figura 1 são descritas sete classes. É possível visualizar o
relacionamento de agregação entre a classe Pedido e a classe ItenPedido, representado por
um losango mais próximo a classe Pedido. É possível ainda observar que existe uma
associação entre as classes Pedido e Cliente indicando também a multiplicidade existente
nesta associação onde um cliente pode ter vários pedidos, porém um pedido pode pertencer a
apenas um cliente.
Neste mesmo diagrama ainda é possível visualizar uma generalização envolvendo as
classes Cliente, ClienteCorporativo e ClientePessoal, onde a classe Cliente possui as
características comuns aos dois tipos de cliente corporativo e pessoal. Pode ser observado
também que a classe ClienteCorporativo além de herdar da classe Cliente alguns
atributos e operações, possui seus próprios atributos e operações.
Neste trabalho é explorada apenas a representação das classes e seus atributos e
métodos. Nenhum tipo de relacionamento entre as classes é tratado.
22
2.3 ALGORITMOS
Segundo Carboni (2003, p. 12-24), existem várias formas de descrever a lógica para
solução de um problema e uma das mais utilizadas é o algoritmo, com suas formas de
representação. O algoritmo pode ser considerado uma seqüência de procedimentos finitos que
serão executados em determinada ordem para atingir certo objetivo.
O nível de complexidade do algoritmo varia de acordo com o tamanho do problema
que este visa resolver. Problemas simples são facilmente representados num fluxograma, em
contrapartida algoritmos com um nível de complexidade maior necessitam de algum tipo de
divisão do problema em problemas menores. Souza (2000, p. 15) afirma que para minimizar a
complexidade utiliza-se o conceito de abstração considerando apenas os dados que são
realmente relevantes para a solução do problema atual, e o método de refinamentos sucessivos
onde o problema é decomposto em problemas menores, caracterizando algoritmos formados
por outros algoritmos menores.
Existem duas técnicas principais adotadas para o desenvolvimento de algoritmos,
sendo elas a abordagem estruturada e a orientada a objetos. A abordagem estruturada visa
decompor o problema inicial em problemas menores, utilizando um conjunto de construções
lógicas simples, onde qualquer algoritmo possa ser elaborado. A abordagem orientada a
objetos trata o problema como um conjunto de objetos que interagindo entre si vão chegar à
resolução do problema, onde cada objeto agrupa seus respectivos dados e funções (SOUZA,
2000, p. 17-19).
A pesquisa na literatura e a prática em universidades brasileiras demonstraram ser a metodologia de Resolução Estruturada de Problemas aquela mais utilizada para elaboração dos algoritmos. Por outro lado, conclui-se também que a Resolução Orientada a Objetos pode fazer uso da metodologia Resolução Estruturada para especificação dos métodos da classe, visto que aquela não apresenta técnica específica para elaboração dos algoritmos que os formam. (SOUZA, 2000, p. 42).
Souza (2000, p. 20) afirma que as técnicas de diagramação estruturada ajudam os
desenvolvedores de algoritmos a manipularem um grande número de detalhes gerados durante
o processo de elaboração da solução de um problema. Existem ferramentas para a criação e
representação de algoritmos, sendo as mais utilizadas:
a) fluxogramas: foi um dos primeiros e mais usados métodos para diagramação,
tendo sido utilizado pela maioria dos programadores e analistas de sistemas antes
do surgimento dos métodos de resolução estruturada;
23
b) português estruturado: é uma ferramenta hierarquicamente estruturada, que utiliza
margens para demonstrar a estrutura e apresenta forma análoga à linguagem
escolhida para implementação do algoritmo. Utiliza palavras-chave para formalizar
o algoritmo e apresenta como vantagem, a facilidade para elaboração;
c) pseudocódigo: utiliza as mesmas diretrizes do português estruturado, porém faz
uso de uma notação mais formal, orientada a profissionais da informática, enquanto
o português estruturado é mais bem compreendido por usuários;
d) diagrama de ações: são ferramentas que utilizam recursos visuais e foram
projetadas para relacionar ações ao modelo de dados. Pode apresentar uma visão
mais geral ou mais detalhada do algoritmo desenvolvido, demonstrando sua
estrutura hierárquica;
e) diagrama N-S: apresenta uma estrutura hierárquica e fornece a visão detalhada do
algoritmo. Apresenta como estrutura básica o retângulo, a partir do qual as demais
estruturas são desenhadas.
O diagrama é uma forma visual de representação do conhecimento. Com o aumento da
complexidade dos programas criados, o processo de criação de software necessita de
ferramentas que auxiliem na representação do problema, com o intuito de amenizar a
complexidade de mesmo, sendo que os diagramas visam facilitar o entendimento do
problema.
Na Figura 2 são apresentadas duas representações distintas para o mesmo algoritmo.
Um algoritmo que soma três valores, calcula a média e se o resultado é maior que seis, tem
como resultado a string “aprovado”. Caso contrário, tem como resultado a string “reprovado”.
Na primeira representação é apresentado o algoritmo na forma de um diagrama N-S. Já na
segunda forma, o mesmo algoritmo é representado na linguagem Java.
Figura 2 – Exemplos de representação de algoritmos
24
2.4 DIAGRAMAS N-S
O diagrama N-S foi apresentado em 1973 por Isaac Nassi e Ben Shneiderman (NASSI;
SHNEIDERMAN, 1973). Segundo eles, os programas de computador passam por várias
fases: entendimento do problema, formulação e definição da solução e codificação do
software. Nestas fases um fluxograma ou diagrama pode ser criado para ajudar no
entendimento do problema abstraindo fases posteriores da solução do problema como a
codificação em uma linguagem de programação, por exemplo.
Conforme Martin e Mcclure (1991, p. 256), “Diagramas de I. Nassi e B. Shneiderman
(N-S) representam estruturas de programas que tem um ponto de entrada e um ponto de saída
e são compostos pelas estruturas básicas de controle de seqüência, seleção e repetição.” Esse
diagrama é formado por um retângulo que representa o algoritmo para a solução de
determinado problema utilizando estruturas de seleção, repetição e a ordem das ações a serem
executadas.
Os diagramas N-S são melhores para representar a solução estruturada de um
algoritmo que os fluxogramas, pois esses dão uma visão não estrutural do problema e tendem
a apresentar muitos saltos. “Enquanto é difícil mostrar o embutimento e a recursividade com o
fluxograma tradicional, é fácil mostrá-los com um diagrama N-S. É fácil, também, converter
um diagrama N-S em código estruturado” (MARTIN; MCCLURE, 1991, p. 256).
Nassi e Shneiderman (1973) citam as seguintes vantagens do diagrama N-S sobre os
fluxogramas:
a) escopo das iterações é bem definido e visível;
b) escopo dos comandos de decisão são bem definidos e visíveis, apresentando em
destaque a condição de decisão;
c) escopo de variáveis globais e locais é facilmente observado;
d) não existe transferência de controle arbitrária;
e) a recursividade tem uma representação muito simples.
Conforme Souza (2000, p. 25) os diagramas N-S apresentam como desvantagem o
problema do dimensionamento das estruturas, que normalmente obriga o desenvolvedor a
redesenhá-lo novamente, consumindo muito tempo na sua elaboração.
Porém é possível eliminar, ou ao menos minimizar este problema utilizando-se de
ferramentas computacionais que automaticamente redimensionem o diagrama conforme a
necessidade.
25
O diagrama N-S é formado por seis elementos básicos, sendo eles: processo, decisão,
repetição, bloco, paralelo e seleção. Basicamente todos os elementos são representados por
retângulos, sendo que cada um deles apresenta particularidades no seu interior.
O símbolo de processo serve para indicar uma ação a ser executada, a qual pode ser um
método a ser invocado ou uma atribuição. É basicamente um retângulo com o seu respectivo
comando dentro. Um exemplo deste símbolo pode ser visto na Figura 3.
Fonte: adaptado de Nassi e Shneiderman (1973).
Figura 3 - Exemplo de um comando de atribuição
O símbolo de decisão serve para indicar uma expressão lógica a ser verificada para
desviar o fluxo de execução do algoritmo em duas possibilidades. Se a expressão for
verdadeira uma coluna de execução é seguida, caso contrário, outra coluna de execução é
seguida. Um exemplo deste símbolo pode ser visto na Figura 4.
Fonte: adaptado de Nassi e Shneiderman (1973).
Figura 4 - Exemplo de um comando de decisão
Outro símbolo que faz parte do diagrama N-S é o que representa a seleção. Este
símbolo representa para o algoritmo que com base no valor de determinada variável, uma das
colunas de execução será seguida. Cada uma das colunas de execução tem um valor que a
representa. Caso o valor da variável definida para ser analisada não seja igual a uma das
colunas, uma coluna de execução padrão é seguida. Um exemplo deste símbolo pode ser visto
na Figura 5.
Fonte: adaptado de Nassi e Shneiderman (1973).
Figura 5 - Exemplo de uma estrutura de seleção
26
O símbolo de repetição serve para indicar um grupo de comandos a serem executadas
até que determinada expressão lógica deixe de ser verdadeira. São de dois tipos, sendo que no
primeiro tipo a expressão fica antes da lista de comandos e o segundo é quando a expressão
fica depois da lista de comandos. Desta maneira quando a condição está depois da lista de
comandos, isto significa que aquela lista vai ser executada pelo menos uma vez. Um exemplo
deste símbolo com a expressão lógica antes da lista de comandos pode ser visto na Figura 6.
Fonte: adaptado de Nassi e Shneiderman (1973).
Figura 6 - Exemplo de um comando de repetição
O símbolo de bloco serve para agrupar uma lista de comandos a serem executados
formando um bloco, sendo que existe uma marcação para o início do bloco e outra para
indicar o final do bloco. Um exemplo deste símbolo pode ser visto na Figura 7.
Fonte: adaptado de Nassi e Shneiderman (1973).
Figura 7 - Exemplo de um bloco de comandos
Por último existe o símbolo de paralelismo, indicando que o algoritmo em determinado
ponto vai ter mais de uma linha de execução. Indica que novas linhas de execução serão
criadas e serão seguidas ao mesmo tempo, retornando a uma única no término de cada uma
das linhas. Um exemplo deste símbolo pode ser visto na Figura 8.
Fonte: Nassi e Shneiderman (1973).
Figura 8 - Exemplo de uma estrutura de paralelismo
27
2.5 GERADORES DE CÓDIGO
O desenvolvimento de um programa torna-se mais fácil se a linguagem utilizada para
sua criação estiver mais próxima do problema a ser resolvido, ou seja, se a linguagem
apresenta construções que refletem a terminologia e/ou elementos usados na descrição do
problema. Este tipo de linguagem é chamada de linguagem de alto nível, porém computadores
apenas entendem sua própria linguagem de máquina, chamada de linguagem de baixo nível,
que geralmente é formada por uma seqüência de zeros e uns (PRICE; TOSCANI, 2001, p. 1).
Para que se tornem operacionais para os computadores, programas escritos em
linguagens de alto nível devem ser traduzidos para linguagem de máquina. Esta tradução é
realizada por programas especializados nesta tarefa, chamados de compiladores ou
interpretadores. Estes têm como entrada uma representação textual do algoritmo, tendo como
saída o mesmo algoritmo expresso em outra linguagem (PRICE; TOSCANI, 2001, p. 1).
A complexidade envolvida neste processo determina a divisão em processos menores
interconectados, exigindo vários componentes para a sua formação, os quais são:
a) analisador léxico: analisa a seqüência de caracteres de entrada e traduz em tokens
da linguagem alvo, que serão utilizados pelo analisador sintático (SOUZA 2000, p.
53);
b) analisador sintático: verifica se a estrutura gramatical do programa criado está
correto conforme as regras gramaticais definidas para a linguagem de programação
utilizada na construção do programa (SOUZA 2000, p. 53);
c) analisador semântico: faz a verificação dos tipos utilizados no programa. Checa se
cada operador recebe os operandos permitidos conforme a especificação da
linguagem (AHO; SETHI; ULLMAN, 1995, p. 4);
d) gerador de código intermediário: gera uma representação intermediária do
programa fonte (AHO; SETHI; ULLMAN, 1995, p. 7);
e) otimizador de código: atua sobre o código intermediário, com o objetivo de
melhorá-lo, tendo como resultado ao final de todo o processo, código de máquina
mais otimizado (AHO; SETHI; ULLMAN, 1995, p. 7);
f) gerador de código: responsável por gerar o código alvo (AHO; SETHI; ULLMAN,
1995, p. 7);
g) gerenciador de tabela de símbolos: responsável por manter uma tabela com os
símbolos encontrados no programa fonte e demais informações necessárias. É
28
utilizado pelos outros componentes do processo de compilação (SOUZA 2000, p.
53);
h) manipulador de erros: responsável por tratar os erros encontrados por cada um dos
componentes da compilação (SOUZA 2000, p. 53).
A Figura 9 apresenta uma representação dos componentes presentes no compilador.
Fonte: Souza (2000, p. 54).
Figura 9 – Componentes de um compilador
A geração de código pode ou não estar precedida de todas as etapas anteriores,
dependendo do tipo de geração de código que se deseja fazer. Um gerador de código pode ser
um simples formatador de código ou uma ferramenta que gere uma aplicação a partir de
modelos abstratos. De acordo com Herrington (2003, p. 3), as vantagens de se utilizar
geradores de código para o desenvolvimento de software são:
a) qualidade: código escrito manualmente tende a ter um nível de qualidade muito
irregular visto que, durante o desenvolvimento da aplicação, podem ser propostas
melhores abordagens para solucionar os problemas, além de depender da
experiência e boas práticas de programação do programador;
b) produtividade: quando são usados geradores no projeto de software, o volume de
29
código produzido manualmente é bem menor se comparado a outro projeto sem o
uso dessas ferramentas. Sendo assim, tem-se mais tempo para outras etapas do
projeto;
c) abstração: a definição de templates é bem mais simplificada que o código alvo.
Com o uso de templates pode-se corrigir erros do projeto ou incluir novas
funcionalidades apenas reescrevendo os templates. Além disso, o gerador pode ser
facilmente reprojetado para outras linguagens ou tecnologias.
Herrington (2003, p. 61-94) apresenta 5 tipos de geração de código, sendo:
a) formatação de código (code munger): é o mais simples dos modelos de geradores,
tendo como entrada um código fonte escrito em alguma linguagem de alto nível, e
apresenta na saída um ou mais arquivos que podem ser documentação, ou ainda
uma extensão do código;
b) expansão de código (inline code expander): permite simplificar o código fonte.
Tem como entrada um código fonte em uma linguagem de alto nível anotado com
algum tipo de marcação que, na execução do gerador, será substituído por código
da linguagem fonte. A saída é código fonte na mesma linguagem da entrada. O
código não pode ser compilado antes da execução do gerador;
c) geração mista (mixed code generator): é uma implementação mais prática que o
modelo de expansão de código. Tem como entrada código fonte em uma
linguagem de alto nível, com marcações feitas utilizando comentários. Tem como
saída código na mesma linguagem de entrada. O código de entrada e o código de
saída podem ser diretamente compilados;
d) geração parcial de classes (partial class generator): este tipo constrói código a
partir de modelos abstratos. Ele tem como entrada uma descrição abstrata dos
requisitos de código e constrói um conjunto de classes que deve ser estendido com
a implementação dos métodos ou subclasses (classes derivadas) para criar a
aplicação completa;
e) geração de camadas de aplicação (tier generator): este tipo de geração constrói
todo o código necessário para um camada da aplicação. Tem como entrada uma
definição abstrata de toda a informação necessária para criar o código completo de
uma camada da aplicação. Utilizando a definição abstrata com um conjunto de
templates, a saída é criada.
Depois de definido qual tipo de gerador é o mais apropriado para a solução, existem
passos a serem observados para a construção do gerador de código sendo (HERRINGTON,
30
2003, p. 93):
a) escrever o código alvo manualmente: determinar qual será a saída do gerador;
b) projetar o gerador: determinar como será a entrada do gerador, como a entrada será
analisada e como o código de saída será gerado;
c) desenvolver a entrada: implementar como as informações de entrada do gerador
serão extraídas;
d) desenvolver a saída: implementar o processamento dos dados de entrada e criar a
saída conforme apresentado na primeira etapa.
A geração de camada de aplicação faz uso do conceito de template. Um template é
basicamente um arquivo texto com marcações especiais. Tais marcações devem ser feitas
levando em consideração o motor que vai ser utilizado, por que o arquivo de template
unicamente não é utilizado. Ele deve ser usado em conjunto com um motor de templates.
2.6 MOTORES DE TEMPLATES
O motor de template é um artefato de software que possibilita a junção de um conjunto
de informações a um arquivo de template. O resultado da ação do motor será a união do
código dinâmico com o código estático. Código estático é o que está definido de forma fixa
no template e código dinâmico são as variáveis que o motor vai tratar e substituir por valores
que recebeu como entrada.
A Figura 10 apresenta uma representação gráfica do funcionamento de um motor de
templates.
31
Fonte: Template Processor (2007).
Figura 10 – Representação do funcionamento de um motor de templates
Segundo Rocha (2005), os motores de templates são mecanismos que permitem
desenvolver geradores de código independentes do código alvo já que este está externo à
aplicação. Deve existir um programa responsável por instanciar o motor, carregar os valores
das variáveis e blocos especiais.
Cada motor implementa sua própria linguagem através da qual os templates deverão
ser escritos. Esta linguagem define os tipos de blocos especiais e como referenciar variáveis e
varia bastante em nível de complexidade, podendo ser definida apenas com estruturas básicas
para substituição de valores de variáveis ou até ter estruturas de controle mais complexas
como loops e comandos condicionais (ROCHA, 2005).
Um dos motores de templates existentes é o Velocity da Apache Software Foundation.
Foi escrito na linguagem Java, sendo um projeto de código aberto. Suas indicações são as
seguintes (APACHE SOFTWARE FOUNDATION, 2007a):
a) aplicações web: criar páginas com informações dinâmicas;
b) geração de código: pode gerar código baseado em modelos;
c) geração automática de correio eletrônico: corpo padrão da mensagem é
armazenado em template e as demais informações são geradas dinamicamente;
d) transformação XML: permite ler diretamente arquivos XML e fazer a
transformação necessária conforme descrito no template.
Ele provê um objeto chamado de contexto, sendo que o mesmo é na verdade uma
32
tabela de objetos, que é utilizado para mesclar as informações estáticas presentes no arquivo
de template com as informações dinâmicas fornecidas ao Velocity pelo programa que fez sua
inicialização (APACHE SOFTWARE FOUNDATION, 2007a).
Os arquivos de template, criados para serem utilizados junto ao Velocity, devem ser
escritos conforme a Velocity Template Language, ou simplesmente VTL. A VTL provê
comandos para controlar o funcionamento do motor no momento do processamento do
arquivo de template. Existem comandos para laços de repetição, condições a serem analisadas
pelo motor, ou ainda a definição de variáveis. O Quadro 1 mostra a construção de uma
condição utilizando a VTL. No momento que o motor processa o arquivo de template, se a
variável foo for igual a variável bar, é produzido como saída “it’s true!”, caso contrário “it’s
not!” (APACHE SOFTWARE FOUNDATION, 2007b).
#if( $foo == $bar)it's true!#{else}it's not!#end Fonte: Apache Software Foundation (2007b).
Quadro 1 – Exemplo de utilização da VTL
Mais informações sobre a VTL podem ser encontradas na guia de referência da VTL,
no site da Apache Software Foundation (APACHE SOFTWARE FOUNDATION, 2007b).
2.7 AMBIENTE DE DESENVOLVIMENTO ECLIPSE
O Eclipse é um projeto de código fonte aberto com o objetivo de criar uma plataforma
de desenvolvimento composto de várias partes extensíveis e ferramentas para apoiar a
construção, implantação e todo o ciclo de desenvolvimento de programas. Foi originalmente
criado pela International Business Machines (IBM) e a partir de janeiro de 2004 se tornou
uma fundação sem fins lucrativos a fim de apoiar a criação de comunidades de
desenvolvimento em torno do projeto Eclipse (ECLIPSE FOUNDATION, 2007c).
2.7.1 Estendendo o ambiente de desenvolvimento
O Eclipse foi projetado para ser amplamente extensível, assim o mesmo provê alguns
mecanismos que permitem serem adicionadas funcionalidades ao ambiente de
desenvolvimento. Estas partes criadas para serem conectadas ao ambiente são chamadas de
33
plugins.
Basicamente, um plugin é um conjunto de funcionalidades a ser integrada ao Eclipse.
Esse deve ser criado acompanhado de um arquivo plugin.xml, que define como deve ser tal
integração. Esse arquivo define desde informações básicas (como nome, fornecedor) até
dados importantes para a integração com o Eclipse (extensões, pontos de extensão). O plugin
por sua vez costuma conter um conjunto de classes Java (para criar um editor, por exemplo),
mas pode conter também outros tipos de arquivo, como páginas html (para estender a Ajuda)
ou simples arquivos de dados (BARROS et al., 2003).
Quando o ambiente é inicializado, o mesmo carrega todos os arquivos plugin.xml do
diretório plugins e os mantém em memória durante todo o tempo de execução e havendo
necessidade, as classes de ativação de cada plugin são carregadas. O diagrama de seqüência
apresentado na Figura 11 demonstra de que forma o plugin é ativado.
Figura 11 – Diagrama de seqüência da ativação do plugin
O arquivo plugin.xml traz as principais informações sobre o funcionamento do plugin
para o ambiente Eclipse. Um exemplo deste arquivo pode ser verificado no Quadro 2.
34
<plugin> <extension point="org.eclipse.ui.editors"> ->ponto de extensão utilizado <editor ->definição de um novo editor class="NSDiagramEditor" ->classe responsável extensions="nsd" ->extensão de arquivo a ser usado icon="icons/drawcode/graphics/nsd.png" id="NSDiagramEditor" name="N-S Diagram Editor"> ->nome do editor </editor> </extension> <extension point="org.eclipse.ui.popupMenus"> ->ponto de extensão utilizado <viewerContribution ->definição de uma nova contribuição visual id="NSCodeGeneration" targetID="NSDiagramEditor"> <action class="NSCodeGeneration" ->classe responsável definitionId=" NSCodeGeneration" icon="icons/drawcode/codegeneration2.png" id=" NSCodeGeneration" label="Generate from NS-Diagram" menubarPath="additions"> </action> </extension> </plugin>
Quadro 2 – Estrutura do arquivo plugin.xml
O ambiente oferece um grande número de pontos de extensão já existentes que
possibilitam incluir menus e opções praticamente em todas as suas partes. Além disso, é
possível criar os seus próprios pontos de extensão para serem utilizados por outros plugins.
Mais informações sobre os pontos de extensão existentes e seu funcionamento podem ser
encontradas diretamente no site da Eclipse Foundation (ECLIPSE FOUNDATION, 2007a).
2.7.2 Editores gráficos no ambiente Eclipse
Um dos sub-projetos da Eclipse Foundation é o Graphical Editing Framework, ou
simplesmente GEF. O GEF é um framework cujo objetivo é permitir que os desenvolvedores
criem aplicações mais ricas graficamente a partir dos seus modelos. É baseado no padrão de
projeto Model, View, Controler (MVC) e fornece funcionalidades para controlar alterações no
modelo, criar uma representação gráfica do mesmo e permitir que alterações feitas na
representação visual sejam propagadas para o modelo e vice-versa.
Internamente o GEF utiliza-se ainda de outro framework, o Draw2d que provê a parte
gráfica, como o desenho de linhas ou círculos e quadrados e as estruturas gráficas básicas para
a criação da representação visual de algum elemento do modelo.
35
A Figura 12 demonstra uma visão geral do GEF, onde o mesmo pode ser definido
como a região central. O framework provê a ligação entre o modelo da aplicação e sua
visualização, onde as ações executadas pelo usuário são tratadas e transformadas em eventos e
comandos. Estes eventos e comandos são usados para encapsular as interações do usuário e
seus efeitos junto ao modelo (ECLIPSE FOUNDATION 2007d).
Fonte: ECLIPSE FOUNDATION (2007d). Figura 12 – Visão geral do GEF
2.8 TRABALHOS CORRELATOS
Para o desenvolvimento deste trabalho foram pesquisadas algumas ferramentas
correlatas que possibilitam a edição de diagramas de classe e N-S, assim como a geração de
código. Serão apresentadas duas ferramentas que possibilitam a edição de diagramas N-S e a
geração de código do mesmo. Serão apresentadas também duas ferramentas que permitem
editar diagramas de classe e posteriormente gerar código para o mesmo.
Durante a pesquisa não foram encontradas ferramentas criadas na forma de plugin para
o ambiente Eclipse que possibilitassem a edição de diagramas N-S e/ou geração de código.
Assim foram pesquisadas as ferramentas NSD Editor e Structorizer.
Para a edição de diagramas de classe as ferramentas pesquisadas são plugins para o
ambiente Eclipse e ambas com o código aberto, sendo elas Jupe UML Plugin for Eclipse e o
36
TopCased.
2.8.1 NSD Editor
Kalt (1996) apresenta o NSD Editor, sendo um editor de diagramas N-S criado no
ambiente Borland Delphi. Dá suporte às instruções de chamada de sub-rotina, atribuição,
decisão e laços de repetição. Permite salvar os diagrama em disco e posteriormente abri-los.
Redimensiona os elementos visuais conforme a necessidade automaticamente e permite gerar
código para as linguagens C e Pascal.
A Figura 13 mostra a tela principal do aplicativo. Nela é possível clicar num novo
elemento a ser inserido no diagrama e arrastar em cima do diagrama e soltar o novo elemento.
Conforme é movimentado o mouse o aplicativo vai sinalizando o ponto exato da inserção do
novo elemento.
Figura 13 – Tela do aplicativo NSD Editor
37
2.8.2 Structorizer
Este aplicativo é um editor para diagramas N-S, criado na linguagem pascal com o
código fonte aberto. Possui compilações para os sistemas operacionais Linux, Windows e
Mac OS. Foi iniciado pelo autor no ano de 2006, devido seu descontentamento com os
editores de diagrama N-S existentes (STRUCTORIZER, 2007).
Permite os elementos de instrução, decisão, laços de repetição, comando de seleção,
chamada de sub-rotina e instrução de salto. Não dá suporte a geração de código. Os diagramas
criados nesta ferramenta são gravados em arquivos no formato XML. A Figura 14 mostra a
tela principal do aplicativo. Nela é possível selecionar um elemento já existente no diagrama e
incluir um novo elemento acima ou abaixo do elemento selecionado.
Figura 14 – Tela do aplicativo Structorizer
38
2.8.3 Jupe
Jupe (JUPE 2007a) é um editor de diagramas de classe escrito em Java na forma de um
plugin para o ambiente Eclipse. É resultado do trabalho de seis alunos da Ecole Centrale Paris
(ECF) sob a supervisão da professora Dominique Sauquet, sendo um projeto de código fonte
aberto. A proposta do Jupe é ser um editor de diagramas da UML para o ambiente Eclipse.
Atualmente ele dá suporte ao diagrama de classe. Diagramas editados por ele são salvos no
formato XML. Permite a geração de código automática para a linguagem Java e engenharia
reversa, permitindo montar o diagrama de classes a partir de programas escritos na linguagem
Java. Possui algumas limitações como (JUPE 2007b):
a) sincronização: o Jupe pode ser configurado para que as alterações realizadas no
diagrama sejam transferidas automaticamente para os arquivos gerados, entretanto,
nem todas as alterações são propagadas para o código fonte e vice-versa, gerando
algumas inconsistências;
b) múltiplos projetos: trabalhar em mais de um projeto pode causar problemas;
c) trabalho em equipe: não podem ser utilizadas ferramentas para alterações
concorrentes;
d) visuais: elementos do diagrama podem se sobrepor.
A Figura 15 apresenta a tela principal do plugin. Nela é apresentada a janela com o
diagrama em edição, onde é possível através da paleta de componentes selecionar um novo
elemento e adicionar ao diagrama. Também é possível verificar as interfaces, classes,
atributos e métodos criados de maneira gráfica.
39
Figura 15 – Tela principal do plugin Jupe
2.8.4 Topcased
O Topcased (TOPCASED, 2007) é um projeto de código fonte aberto com o objetivo
de disponibilizar para a comunidade de código aberto um conjunto de ferramentas de
engenharia de software. Uma destas ferramentas é o Topcased UML2. Esta ferramenta, escrita
na linguagem Java na forma de um plugin para o ambiente Eclipse, permite a criação dos
seguintes tipos de diagrama: classe, caso de uso, seqüência, máquina de estados, atividades,
componentes e implantação. A edição desses diagramas é realizada de maneira integrada ao
ambiente Eclipse. Ela permite a geração de código a partir do diagrama de classes.
Estão envolvidas neste projeto nove empresas francesas e onze instituições de ensino,
entre elas o Departamento de Automação e Sistemas (DAS) do centro tecnológico da
Universidade Federal de Santa Catarina (PROJETO TOPCASED, 2007).
Na Figura 16 é possível verificar a tela para edição de diagramas de classes do plugin.
41
3 DESENVOLVIMENTO DO PLUGIN
Este capítulo descreve a especificação da ferramenta desenvolvida neste trabalho,
doravante denominada de Drawcode, um plugin para o ambiente de desenvolvimento Eclipse
que possibilita gerar código na linguagem Java a partir de diagramas de classe e diagramas N-
S, utilizando para isso o motor de templates Velocity. Na primeira seção estão descritos os
requisitos funcionais e não funcionais que o plugin deve atender. Na segunda seção é
apresentada a especificação do mesmo, demonstrando como o problema foi representado. A
terceira detalha as técnicas e ferramentas utilizadas e a operacionalidade do plugin. Na quarta
são apresentados os resultados e discussões sobre o trabalho, comparando-o com os seus
correlatos.
3.1 REQUISITOS PRINCIPAIS DO PROBLEMA A SER TRABALHADO
Nesta seção são apresentadas as funcionalidades necessárias pesquisadas para o
funcionamento do plugin elaborado neste trabalho. O resultado é demonstrado na Figura 17 e
Figura 18 na forma de requisitos funcionais e não-funcionais.
Figura 17 - Requisitos funcionais do plugin
42
Figura 18 - Requisitos não funcionais do plugin
3.2 ESPECIFICAÇÃO
Os tópicos seguintes descrevem a especificação do plugin Drawcode. As suas
funcionalidades são apresentadas através de casos de uso. Também são descritas as principais
classes modeladas.
3.2.1 Diagrama de casos de uso
O diagrama de casos de uso do Drawcode é mostrado na Figura 19 e descreve as
funcionalidades que ele fornece ao seu usuário. Um detalhamento dos casos de uso é
apresentado no Quadro 3 e no Quadro 4.
Figura 19 - Diagrama de casos de uso do plugin
43
UC01 – Editar diagrama de classe Descrição: Relacionado aos requisitos funcionais RF01 e RF03 Pré-condições:
1) Executar o ambiente de desenvolvimento Eclipse 2) Diretório usado pelo ambiente para armazenar as informações do usuário deve estar
funcional 3) Drawcode plugin deve estar devidamente instalado no ambiente
Cenário principal: Incluir um novo diagrama de classes 1) Selecionar o projeto ou pacote a ser incluído o novo diagrama 2) Clicar com o botão direito do mouse e comandar a criação de um novo arquivo com a
extensão “.drcd” 3) O arquivo é incluído com o nome definido pelo usuário
Cenário alternativo: Abrir um diagrama de classes existente 1) Usuário executa um duplo clique sobre o diagrama a ser editado 2) Ambiente apresenta na janela principal o diagrama previamente salvo 3) Ambiente apresenta uma paleta com os componentes característicos do diagrama de classes
Cenário alternativo: Incluir um novo elemento ao diagrama 1) Usuário seleciona um dos elementos existentes na paleta de componentes 2) Usuário clica sobre um elemento previamente existente no diagrama 3) Novo elemento é inserido
Cenário alternativo: Excluir um elemento existente no diagrama 1) Usuário seleciona qual o elemento do diagrama deve ser excluído 2) Pressionar o tecla <Delete> 3) Elemento é excluído
Cenário alternativo: Editar um elemento existente no diagrama 1) Usuário seleciona o elemento a ser editado 2) Usuário clica novamente sobre o elemento 3) Plugin apresenta um campo sobre o elemento com o conteúdo antigo do elemento 4) Usuário define o novo valor do elemento e ao final tecla <Enter> 5) Novo conteúdo do elemento é atualizado no diagrama
Cenário alternativo: Salvar um diagrama de classes em edição 1) Usuário comanda através do menu do ambiente que as alterações sejam salvas 2) Situação atual do diagrama é salva no arquivo
Cenário alternativo: Excluir um diagrama de classes 1) Selecionar o diagrama de classes a ser excluído 2) Clicar com o botão direito do mouse e comandar a exclusão 3) Arquivo é excluído
Cenário alternativo: Fechar diagrama em edição 1) No título da tela do ambiente onde o diagrama está sendo editado, clicar no ícone em forma
de “x” 2) O diagrama em edição é fechado
Cenário de exceção: Fechar o diagrama em edição com alterações ainda não salvas 1) Usuário é questionado se as alterações pendentes no diagrama devem ser salvas 2) Se a resposta do usuário for positiva as alterações são salvas 3) Diagrama em edição é fechado
Cenário alternativo: Atribuir um diagrama N-S existente a um método da classe 1) Usuário executa um duplo-clique sobre o método desejado 2) Ambiente apresenta uma tela permitindo escolher um arquivo com a extensão “.nsd” 3) Ao confirmar, o caminho completo para este arquivo é armazenado no método
Cenário alternativo: Gerar código para o diagrama de classe 1) Na tela do ambiente onde o diagrama está sendo editado usuário clica com o botão direito
do mouse 2) Usuário seleciona a opção: “Generate from class diagram” 3) Ambiente apresenta tela solicitando o arquivo a ser gerado 4) As classes são geradas no arquivo selecionado
44
Quadro 3 – Detalhes do caso de uso: editar diagrama de classe
UC02 – Editar diagrama N-S Descrição: Relacionado aos requisitos funcionais RF02 e RF03 Pré-condições:
1) Executar o ambiente de desenvolvimento Eclipse 2) Diretório usado pelo ambiente para armazenar as informações do usuário deve estar
funcional 3) Drawcode plugin deve estar devidamente instalado no ambiente
Cenário principal: Incluir um novo diagrama N-S 1) Selecionar o projeto ou pacote a ser incluído o novo diagrama 2) Clicar com o botão direito do mouse e comandar a criação de um novo arquivo com a
extensão “.nsd” 3) O arquivo é incluído com o nome definido pelo usuário
Cenário alternativo: Abrir um diagrama N-S existente 1) Usuário executa um duplo clique sobre o diagrama a ser editado 2) Ambiente apresenta na janela principal o diagrama previamente salvo 3) Ambiente apresenta uma paleta com os componentes característicos do diagrama N-S
Cenário alternativo: Incluir um novo elemento ao diagrama 1) Usuário seleciona um dos elementos existentes na paleta de componentes 2) Usuário clica sobre um elemento previamente existente no diagrama 3) Novo elemento é inserido
Cenário alternativo: Excluir um elemento existente no diagrama 1) Usuário seleciona qual o elemento do diagrama deve ser excluído 2) Pressionar a tecla <Delete> 3) Elemento é excluído
Cenário alternativo: Editar um elemento existente no diagrama 1) Usuário seleciona o elemento a ser editado 2) Usuário clica novamente sobre o elemento 3) Plugin apresenta um campo sobre o elemento com o conteúdo antigo do elemento 4) Usuário define o novo valor do elemento e ao final tecla <Enter> 5) Novo conteúdo do elemento é atualizado no diagrama
Cenário alternativo: Salvar um diagrama N-S em edição 1) Usuário comanda através do menu do ambiente que as alterações sejam salvas 2) Situação atual do diagrama é salva no arquivo
Cenário alternativo: Excluir um diagrama N-S 1) Selecionar o diagrama N-S a ser excluído 2) Clicar com o botão direito do mouse e comandar a exclusão 3) Arquivo é excluído
Cenário alternativo: Fechar diagrama em edição 1) No título da tela do ambiente onde o diagrama está sendo editado, clicar no ícone em forma
de “x” 2) O diagrama em edição é fechado
Cenário de exceção: Fechar o diagrama em edição com alterações ainda não salvas 1) Usuário é questionado se as alterações pendentes no diagrama devem ser salvas 2) Se a resposta do usuário for positiva as alterações são salvas 3) Diagrama em edição é fechado
Cenário alternativo: Gerar código para o diagrama de classe 1) Na tela do ambiente onde o diagrama está sendo editado usuário clica com o botão direito
do mouse 2) Usuário seleciona a opção: “Generate from N-S diagram” 3) Ambiente apresenta tela solicitando o nome do arquivo 4) Código é gerado no arquivo selecionado pelo usuário
Quadro 4 – Detalhes do caso de uso: editar diagrama N-S
45
3.2.2 Diagrama de classes do Drawcode
Nas subseções seguintes são detalhados os diagramas de classes do Drawcode, sendo
eles: a classe principal DrawcodePlugin que representa o plugin e que possibilita a integração
com o Eclipse, diagrama de classes do editor de diagrama de classes, diagrama de classes
relacionadas ao editor de diagramas N-S e diagrama de classes da geração de código dos
editores.
3.2.2.1 Diagrama da principal classe do plugin
A Figura 20 apresenta a principal classe do plugin Drawcode, no formato de um
diagrama de classe, sendo a classe DrawCodePlugin. Essa é a classe que representa o
plugin, controlando o seu ciclo de vida, sendo responsável por tratar a inicialização e
finalização do plugin e controlar quais arquivos o usuário mantêm aberto e qual deles é o
ativo.
Figura 20 - Classe principal do Drawcode
46
3.2.2.2 Diagrama de classe do editor de diagrama de classes
A Figura 21 apresenta na forma de um diagrama de classes a representação do editor
de diagramas de classe.
Figura 21 - Diagrama de classe do editor de diagramas de classe
Este conjunto de classes mapeia para o modelo os elementos existentes num diagrama
47
de classes como por exemplo as classes, seus atributos e métodos, sendo elas:
a) ClassDiagramHandler: é a classe responsável por fazer a persistência do modelo
de dados no formato XML, ler arquivos neste formato e transformar no modelo de
dados novamente, adicionar e remover elementos do modelo, assim como retornar
uma lista de elementos filhos de determinado elemento. Estas operações estão
definidas em classes chamadas de visitadores. O conceito de visitadores é
apresentado a partir da página 56, na subseção 3.3.1.1;
b) ClassDiagramElement: esta classe é a representação do diagrama de classes, ou
seja uma lista de elementos possíveis em um diagrama de classes. Esta classe não
implementa nenhuma funcionalidade. Ao ser solicitada, faz com que o visitador
recebido por parâmetro visite ela mesma e seus filhos;
c) ClassElement: é a representação no modelo para uma classe em um diagrama de
classes. Ela armazena o nome de determinada classe e têm duas listas, sendo elas
uma lista de atributos e uma lista de métodos. Ao receber a solicitação accept faz
com que o visitador recebido por parâmetro, visite a si mesma e suas listas de
atributos e métodos;
d) MethodElement: é a representação no modelo para um método de determinada
classe. Ela armazena a assinatura do método e, caso tenha sido informado, o
caminho para um determinado arquivo. Ao receber um visitador, faz com que tal o
visite;
e) AttributeElement: é a representação de um atributo de uma classe;
f) CDNodeAdder: é a classe responsável por adicionar elementos ao modelo. Recebe
solicitações contendo o elemento a ser inserido e em qual lista de elementos ele
deve ser inserido. Assim, percorre o modelo até encontrar a lista e adiciona o
elemento;
g) CDNodeRemover: esta classe é responsável por retirar elementos do modelo.
Recebe qual elemento deve ser retirado e percorre o modelo à sua procura. Ao
encontrá-lo, o remove do modelo;
h) ICDElementVisitable: esta interface representa os elementos que podem fazer
parte do modelo proposto para representar o diagrama de classes;
i) ICDElementsVisitor: esta interface representa as classes que implementam
alguma funcionalidade sobre o modelo. Classes que pretendem visitar o modelo
independente da funcionalidade desejada devem implementar esta interface;
48
j) MethodsList: esta classe representa a lista de métodos da classe existente no
diagrama;
k) AttributesList: esta classe representa a lista de atributos da classe existente no
diagrama;
l) CDElementList: esta classe representa uma lista com qualquer tipo de elemento
existente no modelo. Para incluir determinado elemento nesta lista, o mesmo deve
implementar a interface ICDElementVisitable.
3.2.2.3 Diagrama de classe do editor de diagrama N-S
A Figura 22 apresenta na forma de um diagrama de classes, as classes que representam
o modelo do editor de diagramas N-S.
50
Este conjunto de classes é o mapeamento das estruturas existentes nos diagramas N-S
para elementos do modelo, sendo:
a) NSDiagramCommand: esta classe é a representação do diagrama N-S, ou seja uma
lista de elementos possíveis em um diagrama N-S. Esta classe mantém uma lista de
comandos do diagrama. Basicamente, ao ser solicitada, faz com que o visitador
informado passe nela mesma e nos seus elementos filhos;
b) BaseElementsTokenizer: esta é uma classe base que é estendida por cada um dos
elementos presentes no modelo proposto para o diagrama N-S. Sua função é,
através de um analisador léxico, receber uma string e retornar uma lista de tokens
reconhecidos;
c) CommandList: é a representação no modelo de uma lista de comandos. Ela tem as
funcionalidades de adicionar e remover elementos e retornar uma lista com os
elementos contidos nela;
d) IfCommand: esta classe representa os comandos de decisão. Armazena uma
condição e duas listas de comandos, sendo uma a lista de comandos verdadeiros,
que devem ser executados caso a expressão da decisão seja verdadeira e a outra
lista caso a expressão seja falsa;
e) IfCommands: esta classe representa a lista de comandos verdadeiros de um
elemento de decisão;
f) ElseCommands: esta classe representa a lista de comandos falsos de um elemento
de decisão;
g) WhileCommand: é a classe que representa um comando de repetição. Armazena a
condição da repetição e a lista de comandos a ser repetido enquanto a expressão
seja verdadeira;
h) DoWhileCommand: representa um comando de repetição com a condição de
repetição sendo verificada no final do laço de repetição. Armazena a lista de
comandos a serem repetidos e a expressão de condição para a repetição;
i) ForCommand: representa um comando de repetição com número de repetições
definido. Armazena a lista de comandos a serem repetidos e a definição da
quantidade de repetições a ser executada;
j) CaseCommand: representa o comando de seleção. Armazena qual é o elemento a ser
comparado, e uma lista de opções possíveis;
51
k) CaseOptionList: esta classe representa a lista de opções possíveis para um
determinado comando de seleção. Tem as funcionalidades de adicionar e remover
opções na lista de opções possíveis;
l) CaseOption: esta classe representa uma das opções do comando de seleção. Ele
armazena o valor que o representa junto ao comando de seleção e sua lista de
comandos a serem executados;
m) NullCommand: esta classe representa um comando vazio, que é criado na lista de
comandos quando vazia e retirado ao incluir o primeiro elemento;
n) InstructionCommand: esta classe representa um comando de atribuição,
declaração de variável ou chamada de sub rotina.
Na Figura 23 são apresentadas algumas classes que fazem parte do editor de diagramas
N-S. As operações das classes foram omitidas para melhor visualização do diagrama. As
operações omitidas estão listadas no apêndice D.
52
Figura 23 - Diagrama de classe da manutenção do modelo e representação gráfica
Este conjunto de classes é responsável pela manutenção do modelo de dados e
produção da sua representação gráfica. São elas:
a) NSDiagramEditor: é a classe principal do editor de diagramas N-S,
responsável pelas inicializações necessárias para que o ambiente possa tratar a
edição deste tipo de diagrama;
b) LayoutCalculatorVisitor: esta classe é responsável por calcular o
posicionamento dos componentes visuais de cada um dos elementos presentes no
diagrama N-S;
c) LayoutAdjustCalculatorVisitor: esta classe ajuda no cálculo do
posicionamento dos componentes visuais;
53
d) NSDiagramHandler: é a classe responsável por fazer a persistência do modelo de
dados do diagrama N-S no formato XML, ler arquivos neste formato e transformar
no modelo de dados novamente, adicionar e remover elementos do modelo
(utilizando os devidos visitadores) e retornar lista de elementos filhos de
determinado elemento, também utilizando um visitador criado com este propósito;
e) ICommandVisitable: esta interface representa os elementos que podem fazer parte
do modelo proposto para representar o diagrama N-S;
f) ICommandVisitor: esta interface representa as classes que implementam alguma
funcionalidade sobre o modelo. Classes que pretendem visitar o modelo
independente da funcionalidade desejada devem implementar esta interface;
g) CommandAdder: esta classe é responsável por incluir elementos do modelo,
recebendo qual elemento deve ser incluído e qual o seu comando anterior. Com
esta informação ele percorre o modelo e insere o elemento após aquele informado
como anterior;
h) CommandRemover: esta classe é responsável por remover elementos do modelo;
i) NodeChildrenDiscover: esta classe é responsável por percorrer o modelo
procurando por um determinado comando e retornar uma lista com os comandos
internos do mesmo;
j) NSPartFactory: esta classe é responsável por receber solicitações do framework
gráfico e criar instâncias de classes controladoras para cada elemento do modelo;
k) NSDiagramEditParts: esta classe controla a relação entre um elemento do modelo
e sua representação gráfica. Cada elemento do modelo está relacionado a uma
instância desta classe;
l) NSXYLayoutEditPolicy: esta classe controla as requisições do framework gráfico,
fazendo o devido tratamento e criando instâncias de comandos a serem executados
posteriormente pelo framework gráfico;
m) NodeChildrenDiscover: esta classe é responsável por montar uma lista com os
elementos existentes dentro de algum elemento do modelo;
n) NSNodeCreateCommand: esta classe é a representação de um comando a ser
executado pelo framework gráfico. Ele é criado pela classe de controle de
requisições;
o) CaseFigure: esta classe trata a representação visual de um elemento de seleção;
54
p) DecisionFigure: esta classe trata a representação visual de um elemento de
decisão;
q) DoWhileFigure: esta classe cuida da representação visual do elemento de
repetição com a condição no final da lista de comandos;
r) ForFigure: esta classe trata a representação visual do elemento de repetição com
número de repetições definido;
s) GenericFigure: esta classe trata da representação visual de componentes
genéricos;
t) InstructionFigure: esta classe trata da representação visual de comandos
simples;
u) NodeFigure: classe base para todas as classes de representação visual. Tem a
funcionalidade de armazenar a referência para o editor ao qual este elemento está
associado. A partir desta referência do editor, requisitar do mapa de
posicionamento de componentes qual a posição e tamanho do componente visual;
v) NullFigure: classe pra representar visualmente o elemento NullCommand;
w) WhileFigure: esta classe cuida da representação visual dos elementos de repetição
do tipo WhileCommand.
3.2.2.4 Diagrama de classes do gerador de código
A Figura 24 apresenta na forma de um diagrama de classes das estruturas responsáveis
pela geração de código, as quais são:
a) CDCodeGenerationVisitor: esta classe é responsável pela geração de código no
modelo do diagrama de classes. Faz a inicialização do Velocity e começa o
processo de visitação dos elementos do modelo;
b) CDGenerationConstants: é uma classe apenas com constantes indicando qual o
template a ser utilizado por cada um dos elementos do modelo;
c) CDNSGenerationProvider: no momento da geração de código para o diagrama de
classe, esta classe é responsável por gerar o código referente ao diagrama N-S nos
elementos do tipo método, quando este possuir um diagrama N-S associado;
55
d) NSCodeGenerationVisitor: esta classe é responsável pela geração de código no
modelo do diagrama N-S. Ela faz a inicialização do Velocity e inicia o processo de
visitação dos elementos do modelo;
e) NSGenerationConstants: é uma classe apenas com constantes indicando qual o
template a ser utilizado por cada um dos elementos do modelo N-S;
f) NSTokenProcessorVisitor: esta classe é responsável por tratar os tokens
reconhecidos em cada um dos elementos do diagrama N-S.
Figura 24 – Diagrama de classe da geração de código
3.3 IMPLEMENTAÇÃO
A seguir são mostradas as técnicas e ferramentas utilizadas no desenvolvimento do
plugin e a utilização do mesmo.
56
3.3.1 Técnicas e ferramentas utilizadas
O Drawcode foi desenvolvido na linguagem Java, utilizando o ambiente de
desenvolvimento Eclipse. Para a geração do analisador léxico optou-se por utilizar o GALS,
uma ferramenta livre que provê esta funcionalidade.
Como motor de template é utilizado o Velocity, uma ferramenta de código aberto
escrita na linguagem Java.
Para fazer a persistência dos modelos foi utilizada a biblioteca XStream pelo seu alto
nível de abstração para converter objetos Java no formato XML e do formato XML para
objetos Java.
3.3.1.1 Entendendo o modelo criado
No projeto foi utilizado o padrão de projeto Visitor. Isso fez com que as classes criadas
para representar o modelo ficassem extremamente simples, contendo apenas os atributos
necessários para cada elemento, apresentando apenas as funcionalidades básicas para permitir
a visitação.
Um exemplo, é a classe IfCommand. Ela foi criada para representar um comando de
decisão da estrutura do diagrama N-S. Conta apenas com um atributo do tipo String para
armazenar a sua expressão lógica de condição, uma lista com os comandos se a expressão for
verdadeira, chamada de ifCommands e outra lista de comandos caso a expressão seja falsa,
chamada de elseCommands. O código completo dela pode ser visto no Quadro 5.
57
package org.henkels.drawcode.editors.nsdiagram; import java.util.List; public class IfCommand extends BaseElementsTokenizer implements ICommandVisitable { //expressão de condição para o comando if public String condition; //lista de comandos “verdadeiros” public IfCommands ifCommands = new IfCommands(); //lista de commandos “falsos” public ElseCommands elseCommands = new ElseCommands(); //construtor padrão public IfCommand() { super(); //inicialização da condição da decisão com texto genérico condition = "if condition"; } @Override public String toString() { //sobrescreve o método toString de Object pra retornar a condição return condition; } public void setValue(String newValue) { //setar o valor da condição da decisão this.condition = newValue; } @Override public boolean accept(ICommandVisitor visitor, Object ctx) { //faz com que o visitador passado visite este elemento if (!visitor.Visit(this, ctx)) { //visitador retornou que o processo de visitação deve ser parado pois o objetivo já foi atingido return false; } //se visitador retornou que processo de visitação deve continuar, manda visitar os elementos filhos verdadeiros e falsos, ifCommands e elseCommands respectivamente return ifCommands.accept(visitor, ctx) && elseCommands.accept(visitor, ctx); } @Override public void vlaccept(ICommandVisitor visitor, Object ctx) { //criado pra ser utilizado pelo velocity //mesma função do accept, apenas ignorando o retorno accept(visitor, ctx); } @Override public List<String> getTokenList() { //chama classe base (BaseElementsTokenizer) pra montar lista de tokens existentes na condição return super.getElementTokenList(condition); } }
Quadro 5 – Código completo da classe IfCommand
Para as operações necessárias foram criadas classes separadas, cada uma delas
incluindo uma nova funcionalidade ao modelo, como por exemplo, a classe CommandAdder,
58
cuja finalidade é incluir novos elementos no modelo. Esta classe é mais detalhada na próxima
subseção. Assim criaram-se dois papéis: as classes “visitáveis” que são os elementos do
modelo, sem funcionalidades específicas e as classes “visitadoras” que representam as
funcionalidades existentes sobre o modelo.
Foram definidas então duas interfaces para estes dois papéis. A interface
ICommandVisitable para as classes visitáveis, sendo que todos os elementos que fazem parte
do modelo têm que implementar esta interface para garantir que podem ser visitadas por
algum visitador que necessite visitar os elementos do modelo. Já a interface
ICommandVisitor foi criada para ser implementada pelas classes ditas “visitadoras”. O
conteúdo de ambas pode ser visto nos Quadro 6 e Quadro 7.
package org.henkels.drawcode.editors.nsdiagram; import java.util.List; public interface ICommandVisitable { //recebe um visitador e um contexto //como retorno indica se o visitador deve continuar visitando o modelo boolean accept(ICommandVisitor visitor, Object ctx); //usado pelo velocity, pois não pode ter retorno //internamente vai chamar accept e desconsiderar o retorno void vlaccept(ICommandVisitor visitor, Object ctx); void setValue(String newValue); //retornar uma lista de strings com os tokens presentes no comando List<String> getTokenList(); }
Quadro 6 – Conteúdo da interface ICommandVisitable
package org.henkels.drawcode.editors.nsdiagram; public interface ICommandVisitor { //visitadores necessitam saber visitar todos os elementos do modelo public boolean Visit(NSDiagramCommand command, Object ctx); public boolean Visit(NullCommand command, Object ctx); public boolean Visit(WhileCommand command, Object ctx); public boolean Visit(DoWhileCommand command, Object ctx); public boolean Visit(ForCommand command, Object ctx); public boolean Visit(InstructionCommand command, Object ctx); public boolean Visit(CaseCommand command, Object ctx); public boolean Visit(CaseOption command, Object ctx); public boolean Visit(IfCommand command, Object ctx); public boolean Visit(IfCommands command, Object ctx); public boolean Visit(ElseCommands command, Object ctx); }
Quadro 7 – Conteúdo da interface ICommandVisitor
59
3.3.1.2 Manutenção dos modelos de dados
Nesta subseção é apresentada a estratégia criada para a manutenção do modelo de
dados. O plugin conta com dois modelos. Um modelo que representa o diagrama de classes e
outro o diagrama N-S. Em seguida é apresentada a estratégia utilizada no diagrama N-S,
sendo que para o diagrama de classes foi utilizada a mesma estratégia, tendo como diferença
apenas os elementos existentes no modelo.
A classe NSDiagramHandler é responsável por controlar as alterações no modelo de
dados, assim a entidade que necessita fazer alterações, precisa fazer requisições a esta classe
para que o modelo seja alterado. Como o modelo é representado graficamente, as
necessidades de alteração do modelo são produzidas de maneira visual. A Figura 25 apresenta
na forma de um diagrama de seqüência de que maneira são geradas as necessidades de
alteração do modelo.
60
Figura 25 – Diagrama de seqüência da inclusão de um elemento no diagrama N-S
A Figura 25 ajuda a demonstrar como são criadas as necessidades de alteração no
modelo de dados. No momento que é solicitado ao editor (NSDiagramEditor), além de
informar qual o novo elemento que está sendo inserido, é passado também como parâmetro o
elemento do modelo que o usuário clicou. Esta informação é importante, pois indica o ponto
que o novo elemento deve ser inserido. Desta maneira a classe criada como visitador de
inserção tem as informações necessárias para iniciar o processo de inclusão do novo elemento
61
no modelo.
Como apresentado anteriormente, quem implementa esta funcionalidade é a classe
CommandAdder. Esta classe acrescenta a funcionalidade de inserir elementos no modelo, e
para fazer isto, ela espera receber como parâmetro além do novo elemento, um elemento que
já exista no modelo. Esta informação é necessária por que esta classe vai procurar por este
elemento no modelo e incluir o novo elemento imediatamente após o já existente.
Esta classe por se caracterizar como sendo um visitador, ela implementa a interface
ICommandVisitor, que em outras palavras indica que a mesma conhece as particularidades de
cada um dos elementos do modelo, e assim sabe como incluir um novo elemento em cada um
deles.
No momento que a classe NSDiagramEditor é inicializada, ela cria internamente uma
instância da classe NSDiagramHandler, que vai controlar suas necessidades junto ao modelo.
Já a classe NSDiagramHandler por sua vez quando é inicializada, cria internamente instâncias
das classe CommandAdder e CommandRemover, que serão usadas respectivamente pra inserir e
pra remover itens. No Quadro 8 são apresentadas algumas partes da classe
NSDiagramHandler. Esta seqüência de ativação é mostrada na Figura 26.
Figura 26 – Seqüência de inicialização da classe NSDiagramEditor
62
package org.henkels.drawcode.editors.nsdiagram; .... public class NSDiagramHandler { //visitador de inserção private CommandAdder commandAdder = new CommandAdder(); //visitador de remoção private CommandRemover commandRemover = new CommandRemover(); //elemento inicial do modelo (lista de comandos inicial) public NSDiagramCommand root = new NSDiagramCommand(); //edit part principal public NSDiagramEditParts rooteditpart = null; //construtor padrao public NSDiagramHandler() { super(); ICommandVisitable nullcmd = new NullCommand(); insertCommand(nullcmd, root.getRootCommand()); } //inserir elemento public void insertCommand(ICommandVisitable node, ICommandVisitable previousBrother) { root.accept(commandAdder, new CommandAdder.AddContext(previousBrother, node)); } //remover elemento public void RemoveCommand(ICommandVisitable killedNode) { root.accept(commandRemover, new CommandRemover.RemoveContext(killedNode)); } //retornar lista de elementos filhos public List<ICommandVisitable> getChildrens(ICommandVisitable node) { List<ICommandVisitable> ret = new ArrayList<ICommandVisitable>(); new NodeChildrenDiscover().fillList(ret, node); return ret; } ..... }
Quadro 8 – Parte da classe NSDiagramHandler
No momento que a função insertCommand é chamada uma instância da classe
AddContext é criada. Seu objetivo é encapsular o elemento a ser inserido e o elemento já
existente no modelo, chamado de “irmão anterior”. Depois de criada a instância desta classe, é
iniciado o processo de visitação chamando o método accept no elemento inicial do modelo,
neste caso o atributo root, instância de NSDiagramCommand.
A Figura 27 apresenta um diagrama de atividades cujo objetivo é ajudar a demonstrar
como ocorre o processo de inserção de novos elementos. Enquanto o elemento irmão não tiver
sido encontrado e o novo elemento não tiver sido adicionado imediatamente ao seu lado, o
63
processo de visitação continua enquanto existirem elementos a serem visitados.
Figura 27 – Diagrama de atividades do processo de inserção de elementos no modelo
3.3.1.3 Representação gráfica do diagrama N-S
Esta subseção apresenta como é montada a representação visual do modelo. Uma das
partes mais importantes do Drawcode é sua interface gráfica. Isto por que a literatura
apresenta que um dos principais problemas dos diagramas N-S é sua representação visual. Ao
incluir, excluir, ou até mesmo alterar os elementos existentes, a sua representação precisa ser
redesenhada para que comporte os elementos internos de cada um dos elementos presentes no
diagrama.
Assim, o plugin deve conter mecanismos que possibilitem essa manutenção de maneira
totalmente automática, eliminando este problema dos diagramas N-S. Diante disto foi criado
um mecanismo que trata sua representação visual.
Para desenvolver tal mecanismo deve ser estudado cada um dos elementos existentes
no diagrama N-S, verificando as características de cada um deles. Externamente todos os
elementos são um retângulo, com particulares para cada um dos elementos na sua parte
interna. As particularidades encontradas são apresentadas a seguir.
Instrução é o elemento que representa uma atribuição ou a chamada de uma sub-rotina.
Suas dimensões (altura e largura) são definidas apenas pelo texto que o usuário definir. A
Figura 28 apresenta um exemplo.
64
Figura 28 – Exemplo de representação gráfica de uma instrução simples
Comando de decisão é o elemento que representa as estruturas de decisão criadas pelo
usuário. Ela apresenta o texto da sua condição e duas listas de comandos, sendo a lista de
comandos verdadeiros e a lista de comandos falsos. Seu tamanho depende do tamanho de seu
texto de condição e do tamanho de sua lista de comandos verdadeiros e falsos
respectivamente. Sua lista de comandos verdadeiros é posicionada abaixo da condição do lado
esquerdo. A lista de comandos falsos é posicionada ao lado da lista de comandos verdadeiros.
Todos os comandos que existirem dentro da sua lista de comandos verdadeiros, independente
de comando, serão posicionados verticalmente a partir do início da lista um abaixo do outro.
Os comandos da lista de comandos falsos também serão posicionados desta maneira. A Figura
29 apresenta um exemplo de um comando de decisão.
Figura 29 – Exemplo de representação gráfica de uma instrução de decisão
Comando de repetição “for” é o elemento que representa os comandos do tipo
repetição com um número de iterações definido. Apresenta um texto indicando sua condição e
uma lista de comandos. Seu tamanho é definido pelo texto da condição e o tamanho da lista
de comandos. Os comandos presentes na sua lista de comandos serão posicionados
horizontalmente, um abaixo do outro. A Figura 30 apresenta um exemplo de um comando de
repetição do tipo “for”.
Figura 30 – Exemplo de representação gráfica de uma instrução “for”
Os comandos de repetição dos tipos “while” e “repeat-until” têm representação
65
parecida com a do comando de repetição “for”. Também apresentam uma condição e uma
lista de comandos que é posicionada verticalmente, com comandos um abaixo do outro. Um
exemplo de representação de comando de repetição “while” pode ser visto na Figura 31.
Figura 31 – Exemplo de representação gráfica de uma instrução “while”
Um exemplo de representação de comando de repetição “repeat-until” pode ser visto
na Figura 32.
Figura 32 – Exemplo de representação gráfica de uma instrução “repeat-until”
Comando de seleção é o elemento que representa as estruturas de seleção criadas pelo
usuário. Ela apresenta o texto da sua condição de seleção e uma ou várias opções, cada uma
contendo uma lista de comandos. Seu tamanho depende do tamanho de seu texto de condição
de seleção, do tamanho das suas listas de comandos de cada uma de suas opções. As opções
são posicionadas abaixo da condição de seleção, horizontalmente uma ao lado da outra,
iniciando do lado esquerdo. Todos os comandos que existirem dentro da lista de comandos de
cada opção, independente do comando, são posicionados verticalmente a partir do início de
sua respectiva lista, um abaixo do outro. Um exemplo de representação de um comando de
seleção é apresentado na Figura 33.
Figura 33 – Exemplo de representação gráfica de uma instrução de seleção
O diagrama é a lista principal de comandos existentes. É formado por uma lista de
comandos posicionados verticalmente um abaixo do outro. Seu tamanho é definido pelo
tamanho dos elementos existente na sua lista de comandos. Um exemplo de representação de
66
um diagrama é apresentado na Figura 34.
Figura 34 – Exemplo de representação gráfica de um diagrama N-S e sua lista de comandos
Verificadas as particularidades gráficas de cada um dos elementos, conclui-se que o
diagrama é formado basicamente por listas de comandos. Algumas posicionadas de maneira
vertical com comandos um abaixo do outro e listas de comandos horizontais com comandos
um ao lado do outro. Além disso, independente da orientação horizontal ou vertical, a
dimensão delas é definida pelo tamanho de todos os elementos existentes nestas listas
internas.
As informações de tamanho dos elementos dependem de cada um dos elementos
presentes nestas listas de comandos, assim não é necessário armazenar informações de
tamanho no modelo que armazena o diagrama. Isso por que estas informações mudam
constantemente, sendo recalculadas a cada interação do usuário que resulte em alterações no
modelo.
Ao abrir um diagrama, ou depois de cada interação do usuário, a representação gráfica
é atualizada. Isso acontece da seguinte maneira: a classe NSDiagramHandler tem uma
referência para o primeiro elemento visual criado pela GEF. Todos os demais elementos
visuais criados são considerados pela GEF como filhos deste elemento. Depois de qualquer
alteração no modelo é mandada uma mensagem para o primeiro elemento visual para que o
mesmo apague todos os seus elementos filhos. Isso apaga a representação desatualizada. A
GEF percebe que houve alguma alteração visual e solicita novamente os filhos do elemento
principal e seus filhos respectivamente, até que não existam mais filhos. No momento que
cada novo elemento é desenhado, este solicita à classe NSDiagramEditor qual deve ser a sua
67
posição na tela. Esta classe mantém um mapa com a posição de cada elemento do modelo.
Sempre que a posição de um elemento for solicitada e a mesma não se encontrar no modelo, o
mapa é apagado e é feita uma solicitação ao visitador que calcula a posição novamente de
todos os elementos do modelo. O diagrama de seqüência apresentado na Figura 35 representa
todo este processo.
Figura 35 – Diagrama de seqüência do processo de atualização gráfica do modelo
Sempre que a posição de um elemento é necessária, a classe NSDiagramEditor é
solicitada através do método getNodeRect. Se a posição deste elemento é encontrada no
mapa de posições, este é retornado, se não o mapa é totalmente limpo. Então é instanciado
LayoutCalculatorVisitor e iniciada a visitação no elemento inicial do modelo. O código
deste método é apresentado no Quadro 9.
68
public Rectangle getNodeRect(ICommandVisitable node) { //se o mapa de posiçoes estiver vazio if (rectmap == null) { //instancia visitor e inicia visitacao no elemento principal rectmap = new LayoutCalculatorVisitor().getLayout(nsDiagram.root); } //pega posicao do elemento no mapa Rectangle ret = rectmap.get(node); if (ret == null) { // se nao encontrou o elemento no mapa de posicoes recalcula tudo rectmap = new LayoutCalculatorVisitor().getLayout(nsDiagram.root); //pega posicao do elemento no mapa ret = rectmap.get(node); } //retorna posicao do elemento return ret; }
Quadro 9 – Método responsável por retornar a posição do elemento
Para calcular a posição de cada um dos elementos foi criada uma classe
LayoutCalculatorVisitor do tipo visitador que tem como objetivo visitar o modelo inteiro,
atualizando um mapa com as posições de cada elemento. Basicamente o que este visitador faz
é, para cada elemento, calcular a posição e tamanho deste elemento e gravar no mapa de
posições.
Para calcular a posição e tamanho ele precisa saber o tamanho de seus elementos
internos, que por sua vez precisam ter definido o tamanho de seus elementos internos, até o
momento que a lista tenha apenas comandos simples, onde o tamanho não depende de
elementos internos, mas apenas do tamanho do texto definido para este comando. No
momento que é definido o tamanho de determinado elemento, o que precisava de seu tamanho
já o tem. Assim é feito recursivamente até o momento que todos os elementos já têm tamanho
e posição definidos. A Figura 36 apresenta um diagrama de atividades representando este
processo.
69
Figura 36 – Diagrama de atividades do processo de cálculo dos elementos visuais
3.3.1.4 Geração de código
Esta subseção apresenta a estratégia utilizada para gerar código. Como apresentado
anteriormente o Drawcode está divido em dois modelos, sendo um representando o diagrama
de classes e outro o diagrama N-S. Desta maneira a geração de código também foi criada
separada. A classe CDCodeGenerationVisitor é um visitador responsável por gerar código
para o diagrama de classes e a classe NSCodeGenerationVisitor outro visitador responsável
por gerar código para o diagrama N-S.
O processo de geração de código é formado por três artefatos de software, sendo eles:
o motor de templates, a classe responsável por instanciar e inicializar o motor e o modelo de
dados do diagrama com os elementos que o usuário inseriu.
O diagrama de seqüência da Figura 37 apresenta o processo de geração de código.
70
Figura 37 – Seqüência para a geração de código do diagrama N-S
A geração de código para o diagrama de classes tem a mesma seqüência que o
diagrama N-S, porém, no momento que é encontrado no modelo um elemento do tipo método
e seu atributo methodElement é diferente de vazio, é criada uma instância da classe
CDNSGenerationProvider. Isto indica que o método tem um diagrama N-S associado, então
esta classe vai ser responsável por gerar o código deste diagrama, instanciando o visitador que
gera código N-S. A Figura 38 apresenta um diagrama de seqüência da geração de código para
o diagrama de classe.
71
Figura 38 – Seqüência de geração de código para o diagrama de classe
Como apresentado na Figura 37 e na Figura 38, para gerar o código, a classe
responsável instancia o Velocity, carrega o template para aquele elemento, seta os valores do
contexto e comanda que o Velocity faça o processamento do template. Cada elemento do
modelo do diagrama de classe e N-S tem seu próprio arquivo de template. Estes arquivos é
que determinam qual o código a ser gerado para cada um dos elementos.
O Quadro 10 apresenta um exemplo de template para o elemento de decisão criado
para gerar código na linguagem Java. Os identificadores precedidos pelo caractere “$” são
variáveis de contexto para o Velocity. Através destas variáveis que cada um dos elementos do
modelo de dados do diagrama é inserido no contexto do Velocity. No momento do
processamento deste arquivo e contexto, estas variáveis serão substituídas e tratadas.
##template para geração de código java do elemento de decisão if ($command.vlaccept($tokentranslator,$ctx)) { $ifchild.vlaccept($this,$ctx) } else { $elsechild.vlaccept($this,$ctx) }
Quadro 10 – Template escrito na VTL para elemento de decisão gerando código Java
72
Na Figura 39 é apresentado o mesmo template do Quadro 10 com algumas anotações
para ajudar no entendimento.
Figura 39 – Exemplo de template VTL de decisão com anotações
Antes de requisitar o processamento do template, o visitador coloca no contexto do
Velocity cada uma das variáveis definidas no arquivo de template. No exemplo da Figura 39
são: $command, $tokenTranslator, $ctx, $ifchild, $elsechild. No momento que o
Velocity processar o template, serão chamados os métodos destas variáveis, nesta ordem:
a) $command.vlaccept($tokentranslator, $ctx): processa o conteúdo da
expressão definida pelo usuário;
b) $ifchild.vlaccept($this,$ctx): processa a lista de comandos verdadeiros da
decisão, gerando código para todos os elementos desta lista;
c) $elsechild.vlaccept($this,$ctx): processa a lista de comandos falsos da
decisão, gerando código para todos os elementos desta lista.
O resultado do processamento do template do elemento de decisão pelo Velocity é
apresentado no Quadro 11.
if ( <resultado do processamento do item a>) { <resultado do processamento do item b> } else { <resultado do processamento do item c> }
Quadro 11 - Esquema representando o resultado do processamento de um elemento de decisão
Quando é solicitado que o visitador visite um elemento do diagrama N-S, dependendo
do tipo de elemento, dois métodos podem ser chamados para tratar a visitação:
processChilds ou processSingleCommand. A implementação de ambos pode ser vista no
Quadro 12 e no Quadro 13.
73
private boolean processChilds(ICommandVisitable command, List<ICommandVisitable> list, Object ctx, String templateFile) { //buffer é utilizado pelo velocity pra gerar a saida BufferedWriter buffer = (BufferedWriter) ctx; //novo contexto do velocity VelocityContext vlctx = new VelocityContext(); //responsavel por fazer a analise lexica no conteudo do comando e gerar a saida processando a tabela de mapeamento NSTokenProcessorVisitor tokenVisitor = new NSTokenProcessorVisitor(); //colocar tradutor de tokens no contexto do velocity vlctx.put("tokentranslator", tokenVisitor); //elemento a ser processado vlctx.put("command", command); // ifCommand eh diferente pois sempre vai ter if e else sides. if (command instanceof IfCommand) { vlctx.put("ifchild", list.get(0)); vlctx.put("elsechild", list.get(1)); } else { //demais elementos do N-S vlctx.put("childs", list); } //colocar no contexto a instancia do visitador pro velocity utilizar nos filhos vlctx.put("this", this); //colocar no contexto do velocity o contexto do visitador vlctx.put("ctx", ctx); try { //iniciar arquivo de template (cada elemento possui o seu) Template template = Velocity.getTemplate(templateFile); //mandar Velocity processar template template.merge(vlctx, buffer); //parar visitacao neste nivel pois elemento já foi "processado" return false; } catch (Exception e) { e.printStackTrace(); return false; } }
Quadro 12 – Implementação do método processChilds
74
private boolean processSingleCommand(ICommandVisitable command, Object ctx) { //processar o comando simples, este não tem "filhos" BufferedWriter buffer = (BufferedWriter) ctx; //novo contexto VelocityContext vlctx = new VelocityContext(); //processador de tradução NSTokenProcessorVisitor tokenVisitor = new NSTokenProcessorVisitor(); //colocar no contexto do velocity vlctx.put("tokentranslator", tokenVisitor); vlctx.put("command", command); vlctx.put("ctx", ctx); try { //iniciar arquivo de template para o elemento de instrucao //(não tem filhos) Template template = Velocity.getTemplate(NSGenerationConstants.SINGLECOMMANDVM); //processar template template.merge(vlctx, buffer); //retornar return false; } catch (Exception e) { e.printStackTrace(); return false; } }
Quadro 13 – Implementação do método processSingleCommand
O resultado do processo de geração de código pode ser afetado por três elementos:
a) texto inserido pelo usuário: é o texto que o usuário do plugin inseriu nos elementos
dos diagramas de classe e N-S. Pode ser o texto da condição de um comando de
decisão, o texto de um comando simples ou ainda o texto de um elemento do tipo
método no diagrama de classes;
b) templates para os elementos dos diagramas: são os arquivos de template criados
para representar cada um dos elementos dos diagramas de classe e N-S. Um
exemplo deste tipo de template é apresentado na Figura 39. Os templates criados
para os elementos dos diagramas de classe e N-S são apresentados nos apêndices A
e B;
c) templates com as tabelas de tradução: são os arquivos de template criados para
representar uma tabela de tradução. Os templates criados para as tabelas de
tradução são apresentados no apêndice C.
A tabela de tradução dá maior flexibilidade à utilização do plugin, pois permite ao
usuário definir uma tabela de palavras a serem substituídas. Se o gerador de código encontrar
75
uma determinada palavra em um elemento do diagrama, ela é substituída por outra palavra no
código gerado. Esta tabela de tradução é determinada através de um arquivo de template onde
apresenta a palavra a ser pesquisada e a palavra resultante. Um exemplo deste tipo de
template para mapear uma tabela de tradução pode ser visto no Quadro 14.
## Table mapping for conditions to JAVA #foreach($token in $tokens)# ##se encontrar ‘<>’ subtitui por ‘!=’ if($token.toUpperCase() == "<>")!= ##se encontrar ‘=’ subtitui por ‘==’ {elseif}($token.toUpperCase() == "=")== ##se encontrar ‘E’ subtitui por ‘&&’ {elseif}($token.toUpperCase() == "E")&& ##se encontrar ‘OU’ subtitui por ‘||’ {elseif}($token.toUpperCase() == "OU")|| ##palavra não encontrada, o resultado é a própria palavra {else}$token end #end
Quadro 14 – Template criado com a tabela de tradução para a condição dos elementos
Para possibilitar este mapeamento, a entrada definida pelo usuário passa por um
analisador léxico, que transforma uma String em uma lista de tokens. Por exemplo, se o
usuário inseriu no diagrama um elemento de decisão e na condição deste elemento ele inseriu
a seguinte String “a = b”, no momento que o Velocity processar esse elemento, esta String
vai passar pelo analisador léxico que vai retornar uma lista de tokens, neste caso “a”, “=” e
“b”. Esta lista é coloca no contexto do Velocity juntamente com o arquivo de template
apresentado no Quadro 14. Assim, a condição definida no elemento pelo usuário como “a =
b”, vai ser gerada na saída como “a == b”.
Existem ferramentas que são capazes de gerar um analisador léxico a partir de uma
definição regular. Uma destas ferramentas é o Gerador de Analisadores Léxicos e Sintáticos,
ou simplesmente GALS (SOURCEFORGE, 2007). Assim, foi criada uma definição regular
na ferramenta e a definição de tokens. A partir delas foi gerado código na linguagem Java que
correspondem às classes: AnalysisError, Constants, LexicalError, Lexico,
ScannerConstants, Token. Estas classes são utilizadas pela classe
BaseElementsTokenizer, para fazer a transformação de uma String em uma lista de tokens.
No Quadro 14 podem ser vistas as definições regulares criadas e no Quadro 15 a definição
dos tokens.
76
letra: [a-zA-Z] dígito: [0-9] caractere: [^\r\n'\\] caracteres: [^!\*] expoente: (E | e) (\+ | \-)? {dígito}+ decimal: "." {dígito}+ {expoente} | {expoente} | "." {dígito}+
Quadro 15 – Definições regulares criadas na ferramenta GALS
//ignorar :[\s\r\n\t] identificador: {letra} ( _ ({letra} | {dígito}) | {dígito} | {letra})* _? cte_inteira: {dígito}+ cte_real: {dígito}+ {decimal} cte_literal: \34 {caractere}* ( \\ \r\n (\s | \t)* \\ {caractere}*)* \34 //símbolos especiais ";" ":" "," "[" "]" "=" "." "(" ")" "+" "-" "*" "/" "<>" "<" "<=" ">" ">=" "%"
Quadro 16 – Definições de tokens criados na ferramenta GALS
3.3.2 Operacionalidade da implementação
O trabalho desenvolvido é um plugin para o ambiente Eclipse, então o primeiro passo
para sua utilização é entrar no ambiente de desenvolvimento. No momento que o usuário
inicia o ambiente, o mesmo solicita qual a pasta de trabalho a ser utilizada. A Figura 40
apresenta a tela que o ambiente apresenta solicitando a pasta de trabalho ou simplesmente
workspace.
77
Figura 40 – Iniciando o ambiente Eclipse: definir pasta de trabalho
Depois de iniciado o ambiente, é possível verificar se o plugin Drawcode está
instalado. Para isto, no menu principal deve-se clicar em Help>About Eclipse SDK. Será
aberta uma tela com informações sobre a versão do ambiente. Ao clicar no botão Plugin-
Details é apresentada uma tela contendo informações sobre todos os plugins instalados no
ambiente. A Figura 41 apresenta esta tela, destacando o plugin Drawcode.
Figura 41 – Informações sobre os plugins instalados no ambiente
A tela principal do ambiente apresenta as informações sobre a pasta de trabalho
escolhida, sendo todos os elementos do projeto armazenados nesta pasta. Na Figura 42 é
apresentada à tela principal do ambiente. Neste exemplo, o usuário criou um projeto chamado
projeto_drawcode_01 na pasta de trabalho. Dentro deste projeto o usuário criou um
diagrama de classes chamado diagrama_classe.drcd e dois diagramas N-S, nomeados
como metodo1.nsd e metodo2.nsd.
78
Figura 42 – Tela principal do ambiente Eclipse
Para editar o diagrama de classes, basta executar um duplo clique sobre o diagrama a
ser editado. Ao editá-lo, o ambiente abre uma nova janela para editar o diagrama e
disponibiliza uma paleta com os componentes possíveis para o diagrama de classes.
A Figura 43 apresenta um diagrama de classes em edição, onde foi definida a classe
Aluno com os atributos nota1, nota2, nota3 e o método getSituacao. Para incluir uma
classe, o usuário deve clicar na paleta sobre o elemento Class e clicar em alguma parte do
diagrama. Uma nova classe vai ser criada. Para incluir um novo atributo, deve-se clicar sobre
o botão Attribute na paleta e clicar dentro da área de Attributes da classe. Para incluir um
novo método, clicar sobre o botão Method e clicar dentro da área de Methods da classe.
79
Figura 43 – Edição do diagrama de classe: incluindo uma classe com atributos e métodos
Para editar o diagrama N-S, basta executar um duplo clique sobre o diagrama a ser
editado. Ao editá-lo o ambiente abre uma nova janela para editar o diagrama e disponibiliza
uma paleta com os componentes possíveis para o diagrama N-S.
A Figura 44 apresenta um diagrama N-S em edição, onde foi desenvolvido um
algoritmo que soma três notas e faz a divisão por três chegando à média. Se a média
encontrada for maior ou igual a seis, o algoritmo retorna a String “aprovado”. Caso contrário
vai retornar a String “reprovado”. Para incluir uma instrução, o usuário deve clicar na paleta
sobre o elemento Instruction e clicar em algum elemento no diagrama. Uma nova instrução
é criada abaixo do elemento selecionado. Para incluir mais uma instrução, basta repetir este
processo. Para incluir um elemento de decisão, deve-se clicar sobre o botão Decision na
paleta e clicar num dos comandos já existentes no diagrama. A instrução será criada abaixo do
elemento clicado.
80
Figura 44 – Edição do diagrama N-S: definindo o algoritmo
Para fazer a associação entre o método existente na classe e o algoritmo definido no
diagrama N-S, é preciso editar o diagrama de classes e dar um duplo clique sobre o método. A
Figura 45 apresenta um exemplo deste processo de associação. O ambiente então vai
apresentar uma tela solicitando um arquivo com a extensão “nsd”. Depois de selecionar o
arquivo e confirmar, a associação estará realizada.
81
Figura 45 – Associar um algoritmo representado por diagrama N-S para o método da classe
Depois de criada a classe e definido o algoritmo para atender o propósito do método, é
possível então gerar o código para o diagrama de classes. Este vai contemplar o corpo da
classe e o corpo dos métodos que tiverem um diagrama N-S associado. Para gerar o código
então é necessário no editor do diagrama de classes, clicar com o botão direito e selecionar a
opção Generate from Class Diagram. O ambiente então vai solicitar que seja definido um
arquivo. Neste arquivo serão geradas as classes definidas no diagrama.
O Quadro 17 apresenta o resultado da geração de código do diagrama de classes,
usando o DrawCode. Ele apresenta a classe Aluno, os atributos nota1, nota2, nota3 e o
método getSituacao(), para o qual também foi gerado o código na linguagem Java para o
algoritmo definido no diagrama N-S, que soma as três notas do aluno, calcula a média e
retorna a String “aprovado” se a média for maior ou igual a seis e “reprovado” se a média for
menor que seis.
O ambiente Eclipse possui um mecanismo para identação automática do código. Este
recurso foi utilizado no código gerado para melhorar sua legibilidade. Nenhum tipo de
alteração no conteúdo do código foi realizado.
82
//código gerado automaticamente pelo drawcode public class Aluno { int nota1 = 0; int nota2 = 0; int nota3 = 0; public String getSituacao() { // Corpo de metodo gerado automaticamento pelo drawcode int soma = nota1; soma = soma + nota2; soma = soma + nota3; int media = soma / 3; if (media >= 6) { return ("aprovado"); } else { return ("reprovado"); } } }
Quadro 17 – Resultado da geração de código a partir do diagrama de classe
3.4 RESULTADOS E DISCUSSÃO
Os resultados obtidos com o desenvolvimento deste projeto estão relacionados ao
tempo de desenvolvimento do software, complexidade para seu desenvolvimento e abstração
de linguagem de programação utilizada para criação. Também o aumento da abrangência de
código gerado por um gerador de código, afinal o corpo do método da classe também é
gerado.
Durante a revisão bibliográfica sobre os termos relacionados ao trabalho, foram
pesquisadas ferramentas para edição de diagramas de classe assim como para edição de
diagramas N-S. As ferramentas pesquisadas apresentam os diagramas N-S e de classe em
contextos diferentes. No Quadro 18 é apresentado um comparativo entre o Drawcode e os
trabalhos correlatos pesquisados.
83
Jupe
Top
case
d
NS
DE
dito
r
Str
ucto
rize
r
Dra
wco
de
Permite associar algum tipo de diagrama (para o corpo do método) com o diagrama de classe X
Diagrama classe X X X
Permite a edição de outros diagramas da UML X
Diagrama N-S X X X
Gera algum tipo de código X X X X
Permite incluir nova linguagem para geração de código X Quadro 18 – Comparativo entre Drawcode e seus correlatos
O principal diferencial do Drawcode entre seus correlatos é a de possibilitar o que
Souza (2000, p. 42) afirma ser possível.
“A Resolução Orientada a Objetos pode fazer uso da metodologia Resolução Estruturada para especificação dos métodos da classe, visto que aquela não apresenta técnica específica para elaboração dos algoritmos que os formam” (SOUZA 2000, p. 42).
Além de trazer essa possibilidade ao ambiente de desenvolvimento de software, outro
diferencial é utilizar um motor de template para a geração de código. Isso permite ao usuário
definir qual a linguagem que o código deve ser gerado, dando flexibilidade na sua utilização.
Os editores de diagramas de classe apenas geram o código para o corpo da classe, seus
atributos e operações mais simples como ler e escrever os valores dos atributos. Já os editores
de diagramas N-S por sua vez fazem a representação do algoritmo e geram o código para o
algoritmo, porém sem estarem contextualizados dentro de uma classe de objetos. O plugin
relaciona estas formas de representação do problema, cada uma contribuindo da melhor
maneira possível para a representação e resolução do problema.
O Drawcode apresenta algumas limitações. Uma delas é no editor de diagrama de
classes. No diagrama de classes serão editados apenas o nome da classe, os atributos e
métodos, não sendo tratados as demais representações deste tipo de diagrama como
associações, agregação, herança, entre outros.
Outra limitação é que o editor do diagrama N-S não possibilita a mudança de posição
de um elemento. Depois que um elemento é colocado no diagrama, não é possível alterar sua
posição. Alterar a ordem de dois comandos, por exemplo, exige que seja excluído e criado
novamente um dos dois comandos.
Outra limitação é quanto à edição do diagrama N-S. Não há nada que ajude o usuário a
consultar quais os atributos existentes na classe, ou ainda quais são os parâmetros recebidos
pelo método. Isso dificulta a criação do algoritmo, exigindo que o usuário conheça todos os
84
atributos ou parâmetros presentes no contexto do método. Os símbolos de paralelismo e bloco
de comandos não foram implementados.
Outra limitação que pode ser citada também é que o Drawcode não faz a validação das
expressões criadas pelo usuário nos elementos do diagrama de classes ou N-S. Se o usuário
criar um comando contendo uma expressão lógica com problema, o mesmo vai ser gerado da
mesma maneira, resultando em erro no momento da compilação do código gerado. Isso
decorre da não existência de formalismos na definição da linguagem interna dos comandos de
um Diagrama N-S.
85
4 CONCLUSÕES
O objetivo deste trabalho era criar uma ferramenta gráfica integrada ao ambiente de
desenvolvimento Eclipse que permitisse criar diagramas de classe e N-S. Depois de criados
estes diagramas permitir ao usuário associar um diagrama N-S para os métodos de uma classe
e a partir desta associação gerar o código completo para uma classe, contemplando o corpo da
classe, atributos, métodos e corpos dos métodos naqueles que apresentam um diagrama N-S
associado. Outro objetivo ainda era que fosse gerado código para a linguagem Java, com a
utilização de um motor de templates que permitiria ao usuário gerar código para outras
linguagens, bastando apenas alterar os templates criados.
Todos os objetivos foram alcançados, pois o Drawcode provê todas estas
funcionalidades. Embora não tivesse sido constatada a necessidade de uma tabela de tradução
nos objetivos iniciais, durante o desenvolvimento do projeto, optou-se por dar esta
possibilidade ao usuário, para aumentar a capacidade de utilização do mesmo. Para permitir
esta tabela de tradução, foi utilizada a ferramenta GALS para gerar um analisador léxico que
trata as entradas do usuário nos elementos do diagrama e gera uma lista de tokens,
possibilitando esta tradução.
Durante o desenvolvimento a escolha do padrão de projeto Visitor mostrou-se uma
escolha acertada, diminuindo a complexidade das operações necessárias sobre o modelo e
dando flexibilidade ao projeto, principalmente nas operações de montar a representação visual
do modelo e gerar código. Como as operações realizadas sobre o modelo são escritas em
classes separadas, novas operações podem ser adicionadas sem necessidade de alterações no
modelo. Se fosse necessária uma nova representação dos diagramas em outro framework
gráfico ou a utilização de outro motor de template, isto seria possível sem alterações no
modelo, sendo necessário apenas escrever um novo visitador que adicionaria esta
funcionalidade.
A utilização do Velocity como motor de templates cumpriu todas as necessidades do
projeto, apresentando simplicidade na linguagem usada para escrever os templates e
facilidade de acoplamento com a linguagem Java utilizada pelo Drawcode.
O ambiente Eclipse mostrou-se uma ferramenta muito adequada para o projeto. Sua
estrutura de funcionamento através de plugins o torna altamente extensível, dando
flexibilidade para que desenvolvedores que não fazem parte do projeto incluam novas
funcionalidades ao ambiente, como é o caso do Drawcode. Documentação completa e
86
exemplos facilitaram a criação do projeto. A criação deste plugin ainda oferece a
oportunidade de utilizá-lo em conjunto com outros plugins que contemplam outras fases do
desenvolvimento de software, como a fase de testes, por exemplo.
Como contribuições deste trabalho, destaca-se que o Drawcode vai possibilitar aos
desenvolvedores desenhar soluções Orientadas a Objeto e criar um algoritmo para representar
o que determinado método de uma classe deve fazer para atender os objetivos da mesma,
preenchendo uma lacuna existente nos diagramas da UML, que não apresenta nenhum de seus
diagramas com estas características.
Também, os professores que lecionam para as primeiras fases dos cursos de
computação podem utilizar o Drawcode para incentivar seus alunos a desenharem soluções
Orientadas a Objeto, porém dando a oportunidade de criar algoritmos utilizando a formalidade
do diagrama N-S para os métodos das classes.
Em ambos os casos citados, a geração de código vai permitir que os usuários do
Drawcode preocupem-se apenas com a definição da solução, abstraindo a linguagem de
programação a ser utilizada.
4.1 EXTENSÕES
Algumas sugestões de extensão para este trabalho são:
a) possibilitar na edição do diagrama N-S alterar a posição dos elementos do
diagrama;
b) incluir o recurso de complementação automática de código. Este recurso seria uma
combinação especial de teclas que ao pressioná-las apresente os comandos e ou
atributos existentes no contexto daquele elemento, no diagrama de classe e N-S;
c) possibilitar a geração de código de cada classe em arquivos separados;
d) definir e implementar uma linguagem e uma sintaxe a ser obedecida durante a
utilização do plugin, possibilitando validações sintáticas e semânticas sobre o
algoritmo criado, ou sobre a definição da classe;
e) implementar os demais elementos existentes no diagrama de classes, tais como,
associação, herança, multiplicidade, navegabilidade, entre outros;
f) possibilitar engenharia reversa, permitindo ler código fonte de programas já
existente e montar o diagrama de classes e o seus respectivos diagramas N-S;
88
REFERÊNCIAS BIBLIOGRÁFICAS
AHO, Alfred V.; SETHI, Ravi; ULLMAN, Jeffrey D. Compiladores, princípios, técnicas e ferramentas. Tradução Daniel de Ariosto Pinto. Rio de Janeiro: LTC, 1995.
APACHE SOFTWARE FOUNDATION. Velocity overview. [S.l.], 2007a. Disponível em: <http://velocity.apache.org/engine/devel/overview.html>. Acesso em: 15 nov. 2007.
_________________________________. VTL reference. [S.l.], 2007b. Disponível em: <http://velocity.apache.org/engine/devel/vtl-reference-guide.html>. Acesso em: 15 nov. 2007.
BARROS, Leliane Nunes de et al. Desenvolvendo plugins. [S.l.], 2003. Disponível em: <http://www.ime.usp.br/~articuno/eclipse/desenvolvendo_plugins.html>. Acesso em: 08 abr. 2007.
CARBONI, Irenice de Fátima. Lógica de programação. São Paulo: Pioneira Thomson Learning, 2003.
ECLIPSE FOUNDATION. What is Eclipse ? [S.l.], 2007a. Disponível em: <http://www.eclipse.org/>. Acesso em: 16 abr. 2007.
_____________________. Eclipse plugin central. [S.l.], 2007b. Disponível em: <http://www.eclipseplugincentral.com/>. Acesso em: 16 abr. 2007.
_____________________. About the eclipse foundation. [S.l.], 2007c. Disponível em: <http://www.eclipse.org/org/>. Acesso em: 08 nov. 2007.
_____________________. Help - Eclipse SDK. [S.l.], 2007d. Disponível em: <http://help.eclipse.org/help33/index.jsp>. Acesso em: 12 nov. 2007.
FOWLER, Martin. UML essencial: um breve guia para a linguagem-padrão de modelagem de objetos. 3. ed. Tradução João Tortello. Porto Alegre: Bookman, 2005.
HERRINGTON, Jack. Code generation in action. Greenwich: Manning, 2003.
JUPE. Jupe is a UML plugin for Eclipse. [S.l.], 2007a. Disponível em: <http://jupe.binaervarianz.de/>. Acesso em: 17 nov. 2007.
____. Documentation. [S.l.], 2007b. Disponível em: <http://jupe.binaervarianz.de/wiki/Documentation>. Acesso em: 17 nov. 2007.
KALT, Marcel. NSD-Editor. [S.l.], 1996. Disponível em: <http://diuf.unifr.ch/softeng/student-projects/completed/kalt/NSD.html>. Acesso em: 15 nov. 2007.
89
MARTIN, James; MCCLURE, Carma. Técnicas estruturadas e case. Tradução Lúcia Faria Silva. São Paulo: Makron, 1991.
MARTIN, James; ODELL, James J. Análise e projeto orientados a objetos. Tradução José Carlos Barbosa dos Santos. São Paulo: Makron Books, 1996.
NASSI, Isaac; SHNEIDERMAN, Ben. Flowchart techniques for structured programming. ACM SIGPLAN Notices, New York, v. 8, n. 8, p. 12-26, ago. 1973.
ORIENTAÇÃO A OBJETO. In: WIKIPÉDIA, a enciclopédia livre. [S.l.]: Wikimedia Foundation, 2007. Disponível em: <http://pt.wikipedia.org/wiki/Orientação_a_objeto>. Acesso em: 10 set. 2007.
PARADIGMA DE PROGRAMAÇÃO. In: WIKIPÉDIA, a enciclopédia livre. [S.l.]: Wikimedia Foundation, 2007. Disponível em: <http://pt.wikipedia.org/wiki/Paradigma_de_programação>. Acesso em: 11 set. 2007.
PILONE, Dan; PITMAN, Neil. UML 2 rápido e prático: guia de referência. Tradução Armando Figueiredo. Rio de Janeiro: Alta Books, 2006.
PLUGIN. In: WIKIPÉDIA, a enciclopédia livre. [S.l.]: Wikimedia Foundation, 2007. Disponível em: <http://pt.wikipedia.org/wiki/Plugin>. Acesso em: 16 abr. 2007.
PRICE, Ana Maria de Alencar; TOSCANI, Simão Sirineo. Implementação de linguagens de programação: compiladores. 2. ed. Porto Alegre: Sagra Luzzato, 2001.
PROJETO TOPCASED. Projeto TOPCASED. [S.l.], 2007. Disponível em: <http://www.das.ufsc.br/das/projetos/projeto_index.php?lang=pt&pg=pe&projeto=13>. Acesso em: 17 nov. 2007.
ROCHA, Lucas. APE: plataforma para o desenvolvimento de aplicações web com PHP. [Salvador], 2005. Disponível em: <http://twiki.im.ufba.br/bin/view/Aside/ProjetoConclusaoDeCursoAPEMonografia#4_2_Motores_de_templates>. Acesso em: 16 abr. 2007.
SOURCEFORGE. GALS: gerador de analisadores léxicos e sintáticos. [S.l.], 2007. Disponível em: <http://gals.sourceforge.net/>. Acesso em: 17 nov. 2007.
SOUZA, Eliane Moreira Sá de. Um modelo para processo ensino-aprendizagem de procedimentos lógicos em diversos domínios. 2000. 202 f. Tese (Doutorado em Engenharia de Produção) – Pós-Graduação em Engenharia de Produção, Universidade Federal de Santa Catarina, Florianópolis. Disponível em: <http://teses.eps.ufsc.br/defesa/pdf/2417.pdf >. Acesso em: 10 abr. 2007.
SOUZA, Marco Antonio Furlan de et al. Algoritmos e lógica de programação. São Paulo: Pioneira Thomson, 2005.
90
STRUCTORIZER. Structorizer: about the project. [S.l.], 2007. Disponível em: <http://structorizer.fisch.lu/>. Acesso em: 17 nov. 2007.
TEMPLATE PROCESSOR. In: WIKIPÉDIA, a enciclopédia livre. [S.l.]: Wikimedia Foundation, 2007. Disponível em: <http://en.wikipedia.org/wiki/Template_processor>. Acesso em: 15 nov. 2007.
TONSIG, Sergio Luiz. Engenharia de software: análise e projeto de sistemas. São Paulo: Futura, 2003.
TOPCASED. UML Tools. [S.l.], 2007. Disponível em: <http://topcased-mm.gforge.enseeiht.fr/website/modeling/uml/index.html>. Acesso em: 17 nov. 2007.
91
APÊNDICE A – Templates criados na linguagem VTL para o diagrama N-S
Este apêndice apresenta os templates criados para a geração de código dos elementos
do diagrama N-S na linguagem Java. Foram criados 9 templates escritos na linguagem VTL,
representando cada um dos elementos do diagrama N-S (Quadro 19, 20, 21, 22, 23, 24, 25, 26
e 27).
## main list of commands to JAVA $command.toString() //Corpo de metodo gerado automaticamento pelo drawcode #foreach($child in $childs) $child.vlaccept($this,$ctx) #end
Quadro 19 - Template para a lista principal do diagrama N-S
## single command to JAVA $command.vlaccept($tokentranslator,$ctx);
Quadro 20 - Template para os comandos simples, atribuições e chamadas de sub-rotinas
## case to JAVA switch ($command.toString()) { #foreach($child in $childs) $child.vlaccept($this,$ctx) #end }
Quadro 21 - Template para o comando de seleção
## case option to JAVA #if ($command.toString().toUpperCase() != "DEFAULT")case $command.toString():#{else}default:#end #foreach($child in $childs) $child.vlaccept($this,$ctx) #end break;
Quadro 22 - Template para as opções do comando de seleção
## do-while to JAVA do { #foreach($child in $childs) $child.vlaccept($this,$ctx) #end } while ($command.vlaccept($tokentranslator,$ctx));
Quadro 23 - Template para o comando de repetição com condição no final do laço de repetição
## for to JAVA for ($command.vlaccept($tokentranslator,$ctx)) { #foreach($child in $childs) $child.vlaccept($this,$ctx) #end }
Quadro 24 - Template para o comando de repetição com número de repetições definido
92
## while to JAVA while ($command.vlaccept($tokentranslator,$ctx)) { #foreach($child in $childs) $child.vlaccept($this,$ctx) #end }
Quadro 25 - Template para o comando de repetição com condição no inicio do laço de repetição
## if to JAVA if ($command.vlaccept($tokentranslator,$ctx)) { $ifchild.vlaccept($this,$ctx) } else { $elsechild.vlaccept($this,$ctx) }
Quadro 26 - Template para o comando de decisão
## if and else sides of commands to JAVA #foreach($child in $childs) $child.vlaccept($this,$ctx) #end
Quadro 27 - Template para a lista de comandos verdadeiros e falsos do comando de decisão
93
APÊNDICE B – Templates criados na linguagem VTL para o diagrama de classes
Este apêndice apresenta os templates criados para representar o diagrama de classes.
Para a geração de código do diagrama de classe foram criados 5 templates escritos na
linguagem VTL que representam cada um dos elementos do diagrama de classe para geração
de código na linguagem Java (Quadro 28, 29, 30, 31, 32 e 33).
## main list of nodes class diagram to JAVA //código gerado automaticamente pelo drawcode #foreach($child in $childs) $child.vlaccept($this,$ctx) #end
Quadro 28 - Template para o lista de classes do diagrama de classes
## class declaration from classdiagram to JAVA public class $node.toString() { #foreach($child in $childs) $child.vlaccept($this,$ctx) #end }
Quadro 29 - Template criado para o elemento classe
## list of attributes from class diagram to JAVA #foreach($child in $childs) $child.vlaccept($this,$ctx) #end
Quadro 30 - Template criado para a lista de atributos da classe
## attribute from class diagram to JAVA $node.toString();
Quadro 31 - Template criado para o elemento atributo
## method from class diagram to JAVA public $node.toString() { $nsGeneration.genNS($node,$buffer) }
Quadro 32 - Template criado para o elemento método
## list of methods from class diagram to JAVA #foreach($child in $childs) $child.vlaccept($this,$ctx) #end
Quadro 33 - Template criado para lista de métodos da classe
94
APÊNDICE C – Relação dos templates da tabela de tradução
No Quadro 34 e Quadro 35 são apresentados os templates criados para representar as
tabelas de tradução.
## Table mapping for instruction to JAVA ## cada uma das opcoes do "if" tem um comentario no final da linha '##' ## por uma organizacao visual, se nao estiver presente o velocity entende ## como uma nova linha #foreach($token in $tokens) #if($token.toUpperCase() == "LEIA")IMPLEMENTAR O LER ## #{elseif}($token.toUpperCase() == "ESCREVA")System.out.println## #{elseif}($token.toUpperCase() == "INT")int ## #{elseif}($token.toUpperCase() == "REAL")Double ## #{elseif}($token.toUpperCase() == "LOGICO")Boolean ## #{elseif}($token.toUpperCase() == "LÓGICO")Boolean ## #{elseif}($token.toUpperCase() == "CHAR")char ## #{elseif}($token.toUpperCase() == "STRING")String ## #{elseif}($token.toUpperCase() == "RETORNA")return ## #{elseif}($token.toUpperCase() == "E")&& ## #{elseif}($token.toUpperCase() == "OU")|| ## #{elseif}($token.toUpperCase() == "<>")!= ## #{else}$token ## #end #end
Quadro 34 - Template contendo a tabela de mapeamento para os comandos do tipo instrução
## Table mapping for conditions to JAVA ## cada uma das opcoes do "if" tem um comentario no final da linha '##' ## por uma organizacao visual, se nao estiver presente o velocity entende ## como uma nova linha #foreach($token in $tokens) #if($token.toUpperCase() == "<>")!=# {elseif}($token.toUpperCase() == "=")==# {elseif}($token.toUpperCase() == "E")&&# {elseif}($token.toUpperCase() == "OU")||# {else}$token #end #end
Quadro 35 - Template com a tabela de mapeamento para as condições dos elementos do diagrama N-S
95
APÊNDICE D – Relação de métodos das classes apresentadas na Figura 23
No Quadro 36 é apresentado todos os métodos definidos para as classes representadas
na Figura 23.
96
Classe: CaseFigure
Método Tipo Visibilidade Parâmetros CaseFigure Public NSDiagramEditor [in] editor;
CaseCommand [in] node; paintFigure void Protected Graphics [in] g;
Classe: CommandAdder
Método Tipo Visibilidade Parâmetros Visit boolean Public NSDiagramCommand [in] command; Object
[in] ctx; Visit boolean Public NullCommand [in] command; Object [in] ctx; Visit boolean Public WhileCommand [in] command; Object [in]
ctx; Visit boolean Public DoWhileCommand [in] command; Object [in]
ctx; Visit boolean Public ForCommand [in] command; Object [in] ctx; Visit boolean Public InstructionCommand [in] command; Object
[in] ctx; Visit boolean Public CaseCommand [in] command; Object [in] ctx; Visit boolean Public CaseOption [in] command; Object [in] ctx; Visit boolean Public IfCommand [in] command; Object [in] ctx; Visit boolean Public IfCommands [in] command; Object [in] ctx; Visit boolean Public ElseCommands [in] command; Object [in] ctx;
Classe: CommandRemover
Método Tipo Visibilidade Parâmetros Visit boolean Public NSDiagramCommand [in] command; Object
[in] ctx; Visit boolean Public NullCommand [in] command; Object [in] ctx; Visit boolean Public WhileCommand [in] command; Object [in]
ctx; Visit boolean Public DoWhileCommand [in] command; Object [in]
ctx; Visit boolean Public ForCommand [in] command; Object [in] ctx; Visit boolean Public InstructionCommand [in] command; Object
[in] ctx; Visit boolean Public CaseCommand [in] command; Object [in] ctx; Visit boolean Public CaseOption [in] command; Object [in] ctx; Visit boolean Public IfCommand [in] command; Object [in] ctx; Visit boolean Public IfCommands [in] command; Object [in] ctx; Visit boolean Public ElseCommands [in] command; Object [in] ctx;
Classe: DecisionFigure
Método Tipo Visibilidade Parâmetros DecisionFigure Public NSDiagramEditor [in] editor; IfCommand [in]
node; paintFigure void Protected Graphics [in] g;
97
Classe: DoWhileFigure
Método Tipo Visibilidade Parâmetros DoWhileFigure Public NSDiagramEditor [in] editor;
DoWhileCommand [in] node; Classe: ForFigure
Método Tipo Visibilidade Parâmetros ForFigure Public NSDiagramEditor [in] editor; ForCommand
[in] node; Classe: InstructionFigure
Método Tipo Visibilidade Parâmetros InstructionFigure Public NSDiagramEditor [in] editor;
InstructionCommand [in] node; Classe: LayoutAdjustCalculatorVisitor
Método Tipo Visibilidade Parâmetros adjustLayout void Public ICommandVisitable [in] node;
HashMap<ICommandVisitable, Rectangle> [in] map;
processHorizontalLayout boolean Private ICommandVisitable [in] command; List<ICommandVisitable> [in] list; Object [in] ctx; Rectangle [in] offset;
processSingleCommand boolean Private ICommandVisitable [in] command; Object [in] ctx;
processVerticalLayout boolean Private ICommandVisitable [in] command; List<ICommandVisitable> [in] list; Object [in] ctx; Rectangle [in] offset;
Visit boolean Public NSDiagramCommand [in] command; Object [in] ctx;
Visit boolean Public NullCommand [in] command; Object [in] ctx;
Visit boolean Public WhileCommand [in] command; Object [in] ctx;
Visit boolean Public DoWhileCommand [in] command; Object [in] ctx;
Visit boolean Public ForCommand [in] command; Object [in] ctx;
Visit boolean Public InstructionCommand [in] command; Object [in] ctx;
Visit boolean Public CaseCommand [in] command; Object [in] ctx;
Visit boolean Public CaseOption [in] command; Object [in] ctx;
Visit boolean Public IfCommand [in] command; Object [in] ctx;
Visit boolean Public IfCommands [in] command; Object [in] ctx;
Visit boolean Public ElseCommands [in] command; Object [in] ctx;
98
Classe: LayoutCalculatorVisitor
Método Tipo Visibilidade Parâmetros getLayout HashMap<ICo
mmandVisitable, Rectangle>
Public ICommandVisitable [in] node;
processHorizontalLayout boolean Private ICommandVisitable [in] command; List<ICommandVisitable> [in] list; Object [in] ctx; Rectangle [in] offSets;
processSingleCommand boolean Private ICommandVisitable [in] command; Object [in] ctx;
processVerticalLayout boolean Private ICommandVisitable [in] command; List<ICommandVisitable> [in] list; Object [in] ctx; Rectangle [in] offSets;
Visit boolean Public NSDiagramCommand [in] command; Object [in] ctx;
Visit boolean Public NullCommand [in] command; Object [in] ctx;
Visit boolean Public WhileCommand [in] command; Object [in] ctx;
Visit boolean Public DoWhileCommand [in] command; Object [in] ctx;
Visit boolean Public ForCommand [in] command; Object [in] ctx;
Visit boolean Public InstructionCommand [in] command; Object [in] ctx;
Visit boolean Public CaseCommand [in] command; Object [in] ctx;
Visit boolean Public CaseOption [in] command; Object [in] ctx;
Visit boolean Public IfCommand [in] command; Object [in] ctx;
Visit boolean Public IfCommands [in] command; Object [in] ctx;
Visit boolean Public ElseCommands [in] command; Object [in] ctx;
Classe: NSDiagramEditParts
Método Tipo Visibilidade Parâmetros activate void Public addRootEditPartChild void Public NSDiagramEditParts [in] child; createEditPolicies void Protected createFigure IFigure Protected deactivate void Public getCastedModel ICommandVisitable Private getModelChildren List<ICommandVisitable> Public NSDiagramEditParts Public NSDiagramEditor [in] editor;
ICommandVisitable [in] node; performDirectEdit void Protected performRequest void Public Request [in] request; propertyChange void Public PropertyChangeEvent [in] evt;
99
refreshChildren void Public removeChildrens void Public
Classe: NSDiagramEditor
Método Tipo Visibilidade Parâmetros commandStackChanged void Public EventObject [in] event; configureGraphicalViewer void Protected createPaletteViewerProvider PaletteViewerProv
ider Protected
createTransferDropTargetListener
org.eclipse.jface.util.TransferDropTargetListener
Private
doSave void Public IProgressMonitor [in] monitor; getChildrens List<ICommandVi
sitable> Public ICommandVisitable [in] node;
getNodeRect Rectangle Public ICommandVisitable [in] node; getNSDHandler NSDiagramHandl
er Public
getPalettePreferences FlyoutPreferences Protected getPaletteRoot PaletteRoot Protected initializeGraphicalViewer void Protected NSDiagramEditor Public RefreshVisual void Public setInput void Public IEditorInput [in] input;
Classe: NSDiagramHandler
Método Tipo Visibilidade Parâmetros getChildrens List<ICommandVisitable> Public ICommandVisitable [in] node; getRootModelNode ICommandVisitable Public insertCommand void Public ICommandVisitable [in] node;
ICommandVisitable [in] previousBrother;
MoveCommand boolean Public ICommandVisitable [in] Source; ICommandVisitable [in] previousBrother;
NSDiagramHandler Public ReadDiagram void Public String [in] file; RemoveCommand void Public ICommandVisitable [in]
killedNode; SaveDiagram void Public String [in] file; toModel void Public String [in] xml; toXML String Public
Classe: NSNodeCreateCommand
Método Tipo Visibilidade Parâmetros canExecute boolean Public execute void Public NSNodeCreateCommand Public NSDiagramEditor [in] editor;
ICommandVisitable [in] newNode; ICommandVisitable [in] previousBrother;
100
redo void Public undo void Public
Classe: NSPartFactory
Método Tipo Visibilidade Parâmetros createEditPart EditPart Public EditPart [in] context; Object [in] node; NSPartFactory Public NSDiagramEditor [in] editor;
Classe: NSXYLayoutEditPolicy
Método Tipo Visibilidade Parâmetros createAddCommand Command Protected EditPart [in] child;
Object [in] constraint; createAddCommand Command Protected EditPart [in] child;
Rectangle [in] constraint; ChangeBoundsRequest [in] request;
createChangeConstraintCommand Command Protected ChangeBoundsRequest [in] req; EditPart [in] nodePart; Object [in] constraint;
createChangeConstraintCommand Command Protected EditPart [in] child; Object [in] constraint;
getAddCommand Command Protected Request [in] generic; getCreateCommand Command Protected CreateRequest [in] request; getDeleteDependantCommand Command Protected Request [in] request; getMoveChildrenCommand Command Protected Request [in] request; NSXYLayoutEditPolicy Public NSXYLayoutEditPolicy Public NSDiagramEditor [in] editor;
XYLayout [in] layout; Classe: NodeChildrenDiscover
Método Tipo Visibilidade Parâmetros fillList void Public List<ICommandVisitable> [in] list;
ICommandVisitable [in] node; Visit boolean Public NSDiagramCommand [in] command; Object [in] ctx; Visit boolean Public NullCommand [in] command; Object [in] ctx; Visit boolean Public WhileCommand [in] command; Object [in] ctx; Visit boolean Public DoWhileCommand [in] command; Object [in] ctx; Visit boolean Public ForCommand [in] command; Object [in] ctx; Visit boolean Public InstructionCommand [in] command; Object [in] ctx; Visit boolean Public CaseCommand [in] command; Object [in] ctx; Visit boolean Public CaseOption [in] command; Object [in] ctx; Visit boolean Public IfCommand [in] command; Object [in] ctx; Visit boolean Public IfCommands [in] command; Object [in] ctx; Visit boolean Public ElseCommands [in] command; Object [in] ctx;
Classe: NodeFigure
Método Tipo Visibilidade Parâmetros NodeFigure Public NSDiagramEditor [in] editor;
ICommandVisitable [in] node;
101
Classe: NullFigure
Método Tipo Visibilidade Parâmetros NullFigure Public NSDiagramEditor [in] editor; NullCommand
[in] node; Classe: WhileFigure
Método Tipo Visibilidade Parâmetros WhileFigure Public NSDiagramEditor [in] editor; WhileCommand [in]
node; Interface: ICommandVisitable
Método Tipo Visibilidade Parâmetros accept boolean Public ICommandVisitor [in] visitor; Object [in] ctx; getTokenList List<String> Public setValue void Public String [in] newValue; vlaccept void Public ICommandVisitor [in] visitor; Object [in] ctx;
Interface: ICommandVisitor
Método Tipo Visibilidade Parâmetros Visit boolean Public NSDiagramCommand [in] command; Object [in] ctx; Visit boolean Public NullCommand [in] command; Object [in] ctx; Visit boolean Public WhileCommand [in] command; Object [in] ctx; Visit boolean Public DoWhileCommand [in] command; Object [in] ctx; Visit boolean Public ForCommand [in] command; Object [in] ctx; Visit boolean Public InstructionCommand [in] command; Object [in] ctx; Visit boolean Public CaseCommand [in] command; Object [in] ctx; Visit boolean Public CaseOption [in] command; Object [in] ctx; Visit boolean Public IfCommand [in] command; Object [in] ctx; Visit boolean Public IfCommands [in] command; Object [in] ctx; Visit boolean Public ElseCommands [in] command; Object [in] ctx;
Quadro 36 – Operações das classes apresentadas na Figura 23