• Nenhum resultado encontrado

CAPÍTULO 3 DESENVOLVIMENTO ORIENTADO A ASPECTOS E

3.2 Desenvolvimento Dirigido a Modelos

3.2.1 Acceleo

Acceleo é um gerador de código a partir de modelos que segue o padrão Model to Text Language (MTL) do OMG. Esse gerador possui duas versões: a versão open-source que é distribuída sob a licença EPL8 e uma versão comercial que possui suporte e treinamento especializado.

Essa ferramenta é resultado de vários anos de desenvolvimento da companhia francesa Obeo9. Segundo a equipe, o Acceleo foi criado considerando as necessidades do contexto industrial e recentes avanços de pesquisa no campo M2T, oferecendo vantagens como: alto nível de customização, interoperabilidade, facilidade para “ponto de partida”, gerenciamento de rastreabilidade entre outras. O Acceleo está em constante aprimoramento e conta com manuais, fóruns, equipe de suporte e uma comunidade ativa. Em 2009, o Acceleo recebeu um prêmio como melhor ferramenta open-source baseada na plataforma Eclipse10. Desde 2009, o Acceleo é um projeto oficial da Eclipse Foundation, sendo uma referência na geração de código na plataforma Eclipse.

Com o Acceleo, pode-se gerar código Java além de outras linguagens de programação partindo de modelos. Essa geração é feita por meio de templates, nos quais podem ser inseridos tags que servem para rotular trechos do código que poderá ser gerado. Dessa maneira, consultas podem ser executadas no template, em que caso um trecho de código esteja rotulado com uma determinada tag, esse trecho poderá fazer parte ou não do código fonte gerado no final do processo. Vale

8 http://www.eclipse.org/legal/epl-v10.html 9 http://www.obeo.fr/ 10 http://www.obeo.fr/pages/open-source/en

ressaltar que tanto as consultas, quanto as tags são implementadas com a linguagem de especificação do Acceleo.

O Acceleo possui um editor de templates, contendo um assistente, realce de sintaxe, detecção de erros entre outros recursos. Além do gerador de código e o editor de templates, o Acceleo conta com um assistente para criação de plug-ins. Com esse artifício, o desenvolvedor pode, por exemplo, criar um plug-in para o Eclipse, especificando: (i) um metamodelo (um modelo ecore criado com apoio do EMF), (ii) a extensão das instâncias desse metamodelo que servirá de entrada para o Acceleo (no formato xmi), (iii) um conjunto de templates que devem ser considerados e (iv) um parser que transforme um modelo de outra extensão que se deseja utilizar, em uma instância do metamodelo a ser considerado. Caso o modelo de entrada seja um xmi e seu metamodelo esteja disponível, basta considerá-lo como entrada para o Acceleo. Por exemplo, no caso de geração de código a partir de modelos UML (em formato xmi), o Acceleo possui um metamodelo ecore correspondente. Assim, não há necessidade de desenvolver um parser nem um metamodelo, pois a partir de modelos UML o Acceleo é capaz de gerar código fonte.

O gerador de código do Acceleo, ao considerar os templates que contém as tags e um conjunto de consultas, o metamodelo e sua instância, torna-se capaz, em tempo de projeto, de gerar código fonte. Por exemplo, supondo a existência de um metamodelo “X” e uma instância “X.y”, cuja extensão criada foi “y” e um template principal T. O metamodelo X descreve um conjunto de elementos, com suas respectivas propriedades e relacionamentos. Cada elemento pode ser considerado como uma classe que pertence a um “esqueleto”. A instância “X.y” respeita a estrutura de “X” e contém dados que foram preenchidos. Se “X” tem uma Classe “A” com o atributo “a” do tipo String, a instância “X.y” pode ter vários elementos do tipo Classe “A” com o atributo “a” do tipo String contendo valores variados. Com base nessa instância, o Acceleo pode realizar uma análise no template T. Caso exista alguma Classe em “X.y” com a estrutura da Classe “A”, cujo atributo “a” contém o valor “zxc” e que exista também, um determinado trecho código no template T rotulado com a tag contendo uma condição correspondente, tal trecho poderá fazer parte do código gerado.

A Figura 12 ilustra a ideia geral de como o Acceleo transforma um modelo em código de forma convencional. Na Etapa 1, há um modelo que pode ser um diagrama de classes. Na Etapa 2, deve-se selecionar o metamodelo da linguagem

Capítulo 3 - Desenvolvimento Orientado a Aspectos e Desenvolvimento Dirigido a Modelos 52

de programação, na qual pretende-se gerar código. Por exemplo: JEE, PHP, .NET e etc. A parte central da figura ilustra o mecanismo de geração de código do Acceleo. Considerando um metamodelo que contém a estrutura de uma linguagem de programação, considerando sua BNF11, o gerador do Acceleo é capaz de gerar código na linguagem definida a partir do modelo, conforme ilustrado na Etapa 3.

Figura 12: Visão geral do processo de geração de código com Acceleo (Acceleo, 2013)

Para exemplificar como os templates Acceleo podem ser implementados, na Figura 13 ilustra-se trechos de código de dois templates. Na parte (1) da figura, apresenta-se a implementação do template principal “main.mtl” (mtl é a extensão dos templates Acceleo). O template principal tem a função de realizar “chamadas” aos demais templates, caso necessário. Note-se que na parte superior há alguns imports a outros templates que são responsáveis pela geração de classes Java. Há também um laço “for” que serve para percorrer completamente o modelo fornecido como entrada para o Acceleo, ou seja, todos os elementos “feature” do tipo “Feature” que pertencem a “domain”. Vale enfatizar que essa estrutura é proveniente de um metamodelo. Em seguida, visualizam-se as tag condicionais do tipo “IF” no template principal. No caso, a parte interna do bloco “IF” está sendo utilizada para “chamar”

11

BNF (Backus Normal Form) ou Formalismo de Backus-Naur é uma meta-sintaxe utilizada para expressar gramáticas livres de contexto, sendo ela a notação mais usual para descrever gramáticas de linguagens de programação (Naur, 1960).

os templates que geram as classes obrigatórias, ou seja, classes que pertencem ao “core” de um framework ou de uma LPS, por exemplo. Caso o modelo de entrada contiver um elemento feature com o atributo “name” com o valor “GRENJ”, isso implica em gerar as classes: “AbstractCalculator”, “QualifiableObject” e etc. Por exemplo, poderia ser [if (feature.name.equalsIgnoreCase(‘X’))] feature.geradorClasseA() [/if], isso significa que se houver algum elemento do tipo feature com o atributo name com o valor X, indicando que a feature X foi selecionada, então o template responsável por gerar a “ClasseA” deve ser chamado.

Capítulo 3 - Desenvolvimento Orientado a Aspectos e Desenvolvimento Dirigido a Modelos 54

Na parte (2) há um trecho do template resource.mtl. Esse template é responsável por gerar a classe “Resource”. Note que na parte superior, em “module resource” é definido o metamodelo a ser considerado. Em seguida há um import de common.mtl, trata-se de um outro template que foi desenvolvido apenas para realização de consultas. Em seguida, têm-se alguns comentários e o código da Classe “Resource”. No lado direito da parte (2) há outro trecho do template resource.mtl que contém um nível diferente de condições. No caso, [if

(feature.getDomain().hasFeature(‘Trade’))] “trecho de código” [/if], isso indica que se a feature “Trade” estiver no modelo de entrada, ou seja, há um elemento do tipo feature com o atributo name contendo “Trade”, o trecho de código associado a essa tag deve ser adicionado ao código que será gerado. Observa-se que, na parte 1 o template principal é responsável por chamar todos os templates que geram as classes que implementam as features selecionadas. De outro lado, há features que impactam em outras features e que provavelmente afetam várias classes. Logo, torna-se necessário verificar quais features foram selecionadas, para que o código de uma classe que participe da implementação de diversas features, contenha somente os métodos e atributos das features selecionadas e que consequentemente pertencem ao modelo de entrada.

3.3 Considerações Finais

Os mecanismos fornecidos pela POA permitem a modularização de software evitando problemas como o entrelaçamento e espalhamento de código que dificultam a realização da manutenção, fundamental no ciclo de vida de um software. De outro lado, o MDD fornece meios para que um modelo seja transformado em código fonte considerando as melhores práticas/padrões de desenvolvimento. Além disso, o MDD permite ao desenvolvedor se concentrar em atividades mais importantes, considerando a possibilidade de evitar tarefas repetitivas que geralmente consomem maior parte do esforço no desenvolvimento.

Considerando tais abordagens, acredita-se que ambas podem ser aplicadas em frameworks amplos e com arquitetura rígida, seja com o intuito de melhorar sua modularidade ou solucionar dificuldades inerentes à quantidade de variabilidades

desnecessárias para determinados conjuntos de aplicações desenvolvidas com seu apoio. No capítulo seguinte, apresenta-se uma discussão acerca dessas dificuldades e uma alternativa para suavizá-las. Essa alternativa envolve a modularização das variabilidades do framework em features, possibilitando alcançar níveis mais efetivos quanto à flexibilidade de composição. Assim, podem-se compor frameworks direcionados às preferências do usuário.