DOMINGUES, W.B. Linguagem EspecÃfica de - LTS-i
Transcrição
DOMINGUES, W.B. Linguagem EspecÃfica de - LTS-i
Instituto de Pesquisas Tecnológicas do Estado de São Paulo Wladimir Braguini Domingues Linguagem Específica de Domínio para Governo Eletrônico em Mídia Cruzada São Paulo 2009 Wladimir Braguini Domingues Linguagem Específica de Domínio para Governo Eletrônico em Mídia Cruzada Dissertação de Mestrado apresentada ao Instituto de Pesquisas Tecnológicas do Estado de São Paulo - IPT, como parte dos requisitos para a obtenção do título de Mestre em Engenharia de Computação Data da aprovação: __ / __ / ____ Prof. Dra. Lucia Vilela Leite Filgueiras IPT – Instituto de Pesquisas Tecnológicas do Estado de São Paulo Membros da Banca Examinadora: Prof. Dra. Lucia Vilela Leite Filgueiras (Orientadora) IPT — Instituto de Pesquisas Tecnológicas Prof. Dr. Jose Eduardo Zindel Deboni IPT — Instituto de Pesquisas Tecnológicas Prof. Dr. João José Neto EPUSP — Escola Politécnica da Universidade de São Paulo Wladimir Braguini Domingues Linguagem Específica de Domínio para Governo Eletrônico em Mídia Cruzada Dissertação de Mestrado apresentada ao Instituto de Pesquisas Tecnológicas do Estado de São Paulo - IPT, como parte dos requisitos para a obtenção do título de Mestre em Engenharia de Computação Área de Concentração: Engenharia de Software Orientadora: Prof. Dra. Lucia Vilela Leite Filgueiras Dez/2009 Dedicatória Dedico este trabalho aos meus avós, Zilda e Hermogenes Braguini (in memorian), por sempre acreditarem em mim e no valor da educação. Agradecimentos À minha orientadora Lucia, não só pela valiosa orientação, mas também pela amizade e compreensão. À minha esposa Luciana, pelo carinho, dedicação e, sobretudo, amor. À minha família, pela apoio constante e incondicional. Um agradecimento especial a todos do IPT por tornarem este trabalho possível. Ao Grupo de Interação Humano-Computador do PCS-LTS da Poli/USP, pelo convívio alegre, pelos momentos de descontração e pela troca de conhecimento. E a todos que, de alguma forma, contribuíram para essa minha vitória. Muito Obrigado! RESUMO Avanços tecnológicos criam novos meios de comunicação e ampliam os modos de interação homem-computador proporcionando uma experiência de uso positiva. Um sistema de mídia cruzada se caracteriza pelo uso de múltiplos meios de comunicação suportando um tema central ou conteúdo principal. Um tema central que pode ser aplicado sobre múltiplas mídias é o de serviços de governo. Este trabalho objetiva projetar uma linguagem específica de domínio que consiga expressar aspectos de serviços de governo em mídia cruzada. Com essa linguagem é possível modelar novos sistemas x-gov em um nível mais alto de abstração. Palavras-chave: DSL, Serviços de Governo, x-gov, Mídia Cruzada. iii ABSTRACT Domain Specific Language for e-Government on Cross-Media Technological advances creates new media that expands the modes of humancomputer interaction providing a positive experience of use. A cross-media system is characterized by the use of multiple media, supporting a central theme or content. A central theme that can be applied over multiple media is the theme of government services. This work aims to design a domain specific language that can express aspects of government services in cross-media. This language allows modeling new x-gov systems in a higher level of abstraction. Key Words: DSL, government services, x-gov, cross-media. iv Sumário Resumo iii Abstract iv Lista de Ilustrações viii Lista de Tabelas ix Lista de Códigos x Lista de Abreviaturas e Siglas xi 1 Introdução 1.1 Motivação . . . . . . . . . . . . . . . . 1.2 Objetivo . . . . . . . . . . . . . . . . . 1.3 Resultados Esperados e Contribuições 1.4 Método de Trabalho . . . . . . . . . . . 1.5 Organização do Trabalho . . . . . . . . . . . . . 1 2 4 5 5 6 . . . . . . . . . . . 8 8 9 12 12 13 13 14 16 16 18 18 3 Mídia Cruzada e Governo Eletrônico 3.1 Mídia Cruzada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 20 2 Linguagem Específica de Domínio 2.1 Introdução . . . . . . . . . . . . . . 2.2 Definição . . . . . . . . . . . . . . . 2.3 Classificação . . . . . . . . . . . . 2.3.1 DSL Externa . . . . . . . . . . . . 2.3.2 DSL Interna . . . . . . . . . . . . 2.4 Método de Desenvolvimento . . . . 2.4.1 Decisão . . . . . . . . . . . . . . 2.4.2 Análise . . . . . . . . . . . . . . . 2.4.3 Projeto . . . . . . . . . . . . . . . 2.4.4 Implementação . . . . . . . . . . 2.5 Considerações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Definição de Mídia . . . . . . . . . . . . . . . . 3.1.2 Mídia Cruzada . . . . . . . . . . . . . . . . . . . 3.2 Governo Eletrônico em Mídia Cruzada . . . . . . 3.2.1 e-gov, m-gov, t-gov, x-gov . . . . . . . . . . . . 3.2.2 Serviços de Governo . . . . . . . . . . . . . . . 3.2.3 Padrões de Tarefas para Serviços de Governo . . . . . . . 20 21 24 24 25 27 . . . . . . . . . 29 29 31 31 33 35 37 37 37 39 . . . . . . 41 41 42 46 52 59 70 6 Conclusões 6.1 Análise dos Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Reflexões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 73 75 77 REFERÊNCIAS 78 A Exemplos de DSLs A.1 jMock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 API Fluente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 83 84 B Framework X-Gov B.1 Diagrama de Classes do FrameworkLibrary . . . . . . . . . . . . . . . . . . 86 86 C Implementação da CroMeL 90 4 Framework X-Gov 4.1 Conceito . . . . . . . . . . . . . . 4.2 Arquitetura . . . . . . . . . . . . . 4.2.1 Modelo de Domínio . . . . . . . 4.2.2 Componentes . . . . . . . . . . 4.3 Partes Integrantes do Framework 4.3.1 Gerenciador de Componentes . 4.3.2 Gerenciador de Transições . . . 4.3.3 Linguagem de Configuração . . 4.4 Conclusão . . . . . . . . . . . . . . . . . . . . . . 5 A Linguagem CroMeL 5.1 Introdução a CroMeL . . . . . . . . 5.1.1 Elementos da linguagem CroMeL 5.1.2 Implementação . . . . . . . . . . 5.2 Gramática . . . . . . . . . . . . . . 5.3 Semântica . . . . . . . . . . . . . . 5.4 Discussão dos Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.1 C.2 C.3 C.4 C.5 C.6 C.7 C.8 Regras Léxicas e Sintáticas da CroMeL . . . . . . . . Regras Semânticas da CroMeL . . . . . . . . . . . . Diagramas de Sintaxe . . . . . . . . . . . . . . . . . Autômato Finito Determinístico . . . . . . . . . . . . ANTLRWorks . . . . . . . . . . . . . . . . . . . . . . CroMeL XML . . . . . . . . . . . . . . . . . . . . . . CromelService para Interpretador na versão C# . . . ComponentFactory para Interpretador na versão C# . vii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 92 99 101 102 102 104 110 Lista de Ilustrações Figura 3.1 Big Brother Brasil 9 . . . . . . . . . . . . . . . . . . . . . . . . . . Figura 3.2 Cadeia de Conteúdo Digital [Fonte: Boumans2004] . . . . . . . . 23 27 Figura 4.1 Figura 4.2 Figura 4.3 Figura 4.4 Figura 4.5 Figura 4.6 Figura 4.7 Figura 4.8 Composição de um X-Gov . . . . . . . . . . . . . . . . . Arquitetura X-Gov . . . . . . . . . . . . . . . . . . . . . ComponentModel . . . . . . . . . . . . . . . . . . . . . . Componente GetTrackIdComponent . . . . . . . . . . . Padrões de Tarefas . . . . . . . . . . . . . . . . . . . . . Modelo X-Gov . . . . . . . . . . . . . . . . . . . . . . . . Ferramenta gráfica para descrição de um serviço . . . . Configuração através do X-Builder e através da CroMeL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 31 32 34 35 36 38 39 Figura 5.1 Figura 5.2 Figura 5.3 Figura 5.4 Figura 5.5 Figura 5.6 Contexto da linguagem CroMeL . . . . . . . . . . . . Mapeamento de contexto na linguagem CroMeL . . Etapas de implementação do interpretador CroMeL Implantação de um script CroMeL . . . . . . . . . . Interpretação de um script CroMeL . . . . . . . . . . Grafo de dependência entre as regras sintáticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 44 46 51 52 58 Figura B.1 Figura B.2 Figura B.3 Figura B.4 Exemplo de classes de componentes . . . . . . . . . . Componentes FindEntityInfo para TV, Mobile e Web . . Componente GetPreServiceInfo para TV, Mobile e Web Classes de Transição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 88 89 89 Figura C.1 Figura C.2 Figura C.3 Figura C.4 Figura C.5 Figura C.6 Figura C.7 Figura C.8 Figura C.9 Diagrama de sintaxe da raiz da gramática . . . . . . . . . . . . . Diagrama da sintaxe de declaração de um serviço . . . . . . . . Diagrama da sintaxe dos elementos que pertencem a um serviço Diagrama da sintaxe de uma atividade . . . . . . . . . . . . . . . Diagrama da sintaxe de declaração de parametros . . . . . . . . Diagrama de sintaxe de transições . . . . . . . . . . . . . . . . . Diagrama de sintaxe de navegação . . . . . . . . . . . . . . . . . DFA reconhecedor dos Tokens da linguagem CroMeL . . . . . . Ferramenta ANTLRWorks no desenvolvimento da CroMeL . . . . 99 99 99 100 100 100 100 101 102 viii . . . . . . Lista de Tabelas Tabela 2.1 Tabela 2.2 Tabela 2.3 Tabela 2.4 Tabela 2.5 Tabela 2.6 Tabela 2.7 Padrões de Decisão . . . . . . . . . . . . . . . . . . . . . . . Exemplos para os Padrões de Decisão . . . . . . . . . . . . Padrões de Análise . . . . . . . . . . . . . . . . . . . . . . . Padrões de Projeto . . . . . . . . . . . . . . . . . . . . . . . . Exemplos de linguagens para os Padrões de Projeto . . . . . Sistemas e Ferramentas de Desenvolvimento de Linguagem Padrões de Implementação para DSLs executáveis . . . . . ix . . . . . . . . . . . . . . 15 15 16 17 17 18 18 Lista de Códigos 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 5.12 5.13 5.14 5.15 5.16 5.17 C.1 C.2 C.3 C.4 C.5 Cenario de matricula escolar . . . . . . . . . . . . . . . . . . . . Raiz da linguagem . . . . . . . . . . . . . . . . . . . . . . . . . . Sentenças de entrada para um serviço e declaração de variáveis Gramática para descrição das ativadades de um serviço . . . . . Sentenças de entrada para uma atividade . . . . . . . . . . . . . Gramática para declaração de transições e navegações . . . . . Sentenças de entrada para transição e navegação . . . . . . . . Regras léxicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . Script CroMeL de entrada . . . . . . . . . . . . . . . . . . . . . . Semântica de declaração de variável . . . . . . . . . . . . . . . . Semântica de uma atividade . . . . . . . . . . . . . . . . . . . . Semântica de navegação . . . . . . . . . . . . . . . . . . . . . . Semântica de uma transição . . . . . . . . . . . . . . . . . . . . Semântica dos parâmetros de componentes e transições . . . . Semântica de expressões . . . . . . . . . . . . . . . . . . . . . . Semântica de um Serviço . . . . . . . . . . . . . . . . . . . . . . Codigo de Saida . . . . . . . . . . . . . . . . . . . . . . . . . . . Gramatica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Semantica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cromel Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . Component Factory . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 . 54 . 54 . 55 . 55 . 56 . 57 . 57 . 60 . 62 . 63 . 64 . 64 . 65 . 66 . 67 . 68 . 90 . 92 . 102 . 104 . 110 Lista de Abreviaturas e Siglas G2C x-gov GPL DSL CroMeL EDSL IETF W3C Mime HTTP ANTLR YAML XAML XUL VB Government to Citizen. Serviço de governo sobre mídia cruzada — cross-media government. Arcabouço de software para apoiar a criação de serviços x-gov — Framework X-Gov. General Purpose Language. Domain-Specific Language. Cross-Media Language. Embedded Domain Specific Language. Internet Engineering Task Force. World Wide Web Consortium. Multipurpose Internet Mail Extensions. Hypertext Transfer Protocol. ANother Tool for Language Recognition. YAML Ain’t Markup Language. eXtensible Application Markup Language. XML User Interface Language. Visual Basic. JSF EJB IHC CTA LP API EBNF AST IDE IPT CMID ORM AJAX TDD MOP Java Server Faces. Enterprise Java Beans. Interação Homem-Computador. call-to-action. Linguagem de Programação. Application Programming Interface. Extended Backus–Naur Form. Abstract Syntax Tree. Integrated Development Environmnet. Instituto de Pesquisas Tecnológicas. Cross-Media Interaction Design. Object Relational Mapping. Asynchronous JavaScript and XML. Test Driven Development. Meta-Object Protocol. FXG xi Seção 1 Introdução A cada nova invenção concebida no transcorrer da história, o homem viu-se obrigado a descobrir meios de interagir com elas e, na maioria das vezes, a necessidade levou-o além, tornando-o capaz de ressignificar a função para a qual o objeto fora originalmente pensado. Sharp et al. (2007) explica: Avanços nas interfaces gráficas, reconhecimento de fala e escrita, junto com a chegada da Internet, telefones celulares, redes sem fios, tecnologias de sensores e um conjunto de outras tecnologias disponíveis com telas grandes e pequenas, mudaram como se dá a interação homemcomputador. . . Por exemplo, maneiras inovadoras de controlar e interagir com informações digitais foram desenvolvidas, o que inclui reconhecimento de gestos, interfaces sensíveis, e até a interação estimulada pela emoção. Pesquisadores e desenvolvedores começaram a combinar o mundo físico com o digital, resultando em novas interfaces. . . Com isso o projeto de novas interfaces vai além do usuário individual, suportando interações sociais de pequena e grande escala para pessoas em trânsito, em casa, ou no trabalho. No mundo atual, onde as informações são produzidas em todo lugar e cada vez mais acessíveis por meios diversos, deve-se aproveitar essas características para criar recursos melhores com o objetivo de facilitar novos tipos de interação. 1 1.1 Motivação Cross media can be defined as the collaborative support of multiple media to delivering a single story or theme, in which the storyline directs the receiver from one medium to the next, according to each medium’s strength to the dialogue. (Filgueiras et al., 2008) Um projeto de mídia cruzada pode ser visto como: “Uso de conteúdo sobre vários dispositivos suportando um tema central.” Neste caso, o tema central será um serviço de governo. Conforme defendido por Boumans (2004), o essencial ao conceito de mídia cruzada (cross-media) é que exista mais de uma mídia ou dispositivo de distribuição para suportar o tema central ou conteúdo principal de um projeto com suas próprias forças. Assim, a informação é distribuída em múltiplas mídias ampliando as formas de acesso ao conteúdo, para o qual muda o paradigma de um usuário interagindo com um computador desktop, e possibilita o acesso a informações e serviços também pela TV, telefone fixo ou celular, além da mídia impressa e do próprio computador desktop. A mídia cruzada é uma particularização importante do conceito de multimodalidade, no sentido de que há uma integração forte entre os meios (Filgueiras, 2007). O governo necessita se comunicar de maneira eficiente e oferecer serviços aos cidadãos para cumprir na totalidade o seu papel. Sendo assim, poderia aproveitarse das várias mídias disponíveis para ampliar as formas de comunicação. Segundo Filgueiras (2007), a mídia cruzada pode ser uma maneira promissora para ampliar a interatividade G2C. No entanto, existe uma grande dificuldade para desenvolver um sistema com apoio às características apresentadas devido à diversidade de tecnologias utilizadas (relacionadas a programação, interface, capacidade de rede e multimídia), sendo que cada programa necessita de um ambiente de execução apropriado. Esse ambiente de execução, ou plataforma, é utilizado para construir e executar as aplicações que fazem parte do sistema e pode-se observar facilmente que uma aplicação para um dispositivo celular com apoio a apenas uma mídia poderia ser desenvolvida em diversas plataformas, como JavaME (Micro Edition), BREW, Symbian e .NET Mobile. Um sistema em mídia cruzada envolve, normalmente, mais de uma aplicação construída sobre diferentes tecnologias/plataformas. Deve ser projetado não apenas para incluir as diversas aplicações, mas também coordená-las, transferir estado e estruturar suas ações a serem executadas em conjunto para correto funcionamento do sistema. Portanto, visto dessa forma, um sistema em mídia cruzada torna-se complexo e distribuído. Nesse contexto surge a necessidade de um framework que apóie a implementação de sistemas em mídia cruzada. 2 Com o intuito de suprir essa necessidade iniciou-se, em 2007, o projeto X-Gov (Filgueiras, 2007), patrocinado pela Fapesp e Microsoft Research, com o objetivo de estudar a mídia cruzada como uma abordagem promissora para ampliar a interatividade entre o governo e o cidadão. Em sua completude, o projejo X-Gov envolve uma série de sub-projetos, entre os quais se encontra esta proposta, que, quando reunidos, resultam em um arcabouço de software (framework ) que facilita o desenvolvimento de serviços de governo utilizando diversos meios de comunicação. O propósito do Framework X-Gov é permitir um desenvolvimento rápido de aplicações, e para conseguir isso, conta com um conjunto de componentes de software, ferramentas de modelagem e uma aplicação central que roda em um servidor web. No texto da proposta do projeto submetida a Fapesp foram colocadas sob enfoque as tendências mundiais referentes à governo eletrônico, e estas demonstraram que, apesar dos aspectos positivos de comunicação e acessibilidade, o governo eletrônico seria suplantado pelo X-Gov, devido ao fato deste atingir o cidadão não somente pelo computador desktop, mas também pela televisão, telefone fixo ou celular, jornais, revistas, enfim, por múltiplas mídias. Essas cenário atual diferencia-se do projeto XGov por apresentar limitadas possibilidades de interação, uma vez que a experiência do usuário restringe-se a um computador desktop, provavelmente em um centro de inclusão digital. Considerando que estas interações ocorrem sobre diferentes plataformas e associado a elas estão diversas tecnologias, deve-se trabalhar em um nível de abstração adequado, para construir sistemas que são constituídos de componentes distribuídos em vários dispositivos, sendo este nível de abstração, por sua vez, o tema desta dissertação; assim faz-se necessário um nível de abstração adequado para ser utilizado como ferramenta de modelagem no projeto X-Gov. Buscar uma linguagem capaz de descrever os vários componentes contidos nos dispositivos de uma plataforma de mídia cruzada apresentou-se como uma oportunidade para explorar as diferenças entre uma enfoque genérico e um específico aplicado às disciplinas de engenharia de software. Assim, notou-se que um enfoque genérico fornece soluções para muitos problemas, mas poderá não ser o mais adequado quando se trata de um problema particular, enquanto que, um enfoque específico fornece uma solução melhor para um pequeno grupo de problemas, porém sua utilização é limitada a essa classe de problemas, o que torna difícil sua aplicação em situações diferentes. Dentro dessa dicotomia em computação, encontra-se linguagens específicas de domínio (DSLs) versus linguagens de propósito geral (GPLs) (van Deursen et al., 2000). Segundo Brooks (1975) programadores criam instruções (statements), ou linhas de código, a uma taxa constante, portanto linguagens de mais alto nível são 3 mais produtivas. O uso de DSLs pode aumentar o nível de abstração aplicado na programação, podendo declarar, ou especificar o que deverá acontecer e deixar para camadas inferiores, de interpretação, tratar de executar as instruções, uma característica típica de linguagens declarativas ou de configuração. A seguir são apresentadas algumas DSLs muito utilizadas, junto com seus respectivos domínios Jones (1996) apud Mernik et al. (2005): • BNF (Backus–Naur Form): Especificação formal de sintaxe de linguagens; • Excel: Manipulação de dados em planilhas; • HTML: Páginas web com hypertexto; • LATEX: Processador e formatador de textos; • Make: Ferramenta para construção de software; • MATLAB: Computação técnica matemática; • SQL (Structured Query Language): Consulta a bancos de dados; • VHDL (VHSIC hardware description language): Linguagem para descrição de hardware. Linguagens específicas de domínio são importantes para o desenvolvimento de software porque representam uma maneira de codificar a solução de um problema de forma mais natural, com maior fidelidade e manutenabilidade do que as linguagens de propósito geral. 1.2 Objetivo Essa pesquisa é motivada pela dificuldade em se criar sistemas constituídos de diversas tecnologias, característica intrínseca da mídia cruzada, e como as questões de comunicação do governo com o cidadão é um forte fator motivador para aplicar a mídia cruzada, faz-se necessário considerar uma forma de programação que facilite a criação de sistemas dessa natureza. Dessa maneira, o principal objetivo desta pesquisa é elaborar uma linguagem específica de domínio que por meio de notações adequadas consiga expressar os conceitos de serviços de governo em mídia cruzada. Mais especificamente, a linguagem permite descrever quais são as etapas de um serviço, as mídias utilizadas e as transições entre mídias, além de servir para configurar os componentes utilizados dentro de um processo de governo possibilitando assim disponibilizar aplicações sobre o Framework X-Gov. 4 1.3 Resultados Esperados e Contribuições Esse trabalho tem como resultado prático, atendendo aos requisitos do mestrado profissional, criar uma linguagem de programação que permitirá ao gestor público descrever os serviços de governo auxiliando na criação de um sistema em ambiente de mídia cruzada. Mais especificamente, a linguagem permite descrever quais são as etapas de um serviço, as mídias utilizadas e as transições entre mídias, além de servir para configurar os componentes utilizados dentro de um processo de governo. Com auxílio dessa ferramenta, o gestor conseguirá implementar, validar e modificar os serviços com mais agilidade, já que para isso utiliza uma linguagem criada sob medida para esse problema. Foi feito um ensaio da linguagem aplicado na descrição de um cenário de serviço de governo, que pode ser utilizado para analisar o aspecto de como uma linguagem específica de domínio (DSL) pode contribuir para facilitar o desenvolvimento de um novo sistema X-Gov. Esse ensaio, também serve de exemplo de script para quem quiser utilizar futuramente esta linguagem. O resultado deste trabalho contribui para o levantamento do vocabulário e a definição de um modelo de domínio em sistemas de mídia cruzada, aplicado em governo eletrônico. O domínio e a linguagem poderão ser extrapolados para outra áreas de aplicações como jogos eletrônicos, publicidade, entretenimento, etc. Entre as contribuições acadêmicas destacam-se o levantamento de referências que podem ser utilizadas para o desenvolvimento de linguagens específicas de domínio. Além disto, todo o código fonte está disponível para o uso no desenvolvimento de novas aplicações e para trabalhos futuros. Como contribuições adicionais, destacamse a revisão de metodologias, ferramentas e técnicas para construção de uma DSL. Este trabalho é parte integrante do projeto X-Gov e tornou-se a ferramenta de modelagem do framework. 1.4 Método de Trabalho O desenvolvimento desta pesquisa segue as etapas listadas para atingir seu objetivo proposto: Na etapa de revisão bibliográfica, obteve-se o estado da arte sobre linguagens específicas de domínio, com intuito de se determinar os conceitos, trabalhos relacionados e método de desenvolvimento. Em seguida, foi analisada a área de mídia cruzada, seu significado e aplicação, com destaque em serviços de governo. Posteriormente foram levantados os requisitos do Framework X-Gov. As referências teóricas o estudo da implementação de uma prova de conceito 5 são a base para proposta de uma nova linguagem que serve para modelar serviços de governo sobre mídia cruzada. Na definição da sintaxe desta linguagem são analisados os componentes do Framework X-Gov e as transições de mídias em três serviços de governo simulados. Após as considerações acima, têm início as fases clássicas de um projeto de software: análise, projeto, implementação e deployment. Na fase de análise é descrito o modelo de domínio e são identificados os componentes do Framework X-Gov associados aos padrões de tarefa. Assim pode-se agrupar o conhecimento em notações e operações úteis para a linguagem. Na fase de projeto é criado um rascunho da DSL por meio do mapeamento dos conceitos de domínio com a implementação dos elementos do Framework X-Gov. Observe que variabilidades indicam precisamente que informação é necessária para especificar uma instância do sistema. Essa informação deve ser especificada diretamente em um programa da DSL ou derivada dele. Terminologia e conceitos são utilizados para guiar o desenvolvimento das construções da DSL correspondente às variabilidades. O que é comum é utilizado para definir o modelo de execução (por um conjunto de operações comuns) e primitivas da linguagem. Na fase de implementação as seguintes atividades foram executadas: 1. Construção da gramática da linguagem no nível léxico e sintático; 2. Construção de ações semânticas embutidas no reconhecedor gerado; 3. Construção de um conjunto de classes para servir como interface da linguagem como o framework. Após a fase de implementação, foi necessário criar um mecanismo de deployment para a linguagem ser instalada no Framework X-Gov. Para efeito de avaliação da aplicabilidade da DSL, foi desenvolvida uma prova de conceito para um serviço de agendamento médico que será utilizado como exemplo posteriormente. 1.5 Organização do Trabalho Este trabalho estrutura-se da seguinte forma: A Sessão 1 é esta introdução. A Sessão 2 intitulada Linguagem Específica de Domínio apresenta revisão da literatura do estado da arte sobre DSL, sua definição, os tipos, exemplos e metodologia de desenvolvimento. A Sessão 3 intitulada Mídia Cruzada e Governo Eletrônico apresenta uma breve descrição sobre os conceitos de mídia cruzada e serviço de governo eletrônico. 6 A Sessão 4 intitulada Framework X-Gov apresenta as partes que constituem o Framework X-Gov relevantes aos objetivos desse trabalho. A Sessão 5 intitulada A Linguagem CroMeL introduz a linguagem CroMeL e apresenta seu projeto e implementação. A Sessão 6 intitulada Conclusões concentra os resultados obtidos e possíveis direções para trabalhos futuros. 7 Seção 2 Linguagem Específica de Domínio “Se sua única ferramenta é um martelo, você tende a ver todo problema como um prego.” (Abraham Maslow) Este capítulo apresenta diversos trabalhos relacionados à linguagens específicas de domínio com objetivo de definir seu conceito, a classificação dos diferentes tipos existentes, e alguns exemplos para ilustrar as vantagens, técnicas de programação e alternativas sobre métodos de desenvolvimento. Ainda serão analisados alguns projetos e padrões que podem ser aplicados na solução proposta no capítulo 5. Não existe um consenso entre os autores quanto a sigla DSL, várias definições foram criadas para a mesma como referenciadas em Mernik et al. (2005): linguagem orientada a aplicação (Sammet, 1969), linguagem de propósito especial (Wexelblat, 1981), linguagem especializada (Bergin & Gibson, 1996), linguagem específica de uma tarefa (Nardi, 1993), linguagem específica de uma aplicação (Martin, 1985) e linguagens pequenas (Bentley, 1986). 2.1 Introdução Qual é a abstração ideal para uma aplicação particular? Segundo Hudak (1996) é uma linguagem de programação projetada para essa aplicação: deve capturar precisamente a semântica do domínio do problema (nem mais, nem menos). A Engenharia de Software e as linguagens atuais de programação propõem diversos mecanismos de abstração: componentes, módulos, classes, objetos, tipos 8 de dados abstratos, interfaces, funções de ordem superior, lambdas, monadas, continuações, etc. Uma determinada linguagem de programação suporta melhor muitos desses mecanismos do que outras. Guy Steele Jr. 1 explica em Steele (1998): . . . um bom programador, nestes tempos, não apenas escreve programas. . . . um bom programador projeta uma linguagem, não do zero, mas sim a contrói a partir de uma linguagem base. Considera-se que especialistas de um domínio possuem um vocabulário próprio que expressa conceitos dentro de um contexto particular, permitindo que façam afirmações sem explicar detalhes sobre o que estão falando, o que torna sua comunicação eficiente dentro do grupo no qual se insere. Pode-se ver que essa forma de comunicação acontece por meio de uma linguagem específica de domínio. Por exemplo, um americano pode pedir um café no Starbucks da seguinte forma: “one non fat, no whip, no foam, ventti half coffe latte” (um café com leite desnatado, tamanho grande, sem expresso, sem espuma e sem chantilly 2 ) e já que fala dentro de um contexto será corretamente interpretado. No artigo van Deursen et al. (2000) é destacado que ao longo do tempo as seguintes soluções foram adotadas para o desenvolvimento de aplicações: 1. Bibliotecas de subrotinas: contém subrotinas que executam tarefas relacionadas em um domínio bem definido como equações diferenciais, gráficos, GUI, bancos de dados — método clássico para reutilizar conhecimento de domínio. 2. Frameworks orientados a objetos e de componentes: Conjunto de classes que definem uma interface de programação (API) usada diretamente enquanto controla execução usando métodos fornecidos por um código específico da aplicação. 3. DSLs: linguagens pequenas, normalmente declarativas que oferecem expressividade em um domínio de problema particular. Em muitos casos o programa é traduzido para chamadas de uma biblioteca comum e a DSL pode ser vista como uma maneira de esconder os detalhes dessa biblioteca. 2.2 Definição Linguagem Específica de Domínio, ou DSL (Domain-Specific Language), como muitos outros termos em computação, tem uma definição um pouco confusa e ampla, 1 Participou de comitês para especificação de linguagens como ECMAScript, C, Fortran, Scheme, *LISP, Java e mais recentemente Fortress 2 Se achar que a tradução não está coerente consulte http://www.quicksilverweb.net/sbucks/ sbcharts.htm 9 mas existe um entendimento razoável do que elas são pela observação de exemplos que aparecem de diferentes maneiras em diversas comunidades. A definição adotada para DSL é: uma linguagem de programação que oferece, através de notações e abstrações apropriadas, poder de expressão enfática e restrita a um domínio de problema particular. Uma comunidade particular em que as DSLs são notadas é a comunidade UNIX, que tem como tradição chamá-las de linguagens pequenas ou mini-linguagens. Como exemplo, existem os arquivos de configuração utilizados em sistemas UNIX (e.g. Makefile), que podem ser vistos como uma DSL para descrever o processo de construção (compilação, bibliotecas, diretórios, etc.) de um sistema. Um bom exemplo é expressão regular, usada para reconhecimento de padrões de textos disponível em praticamente qualquer plataforma de desenvolvimento (e.g. Java, C#, Ruby). Outra comunidade que se destaca por utilizar essa técnica desde o inicio é a comunidade LISP, que há muito tempo tem o hábito de criar DSLs utilizando a própria sintaxe da linguagem. Por ter uma característica metacircular (Abelson & Sussman, 1996), na qual os dados e o programa usuário estão no mesmo espaço de memória, então o interpretador age como uma ponte entre os objetos de dados que são manipulados pela linguagem de programação e a própria linguagem de programação. A forma na qual as pessoas desenvolvem sistemas em LISP se inicia com a concepção de uma linguagem personalizada para descrever o sistema obtendo um novo “dialeto” de LISP, e a partir dele, descreve-se a solução do problema por meio dessa extensão funcional (i.e. Emacs Lisp, Auto Lisp). Essa idéia de construir uma linguagem embutida em outra também é bastante utilizada pela comunidade Ruby que utiliza de recursos de metaprogramação da linguagem (apresentado inicialmente por Kiczales & Rivieres (1991)) para alcançar o mesmo objetivo. De certa forma, bibliotecas de aplicações (APIs) são competidoras de DSLs (Mernik et al., 2005). Na maioria das vezes a linguagem utilizada para solucionar um problema é construída na forma de bibliotecas. Utiliza classes, atributos e métodos na sua implementação (no caso de linguagens orientadas a objetos) ou composição de funções (em linguagens funcionais). Desta forma, a linguagem da GPL é obrigatoriamente usada (i.e. notação de “ponto” em Java para acessar os membros de uma classe/objeto). Isto pode não ser muito adequado a um especialista de domínio, porque ele precisará conhecer as várias construções que pertencem a GPL, e que não são necessariamente úteis ao entendimento do programa (i.e. declaração de uma variável de controle para construir uma iteração em um loop). Freeman & Pryce (2006) apresentam um estudo de caso no qual uma linguagem explícita é embutida em um framework por meio de uma API fluente (tradução 10 livre do termo fluent interfaces3 ). Apesar de construída em uma linguagem com sintaxe grande e rígida (nesse caso a linguagem Java) os autores preocupam-se com a legibilidade do código e seu resultado, e assim torna a programação sobre essa API mais natural e contextualizada. O framework JMock usa interfaces encadeadas para definir uma sintaxe concisa e auto-explicativa que facilita a leitura do código e seu uso por parte de um programador, se o leitor desejar, pode ver um exemplo no apêndice A.1. Esse framework permite criar objetos mock, que são muito utilizados em desenvolvimento orientado a testes. A experiência demonstrou que a partir do momento em que a API se tornou uma DSL, o desenvolvimento ficou mais simples e direto por dois motivos destacados por Freeman & Pryce (2006): Primeiro, com uma clara separação da sintaxe e interpretação em camadas. Segundo, livrou do estilo de programação comum em Java quando apropriado, criando novas convenções, onde o estilo chamada em cadeia (call chain) faz da leitura do código mais uma especificação declarativa do que o uso de uma API imperativa (pode-se ver um exemplo de API fluente no apêndice A.2). Contrasta com uma GPL no sentido em que seus recursos sintáticos e semânticos são limitados para implementar apenas algumas funcionalidades específicas necessárias dentro de um domínio de problema e não precisa ser Turing-completa 4 . Seu valor está no fato dela representar muito melhor o vocabulário desse domínio o que torna mais fácil sua programação e entendimento por um especialista no domínio. Uma GPL (e.g. C, C#, VB, Java, Ruby, Python, LISP), por sua vez, implementa uma linguagem equivalente ao modelo de máquina de Turing, e permite desenvolver soluções para qualquer domínios. A interface de programação de uma aplicação (API) constitui um vocabulário específico de domínio, com nomes de classes, métodos e funções disponíveis para criação de um programa em uma GPL. Contudo uma DSL oferece especificidade de domínio de uma maneira melhor como é destacado por Mernik et al. (2005): • Notação específica de domínio estabelecida ou apropriada vão além dos operadores disponíveis na GPL. Não devem ser subestimados já que estão associados a maior produtividade; • Construções e abstrações específicas de domínio nem sempre podem ser mapeadas para funções e/ou objetos de uma biblioteca; • Uso de uma DSL oferece possibilidade de análise, verificação, otimização, paralelização e transformação; no caso de uma GPL, devido à padronização do 3 Termo criado por Martin Fowler sobre um estilo de programação que objetiva criar um código de fácil leitura, veja mais em: http://martinfowler.com/bliki/FluentInterface.html 4 http://en.wikipedia.org/wiki/Turing_completeness 11 código-fonte torna-se muito complexo ou não é bem definido; • Ao contrário de uma GPL, uma DSL não precisa ser executável — apesar de que não existe acordo sobre isso na literatura segundo Wile (2001) e van Deursen et al. (2000). Outro aspecto importante no que tange às DSLs é que também são consideradas como uma forma de reuso de artefatos de software (Biggerstaff, 1998). Os artefatos nesse caso são: a gramática, o código fonte e as abstrações modeladas. A partir desse modelo, também é possível gerar aplicações completas segundo Krueger (1992) apud Mernik et al. (2005). Freeman & Pryce (2006) descrevem uma DSL para o domínio de teste de software que começou sua história na forma de uma biblioteca de classes (API) que implementava as funções do framework e depois evoluiu para uma linguagem embutida, a qual é explicada na seção 2.3.2. É essa evolução postulada como nível mais maduro desse framework o que facilita seu uso e disseminação. 2.3 Classificação A maior parte das DSLs encontradas atualmente é textual, mas também existem na forma gráfica. As DSLs gráficas necessitam de uma ferramenta e símbolos para representar sua notação, como também um gerador de artefatos (e.g. código, dados, arquivos de configuração) e são chamadas de linguagens de modelagem específica de domínio. Uma importante forma de classificar os tipos de DSLs encontrados pode ser feita de acordo com sua forma de construção, que as divide entre DSLs externas e internas. 2.3.1 DSL Externa Uma DSL externa é uma linguagem que pode ser compilada, interpretada ou executada, e tem uma sintaxe própria ou usa alguma representação pré-definida como YAML Ain’t Markup Language (YAML) ou Extensible Markup Language XML — como por exemplo Extensible Application Markup Language (XAML) e XML User Interface Language (XUL) — entre outras, mas precisa de um parser para processá-las, um gerador de código objeto, ligação de bibliotecas, etc. Trata-se de uma linguagem construída muitas vezes da mesma forma que linguagens tradicionais completas. Tem-se total liberdade para criar sua estrutura sintática e semântica. Existem ferramentas tais como analisadores léxicos e sintáticos (e.g. lex, yacc) e geradores de parser (e.g. ANTLR Parr (2007)) que são utilizados na construção, compilação e interpretação da linguagem. 12 São exemplos de DSLs externas: arquivos de configuração de ferramentas para compilação em Java (ANT5 ), em .NET (NANT6 ), em C/C++ (Make7 ) e em Ruby (Rake8 ). Todos estes utilizam uma linguagem personalizada que descreve as dependências entre as partes do sistema no processo de compilação e ligação. Outros exemplos citados por Fowler (2008) incluem: CSS, expressões regulares, SQL, HQL, linguagem gráfica de pontos graphviz, FIT, arquivo de configuração que utilizam notação XML como do Struts, Spring, Java Server Faces (JSF) e Enterprise Java Beans (EJB) 2.x. Como exemplo histórico, a NASA utiliza de DSL desde a década de 60 para computação vetorial no projeto Apollo 9 . 2.3.2 DSL Interna Também chamada embutida (embedded language), é uma linguagem expressa dentro de uma GPL. Essa modalidade requer uma linguagem “hospedeira” e sua sintaxe é valida dentro da linguagem de propósito geral que a contém. A partir dessa extensão da linguagem base podem-se personalizar os símbolos e mecanismos de controle de uma maneira especial de acordo com a necessidade do domínio ao desenvolver essa nova linguagem. Quando uma DSL não vai além do nível de uma biblioteca da aplicação (isto é não tem um compilador que a transforma em código de máquina) é chamada também de DSEL (Domain Specific Embedded Language) segundo Hudak (1996). Usa-se o termo DSL Interna no lugar de DSL Embutida para não confundir com linguagens de scripting (e.g. JavaScript) utilizada na construção de aplicações, embora o segundo termo tenha sido mais utilizado historicamente pela academia, atualmente a mesma técnica tem sido chamada pelos praticantes de linguagem específica de domínio interna (Fowler, 2008). São exemplos de DSLs internas: parte do framework Ruby on Rails (e.g. ActiveRecords para mapeamento objeto-relacional), dialeto LISP para programação do editor Emacs, expectativas com JMock em Java, etc. 2.4 Método de Desenvolvimento Não é fácil de determinar quando e como construir DSLs, vantagens como aumento de produtividade, facilidade de manutenção, rápido processo de aprendizado, além de ser uma maneira de reutilizar artefatos de software, não são obtidas sem 5 http://ant.apache.org/ http://nant.sourceforge.net/ 7 http://www.gnu.org/software/make/ 8 http://rake.rubyforge.org/ 9 http://www.ibiblio.org/apollo/assembly_language_manual.html 6 13 grandes esforços. Contudo deve-se considerar ainda os seguintes itens: • Existe dificuldade no desenvolvimento da DSL pois se requer especialistas na linguagem e no domínio; • Diversas técnicas de desenvolvimento são encontradas, portanto requer consideração cuidadosa dos fatores envolvidos; • Dependendo do tamanho da comunidade de usuários, demanda alto custo na criação de material de treinamento, suporte, padronização e manutenção. Seu desenvolvimento também pode vir posteriormente na forma de reengenharia de software ou evolução do software (Bennett & Rajlich, 2000). Na literatura encontram-se importantes contribuições como o trabalho de van Deursen et al. (2000) que é uma bibliografia anotada e serve de referência histórica sobre o assunto. O trabalho de Mernik et al. (2005) trata-se de um survey que objetiva responder as perguntas: quando e como construir DSLs. Trata-se de um dos poucos trabalhos que oferecem um guia ou método para criação de DSLs, apresentando uma revisão sistemática dos vários fatores envolvidos, por meio da identificação de padrões em cada uma das fases de desenvolvimento: decisão, análise, projeto e implementação. Grande parte da metodologia descrita nas seções 2.4.1, 2.4.2 e 2.4.3 foi extraída deste trabalho Mernik et al. (2005), sendo que algumas técnicas de implementação consideradas na seção 2.4.4 podem ser encontradas em Fowler (2008), Fernandez (2007), Kilmer (2008), Ford (2008), Subramaniam (2008) e Parr (2007). A seguir serão apresentadas as fases no desenvolvimento de uma DSL e os padrões destacados no que tange a este trabalho em particular. Na prática, o desenvolvimento de uma DSL não é um processo seqüencial, no qual o processo decisório pode ser influenciado por uma análise preliminar, e o projeto é muitas vezes influenciado por restrições ou diretivas de implementação. 2.4.1 Decisão Para determinar quando o desenvolvimento de uma DSL deve ser aplicado, usa-se os padrões de decisão conforme destacados na Tabela 2.1, extraído de Mernik et al. (2005), pode-se observar que esses padrões ajudam no processo decisório sobre a devida aplicação de uma DSL. 14 Tabela 2.1: Padrões de Decisão O padrão Interaction, por exemplo, objetiva tornar a interação programável. Esse padrão é definido da seguinte forma: Interações baseadas em menu ou texto freqüentemente devem ser suportadas por uma DSL apropriada para especificar entradas complicadas ou repetitivas de dados. A linguagem de macro do Excel suporta sua manipulação interativa o que a torna programável. Seguem alguns exemplos de linguagens criadas nas quais observou-se a utilização do padrão Interaction: CHEM, FPIC, Fran, Mawl, Service Combinators. Outras linguagens associadas a outros padrões, bem como suas referências, podem ser vistas na Tabela 2.2, encontrado em Mernik et al. (2005). Um exemplo de DSL que não é apresentado na tabela, mas foi possível notar que segue o mesmo padrão de decisão é a WebDSL. A WebDSL é utilizada para implementação de aplicações web dinâmicas (Groenewegen et al., 2008). Também é fácil evidenciar o padrão GUI construction, já que normalmente a construção de interface gráfica é feita por meio de DSLs (e.g. XUL, XAML, JavaFX). Tabela 2.2: Exemplos para os Padrões de Decisão 15 2.4.2 Análise Para a fase de Análise: o domínio do problema é identificado e o conhecimento sobre esse domínio é adquirido. Para isso várias fontes de informações sobre o domínio (implícitas e explícitas) são necessárias, como documentos técnicos, conhecimento fornecido por um especialista de domínio, código pré-existente e questionários com clientes e usuários. O resultado da análise de domínio consiste basicamente de terminologia e semântica da linguagem, existe uma forte relação entre a “Análise de Domínio” e “Engenharia de Informação” para capturar conhecimento, representar conhecimento e desenvolvimento de ontologias (Denny (2003) apud Mernik et al. (2005)) que também pode ser útil nessa fase de análise. Padrões de análise são destacados na Tabela 2.3, extraído de Mernik et al. (2005), sendo que muitas vezes essa análise de domínio é feita de maneira informal. Tabela 2.3: Padrões de Análise A partir da análise pode-se construir um modelo de domínio. Esse modelo é constituído da seguinte forma: • definição do domínio e especificação do escopo; • terminologia do domínio (vocabulário, ontologia); • descrição dos conceitos do domínio; • modelo de requisitos que descreve o que é constante e variável no domínio, conceitos e suas interdependências. Note que o modelo de execução de uma DSL é muito mais rico do que para uma GPL, pois, com base em uma única análise de domínio muitas DSLs diferentes podem ser desenvolvidas sendo que todas compartilham características importantes encontradas nos requisitos. 2.4.3 Projeto Abordagens para projetar uma DSL podem ser caracterizadas por duas dimensões ortogonais: (1) a relação da DSL com linguagens existentes, e (2) a natureza 16 formal da descrição do projeto. Pode-se observar os padrões de projeto na Tabela 2.4 e exemplos de linguagens que seguem esses padrões na Tabela 2.5 — ambas extraídas de Mernik et al. (2005). Tabela 2.4: Padrões de Projeto Tabela 2.5: Exemplos de linguagens para os Padrões de Projeto Uma das formas mais utilizadas para se projetar uma nova linguagem é fazer uma extensão funcional ou sintática em uma linguagem já existente, com o benefício de ter usuários já familiarizados com a sintaxe da linguagem original. Dessa maneira adicionam-se novos recursos de acordo com os conceitos do domínio, e aproveitam-se recursos que já existem na linguagem base. O desafio é integrar recursos específicos do domínio com o resto da linguagem de uma maneira que não haja conflitos. Como exemplo, tem as comunidades de LISP e Ruby que utilizam com freqüência o padrão de exploração de uma linguagem por meio de extensão, onde uma linguagem pré-existente é estendida para acomodar DSLs. Em um projeto informal, a especificação é normalmente feita por meio de uma linguagem natural, e provavelmente inclui um conjunto de programas para ilustrar o uso da DSL. Já o desenvolvimento de uma descrição formal possibilita a aplicação de ferramentas de desenvolvimento de linguagens que são capazes de gerar uma implementação automática de parsers e analisadores sintáticos. 17 A indústria também tem investido na criação de ferramentas desse tipo, como por exemplo, o Eclipse Modeling Project (EclipseFoundation, 2009), Xtext (OpenArchitectureWare, 2009), Netbeans Generic Languages Framework (Netbeans, 2009), Microsoft OSLO (Microsoft, 2009), e outras. A Tabela 2.6 apresenta outras ferramentas observadas no survey de Mernik et al. (2005). Tabela 2.6: Sistemas e Ferramentas de Desenvolvimento de Linguagem 2.4.4 Implementação Quando uma DSL executável é projetada é preciso escolher sob qual ótica ela é implementada: na forma de um interpretador, um compilador/gerador de aplicações, um pré-processador, uma linguagem embutida ou híbrida que trata-se da combinação de mais de uma forma. Pode-se observar padrões de implementação na Tabela 2.7, encontrado em Mernik et al. (2005), que auxiliam no processo de escolha. Tabela 2.7: Padrões de Implementação para DSLs executáveis 2.5 Considerações Em virtude das dificuldades que surgem ao se criar uma nova linguagem, como definir seus símbolos e sua sintaxe, normalmente opta-se pelo uso de mecanismos 18 encontrados nas linguagens padrões, porém estes podem não suportar devidamente as abstrações exigidas pela aplicação e consequentemente perderem expressividade, com a intercalação sem critério da sintaxe da própria linguagem de programação com as abstrações do modelo de domínio. Portanto, a opção pelas DSLs justifica-se pelo fato destas permitirem que soluções sejam expressas no idioma e nível de abstração do problema de domínio, e desta forma possibilitam à especialistas de domínio (não programadores) poderem entender, validar, modificar e até mesmo criar programas por meio dessas linguagens específicas. 19 Seção 3 Mídia Cruzada e Governo Eletrônico “As sociedades sempre foram moldadas mais pela natureza dos meios do que pelo conteúdo da comunicação.” (Marshall McLuhan) Este capítulo introduz o domínio de aplicação no qual este trabalho está inserido, primeiramente apresenta o conceito de mídia e mídia cruzada, seguido pela sua aplicação em governo eletrônico. Os termos mídia cruzada, cross-media, crossmedia e transmedia serão utilizados de forma intercambiada para se referir a mesma coisa de acordo com os autores e contextos apresentados — diferentes autores utilizam esses termos em conformidade apenas com sua área de aplicação. 3.1 Mídia Cruzada Para se entender mídia cruzada é necessário analisar o conceito de mídia empregado em comunicação e posteriormente como esse conceito é expandido para múltiplas mídias. 3.1.1 Definição de Mídia Para esse trabalho entende-se como mídia os meios pelos quais as mensagens chegam até o público. A própria palavra mídia deriva do latim media, que quer dizer meio. Na mídia tradicional o público era mero receptor da mensagem, sem a possibilidade de interagir com esta pelo meio na qual ela foi produzida, porem isso mudou, atualmente existem muitos meios para a difusão de mensagens que permitem 20 a interação do receptor, por exemplo web, e-mail, twitter, sms, mms, portal de voz, entre outros. Segundo Cunha (2006): “É esta mesma recepção que, em momento de expansão tecnológica mais propício, assume o papel da narração antes delegado a outros centros emissores e busca construir um conteúdo cada vez mais individualizado. Para tanto, a recepção se apropria das linguagens que estão na base de qualquer narração midiática e passa a produzir para si e para os públicos que se auto-organizam na rede.” Ainda, no que se refere ao conceito de mídia, Lima (2001) consegue articular uma definição mais precisa do que mídia significa hoje e esclarece um pouco mais a íntima conexão entre comunicação e mídia. Segundo ele, mídia pode ser entendida como o conjunto de instituições que utilizam tecnologias específicas para realizar a comunicação humana. Vale dizer que a mídia implica a existência de um intermediário tecnológico para que a comunicação se realize. A comunicação passa, portanto, a ser uma comunicação mediatizada. Dessa forma, aparece um tipo específico de comunicação que constitui um dos importantes símbolos da modernidade. Em outras palavras, se assim como afirmou Lima é imprescindível a existencia de um intermediário tecnológico para que a comunicação se realize, quando fala-se em mídia cruzada esta mesma comunicação só se tornará possível a partir da interação de múltiplos dispositivos que necessitam de alguma rede para distribuição dessas mídias como por exemplo a Internet. A Internet é um dos intermediários tecnológicos que torna possível as pessoas se comunicarem sobre diversas mídias. Padrões mantidos pelo Internet Engineering Task Force (IETF) foram criados para definir os tipos de mídias suportadas na rede — o tipo de mídia da internet foi derivado do Multipurpose Internet Mail Extensions (Mime), criado para que diversos tipos de conteúdos fossem incluídos em e-mail, e expandiu para outros protocolos (e.g. Hypertext Transfer Protocol, Real-time Transport Protocol, Session Initiation Protocol). Por meio do Mime Type, o tipo de mídia transportado é definido a partir de um tipo e subtipo, como por exemplo: text/html (para transporte de hypertexto), image/gif (para transporte de imagem no formato gif), application/pdf (para transporte de um documento no formato pdf), entre outros. Podese consultar tipos de mídias suportados para imagem, audio, vídeo e aplicações na RFC2046 (Freed & Borenstein, 1996). 3.1.2 Mídia Cruzada O termo mídia cruzada (cross-media) é recente e tem significados diferentes de acordo com a disciplina em que é aplicado. Contudo, segundo Boumans (2004), existe 21 um significado comum que se traduz como o uso de múltiplos meios para propagar uma mesma mensagem com o objetivo de tornar o conteúdo mais acessível. Quando se fala em Web, o termo é associado com o uso eficiente de mais de uma plataforma técnica, que torna o conteúdo disponível para um grande número de pessoas sobre diferentes dispositivos, em marketing significa usar múltiplos canais de distribuição, e assim por diante, o conceito de cross-media vai adquirindo novas características a medida que é explorado por áreas distintas como e-learning, turismo, propaganda, etc. De acordo com Boumans (2004) podem-se observar diversos sinônimos ao termo cross-media, criados ao longo dos anos e por diferentes disciplinas, como multimídia, multiplas mídias, mídia interativa e integrada, multiplataforma, mídia convergente e híbrida. Embora o termo seja recente, o seu conceito de utilização já era empregado na década de 70 quando o conteúdo de enciclopédias eram distribuídos também em fita cassete, e posteriormente em CD-ROM quando o termo multimídia passou a ser utilizado. Até meados da década de 90, a idéia de cross-media (embora não com este nome) esteve ligado com o slogan “Create Once, Publish Everywhere” usado por Paul Zazzera, CEO da Time Inc. em 1996 (hoje, pertence ao grupo Time Warner e é uma das maiores companhias de conteúdo do mundo distribuídos em revistas, na web, em rádio e na televisão). Quando o termo começou a ser usado no final dos anos 90 (principalmente devido a popularização da Internet), significava obter mais informações sobre um programa na Web. Somente em 1999, com o lançamento do programa de televisão Big Brother, criado pela produtora Endemol na Holanda, e seu respectivo sucesso, o termo cross-media bem como seu uso em áreas diversas, no caso entretenimento, popularizou-se. O programa de TV tornou-se um significativo exemplo de um bem sucedido uso de mídia cruzada, uma vez que sua imensa repercussão deveu-se ao fato que em sua veiculação foram usadas além da TV analógica, a TV interativa, telefone, celular e Internet, sendo ainda apoiado pela mídia impressa (jornal e revista) para produzir diálogos únicos sobre múltiplas mídias. Ainda, entre os exemplos de utilização de múltiplas mídias (com diálogos diferenciados em cada mídia) na industria de entretenimento, pode-se citar a trilogia Matrix que teve além dos filmes uma versão em quadrinhos e jogos e a série Lost da ABC que tem sites na web em que o usuário pode continuar a explorar o universo criado pela série. O conceito de mídia cruzada utilizado neste trabalho é semelhante aquele empregado pelo programa Big Brother (em que até o momento já ocorreram nove edições no brasil 3.1), onde são utilizados diversos meios para produzir diálogos únicos sobre múltiplas mídias. Em outras palavras, para este trabalho, mídia cruzada (cross-media) é uma forma de comunicação na qual o receptor é convidado a utilizar diferentes mídias para acessar um conteúdo que pode levá-lo para outras mídias. 22 Figura 3.1: Big Brother Brasil 9 A mídia cruzada possui cinco características que a distinguem, listadas por Boumans (2004): (1) a mídia cruzada envolve mais de uma mídia; (2) a mídia cruzada objetiva uma produção integrada; (3) o conteúdo entregue em múltiplas mídias; (4) mais de uma mídia é necessária para apoiar uma única mensagem/narrativa/meta; (5) a mensagem/narrativa/meta é distribuída em múltiplas plataformas e a interação apoiada pode acontecer nestas diferentes plataformas. No cenário atual existe uma mistura de aplicações, plataformas, dispositivos, que possibilitam o acesso de conteúdo sobre um meio, são exemplos as redes sociais e organizacionais que suportam muitas atividades humanas como jogos, compras, comunicação, até serviços públicos. Por meio destes exemplos, percebe-se o quão fundamental a Internet tornou-se, mesmo para ações corriqueiras de nosso cotidiano, e que como disse Bolter & Grusin (2000) apud Wiberg et al. (2007) a Internet segue um rumo de alto grau de convergência entre diferentes tipos de mídia e conteúdo. Um fenômeno similar a este de acordo com Wiberg et al. (2007) está sendo estudado pelas áreas de IHC e novas mídias. Esse fenômeno visto como uma mensagem contada em mais de uma mídia também é chamado de cross-media (conceito observado principalmente pelas áreas de comunicação e novas mídias). Quando uma história, ou diálogo de interação, é contada sobre mais de uma mídia e o receptor é convidado para mudar de uma mídia para outra, pode-se dizer que ocorre um diálogo cross-media e segundo Dena (2007), esse convite é chamado “call-to-action” (CTA). O “call-to-action” é um termo criado pela área de marketing que objetiva levar a pessoa a tomar uma ação diante de uma propaganda. Neste trabalho, o mesmo conceito pode ser aplicado a outros domínios como serviços de governo. Dena propõe um processo constituído por três fases que resultarão neste con23 vite à ação (CTA): (1) Preparar e motivar o ator a agir; (2) Fornecer o meio e as instruções de como e quando agir e (3) Reconhecer e recompensar a ação. O sucesso de um projeto de interação sobre mídia cruzada é evidente quando a pessoa migra de uma plataforma para outra e quando esse movimento tem um impacto positivo na experiência do próprio usuário. Essa experiência é muito diferente daquela com apenas uma mídia (forma tradicional e dominante) porque a pessoa tem que tomar uma ação muitas vezes de forma ativa, embora também possa ocorrer transições automáticas (passivas) . Existem mecanismos que podem facilitar uma transição como por exemplo o QR-CODE1 que permite um telefone celular capturar uma imagem em uma mídia impressa (jornal, revista) e levar o usuário para uma página na web que continua a narrativa, por exemplo apresentando um mapa (Dena, 2007). Ainda hoje no Brasil, o principal meio pelo qual as pessoas buscam se informar é a televisão, sendo seu número em domicílios muito mais representativo do que o de computadores, estejam estes conectados ou não a internet, seguidos apenas pelo número de telefones usados principalmente para serviços de voz 2 . Assim, tendo em vista este contexto sócio-cultural, este conceito de comunicação (cross-media) tornase mais atrativo aos olhos do cidadão, uma vez que o conteúdo chega até ele pela TV, telefone fixo, celular, além da mídia impressa e do computador. Este é um fator chave para explicar a necessidade do governo em comunicar-se com o cidadão por diversas mídias ampliando sua presença em todos os extratos sociais. No futuro, usuários estarão tão acostumados a cross-media que não irão notar sua presença, mas irão perceber sua falta Boumans (2004). 3.2 Governo Eletrônico em Mídia Cruzada Com base nos conceitos anteriormente expostos de mídia e mídia cruzada, nesse ponto faz-se necessário mostrar como podem ser aplicados em governo eletrônico. A seguir são apresentadas as formas de comunicação utilizadas pelo governo, o que são esses serviços e como eles podem ser mapeados para o desenvolvimento de uma solução tecnológica. 3.2.1 e-gov, m-gov, t-gov, x-gov Atualmente o governo se relaciona com os cidadãos tanto fisica quanto virtualmente. Cada vez mais conta-se com o auxílio de dispositivos computacionais que 1 QR-CODE é um tipo de código de barras de duas dimensões contendo um conjunto limitado de dados que pode ser por exemplo um endereço na internet ou uma imagem 2 O CGI.BR faz uma pesquisa anual sobre o uso das Tecnologias da Informação e da Comunicação no Brasil que pode ser vista em http://cetic.br/usuarios/index.htm 24 permitem a interação do governo com o cidadão, e a mídia cruzada é uma forma de ampliar ambas as formas de relacionamento. Os acrônimos e-gov, m-gov, t-gov apresentam meios pelos quais o governo interage com o cidadão, e-gov sendo pelo meio eletrônico (usualmente pela web3 ), mgov é normalmente quando o usuário interage por meio de um telefone celular, e t-gov é a interação do cidadão com o governo pela tv (em um futuro próximo com a tv digital essa interação também será bidirecional). O termo x-gov, mais recente, determina o uso das diversas mídias (daí o “x” que refere-se a cross em inglês) para interação do governo com o cidadão. Para Filgueiras (2007) x-gov é definido como sendo a entrega de serviços de governo em mídia cruzada, na qual a comunicação G2C é apoiada por diversos meios alternativos, cada qual direcionando o cidadão ao próximo passo no processo de interação e ao meio mais adequado a este passo . . . x-gov difere das demais aplicações de mídia cruzada porque no x-gov a narrativa principal deve ser apoiada por mídias alternativas. Nas demais aplicações, há uma mídia principal (em geral, a TV) que apóia o tema central. Apesar dos esforços do governo e das entidades civis o acesso a internet ainda é restrito a um pequeno número de pessoas (comparando esse número com toda população do país), assim, o governo eletrônico brasileiro não pode se apoiar apenas nesse meio, mas deve explorar outros meios de comunicação. Alguns benefícios do método x-gov, segundo o relatório de Filgueiras (2007) são: • aumentar o número de alternativas pelas quais o cidadão alcança o governo, bem como a possibilidade de obter esse acesso a qualquer momento, de qualquer lugar; • mover a interação eletrônica para além do ponto em que ela se interrompe hoje: transações eletrônicas são substituídas por interações presenciais; • favorecimento de uma diversidade de usuário, pessoas com algum tipo de deficiência podem se comunicar com o governo pelo canal mais adequado a elas; • a vida moderna exige a linguagem de mídia cruzada: envia-se um e-mail ao mesmo tempo em que se conversa ao telefone e acompanha o noticiário na TV. 3.2.2 Serviços de Governo Como dito anteriormente, conceito de cross-media tornou-se popular em diferentes contextos como no meio artístico, de jogos, filmes, rádio e TV. Com a tecnologia 3 pode-se ver um exemplo de diversos serviços oferecidos pelo governo do estado de São Paulo em http://www.cidadao.sp.gov.br/ 25 digital e uma gama cada vez maior de dispositivos, o conteúdo pode ser acessado, transmitido e armazenado facilmente em diversas plataformas. Apesar do aspecto de entretenimento, este conceito é facilmente extrapolado para outras aplicações, como neste trabalho para serviços de governo. O dicionário Oxford (2a edição) define serviço como “(1) a ação de ajudar ou fazer trabalho para alguém; (2) um sistema que fornece uma necessidade pública como transporte, comunicação, ou utilidades como elétrica e de saneamento”. É necessário estreitar essa definição para serviços públicos que são executados por uma unidade/departamento/organização do governo para atender seus cidadãos. Usando este conceito entende-se como serviço de governo: serviços executados por uma unidade/departamento/organização do governo com objetivo de fornecer um bem público. Para ser melhor compreendido, um determinado serviço de governo deve ser decomposto em um conjunto de atividades que serão executadas por um ator, podendo ser este uma unidade/departamento/organização/representante do governo ou um cidadão (pessoa física ou jurídica) que precise desempenhar essas atividades. Normalmente o ator deverá executar vários passos para atingir seu objetivo, e existem vários recursos como informação, dinheiro, dcumentos entre outros que devem ser trocados durante o processo. Dentro de cada passo existe um diálogo entre o ator e a ação que precisa ser executada, um conceito popularmente conhecido como round ou rodada de acordo com Filgueiras (2007). Ainda, é importante ressaltar a escolha de mídias ideais para um serviço, partindo, por um lado, das características de apresentação, geração ou recebimento de cada mídia e, por outro, das necessidade de recursos (informação, transação financeira, documento) de cada etapa do serviço. A produção de conteúdo sobre as diferentes mídias deve ser complementar para que a pessoa possa (1) em alguns casos, escolher qual quer usar; (2) usar a mídia mais adequada para uma certa situação como por exemplo, ter disponível apenas o telefone celular quando estiver em trânsito; e (3) usá-las simultaneamente para apoiar uma narrativa/atividade/meta. Dessa forma surgem tres conceitos que podem ser benéficos para serviços de governo (Miyamaru et al., 2008a), abaixo descritos: 1. Corroboração 2. Concomitância 3. Completude Corroboração prega que as mídias carreguem o mesmo conteúdo, o que reforça a mensagem para o receptor. O conceito de Concomitância determina que uma mídia esteja conectada com outra mídia (normalmente sobre outro dispositivo) e essa conexão permite criar um sincronismo entre as mídias. O conceito de Completude é 26 Figura 3.2: Cadeia de Conteúdo Digital [Fonte: Boumans2004] aplicado quando uma determinada informação não é adequada para ser entregue em uma mídia, então o dialogo prossegue em outra. 3.2.3 Padrões de Tarefas para Serviços de Governo Em virtude das questões apresentadas em 3.1.2 e em 3.2.2, compreendeuse que um projeto de interação integrado de múltiplas mídias/plataformas/dispositivos deve contemplar toda a cadeia de produção de conteúdo digital (apresentado na figura 3.2) desde a criação até o consumo desse conteúdo (Boumans, 2004, p 6). O propósito de um projeto de interação em mídia cruzada, ou Cross-Media Interaction Design (CMID), é mostrar o conteúdo que deve estar disponível em cada mídia, levando em consideração as características do conteúdo e da mídia, do dispositivo, e do meio de distribuição. CMID é uma particularização da multimodalidade, já que contempla um projeto de movimento sobre diferentes modalidades de interação. Um projeto de interação sobre mídia cruzada preocupa-se com aspectos que possibilitem transitar sobre as diferentes modalidades, no qual o ator, dessa transição, é o usuário que segue dicas migratórias criadas pelo projetista como caminhos de uma narrativa. Ainda no projeto deve ser definido como implementar uma narrativa (do inglês storytelling), e quais metáforas são mais adequadas para a interação com o usuário. Assim, segundo Miyamaru et al. (2008b), padrões de tarefas são boas soluções para projeto de interação com serviços de governo e são convenientes para aplicações disponíveis em múltiplos dispositivos, uma vez que padrões de tarefa capturam a dimensão humana da interação, sendo capazes de expressar intenções humanas que devem ser atendidas pela interface de usuário. 27 A etapa inicial deste trabalho foi desenvolver, junto com outros pesquisadores, 18 padrões de tarefa para expressar o uso de serviços de governo em ambiente de mídia cruzada. Para isso foram analisados 30 serviços públicos dos quais 27 estavam disponíveis pela internet, 6 foram serviços que requerem a presença do cidadão em alguma etapa e 2 foram serviços disponíveis para celulares. 4 Os 18 padrões de tarefa para governo eletrônico em mídia cruzada foram divididos em 4 categorias da seguinte forma: • Informação: (1) Obter informações a respeito de um serviço; (2) Enviar informações para o governo; (3) Enviar informações pessoais; (4) Encontrar informações públicas; (5) Encontrar informações sobre alguma entidade e (6) Encontrar informação privada. • Documento: (7) Obter documento com assinatura digital; (8) Criar uma fatura; (9) Verificar validade de um documento; (10) Imprimir documento e (11) Salvar como arquivo. • Transação: (12) Autenticação; (13) Obter identificador do processo; (14) Pagar taxa/imposto e (15) Agendamento. • Relacionamento: (16) Falar com ombudsman; (17) Receber uma mensagem e (18) Acompanhar um processo. 4 A lista completa dos padrões de tarefa e outros detalhes pode ser obtida no site http://lts-i. pcs.usp.br/index.php/projetos/xgov/63. 28 Seção 4 Framework X-Gov “Para visão exigem-se três coisas, o objeto, o orgão e o meio.” (Raymond Williams) O desenvolvimento do arcabouço tecnológico chamado de Framework X-Gov tem o objetivo de projetar e desenvolver uma arquitetura reutilizável de componentes computacionais para a criação de serviços de governo em mídia cruzada. Fez parte deste trabalho elaborar a arquitetura do Framework que é descrito nessa seção, assim como uma forma alternativa de programar aplicações geradas a partir dele por meio de uma linguagem específica de domínio. A seguir é apresentada a arquitetura definida, seu conceito e propósito, assim como um detalhamento de suas partes integrantes. Essa arquitetura oferece uma visão de alto nível do projeto que pode ser aplicado a outros domínios com requisitos semelhantes como: utilização de componentes para criar aplicações em ambiente de mídia cruzada. O termo x-gov ou X-Gov representa um serviço de governo sobre mídia cruzada arbitrário, enquanto Framework X-Gov (FXG) será usado para se referenciar ao arcabouço de software criado para apoiar o desenvolvimento desse tipo de sistema. 4.1 Conceito Governo eletrônico em mídia cruzada, ou simplesmente X-Gov, trata-se de um sistema complexo que busca integrar diversas plataformas computacionais, dispositivos e mídias para permitir a interação do cidadão com o governo por esses múltiplos meios. Visto desta forma, é um sistema complexo, distribuído, no qual um arcabouço 29 tecnológico se faz necessário para permitir que sejam construídas aplicações desse tipo. O conceito de framework pode ser entendido como uma arquitetura (design) reutilizável em seu todo ou como parte de um sistema, que é representado por um conjunto de classes e a forma pela qual suas instâncias interagem. Outra definição comum para framework é compará-lo ao esqueleto de uma aplicação que pode ser personalizado por um desenvolvedor. Enquanto a primeira definição descreve a estrutura de um framework, a segunda descreve seu propósito (Johnson, 1997). O propósito do Framework X-Gov é permitir que gestores públicos1 definam um ou mais serviços de governo em um ambiente de mídia cruzada. O processo para definir um serviço de governo (de maneira macroscópica) significa planejar quais as atividades de um serviço, o padrão de tarefa e as mídias a serem utilizadas em cada atividade, além das transições que ocorrem entre as mídias — a composição desse processo pode ser analisado na figura 4.1 onde um portal de governo eletrônico é representado por um conjunto de serviços, que por sua vez possui um conjunto de atividades e associado a cada atividade uma ou mais mídias. Figura 4.1: Composição de um X-Gov 1 generalização de um funcionário público que pode ser a equipe técnica de uma unidade/departamento/organização do governo 30 4.2 Arquitetura O diagrama de deployment de alto-nível apresentado na figura 4.2 apresenta as partes do FXG, como elas são distribuídas nos seus respectivos nós de hardware e os protocolos de comunicação. A decisão por utilizar Web Services na comunicação dos componentes com o servidor X-Gov oferece um baixo acoplamento entre os componentes distribuídos nos diferentes dispositivos e o servidor. Essa decisão também é apoiada pela proposta de que um serviço ou cliente de Web Service podem ser construídos em diferentes plataformas de desenvolvimento, o que garante a interoperabilidade necessária a esta arquitetura. Figura 4.2: Arquitetura X-Gov 4.2.1 Modelo de Domínio O modelo de domínio apresentado na figura 4.3 detalha os principais objetos criados para descrevem a estrutura de classe dos componentes do Framework XGov 2 . Outros diagramas com classes criadas até o momento podem ser vistos no apêndice 4. Os padrões de tarefa foram obtidos pela equipe do projeto X-Gov em 2 Por convenção determinada no projeto, os módulos, as classes, as propriedades, e operações, foram nomeados em inglês e são trazidos aqui dessa forma por tratar-se de um projeto de cunho internacional. 31 um trabalho (do qual o autor deste trabalho participou) em que 32 sites de governo eletrônico foram analisados para se obterem as tarefas humanas recorrentes. Estas tarefas foram modeladas usando-se o conceito de design patterns3 . Figura 4.3: ComponentModel No modelo, observe que existe uma classe que representa todos os componentes chamada ‘Component’ especializada para cada tipo de padrão de tarefa identificado como ‘FindEntityInfoComponent’, ‘AuthenticationComponent’ e ‘PayFeeTaxComponent’. Por sua vez os padrões de tarefa são implementados para cada uma das mídias alvo do projeto (tv, web e mobile). Existe uma classe que representa todas as transições ‘Transition’ e outra que representa navegações ‘ComponentConnection’. Essas classes servem para embutir dados e comportamentos necessários para implementação de cada componente em cada mídia. Todas compartilham uma estrutura básica de propriedades (identificação do componente, seu nome, seu tipo) para o correto funcionamento das partes integrantes do FXG. Cada especialização dessa classe corresponde a um padrão de tarefa identificado na análise de serviços de governo realizada anteriormente (3.2.3). Por exemplo, o componente que implementa o padrão de tarefa ‘Obtain preservice information’ é definido pela classe ‘GetPreServiceInfoComponent’ depositada 3 verificar no endereço http://lts-i.pcs.usp.br/ onde está o trabalho de task patterns. 32 na camada de domínio da aplicação, e cada versão específica para uma mídia corresponde a uma especialização dessa classe. Assim, as classes relacionadas com a implementação de um componente herdam operações e atributos determinados pelo padrão de tarefa. Foi feita uma análise de vários padrões de tarefa para encontrar todos elementos necessários à sua implementação, onde esses elementos foram capturados na forma de classes, atributos e métodos. Este processo é semelhante ao processo de “sedimentação” (Fach, 2001) no qual os elementos analisados são colocados em camadas, e os elementos de camadas superiores utilizam os elementos das camadas inferiores. No desenvolvimento do Framework foram criados componentes para atender cada um dos padrões de tarefa estudados. O conjunto dessas classes correspondem a um módulo chamado FrameworkLibrary. Para atender a um novo padrão de tarefa, é necessário apenas adicionar ao FrameworkLibrary novas classes que a partir desse momento, podem ser utilizadas em um serviço de governo — o conjunto de classes do FrameworkLibrary corresponde aos objetos de domínio da aplicação. Cada nova mídia incluída também necessita de especializações das classes correspondentes aos padrões de tarefa em que essa mídia pode ser aplicada. 4.2.2 Componentes A idéia de reuso de software sempre esteve associada à componentes os quais podem ser facilmente conectados para montagem de um sistema. Inclusive, assim, surgiram ambientes de programação orientados a componentes (e.g. Visual Basic, Delphi). A mesma idéia é aplicada ao Framework X-Gov, onde um determinado tipo de componente foi criado para atender um padrão de tarefa, e especializado para cada uma das mídias suportadas: tv, mobile e web. A biblioteca de componentes tem o importante papel de fornecer soluções padronizadas para o projeto de um serviço de governo elaborado pelo gestor público. Do ponto de vista técnico, por ser construído com linguagens orientadas a objeto, o Framework X-Gov é uma coleção de classes dos quais originam seus objetos que trabalham em cooperação, formando assim uma biblioteca de componentes. Cada componente foi originado a partir de um padrão de tarefa, por exemplo, o padrão ‘Get track id’, que corresponde à tarefa de obter um número de processo para ser futuramente acompanhado, originou um componente representado pela classe ‘GetTrackIdComponent’. Como cada mídia tem necessidades específicas, essa classe foi especializada gerando outras 3 classes: ‘WebGetTrackIdComponent’, ‘TVGetTrackIdComponent’ e ‘MobGetTrackIdComponent’ — veja na figura 4.4. 33 Figura 4.4: Componente GetTrackIdComponent Os componentes de interface são as peças que representam as soluções para as tarefas de interação do cidadão em cada mídia. O componente oferece os elementos de interface com o usuário como uma página web, uma mensagem SMS, um e-mail, ou um programa interativo da TVDi, etc. O objetivo de passar um componente pelo processo de sedimentação é torná-lo menor e mais flexível, uma vez que um componente novo realiza uma tarefa macro, com pouca flexibilidade. A tendência é que a tarefa realizada por um componente seja dividida em tarefas menores e com maiores opções de configurações, permitindo uma composição de componentes mais flexível. Os padrões de tarefa apresentados, e resumidos pela figura 4.5, estão conectados aos componentes de interface de usuário. Dessa forma, faz parte do Framework X-Gov uma biblioteca de componentes composta pelos 18 padrões de tarefa com suporte para 3 mídias, totalizando 54 tipos diferentes de componentes. 34 Figura 4.5: Padrões de Tarefas No entanto, é impossível criar uma biblioteca com extensão suficiente para cobrir todas as necessidades atuais e futuras. A arquitetura do FXG permite a extensão desses componentes para aplicação em outros serviços que necessitem de novos componentes ou versões modificadas dos mesmos. Conforme exposto, deve existir a possibilidade de se criar e adicionar novos componentes. As novas classes criadas devem seguir a mesma estrutura definida pelas outras classes, ou reutilizar classes que existam em camadas inferiores. O mecanismo para criar novos componentes, considerando que os componentes podem ser feitos em diferentes plataformas de desenvolvimento como Java, .NET, Symbian, Android, etc., é seguir uma interface de programação pré-definida com métodos de retorno utilizados na integração com o FXG. O desenvolvimento dos componentes do framework X-Gov seguiu um modelo iterativo com entregas determinadas por três provas de conceito. Cada prova de conceito adicionou novas características à arquitetura, o que levou a uma nova etapa de sedimentação. Note que o conjunto de padrões de tarefa permitem criar serviços de governo além daqueles implementados nas provas de conceito. 4.3 Partes Integrantes do Framework Quando um novo serviço de governo ou a atualização de um existente é proposta por gestores públicos, eles deverão projetar como desejam que o cidadão interaja com o serviço. É necessário, portanto, um processo de modelagem que forneça 35 o ferramental para que esse serviço seja produzido, concentrando-se o projetista na escolha das tarefas a serem realizadas pelo cidadão utilizando múltiplas mídias de forma integrada. Podem-se ver os elementos gerais que compõem o FXG na figura 4.6 notandose a existencia de: • uma ferramenta capaz de modelar um serviço e suas mídias utilizada pelo gestor para descrever um serviço; • uma linguagem que descrever o que foi modelado e serve como dados de configuração para o FXG; • um repositório de componentes que contém implementações na forma de classes para cada tipo de componente; • um repositório de transições que contém a implementação na forma de classes e acionam outras aplicações externas (e.g. um servidor de e-mail) para cada tipo de transição; • um gerenciador de componentes capaz de processar os dados de configuração, instanciar componentes e transições para criar uma aplicação X-Gov. Figura 4.6: Modelo X-Gov 36 4.3.1 Gerenciador de Componentes O Gerenciador de Componentes (Component Manager ) é uma peça central do Framework X-Gov responsável por instanciar os componentes utilizados por um serviço de governo. Ele mantém uma lista de componentes em memória para que as diversas aplicações que fazem parte de um serviço possam acessar, e disponibiliza os dados destes componentes por meio de Web Services. 4.3.2 Gerenciador de Transições Essa parte do Framework X-Gov reúne uma série de mecanismos e funcionalidades para a navegação cross-media. Objetiva integrar componentes utilizados em múltiplos meios de comunicação. Oferece serviços para controle de navegação do usuário, controlar dados compartilhados entre várias mídias, semelhante a idéia de sessão web, chamada de X-Session, e possui ainda adaptadores para comunicação com servidores de e-mail, gateways de SMS, portais de voz e envio de mensagens instantâneas (e.g. MSN). 4.3.3 Linguagem de Configuração O FXG necessita de uma linguagem de modelagem para descrever um serviço que sirva para alimentar o gerenciador de componentes na hora de configurar uma nova aplicação X-Gov. A Cross-Media Language (CroMeL) é uma linguagem específica de domínio definida neste trabalho, usada para modelar um serviço de governo sobre mídia cruzada, ou simplesmente, para modelar um serviço X-Gov. Ela é capaz de descrever quais as atividades que fazem parte de um serviço, quais as mídias utilizadas em cada atividade (determinando assim os componentes), além de especificar as transições que ocorrem entre elas. Um serviço X-Gov pode ser especificado por meio de uma ferramenta gráfica chamada de X-Builder (veja figura 4.7) que gera um código XML com as informações necessárias para criar uma aplicação pelo FXG. Uma desvantagem dessa alternativa atualmente, é a falta de meios para inserir código embutido, mas que poderia ser implementada com uso de elementos XML tipo CDATA e a inclusão de outros editores no X-Builder. Outra ponto a se considerar é a necessidade do gestor utilizar essa ferramenta na hora de criar um novo serviço, seria difícil criar esse código XML sem o auxílio da ferramenta. 37 Figura 4.7: Ferramenta gráfica para descrição de um serviço A CroMeL visa facilitar a foram de descrever a conexão entre as mídias, os componentes e seus parâmetros, assim como os demais elementos de um modelo X-Gov no que diz respeito a criação de uma aplicação como o FXG. Na sua versão em XML, dos dados de configuração são gerados pela ferramenta supracitada, e o gerenciador de componentes interpreta esses dados para gerar uma aplicação X-Gov. Na versão da CroMeL, os dados de configuração são inseridos em um tipo de script e o gerenciador de componentes torna-se o interpretador desse script. A figura 4.8 destaca as partes afetadas dos elementos que compõem o FXG. 38 Figura 4.8: Configuração através do X-Builder e através da CroMeL 4.4 Conclusão O Framework X-Gov é apoiado pelo reuso de seus componente (o que contempla seus dados, interfaces e controles), e por isso garante a consistência do modelo de interação por todos os componentes em diversas instâncias de aplicações com o FXG. Do ponto de vista de IHC, devido ao reuso dos componentes, caso seja necessário realizar alterações de interface ou do modelo de interação após uma análise de usabilidade, com a simples alteração de um componente todos os serviços construídos que o utilizam serão atualizados. De acordo com Fach (2001), o processo de sedimentação funciona bem quando aplicado para a uma industria tradicional como o setor bancário, onde o domínio é conhecido e apresenta-se estável por muitos anos. Contudo, em novos campos de negócio onde o domínio da aplicação está sendo explorado ou elaborado, como é este caso, existe uma dificuldade maior para aplicar este processo na definição do seu modelo de domínio. O processo para modelar, e consequentemente, criar um novo serviço de governo com o FXG depende primeiramente da competência de um usuário conhecer os padrões de tarefa suportados pelo FXG, bem como conhecer os serviços de transição e as mídias disponíveis na hora de se modelar um serviço X-Gov. A partir daí, ele pode criar uma descrição do serviço por meio da linguagem de configuração do FXG (CroMeL) e quando a descrição é carregada pelo FXG automaticamente uma nova aplicação X-Gov é disponibilizada. É da competência dos programadores do governo ampliar os componentes, transições e mídias conforme novas necessidades de um serviço, podendo para isso reutilizar os elementos disponíveis inicialmente nos repo- 39 sitórios do FXG. Eles também devem criar integrações com os sistemas legados para que sejam utilizados por uma aplicação X-Gov. 40 Seção 5 A Linguagem CroMeL “Aquele que não conhece outras línguas não conhece a sua própria.” (GOETHE) Esse capítulo introduz a linguagem CroMeL, detalha sua sintaxe e semântica com todos os elementos necessários para modelar serviços de governo no Framework X-Gov. A sintaxe é definida por meio da notação Extended Backus–Naur Form (EBNF) e para implementação foi utilizada uma ferramenta chamada ANother Tool for Language Recognition (ANTLR)1 . 5.1 Introdução a CroMeL CroMeL significa Cross-Media Language, e seu nome já indica uma linguagem aplicada ao domínio de mídia cruzada. Por uma feliz coincidência CroMeL também é um termopar do tipo K ou E 2 , e a título de curiosidade, um termopar é a junção de dois metais utilizado para medição de temperatura. Neste caso também trata-se de uma linguagem criada com objetivo de unificar componentes presentes em diferentes mídias, particularizado para serviços de governo. CroMeL é uma linguagem específica de domínio, declarativa, que permite especificar um serviço de governo em mídia cruzada. Para entender melhor o conceito da linguagem, veja a figura 5.1 que apresenta seu contexto. Nessa figura pode-se observar que a CroMeL é uma linguagem utilizada no mapeamento de conceitos do domínio X-Gov com o Framework X-Gov, que corresponde aos conceitos de serviço, 1 2 http://www.antlr.org/ http://pt.wikipedia.org/wiki/Termopar 41 atividades, padrões de tarefa, transições e navegações com as classes que implementam esses conceitos. Figura 5.1: Contexto da linguagem CroMeL Os conceitos de domínio podem ser observados da seguinte forma: • Dentro do contexto de um serviço, pode existir diversas atividades, transições e navegações; • Uma atividade depende da determinação explícita de um padrão de tarefa, e é composta por uma ou mais declarações de mídias; • A mídia junto com o padrão de tarefa define qual implementação de componente deve ser utilizado; • As navegações permitem definir uma migração na mesma mídia; • As transições permitem definir uma maneira de migrar de uma mídia para outra. O conceito de mídia cruzada é visível na linguagem quando observa-se que a partir da declaração de uma mídia, dentro de uma atividade, pode-se declarar uma transição que leva para outra mídia da mesma ou de outra atividade. 5.1.1 Elementos da linguagem CroMeL O mapeamento dos elementos de domínio feitos pela CroMeL podem ser observados na figura 5.2. A seguir é feito um detalhamento desses elementos que fizeram parte dos requisitos para construção da gramática da linguagem. 42 Um serviço de governo é a instância de um sistema com objetivo de suprir uma necessidade pública (veja na sessão 3.2.2 mais informações sobre essa definição). Na CroMeL, um serviço é definido por um nome e um contexto formado por um conjunto de atividades, transições e navegações. Uma atividade é uma tarefa executada por um cidadão em um serviço de governo, e é definida por um nome e por um padrão de tarefa (veja na sessão 3.2.3 os padrões de tarefa disponíveis). Dentro do contexto de uma atividade, contém a declaração de uma mídia, e de acordo com o padrão de tarefa selecionado e a mídia, um tipo de componente é definido. Para cada tipo de componente, deve-se passar parâmetros utilizados na sua configuração. Por exemplo, se for declarada para a atividade ObterSenhaParaAtendimento o padrão de tarefa GetTrackId, e a mídia mobile, o tipo de componente definido será MobGetTrackIdComponent que contém uma série de propriedades chamadas de parâmetros desse componente. Uma transição é uma maneira de migrar de uma mídia para outra, e depende da definição do seu tipo — o tipo da transição, assim como o tipo do componente, determina quais os parâmetros devem ser passados, para consultar as transições disponíveis, veja a figura B.4 no apêndice B.1) — e qual é a mídia de origem e destino que deverá ocorrer uma transição. Para declarar tanto a mídia de origem quanto a mídia de destino deve-se usar o nome da atividade e o tipo de mídia declarado na atividade. Por exemplo, pode-se declarar uma transição da atividade/mídia ObterSenhaParaAtendimento.mobile para a atividade/mídia PreencherCadastro.web por uma transição do tipo PushTransitionData. Uma navegação, é mais simples que uma transição, e permite declarar um caminho de uma atividade para outra dentro da mesma mídia. Necessita apenas de um identificador dessa navegação chamado de label e qual a atividade/mídia de origem e destino. Veja que uma navegação não tem tipo e nem parâmetros de configuração e suas informações são obtidas pelos componentes de uma mídia para indicar que ele pode levar o usuário para um outro componente da mesma mídia. 43 Figura 5.2: Mapeamento de contexto na linguagem CroMeL Além dos elementos de domínio, outros elementos foram incorporados na CroMeL para incrementar a linguagem: • Uma forma de declarar variáveis utilizadas internamente na hora de atribuir va44 lores aos parâmetros dos componentes e das transições; • Uma forma de fazer referência a uma atividade/mídia por meio do nome da atividade e o tipo da mídia na hora de declarar uma navegação ou transição; • Incluir código embutido para ser executado na inicialização de cada atividade; • Comentários que não são processados pelo interpretador. Para a declaração de variáveis utilizadas internamente foi usada a forma mais comum encontrada em linguagens de programação: um identificador para a variável, o símbolo de atribuição (=) e seu valor (não sendo necessário definir o tipo). Podese recuperar o valor de uma variável, na hora de atribuir o valor de um parâmetro, adicionando-se $ antes de seu identificador. Para declarar a referência de uma atividade/mídia na determinação da origem e destino de uma navegação ou transição, foi utilizado o mesmo símbolo de passagem de parâmetro por referência da linguagem C (&), dessa forma, a referência de uma atividade/mídia deve ser escrita como &NomeAtividade.mídia. A inclusão de código embutido permite ampliar o uso de um script CroMeL na declaração das atividades, podendo conter códigos que são executados na inicialização do serviço3 . A inspiração na forma utilizada para incluir regras de negócio como código embutido veio da conceito de literate programming (Knuth, 1984) que permite que cada trecho de código seja associado com uma pequena descrição de seu significado. Comentários em múltiplas linhas foram influenciados pela notação clássica de C e outras linguagens (\* ... *\) e comentário em linha foi inspirado pela sintaxe de Ruby onde o símbolo # indica para o interpretador ignorar qualquer coisa até o final da linha. Em resumo, na definição da linguagem CroMeL foram utilizados elementos para indicar o tipo de mídia (web, mobile, tv), o tipo de transição (nome da classe de transição), o nome e o tipo da atividade (definido pelo padrão de tarefa), o tipo do componente (definido pelo padrão de tarefa + mídia) e uma forma de passar parâmetros de configuração para os componentes e para as transições. Além dos elementos de domínio foram acrescentados símbolos que permitem declarar variáveis, comentários e referência aos componentes. Além disso, com intuito de ampliar sua capacidade, foi criado uma maneira de embutir código de uma linguagem GPL. 3 O código embutido poderia ser executado em outras etapas do ciclo de vida do serviço além da inicialização, como por exemplo, na hora em que uma atividade é iniciada por um usuário, no momento que uma transição ocorre, ou quando uma atividade é finalizada, no entanto, essa lógica ainda não foi especificada no FXG, e portanto, não foi incluído suporte a outros estados na linguagem CroMeL até o momento. 45 5.1.2 Implementação Desenvolver uma linguagem de programação depende da implementação de um programa capaz de analisar e processar dados de entrada, e dessa forma, significa construir uma aplicação que executa determinadas ações de acordo com as sentenças definidas para essa nova linguagem. Desenvolver uma linguagem de programação pode ser bastante complicado, portanto essa tarefa deve ser decomposta em etapas que incluem a criação de um reconhecedor capaz de realizar a análise léxica e sintática e a criação de um interpretador capaz de executar ações de acordo com a semântica definida. Um reconhecedor, conhecido também como dispositivo cognitivo, é um sistema formal capaz de aceitar todas as sentenças que pertençam a uma determinada linguagem (Neto et al., 2009). Um reconhecedor é capaz criar uma representação intermediária das informações encontradas nos dados de entrada, enquanto o interpretador utiliza as informações coletadas para executar ações e produzir dados de saída. A figura 5.3 representa as partes que compõem a implementação da CroMeL. Figura 5.3: Etapas de implementação do interpretador CroMeL O objetivo principal em criar uma linguagem específica de domínio é aumentar a produtividade de um Engenheiro de Software por meio da definição de notações melhores em um determinado domínio, e assim, aumentando o nível de abstração do problema (como conseqüência também facilita a leitura do código escrito nessa linguagem). Diversos frameworks como Ruby on Rails 4 , JBOSS Seam 5 , ROMA 6 , utilizam técnicas consideradas por muitos como aplicação de DSLs para realizar ma4 http://rubyonrails.org/ http://seamframework.org/ 6 http://www.romaframework.org/ 5 46 peamento objeto-relacional, especificar templates de páginas e declarar componentes de interação, e por meio dessas técnicas, conseguem elevar o nível do desenvolvimento para camadas mais altas de abstração, simplificando o criação de sistemas com esses frameworks (Se interessar, veja um vídeo em que um sistema de blog é construído em apenas 15 minutos, incluindo a definição do schema do banco de dados e interface web com recursos AJAX em apenas 15 minutos http: //media.rubyonrails.org/video/rails_blog_2.mov.). Para o Framework X-Gov atingir todo seu potencial existe a necessidade de facilitar a modelagem de um serviço de governo em mídia cruzada. Para simplificar o desenvolvimento de um sistema com o Framework X-Gov foram consideradas diferentes alternativas na implementação de sua DSL: • Representação da linguagem em notação XML; • Uma DSL Interna feita em Ruby; • Uma DSL Externa. A vantagem em se criar uma representação da linguagem em notação XML foi não ser necessário construir o reconhecedor — existem inúmeros reconhecedores de XML disponíveis nas mais diversas linguagens de programação — no entanto, a notação em XML não atende o objetivo principal para o qual se define uma DSL que é aumentar a produtividade através de um nível de abstração mais alto. E apesar do uso da notação em XML ser adequado para comunicação entre programas, ele não se apresentou adequado para servir para comunicação com outros seres humanos encarregados de escrever e ler esse código. Essa foi a primeira alternativa implementada completamente e serviu para definir muitos dos elementos necessários para a construção do interpretador que envolve a execução de ações a partir das informações coletadas do XML, essa versão foi chamada de CromelXML. Como modelar um serviço em CromelXML não é muito adequado para ser escrita por pessoas, foi criado uma ferramenta gráfica7 que gera o código em XML a partir de um diagrama em que são declarados os elementos apresentados na sessão 5.1.1. Embora alguns autores também considerem arquivos de configuração em XML uma DSL Externa, se diferencia de uma verdadeira DSL Externa pois sua notação ainda fica restrita as regras de criação de um XML bem formado, sendo que em uma DSL Externa autêntica pode-se definir a notação que quiser, ou seja, aquela que for mais adequada para um domínio. A implementação da CroMeL como uma DSL Interna em Ruby pareceu promissora no inicio pelas seguintes razões: 7 trabalho de iniciação científica associado ao projeto X-Gov, desenvolvido pelos alunos Daniel Interliche de Oliveira, com bolsa da FUSP e André Martini Diniz. 47 • Ruby é extensível por natureza, e tem uma sintaxe flexível na qual é possível definir sobrecarga de operadores, parêntesis são opcionais, classes abertas como Number e String que permitem incluir novas funções aos objetos principais da linguagem; • Ruby oferece recursos de meta-programação (e.g. method missing, alias method) ou MOP (meta-object protocol) que de acordo com Kiczales & Rivieres (1991), trata-se de uma interface orientada a objeto para especificação de extensão de linguagem e transformação e ainda conta com alguns recursos de linguagens funcionais como closures e lambdas; • Existe implementação de Ruby em C8 , e nas plataformas Java (JRuby9 ) e .NET (IronRuby10 ). Não foram consideradas outras linguagens inicialmente por não atenderem aos três requisitos apresentados acima — Python atendia bem o segundo e terceiro, enquanto Groovy atendia bem o primeiro e o segundo. Essa estratégia de criar uma DSL embutida (ou interna) possui como vantagem: (a) Menor esforço de desenvolvimento já que a implementação atual pode ser utilizada; (b) Normalmente produz uma linguagem mais poderosa do que os outros métodos, já que muitos recursos da LP hospedeira estão disponíveis ou pré-existem; (c) a infra-estrutura da linguagem hospedeira pode ser reutilizada (ambiente de desenvolvimento, editores, debuggers, profilers, etc.) e (d) caso o usuário conheça a linguagem hospedeira, a compreensão da nova DSL torna-se para este mais fácil. Embora essa alternativa pareceu promissora no início, foi descartada pois não era possível atender o objetivo principal em ter uma notação totalmente adequada ao domínio sendo obrigatório que o usuário da CroMeL soubesse primeiramente programar em Ruby para utilizar essa versão — não é a realidade de muitos funcionários públicos conhecer mais de uma linguagem de programação, ainda mais uma linguagem que não é muito popular11 . Pode-se dizer que a alternativa de criar uma DSL Interna é uma forma mais simples de implementar uma DSL (comparando com uma DSL Externa) pois aproveita o reconhecedor e o analisador da linguagem hospedeira, e embora facilite sua construção (pode ser por isso que observa-se tantas DSLs internas atualmente), pode não ser uma alternativa adequada a determinados tipos de aplicações como foi neste caso. Um ponto que pesou fortemente para essa que essa alternativa fosse descartada, foi a falta de capacidade de retornar informações de erro 8 http://www.ruby-lang.org/en/ http://jruby.codehaus.org/ 10 http://www.ironruby.net/ 11 a popularidade de uma linguagem de programação pode ser analisada no índice TIOBE http: //www.tiobe.com/index.php/content/paperinfo/tpci/index.html. 9 48 relativos a sintaxe do script, e não a sintaxe do Ruby, o que por si só apresenta um grande desafio para o uso de DSLs internas. A escolha em criar uma DSL Externa veio do amadurecimento obtido sobre esses conceitos, e o desejo de criar notações mais adequadas para a linguagem conseguindo assim aproximar-se do objetivo principal de definir um nível mais alto de abstração e permitir que especialistas de domínio entendam seu código, e inclusive, auxiliem os programadores na modelagem de um serviço de governo eletrônico com o Framework X-Gov. Para sua implementação existiam diversas ferramentas disponíveis, desde geradores de parsers como os clássicos lex, yacc, bison, até ferramentas chamadas de language workBenches que tratam-se de verdadeiras IDEs para construção de linguagens como o Meta Programming System (http://www.jetbrains.com/mps/) da JetBrains ou o xText (http://www.eclipse.org/Xtext/) doado para fundação eclipse. A escolha da ferramenta não foi sistemática por não ser foco deste trabalho, e apesar das diversas opções, foi escolhida a ferramenta chamada ANTLR que atendeu a uma simples premissa: gerar o código do parser em Java e C#. Essa é uma ferramenta que pode ser utilizada para construção de reconhecedores, interpretadores, compiladores e tradutores a partir de ações contidas na descrição da gramática. Seguem algumas outras vantagens encontradas: • Gera código que pode ser modificado posteriormente, e é facilmente integrado em outras aplicações; • Gera um reconhecedor descendente-recursivo utilizando uma extensão do LL(k) chamada de LL(*) capaz de utilizar lookahead arbitrário; • Integrado com um engine de template chamado StringTemplate projetado para gerar código estruturado; • Possui um ambiente de desenvolvimento de gramática chamado ANTLRWorks; • Open-source liberado sob a licença BSD; • Suporta diversas linguagens destino como: Java, C#, Python, Ruby, Objective-C, C/C++ O desenvolvimento da CroMeL pode ser visto sob a ótica de um método interativo/incremental, já que seus elementos foram determinados a partir da construção de provas de conceito que tornaram possível refinar a linguagem para atender aos cenários planejados. Um primeiro cenário trata de uma simulação de matricula escolar com múltiplos dispositivos e mídias e pode ser visto pelo vídeo disponível em http://lts-i.pcs. usp.br/index.php/projetos/xgov/61. A seguir é descrito o cenário: 49 1 2 3 4 5 6 7 8 O usuário inicia sua interaç~ a o do caso de uso pela TV digital que contém informaç~ o es sobre o serviço de matrı́cula . Após obter algumas informaç~ o es básicas sobre o serviço , ele seleciona onde quer continuar o diálogo : no celular ou na internet . A impossibilidade de continuar a interaç~ a o sobre uma determinada mı́dia ilustra a situaç~ a o na qual aquela mı́dia pode n~ a o ser adequada para a atividade em quest~ a o , e indica um \ emph { call - to - action } sobre qual mı́dia o usuário pode continuar a interaç~ ao . O usuário seleciona continuar pelo celular , e para facilitar a transiç~ ao , aparece uma imagem QR Code \ footnote { Para saber mais sobre QR Code ver \ url { http :// en . wikipedia . org / wiki / QR_Code }} que um aplicativo instalado no celular é capaz de capturar e interpretar . No celular , o QR Code é decodificado em uma URL , e pergunta se o usuário quer navegar na Web . Ao acessar a página do serviço de matrı́cula pelo celular s~ a o apresentadas opç~ o es na página inicial . O usuário seleciona a opç~ a o buscar escolas pelo nome , entra com parte do nome e executa a busca . Após o sistema apresentar os resultados , o usuário seleciona uma das escolas encontradas e o sistema retorna com informaç~ o es da escola e opç~ o es para continuar o diálogo na TV . Pode - se ver a foto da escola na TV ou ver o mapa da escola na TV , que pelo fato de ter uma tela grande , é uma mı́dia mais adequada para apresentar esse conteúdo . O usuário pode entrar também no celular com seu endereço de e - mail para receber o formulário de matrı́cula . Em seguida , já no \ emph { desktop } , ao selecionar um link no e - mail recebido , o usuário é levado ao portal web para preencher seu cadastro . Nesse momento ocorreu uma transiç~ ao de dispositivos do celular para o \ emph { desktop } , e no \ emph { desktop } ocorreu uma transiç~ a o de mı́dias do e - mail para a web --- preencher um formulário na web pelo \ emph { desktop } é muito mais adequado do que por exemplo na web pelo celular . Ao terminar o cadastro , o sistema conhece o número do celular do usuário , e envia um SMS notificando que a matricula foi recebida e informa um número para acompanhamento do processo . Listagem 5.1: Cenario de matricula escolar A partir deste cenário a maior parte dos elementos da CroMeL foram definidos como a necessidade de se declarar atividades, e no seu contexto, as mídias. Também ficou fácil notar a necessidade de existir alguma construção na linguagem para declarar uma transição. A partir de outro cenário para construção de um agendamento médico, foi possível perceber a necessidade de declarar uma navegação entre componentes na mesma mídia. 50 O script CroMeL é um arquivo texto que pode ser criado com qualquer editor de texto simples. Depois desse código ter sido escrito, ele é implantado no servidor que contém o interpretador da linguagem — fase conhecida como deployment. A implantação é feita a partir de qualquer desktop com auxílio de um browser web. Para isso, o desenvolvedor acessa uma página do servidor e selecionar a opção de implantar um novo serviço em CroMeL. A figura 5.4 ilustra o processo de implantação representado por um diagrama de atividade. Após o script ser carregado, ocorre a validação sintática e semântica. Se não ocorrerem erros de validação, ele é interpretado, o que disponibiliza um serviço para ser acessado pelos cidadãos. A validação sintática visa verificar se os símbolos encontrados no script pertencem à gramática da linguagem. E a validação semântica verifica se os componentes utilizados de fato existem, se as mídias utilizadas nas transições foram declaradas no serviço e se os parâmetros apontados para cada componente estão corretos e em acordo com seu tipo. Caso ocorram erros, eles serão apresentados ao usuário na interface web de deployment e a implantação será cancelada, permitindo ao deployer ou desenvolvedor corrigir erros do script. Figura 5.4: Implantação de um script CroMeL O final da implantação do script consiste no seu armazenamento no servidor e posterior interpretação. A figura 5.5 ilustra o interpretador criado para CroMeL e as classes utilizadas pelo interpretador para realizar as funções necessárias durante a interpretação de um script no Framework X-Gov. A interpretação do script aciona 51 a classe CromelService que implica em criar uma série de objetos para alimentar a estrutura de dados interna necessária, preparar as transições (e.g. gerador de QRCode, envio de e-mail, envio de sms). Cada componente tem uma estrutura de dados específica, mas compartilham o modelo de transição descrito no script e as regras de negócio executadas na inicialização de cada atividade. Figura 5.5: Interpretação de um script CroMeL 5.2 Gramática A sintaxe da linguagem foi criada em inglês de acordo com as convenções adotadas pelo projeto, no entanto seria fácil criar uma versão traduzida para português o que poderia facilitar seu aprendizado por programadores brasileiros. Uma gramática é uma DSL que foi projetada especificamente para descrever outras linguagens, também chamada de metalinguagem. Ela é formada por um conjunto de regras que descrevem as frases de um linguagem, e o ANTLR é capaz de converter essas regras em um programa reconhecedor. Os requisitos para construção da gramática da linguagem CroMeL determinam que ela deve suportar as seguintes construções (ilustradas pelos seus respectivos diagramas de sintaxe) — caso queira, o leitor poderá consultar os diagramas de sintaxe para verificar a maioria dessas regras no apêndice C.3 (alguns diagramas de sintaxe foram omitidos por serem extremamente simples). 52 1. Declaração de um ou mais serviços (Figura C.1); 2. Declaração de variáveis (Figura C.1); 3. Descrição das atividades que pertencem a um serviço (Figura C.4); 4. Descrição das mídias aplicadas à uma atividade e seus parâmetros (Figura C.4); 5. Declaração de transições entre mídias que pertencem a um serviço (Figura C.6); 6. Declaração de parâmetros para navegação dos componentes web que pertencem a um serviço (Figura C.7). Segundo Neto et al. (2009), existem muitas notações (metalinguagens) utilizadas na definição gramatical das linguagens formais. Entre elas, as Expressões Regulares, o Backus-Naur Form (BNF), a Notação de Wirth e os Diagramas de Sintaxe são bastante populares. Os próximos parágrafos explicam em detalhes cada uma das regras léxicas e sintáticas da linguagem CroMeL utilizando a Notação de Backus-Naur extendida (EBNF) e alguns exemplos. Para ver a gramática completa ainda sem ações semânticas consulte o apêndice C.1 (as regras já com ações semânticas serão apresentadas na seção 5.3). Regras léxicas começam com uma letra maiúscula (para CroMeL essas regras foram escritas todas em maiúsculo o que facilita sua identificação), e as regras sintáticas começam em minúsculo. Ambos os tipos de regras foram definidos no mesmo arquivo. A linguagem começa pela declaração do nome de sua gramática e esse nome faz parte do nome da classe do código gerado (primeira linha da listagem 5.2). A primeira regra sintática contém a raiz da linguagem que permite declarar zero ou mais variáveis e um ou mais serviços — o leitor pode ver que, na linha 2 da listagem 5.2, existe uma declaração da regra prog que contém zero ou muitas variáveis (var *) e um ou muitos serviços (service+). As variáveis podem ser utilizadas para armazenar um valor de tipos diferentes e esse valor pode ser recuperado posteriormente durante a interpretação do script. No que service é uma palavras-chave obrigatória e por isso aparece entre aspas simples na regra gramatical service na linha 4 da listagem 5.2. Cada serviço, por sua vez, possui um nome opcional (service_name?) (atualmente o nome do serviço não é utilizado para nada, porém no futuro poderá servir para identificar diferentes serviços criados em um mesmo script CroMeL), e declaração de suas partes que correspondem a uma ou mais atividades (task+), zero ou mais transições (transition*), e navegação entre componentes web (web_navigation*) — sendo a primeira obrigatória e as outras duas opcionais pois pode existir um serviço com apenas uma atividade e sem nenhuma transição. 53 1 2 3 4 5 6 7 8 9 grammar prog var service decl assign CroMeL ; : var * service + ; : assign ; : ’ service ’ service_name ? ’{ ’ decl ’} ’ ; : task + transition * web_navigation * ; : ID ’= ’ expr Listagem 5.2: Raiz da linguagem Quando uma variável for encontrada é executada a regra de atribuição (assign), que o leitor pode ver na linha 3 da listagem 5.2, e de acordo com essa regra, recebe o token ID (do analisador léxico) e seu respectivo valor, que inicia a execução de outra regra (expr ) que é apresentada posteriormente. O valor de uma variável pode conter uma seqüência de caracteres colocados entre aspas simples ou duplas, um número inteiro ou um valor booleano. A entrada presente na listagem 5.3 é reconhecida pelas regras da listagem 5.2. 1 2 3 4 5 6 7 var1 = ’ texto ’ var2 =123 var3 = true var4 = ’ Detalhes do seu CPF ’ service ’ Consulta CPF ’ { ... } service ’ Matricula Escolar ’ { ... } Listagem 5.3: Sentenças de entrada para um serviço e declaração de variáveis Na declaração de uma atividade (task ) — primeira linha da listagem 5.4 — é obrigatório a definição do seu nome (usado posteriormente para identificar um componente em uma transição/navegação), e o padrão de tarefa dessa atividade colocado após a palavra-chave ‘of’ (usado posteriormente para definir a classe do componente que será instanciada de acordo a mídia). O conteúdo de uma atividade é colocado dentro de ‘{’ e ‘}’ e contém a declaração do tipo de mídia e seus parâmetros. Os parâmetros de cada mídia (params) contêm instruções para atribuição de valores aos parâmetros do componente. A entrada presente na listagem 5.5 é reconhecida pelas listadas em 5.4. Observe que para a atribuição dos valores nos parâmetros de uma mídia pode-se usar as variáveis declaradas anteriormente, desde que colocadas com o símbolo $ na frente, por exemplo, o leitor pode ver na linha 3 das sentenças de entrada de uma atividade o uso da variável $var4 que deve ter sido declarada anteriormente. 54 1 2 3 4 5 6 7 8 9 10 11 12 task : ’ task ’ task_name ’of ’ pattern_name ’{ ’ media + ’} ’ ; media : MEDIA params ; params : ’( ’ assign ( ’ , ’ assign ) * ’) ’; assign : ID ’= ’ expr task_name : ID ; pattern_name : ID ; expr : STRING | INT | BOOLEAN | QID // substituir ID por valor em memoria | REF // substituir ID por numero gerado pela Task . media ; Listagem 5.4: Gramática para descrição das ativadades de um serviço A regra dos parâmetros (params) chama de maneira recursiva a regra de atribuição (assign), e pode ser usado quando tiver apenas um parâmetro, ou para muitos parâmetros separados por vírgula, sendo que todos eles devem estar entre parênteses — veja o exemplo nas linhas 2,3 e 4 da listagem 5.5 dos parâmetros passados para a mídia web, ou nas linhas 6,7 e 8 da mesma listagem os parâmetros passados para a mídia mobile. 1 2 3 4 5 6 7 8 9 10 task ConsultaCpf of GetPreServiceInfo { web ( componentName = ’ Informacoes sobre como consultar seu CPF ’ , description = $var4 , urlCalled = ’ webCpfInfo ’ ) mobile ( componentName = $var4 , uriCalled = ’ mobCpfInfo ’ , welcomeMessage = ’ Bem vindo a consulta de CPF ’ ) } Listagem 5.5: Sentenças de entrada para uma atividade A regra de atribuição (assign) de um valor utiliza um identificador (ID) de uma variável e uma expressão (expr ). A regra de expressão determina o tipo de dado por inferência de acordo com o token enviado pelo reconhecedor léxico. Os tipos podem ser: • STRING que corresponde a um valor entre aspas simples ou duplas; • INT que corresponde a um valor numérico inteiro; • BOOLEAN que corresponde a um dos literais ‘true’ ou ‘false’; 55 • QID que corresponde ao valor de uma variável declarada anteriormente e começa com ‘$’ seguido pelo nome da variável; • REF que corresponde a referência de um componente, deve começar por ‘&’ seguido pelo componente identificado pelo nome ‘tarefa.mídia’ em que ele foi declarado. Os outros elementos que fazem parte de um serviço (além das atividades) são: transições (transition) e navegações (navigation) que ocorrem entre mídias e componentes (Listagem 5.6). Estes elementos são opcionais, embora seja difícil imaginar um serviço em mídia cruzada sem nenhuma transição entre mídias, podem existir serviços simples que não necessitam de transições neste caso o Framework X-Gov poderia ser usado com intuito de aproveitar os seus componentes. Uma transição começa pela palavra reservada ‘transition’, seguida de qual tipo de transição será utilizado (o tipo determina a classe a ser utilizada pelo FXG). Uma transição deve levar a ação de um componente para outro, o que fica explícito na regra de navegação (navigation). Para determinar uma navegação, utiliza-se a referência de um componente declarado em alguma atividade precedido pelo caractere ‘&’ — veja um exemplo de entrada reconhecida por esse gramática na listagem 5.7, onde deve observar a linha 1 que contém a declaração de uma trasição do tipo BarCode que deve ser realizada entre o componente web declarado na atividade ConsultaCpf e o componente mobile declarado na mesma atividade. 1 2 3 4 5 6 7 transition web_navigation navigation begin end transition_type label : : : : : : : ’ transition ’ transition_type navigation params ; ’ navigation ’ label navigation ; ’[ ’ begin ’->’ end ’] ’ ; REF ; REF ; ID ; STRING ; Listagem 5.6: Gramática para declaração de transições e navegações Além da declaração da navegação entre os componentes, uma transição geralmente necessitará de parâmetros, utilizados pela sua implementação, pois aciona outros recursos como envio de um e-mail ou geração de uma imagem — a regra para atribuição de parâmetros é a mesma apresentada anteriormente na listagem 5.4. A regra de navegação (web_navigation) é mais simples do que uma transição, ela contém um label usado na apresentação de um link e declaração de navegação entre os componentes — da mesma maneira que ocorre em uma transição, os componentes são identificados pela atividade, e pela mídia, como pode ser observado na listagem 5.7 na linha 9 onde foi declarada uma navegação do componente web 56 da atividade InfoSobreMatricula para o componente web da atividade SelecaoEscola. Atualmente o recurso de navegação tem sido utilizado apenas pelos componentes web, mas a CroMeL não tem nenhuma limitação na sua construção de ser utilizada para declarar navegação entre componentes de mídias diferentes. 1 2 3 4 5 6 7 8 9 transition BarCode [ & ConsultaCpf . web -> & ConsultaCpf . mobile ] ( BaseUrl = ’ http :// www . receita . fazenda . gov . br / WS / consultaCpf ’ , ErrorCorrection = ’M ’ , ImageSize =5 , LabelMessage = ’ Use esse QRCode para acessar o proximo passo do servico . ’ , TransitionId =7 , TransitionName = ’ QRCODE teste web -& gt ; mob ’) navigation ’ Veja os dados de sua matricula ’ [ & InfoSobreMatricula . web -> & SelecaoEscola . web ] Listagem 5.7: Sentenças de entrada para transição e navegação As regras léxicas são mais simples que as sintáticas e servem para determinar os token utilizados pelas regras sintáticas. Esses tokens são formados pela cadeia de caracteres lidos e selecionados de acordo com as seguintes regras apresentadas na listagem 5.8. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 MEDIA : ( ’ mobile ’ | ’web ’ | ’tv ’) ; BOOLEAN : ( ’ true ’| ’ false ’) ; INT : ’0 ’.. ’9 ’+ ; ID : ( ’a ’.. ’ z ’| ’A ’.. ’ Z ’| ’_ ’) ( ’a ’.. ’ z ’| ’A ’.. ’ Z ’| ’0 ’.. ’9 ’| ’ _ ’) * ; // referencia de uma variavel ( usada para recuperar seu valor ) QID : ’$ ’ ID ; // uma referencia do tipo Task . media ( usado para identificar componentes ) REF : ’\& ’ ID ( ’. ’ MEDIA ) ; STRING : ’" ’ .* ’" ’ | ’\ ’ ’ ~( ’\\ ’| ’\ ’ ’| ’\* ’) * ’\ ’ ’ ; // espacos em branco WS : ( ’ ’| ’\t ’| ’\ r ’| ’\ n ’) { $channel = HIDDEN ;} ; // comentarios CMT : ’# ’ ~( ’\ n ’| ’\ r ’) * ’\r ’? ’\n ’ { $channel = HIDDEN ;}; COMMENT : ’/* ’ .* ’*/ ’ { $channel = HIDDEN ;} ; Listagem 5.8: Regras léxicas MEDIA identifica o tipo de mídia podendo ser apenas um dos literais ‘mobile’, ‘web’ ou ‘tv’. Os tipos de dados reconhecidos são STRING, BOOLEAN e INT, e são di57 ferentes da referência de uma variável QID que começa com ‘$’ e da referência de um componente REF que começa com ‘&’. Espaços em branco (que incluem tabs e salto de linhas), assim como comentários, não são enviados para o analisador sintático, pois é escolhido um canal de comunicação diferente (HIDDEN) 12 . O estudo da dependência entre as regras — que pode ser viso na figura 5.6 — pode ajudar a otimizar a construção do reconhecedor, permitindo identificar situações de reuso, e dessa forma criar um reconhecedor equivalente mais eficiente. Figura 5.6: Grafo de dependência entre as regras sintáticas O autômato finito deterministico (DFA) gerado para reconhecer todos os tokens definidos tem 72 estados, e se o leitor desejar, pode consultar seu diagrama no apêndice C.8. O resultado da geração de um reconhecedor a partir da gramática apresentada permite responder apenas SIM ou NÃO se as sentenças de entrada são válidas. Porém para construir algo útil, como um interpretador, a gramática precisa ser ampliada com ações semânticas. 12 O ANTLR permite que cada token seja emitido por canais diferentes de comunicação entre o analisador léxico e sintático, assim como freqüências de rádio, o parser pode ‘sintonizar’ em um canal e ignorar os tokens emitidos pelos outros 58 5.3 Semântica Ações semânticas são blocos de código escritos na linguagem de programação do programa reconhecedor gerado e inseridas em diversos lugares dentro da gramática (como poderá ser observado pelos exemplos a seguir). O ANTLR realiza substituições de símbolos relativos aos atributos declarados, parâmetros e retorno das regras sintáticas, mas não interpreta nenhuma instrução inserida nesses blocos de código que pertence a linguagem destino do programa reconhecedor gerado. Para interpretar o código da CroMeL uma série de ações semânticas foram colocadas em sua gramática para extrair as informações necessárias na execução de um script. Essas ações devem ser capazes de atender os seguintes requisitos para integração da CroMeL com o Framework X-Gov : • Para cada componente (definido pelo par atividade/mídia) deve ser atribuído um identificador numérico único que pode ser utilizado em transições e navegações entre os componentes; • Cada par padrão/midia é determinado o tipo de componente a ser instanciado (o nome da classe que implementa o componente é encontrado em um arquivo de configuração externo, o que permite adicionar novos tipos de componentes sem alteração na linguagem); • A declaração de um tipo de transição determina a classe a ser instanciada (esse tipo corresponde a uma classe que também fica em um arquivo de configuração externo); • Os parâmetros dos componentes e das transições devem corresponder as propriedades de suas classes conforme foram declarados, para serem atribuídos aos objetos criados por meio de reflexão; • As variáveis podem ser utilizadas para atribuir valores para qualquer parâmetro facilitando reutilizar esses valores em parâmetros repetidos, assim como isolar parâmetros que mudam com freqüência; • O nome do componente definido por um par atividade/mídia precedido pelo sinal de ‘&’ pode ser utilizado para fazer referência ao identificador numérico criado. Declarações tanto de transição quanto navegação necessitam desse identificador numérico e o programador pode usar o seu nome. • Identifica e extrair código embutido em uma atividade para executar quando uma atividade for inicializada. 59 Para ilustrar todas as regras semânticas adicionadas, acompanhe pela listagem 5.9 um exemplo de script de entrada que alimenta o interpretador da CroMeL com um serviço de agendamento médico. Se quiser, o leitor pode comparar essa entrada com uma versão em XML utiliza inicialmente no apêndice C.6, e poderá observar algumas vantagens no uso da CroMeL em comparação com a representação em XML como por exemplo: o uso de variáveis para atribuição de valores aos parâmetros, a declaração de componentes por meio de seu identificador (atividade/mídia) na hora de realizar uma transição ou navegação, e a inclusão de código executado na inicialização de uma atividade. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 G W S F i n d P r i v a t e I n f o r m a t i o n = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’ service ’ Exams Schedule ’ { task Ba s i c I nf o A b ou t S c h ed u l e of GetPreServiceInfo { web ( componentName = ’ Basic information ’ , description = ’ For more information use the menu ’ , urlCalled = ’ webExamInfo ’ ) mobile ( componentName = ’ informations ’ , uriCalled = ’ mobExamInfo ’ , welcomeMessage = ’ Welcome to the X - Media Service ’ ) tv ( componentName = ’ My Exams List ’ , uriCalled = ’ tvExamInfo ’ , first = true ) << Test if database is online > >= unless databale_online ? update_site ’ come back later . ’ @ << Pre - notify health center > >= var now = Time . now schedule_new_exam ( now ) @ } task ExamsList of FindPrivateInfo { web ( componentName = ’ My Exams List ’ , au th ent ica ti onC om pId =& Authentication . web , uriCalled = ’ webExamList ’ , dataUrl = $GWSFindPrivateInformation , g e t F u l l E n t i t i e s L i s t W e b M e t h o d = ’ GWSGetPermittedExams ’ , 60 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 g e t E n t i t y I n f o r m a t i o n W e b M e t h o d = ’ GWSGetExamInformation ’ , scheduleCompId =& Schedule . web ) mobile ( componentName = ’ My Exams List ’ , au th ent ic ati onC om pId =& Authentication . mobile , uriCalled = ’ mobExamList ’ , instructionText = ’ Select an exam : ’ , listName = ’ Exams Requested ’ , dataUrl = $GWSFindPrivateInformation , g e t F u l l E n t i t i e s L i s t W e b M e t h o d = ’ GWSGetPermittedExams ’ , g e t E n t i t y I n f o r m a t i o n W e b M e t h o d = ’ GWSGetExamInformation ’ ) tv ( componentName = ’ My Exams List ’ , entityType = ’ Exam ’ , compAuthId =& Authentication . tv , compAuthId =& B as i c I n fo A b o u tS c h e d ul e . tv , uriCalled = ’ tvExamList ’ , dataUrl = $GWSFindPrivateInformation , g e t F u l l E n t i t i e s L i s t W e b M e t h o d = ’ GWSGetPermittedExams ’ , g e t E n t i t y I n f o r m a t i o n W e b M e t h o d = ’ GWSGetExamInformation ’ ) } transition BarCode [ & B a si c I n f oA b o u tS c h e d ul e . tv -> & ExamsList . mobile ] ( BaseUrl = ’ http ://143.107.102.15/ poc3xgov / Mobile_Comp / mobile / mobFindPrivExam ’ , ErrorCorrection = ’M ’ , ImageSize =5 , LabelMessage = ’ Use this QRCode to access next service step . ’ , TransitionId =7 , TransitionName = ’ QRCODE teste web -& gt ; mob ’ ) 59 60 61 62 63 64 65 66 67 68 navigation ’ See your exam list ’ [ & B a s i cI n f o Ab o u t S ch e d u l e . web -> & ExamsList . web ] } Listagem 5.9: Script CroMeL de entrada Toda ação semântica embutida na gramática fica entre { }. Por exemplo, para guardar o valor de uma variável quando executada a regra ‘var’ é recuperado os valores de ‘ID’ e ‘expr’ obtidos pela chamada da regra ‘assign’ por meio de uma instrução de retorno dos valores ‘n’ e ‘v’. A chamada de uma regra é bem semelhante a chamada de uma função em uma linguagem de programação e permite passar e retornar parâmetros. Pode-se observar pela regra ‘assign’ na listagem 5.14 que ela é capaz 61 de retornar dois valores simultaneamente para a regra ‘var’ que armazena o nome e o valor da variável na memória que é um HashTable no escopo global. Esta ação será utilizada para satisfazer o requisito de substituir os valores de variáveis na declaração de parâmetros, veja a declaração de uma variável no código de entrada 5.9 na linha 1. 1 2 3 4 5 6 7 8 9 10 11 var : assign { System . out . println (" Declaracao de variavel : "+ $assign . n +"="+ $assign . v ) ; memory . put ( $assign .n , $assign . v ) ; }; assign returns [ String n , Object v ] : ID ’= ’ expr { $n = $ID . text ; $v = $expr . value ; }; Listagem 5.10: Semântica de declaração de variável A semântica de uma atividade (task ) apresentada na listagem 5.11 é um pouco mais complexa pois envolve a passagem de parâmetros, apelidos para regras e uso de variáveis com escopo dinâmico. Em resumo ela cria os objetos correspondentes aos componentes declarados na atividade, determinar qual o tipo de cada componente e coleta seus parâmetros. Depois guarda a representação do componente criado em uma lista de componentes de escopo global, e por fim, executa um ou mais códigos embutidos na hora de inicializar a atividade. Para realizar isso, observe primeiramente a regra ‘media’: Ela recebe como parâmetro o nome da atividade (taskName) em que foi declarada, e o padrão de projeto associado a essa atividade (patternName), — linha 12 da listagem 5.11 — obtém um identificador para o componente por meio de uma variável contadora que pertence ao escopo de um serviço (assim nenhum componente do mesmo serviço receberá o mesmo identificador) e guarda o identificador em uma tabela de símbolos global para ser usado posteriormente quando fizer referência a este componente pelo par: nome da atividade e mídia (linha 17). Em seguida, o tipo do componente é determinado de acordo com o padrão de tarefa e o tipo de mídia (linha 20), obtém sua lista de parâmetros (linha 23) e por fim é criado um objeto que contém os dados do componente e serve para representar o componente reconhecido armazenando na lista de componentes criado na etapa final do interpretador (linha 28). Ao final da regra ‘task’ é executado o código embutido de inicialização de uma atividade que pode ser visto nas linhas 7-8. Esse código escrito em Ruby13 é passado 13 Outras linguagens como JavaScript ou Python poderiam ser suportadas desde que incluído algum 62 para o IronRuby da versão em .NET ou JRuby da versão em Java dentro do FXG. Para que o código seja processado pelo interpretador na versão em C#, é chamada a função RunCromelScript da classe CromelService listado no apêndice C.7 — o leitor pode ver como um código Ruby é executado pelo Dynamic Language Runtime do .NET nas linhas 23-33. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 task : ’ task ’ task_name { System . out . println (" Declaracao da atividade :"+ $task_name . text ) ; } ’of ’ pattern_name ’{ ’ media [ $task_name . text , $pattern_name . text ]+ ( lc = literate_code { // Executa as regras definidas em um servico System . out . println (" Executa codigo embutido : "+ $lc . comment ) ; System . out . println ( $lc . code ) ; } ) * ’} ’ ; media [ String taskName , String patternName ] : m = MEDIA params { int componentId = $service :: componentId ++; String media = $m . text ; String componentName = $taskName +"."+ media ; componentIds . put ( componentName , componentId ) ; String componentType = $patternName +"."+ media ; System . out . println (" Novo componente do tipo "+ componentType +" [ id ="+ componentId +"]") ; System . out . println (" parametros ="+ $params . p ) ; ComponentDTO dto = new ComponentDTO () ; dto . type = componentType ; dto . parameters = $params . p ; components . add ( dto ) ; }; Listagem 5.11: Semântica de uma atividade A semântica de navegação (listagem 5.12) é bem mais simples e se resume a armazenar o label (linha 6), e obter o identificador dos componentes de navegação parâmetro na CroMeL para indicar em qual linguagem o código embutido foi escrito. 63 referenciados na entrada (linhas 7 e 8). Finalmente guarda um objeto que representa a navegação na lista global de objetos de navegação (linha 9). Para obter o ID do componente de navegação referenciado, as regras ‘begin’ e ‘end’ executam uma função embutida no interpretador (linhas 19 e 22)14 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 web_navigation : ’ navigation ’ label navigation { NavigationDTO dto = new NavigationDTO () ; dto . label = $label . text ; dto . begin = $navigation . b ; dto . end = $navigation . e ; navigations . add ( dto ) ; }; navigation returns [ int b , int e ] : ’[ ’ begin ’->’ end ’] ’ { $b = $begin . id ; $e = $end . id ; System . out . println (" Navegacao do componente ["+ $begin . id +"] -> ["+ $end . id +"]") ; }; begin returns [ Integer id ] : REF { $id = getComponentId ( $REF . text ) ; }; end returns [ Integer id ] : REF { $id = getComponentId ( $REF . text ) ; }; Listagem 5.12: Semântica de navegação Uma transição tem ações bem parecidas com uma navegação ao que diz respeito da navegação entre componentes (linhas 11 e 12 da listagem 5.13), acrescentando sua lista de parâmetros obtidos pela chamada da regra ‘params’, armazenados em um objeto na linha 10 e depois guardado na lista global de transições na linha 13. 1 2 3 4 5 transition : ’ transition ’ transition_type navigation params { 14 O código completo que contém essa função embutida pode ser visto no apêndice C.2 declarado na linha 48. 64 6 7 8 9 10 11 12 13 14 System . out . println (" Nova transicao do tipo "+ $transition_type . text ) ; System . out . println (" parametros ="+ $params . p ) ; TransitionDTO dto = new TransitionDTO () ; dto . type = $transition_type . text ; dto . parameters = $params . p ; dto . begin = $navigation . b ; dto . end = $navigation . e ; transitions . add ( dto ) ; }; Listagem 5.13: Semântica de uma transição A regra ‘params’ apresentada na listagem 5.14 tem alguns elementos novos: tem uma rotina de inicialização para criar um objeto do tipo HashMap (linha 3) que implementa uma estrutura de dados do tipo nome-valor para guardar os parâmetros obtidos na entrada. Como um componente ou transição pode conter um ou mais parâmetros, ela tem uma função para guardar o parâmetro do primeiro caso (linha 5) e um loop para guardar os outros parâmetros quando fornecidos (linha 6) — como existe mais de uma chamada a mesma regra ‘assign’, cada para cada chamada foi atribuído um label ‘a1’ e ‘a2’ para que possam ser utilizados de maneira independente nas suas respectivas regras semânticas. Por fim, esse Map é retornado para que quem chamou essa regra possa recuperar seus parâmetros. Esses parâmetros são utilizados na inicialização dos componentes e das transições como visto anteriormente no código semântico das listagens 5.13 e 5.11 — se o leitor quiser, pode ver exemplo dos parâmetros passados aos componentes nas linhas 6-8, 10-12, 14-16, 29-35, 3744, 46-53 e exemplo dos parâmetros passados a uma transição nas linhas 58-63 do script de entrada 5.9 1 2 3 4 5 6 7 params returns [ Map p ] @init { p = new HashMap () ; } : ’( ’ a1 = assign { p . put ( $a1 .n , $a1 . v ) ; } ( ’ , ’ a2 = assign { p . put ( $a2 .n , $a2 . v ) ; } ) * ’) ’; Listagem 5.14: Semântica dos parâmetros de componentes e transições Toda atribuição de um valor apresentado pela regra ‘assign’ (listagem 5.14) chama a regra ‘expr’ (listagem 5.15) que é capaz de determinar o tipo de dado por inferência (de acordo com o TOKEN emitido) e fazer a conversão necessária. Quando o valor identificado começar com $ (TOKEN QID) o valor da variável armazenada é recuperado na memória. Quando o valor identificado começar com & (TOKEN REF) que 65 corresponde a referência de um componente, seu identificador é buscado na tabela de símbolos global. Observe que o tipo REF é utilizado também nas regras de navegação é para não ter que repetir o código da ação de consultar a tabela de símbolos, foi declarado um método membro do parser. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 expr returns [ Object : STRING { | INT { | BOOLEAN { value ] $value = $STRING . text ; } $value = Integer . parseInt ( $INT . text ) ; } $value = Boolean . parseBoolean ( $BOOLEAN . text ) ; } | QID // substituir ID por valor em memoria { // busca valor na memoria ( eliminando o $ que nao foi colocado na tabela ) Object v = memory . get ( $QID . text . substring (1) ) ; // se encontrado seta o valor de retorno , caso contrario imprime erro if ( v != null ) { $value = v ; System . out . println (" resolucao da variavel "+ $QID . text +"="+ v ) ; } else System . err . println (" undefined variable "+ $QID . text ) ; } | REF // substituir ID por numero gerado pela Task . media { $value = getComponentId ( $REF . text ) ; } ; Listagem 5.15: Semântica de expressões Para finalizar a apresentação das ações semânticas implementadas, veja o código da regra ‘service’ na listagem 5.16. Elas são responsáveis por acionar as funções do interpretador que criam os objetos dos componentes (linha 9), os objetos de transição (linha 15) e navegação (linha 22) guardados nas listas globais. Note que todas essas ações são executadas após todos os elementos de um serviço declarado em um script terem sido reconhecidos. O leitor deve se lembrar que código semântico pode ser inserido em diversos lugares dentro da gramática, esse código é transplantado para o reconhecedor gerado pelo ANTLR. Para executar um código ao final da execução de uma regra ele é inserido na instrução ‘@after’ (linha 6). 66 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 service scope { // contador usado para atribuir um ID para cada componente em um servico int componentId ; } @after { System . out . println (" Execucao apos processamento da entrada !") ; // Cria os componentes da CroMeL e seta seus parametros por reflexao for ( ComponentDTO component : components ) { System . out . println (" Criando componente "+ component . type ) ; System . out . println (" Setando "+ component . parameters . size () +" parametros ") ; } // Cria os objetos de transicao e seta seus parametros por reflexao for ( TransitionDTO transition : transitions ) { System . out . println (" Criando transicao "+ transition . type ) ; System . out . println (" Setando "+ transition . parameters . size () +" parametros ") ; System . out . println (" Transicao entre componente "+ transition . begin +" e "+ transition . end ) ; } // Cria os objetos de navegacao for ( NavigationDTO navigation : navigations ) { System . out . println (" Criando navegacao "+ navigation . label ) ; System . out . println (" Navegacao entre "+ navigation . begin +" e "+ navigation . end ) ; } } : { $service :: componentId =1; } // inicializacao do contador ’ service ’ service_name ? ’{ ’ decl ’} ’ ; Listagem 5.16: Semântica de um Serviço A maior parte do código semântico da CroMeL foi apresentado, algumas partes foram omitidas por tratarem de instruções para resolução do nome de classes, da definição de classes internas, inicialização das listas globais de componentes, transições 67 e navegação. Se o leitor quiser, pode consultar o código da gramática completa no apêndice C.2. Quando este código é alimento com a entrada apresentada na listagem 5.9, obtem-se a saída apresentada na listagem 5.17 que serve para acompanhar a execução do interpretador quando alimentado com o script CroMeL de entrada supracitado. Essa versão apresentada trata-se de uma versão para depuração da implementação da CroMeL e contém uma série de instruções de log (println) que foram colocadas para permitir o acompanhamento da execução de um script em cada uma de suas regras, e dessa forma, pode-se observar que todos os elementos necessários para executar o script estão presentes. Para que os componentes, transições e navegações sejam processados pelo interpretador na sua versão em C#, são chamadas respectivamente as funções CreateComponents (linha 86), CreateTransitions (linha 125) e CreateNavigations (linha 36) da classe CromelService listado no apêndice C.7. Essa classe serve como um camada de serviço usado pelo código do interpretador para processamento das instruções reconhecidas no script. Ela por sua vez utiliza outras classes auxiliares como o ComponentFactory listado no apêndice C.8 para processar o script e acionar funções do FXG. A classe ServiceComponent serve como uma interface simplificada para grande quantidade de código executado pelo FXG, ela implementa o padrão de projeto Façade (Gamma et al., 1995). Para construção das classes que transmitem os dados entre a camada do interpretador e o ServiceComponent foi aplicado o padrão de projeto Data Transfer Object (Alur et al., 2001). E para a criação dos componentes, transições e navegações foi aplicado o padrão de projeto Factory (Gamma et al., 1995). 1 2 3 4 5 6 7 8 9 10 11 - declaraç~ a o da variável : G W S F i n d P r i v a t e I n f o r m a t i o n = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’ Declaraç~ a o da atividade : B as i c I n fo A b o ut S c h e du l e Novo componente do tipo GetPreServiceInfo . web [ id =1] parametros ={ componentName = ’ Basic information ’ , description = ’ For more information use the menu ’ , urlCalled = ’ webExamInfo ’} Novo componente do tipo GetPreServiceInfo . mobile [ id =2] parametros ={ componentName = ’ informations ’ , uriCalled = ’ mobExamInfo ’ , welcomeMessage = ’ Welcome to the X - Media Service ’} Novo componente do tipo GetPreServiceInfo . tv [ id =3] parametros ={ componentName = ’ My Exams List ’ , uriCalled = ’ tvExamInfo ’ , first = true } Executa código embutido : Pre - notify health center var now = Time . now schedule_new_exam ( now ) 68 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Executa código embutido : Test if database is online unless databale_online ? update_site ’ come back later . ’ Declaraç~ a o da atividade : ExamsList Erro : refer^ e ncia indefinida & Authentication . web - resoluç~ a o da variável $ G W S F i n d P r i v a t e I n f o r m a t i o n = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’ Erro : refer^ e ncia indefinida & Schedule . web Novo componente do tipo FindPrivateInfo . web [ id =4] parametros ={ g e t F u l l E n t i t i e s L i s t W e b M e t h o d = ’ GWSGetPermittedExams ’ , componentName = ’ My Exams List ’ , uriCalled = ’ webExamList ’ , au th ent ic ati onC om pId = null , scheduleCompId = null , g e t E n t i t y I n f o r m a t i o n W e b M e t h o d = ’ GWSGetExamInformation ’ , dataUrl = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’} Erro : refer^ e ncia indefinida & Authentication . mobile - resoluç~ a o da variável $ G W S F i n d P r i v a t e I n f o r m a t i o n = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’ Novo componente do tipo FindPrivateInfo . mobile [ id =5] parametros ={ g e t F u l l E n t i t i e s L i s t W e b M e t h o d = ’ GWSGetPermittedExams ’ , componentName = ’ My Exams List ’ , uriCalled = ’ mobExamList ’ , au th ent ic ati onC om pId = null , instructionText = ’ Select an exam : ’ , g e t E n t i t y I n f o r m a t i o n W e b M e t h o d = ’ GWSGetExamInformation ’ , dataUrl = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’ , listName = ’ Exams Requested ’} Erro : refer^ e ncia indefinida & Authentication . tv - resoluç~ a o da refer^ e ncia id = 3 - resoluç~ a o da variável $ G W S F i n d P r i v a t e I n f o r m a t i o n = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’ Novo componente do tipo FindPrivateInfo . tv [ id =6] parametros ={ g e t F u l l E n t i t i e s L i s t W e b M e t h o d = ’ GWSGetPermittedExams ’ , componentName = ’ My Exams List ’ , uriCalled = ’ tvExamList ’ , compAuthId =3 , g e t E n t i t y I n f o r m a t i o n W e b M e t h o d = ’ GWSGetExamInformation ’ , entityType = ’ Exam ’ , dataUrl = ’ http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx ’} - resoluç~ a o da refer^ e ncia id = 3 - resoluç~ a o da refer^ e ncia id = 5 Navegaç~ a o do componente [3] -> [5] Nova transiç~ a o do tipo BarCode parametros ={ BaseUrl = ’ http ://143.107.102.15/ poc3xgov / Mobile_Comp / mobile / mobFindPrivExam ’ , ImageSize =5 , TransitionName = ’ QRCODE teste web -& gt ; mob ’ , ErrorCorrection = ’M ’ , LabelMessage = ’ Use this QRCode to access next service step . ’ , TransitionId =7} - resoluç~ a o da refer^ e ncia id = 1 69 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 - resoluç~ a o da refer^ e ncia id = 4 Navegaç~ a o do componente [1] -> [4] Execuç~ a o após processamento da entrada ! Criando componente GetPreServiceInfo . web armazenamento de 3 parametros Criando componente GetPreServiceInfo . mobile armazenamento de 3 parametros Criando componente GetPreServiceInfo . tv armazenamento de 3 parametros Criando componente FindPrivateInfo . web armazenamento de 7 parametros Criando componente FindPrivateInfo . mobile armazenamento de 8 parametros Criando componente FindPrivateInfo . tv armazenamento de 7 parametros Criando transiç~ a o BarCode armazenamento de 6 parametros transiç~ a o entre os componentes 3 e 5 Criando navegaç~ a o ’ See your exam list ’ navegaç~ a o entre os componentes 1 e 4 Listagem 5.17: Codigo de Saida 5.4 Discussão dos Resultados Essa seção apresentou as técnicas utilizadas para criar o interpretador da CroMeL utilizado no Framework X-Gov. Toda sua sintática e semântica foi definida nas sessões 5.2 e 5.3, e foi mostrado como uma entrada é processada internamente pelo interpretador. Por meio da CroMeL provou-se que é possível declarar um serviço, suas atividades, transições e navegações, além de outras construções mais específicas para mapear os conceitos do domínio de governo em mídia cruzada na implementação do Framework X-Gov. Da maneira que a linguagem foi construída, ela permite incluir novos tipos componentes e tipos de transições, o que a torna extensível para o contínuo aperfeiçoamento do FXG. Uma limitação observada se refere a possibilidade de declarar apenas um tipo de componente de cada mídia dentro de uma atividade. Como não foram criados cenários que necessitassem de mais de um tipo de componente da mesma mídia na mesma atividade, essa limitação não foi percebida inicialmente, porém ela pode ser contornada com a declaração de outra atividade com o mesmo padrão de tarefa onde um novo componente do mesmo tipo e para mesma mídia daquele declarado anteriormente pode ser definido. 70 Ficou claro pelas propostas de implementação as vantagens de construir uma DSL Externa, e embora a alternativa adotada seja mais trabalhosa pois necessita criar um reconhecedor e um interpretador, e as outras alternativas (notação em XML ou DSL Interna) já fornecem uma ou as duas etapas prontas, se mostrou a mais versátil para definição das notações e da semântica desejada. 71 Seção 6 Conclusões “O verdadeiro prazer está em descobrir ao invés de saber.” (Isaac Asimov) Esta sessão apresenta uma discussão dos resultados obtidos tanto no desenvolvimento da linguagem quanto na sua aplicação, ainda, resume as principais contribuições desta pesquisa e propõe recomendações para trabalhos futuros. Diante das necessidades de configuração do Framework X-Gov e dos resultados obtidos na implementação da CroMeL constatou-se que, para muitos problemas específicos, linguagens mais próximas de linguagens naturais oferecem um alto grau de expressividade. Infelizmente linguagens naturais são ambíguas e difíceis de serem reconhecidas e interpretadas por um computador, mas com um pouco de trabalho é possível definir um subconjunto dessa linguagem, sem ambiguidade, e ainda assim expressiva o bastante para se aplicar a um domínio de problema. Abstração é um conceito chave no progresso da engenharia de software. Encapsulando detalhes de operações de baixo nível em abstrações de alto nível, desenvolvedores são mais produtivos e utilizam de um vocabulário determinado por uma linguagem para comunicar-se com especialistas de domínio nos mesmos termos. Depois de trabalhar por um certo tempo com as abstrações do nível ‘n’, padrões emergem, e permitem identificar novas abstrações no nível ‘n+1’. Assim o conceito continuará a ser desenvolvido. O principal objetivo de uma DSL é aumentar a produtividade de Engenheiros de Software abstraindo código boilerplate e de níveis mais baixos de abstração. Os mecanismos usados nas linguagens de programação tradicionais para definir abstrações, como métodos, atributos e classes, não serão suficientes para criar 72 novas camadas de abstração no futuro. Mesmo bibliotecas e frameworks sendo boas formas de implementar funcionalidades, as linguagens que o desenvolvedor precisa utilizar para acessar essas funcionalidades são muitas vezes inadequadas. Atualmente, diversos enfoques tem sido dados a questão de buscar novos mecanismos de abstração para o desenvolvimento de software, incluindo arquitetura dirigida a modelo (model-driven-architecture) Ivkovic & Kontogiannis (2004), engenharia dirigida a modelo (model-driven-engineering) Schmidt (2006), modelagem específica de domínio (domain-specific modeling) Kelly & Tolvanen (2008), fabricas de software (softwarefactories) Greenfield & Short (2003) e software intencional (intentional software) Laird & Barrett (2009). Existem dois caminhos para se projetar uma DSL: um caminho descendente que observa as palavras do domínio de problema e foca em uma boa linguagem para capturar os requisitos funcionais de forma não ambígua sem se preocupar como a linguagem será interpretada; e o caminho ascendente, que observa padrões de código, repetições, e busca maneiras de descrever as variações encontradas para que possam ser substituídas por abstrações, as quais são interpretadas nessa nova linguagem mais concisa. O caminho seguido para a definição da CroMeL foi intermediário (tanto descendente quanto ascendente), no qual alguns elementos necessários na linguagem foram obtidos dos requisitos do Framework X-Gov, o que inclui a definição de serviços de governo, atividades e transições entre mídias, e outros elementos foram determinados pelo próprio código implementado no Gerenciador de Componentes e no arquivo de configuração em XML utilizado por ele. 6.1 Análise dos Resultados O desenvolvimento da CroMeL apresentou resultados específicos para cada uma de suas fases: • Na fase de análise foi possível identificar que cada padrão de tarefa possui um tipo de componente específico para cada uma das mídias utilizadas no projeto (web, tv e mobile), em outras palavras, um componente está relacionado a um padrão de tarefa e a uma mídia, identificados por uma classe especializada que contém atributos e comportamentos específicos para as necessidades de cada mídia. Desta forma, foi possível determinar que um dos elementos da linguagem deve identificar o tipo do componente, e para isso necessita reconhecer qual o padrão de tarefa e a mídia associada, para ser possível determinar qual objeto deve ser criado — os padrões utilizados nessa fase foram ‘Informal’ e ‘Extract from code’ apresentados na tabela 2.3 da sessão 2.4.2. 73 • Na fase de projeto, observou-se que a CroMeL necessitaria permitir adicionar novos componentes e realizaria uma busca pelo nome de suas classes. Para suprir essa necessidade foi desenvolvido um dicionário externo à linguagem, que indica para cada tipo de componente a classe que o implementa (determinado pelo padrão de tarefa x mídia). Constatou-se que a linguagem também deveria permitir a definição de parâmetros para os componentes enquanto eles estavam sendo desenvolvidos e alterados, portanto sua gramática foi construída para ser flexível nesse ponto tanto em relação ao número de parâmetros quanto aos seus nomes e valores. Também foi decidido acrescentar recursos semânticos para facilitar sua utilização por um programador na hora de fazer referência aos componentes declarados. Assim, outros elementos da linguagem surgiram para referenciar componentes durante a declaração de uma transição ou navegação — dentre as opções de padrões encontrados nessa fase de acordo com a tabela 2.4 da sessão 2.4.3 foi aplicado o padrão ‘Formal’. • Durante a implementação ocorreram as maiores mudanças. A primeira versão implementada foi na forma de uma DSL Interna em Ruby. Embora o Ruby, assim como outras linguagens como Groovy, Scala, Boo, ofereçam ótimos recursos para definir extensões funcionais como classes abertas, captura de mensagens para métodos que não existem e outros “truques” de meta-programação, o que faz delas boas candidata para a construção de uma DSL interna, essa alternativa trouxe algumas desvantagens: Não existe separação entre a sintaxe da DSL e da GPL; Dificuldade em mapear erros relativos a DSL; Dificuldade em balancear especificidade do domínio dentro dos limites de construção sintática da GPL; O usuário (programador) deve conhecer a linguagem hospedeira e as novas construções da DSL para usar esta solução — assim inicialmente foi aplicado o padrão ‘Embedding’ encontrado na tabela 2.7 para construção de uma linguagem embutida na linguagem Ruby. • A nova implementação como um DSL Externa permitiu um controle total de sua sintaxe. Para o desenvolvimento dessa solução foi especificada a gramática formalmente em EBNF e utilizada a ferramenta ANTLR para geração do reconhecedor e do interpretador da CroMeL (apresentados na sessão ??). Nesse caso, o usuário da CroMeL (programador) utiliza uma nova notação para declarar os elementos de configuração de um serviço (i.e. atividades, transições e navegações) utilizado pelo Framework X-Gov. Uma das principais vantagem dessa ferramenta em comparação com outras (e.g. lex/yacc, bison, tree-top) é que ela é capaz de gerar o código do reconhecedor em diversas linguagens de programação, sendo Java e C# importantes para essa solução. Dessa forma foi criado o interpretador da CroMeL que substitui o Gerenciador de Componentes desenvolvido anterior74 mente que trabalhava com XML1 . O interpretador conta com classes auxiliares para implementar as ações determinadas na fase de análise e projeto — Na implementação final apresentada, foi utilizado o padrão ‘Interpreter ’ encontrado na tabela 2.7 da sessão 2.4.4. • Após a fase de implementação, foi necessário criar um mecanismo de deployment para um arquivo CroMeL ser instalada no servidor do Framework X-Gov. 6.2 Reflexões Estudos demonstram que a maioria dos projetos de software falha, seja porque não cumprem o orçamento, ou não cumprem o cronograma, ou as funcionalidades não atendem às necessidades dos usuários ou porque todos estes fatores estão presentes em conjunto. Alguns deles ocorrem devido a problemas de comunicação nas diversas fases de projeto conhecidas pela engenharia de software 2 . Em inúmeros casos, devido a perda de informações, simplificações, generalizações na fase de análise a diferenças entre o resultado obtido e o esperado é muito longa. Essa distância do resultado é um fator de risco para qualquer projeto de software no qual regras de negócio devem ser definidas pelos especialistas e praticantes e os programadores precisam compreender e implementar essas regras — usar uma linguagem mais próxima do domínio do problema pode ser uma forma de minimizar problemas dessa natureza. O desenvolvimento de uma DSL é difícil pois requer conhecimento de domínio e na linguagem de desenvolvimento, mas poucas pessoas têm os dois (Mernik et al., 2005). Embora já seja possível criar ambientes de mídia cruzada, essa não é uma tarefa fácil, recorre-se na maioria das vezes à soluções ad-hoc que utilizam apenas uma tecnologia/plataforma específica. Seria ideal a utilização combinada de diversas tecnologias e dispositivos para emergir sistemas dessa natureza. Esse foi o objetivo da construção do Framework X-Gov e consequentemente de sua linguagem de modelagem, a CroMeL. A construção de linguagens pequenas (declarativas) com alto poder de expressão dentro de um domínio de problema não é uma prática nova da Engenharia de Software, mas encontra-se em um momento de renaissance e não se trata de uma arte perdida, aplicável apenas para construção de compiladores, ou protocolos de comunicação, como pode ser ser observado nesta pesquisa, portanto deve(ria) tornar-se mais popular no desenvolvimento das mais diversas soluções. 1 XML não é uma interface de programação adequada para o ser humano, veja http://www.ibm. com/developerworks/xml/library/x-sbxml.html 2 Veja figura popular que ilustra esses problemas na Engenharia de Software http://www. openplans.org/projects/opencore/iteration-tracker/software_engineering_explained.gif 75 Criar uma DSL Interna foi a idéia inicial deste trabalho, no entanto, durante a implementação, notou-se não se tratar da criação de uma “nova” linguagem, mas apenas uma lapidação de uma linguagem pré-existente para incluir algumas expressões idiomáticas específicas do domínio. Essa pseudo-linguagem ainda estaria presa a todas construções sintáticas da linguagem hospedeira, como por exemplo, o uso da notação de ponto (.) para acesso de métodos e atributos. Ainda, a validade de sua implementação seria questionável, pois era aplicável apenas a uma única linguagem hospedeira. No entanto, uma vantagem dessa forma de implementação é que não precisa especificar a gramática formalmente — o que deve facilitar a entrada de muitos programadores a este universo. A decisão em usar o ANTLR foi acertada, pois além de contar com um arsenal de recursos como livros, sites, e exemplos, também disponibiliza uma excelente ferramenta de desenvolvimento chamada ANTLRWorks que pode ser verificada no apêndice C.9 e plug-ins para trabalhar com sua gramática no Netbeans, Eclispe e Visual Studio. O uso dessa ferramenta tornou mais simples o trabalho de construção da CroMeL como pode ser observado pelas seguintes métrica: 198 linhas de código na CroMeL.g gerou 1214 linhas de código do analisador léxico e 1600 linhas de código do analisador sintático, totalizando 2814 linhas de código geradas automaticamente. Isso corresponde a cerca de 7% do trabalho de programar o mesmo reconhecedor manualmente. As ações semânticas foram inseridas diretamente nas regras do parser tornando a gramática complexa, o que dificulta sua manutenção. Poderia ser criada uma representação intermediária na forma de uma Abstract Syntax Tree (AST), por meio de regras de tradução da gramática, e incluir uma nova fase no processo que recebe a AST criada e executa as ações semânticas da mesma forma sobre uma estrutura de dados mais conveniente. Uma sugestão de melhoria para implementação é refatorar a gramática para utilizar essa representação intermediária, facilitaria a inclusão de novas ações semânticas. Com algumas soluções “engenhosas” para construir uma DSL Externa pode-se despender menos tempo do que a princípio aparentava, por meio da construção de uma sintaxe simplificada, padrões de projeto, e o uso de uma linguagem hospedeira com recursos de reflexão. A mesma técnica poderia ser aplicada a outras partes do Framework X-Gov, como por exemplo, na integração de um componente com as APIs do governo ou com o gerenciador de transições. No entanto a principal dificuldade no desenvolvimento da CroMeL foi em criar uma linguagem para servir a um framework que não estava pronto e não havia uma versão estável ou especificada. 76 6.3 Trabalhos Futuros Esta pesquisa é o início de um trabalho que pretende criar uma linguagem declarativa para especificar serviços de governo em mídia cruzada, pautado pela importante questão de inserir cross-media na interação do governo com os cidadãos, e a potencialidade para sua continuidade, existe uma série de possíveis trabalhos futuros a serem desenvolvidos: 1. Validação dos estudos sobre métodos de desenvolvimento de linguagem específica de domínio; 2. Estudo sobre um processo de desenvolvimento interativo e incremental para construção de DSLs; 3. Estudo de novas alternativas para construção de linguagens e os limites de cada técnica, a determinação desses limites ainda é um desafio para os Engenheiros de Software; 4. Estudo destinado a solucionar o problema da análise de um domínio com base na Engenharia de Informação; 5. Estudo de alternativas sintáticas para construção da linguagem CroMeL. 6. Tradução das palabras reservadas da sintaxe da CroMeL para o idioma português, o que pode ser um atrativo para desenvolvedores brasileiros; 7. Desenvolvimento de plug-ins para o Eclipse, Netbeans e/ou Visual Studio para oferecer suporte a linguagem CroMeL com realce de sintaxe, recurso de autocompletar, refactoring, entre outros; 8. Melhorar o suporte a informações sobre erros do reconhecedor para facilitar a utilização da linguagem; 9. Criação de um editor que permita modificar uma configuração já instalada no servidor (semelhante aqueles disponíveis pelas ferramentas do tipo wiki). 77 REFERÊNCIAS Abelson, H. e Sussman, G. J. (1996). Structure and Interpretation of Computer Programs. MIT Press, Cambridge, MA, USA. Alur, D., Malks, D., e Crupi, J. (2001). Core J2EE Patterns: Best Practices and Design Strategies. Prentice Hall PTR, Upper Saddle River, NJ, USA. Bennett, K. H. e Rajlich, V. T. (2000). Software maintenance and evolution: a roadmap. In ICSE ’00: Proceedings of the Conference on The Future of Software Engineering, pp. 73–87, New York, NY, USA. ACM. Bentley, J. (1986). Programming pearls: little languages. Commun. ACM, 29(8):711– 721. Bergin, Jr., T. J. e Gibson, Jr., R. G., editors (1996). languages—II. ACM, New York, NY, USA. History of programming Biggerstaff, T. J. (1998). A perspective of generative reuse. Ann. Softw. Eng., 5:169– 226. Bolter, J. D. e Grusin, R. (2000). Remediation: Understanding New Media. The MIT Press, 1st edition. Boumans, J. (2004). Cross media: E-content report 8. <http://www.acten.net>. Acesso em: 10 abr. 2008. Disponível em Brooks, Jr., F. P. (1975). The mythical man-month. In Proceedings of the international conference on Reliable software 193, p., New York, NY, USA. ACM. Cunha, M. R. (2006). Possibilidades tecnológicas apontam para mudanças em conceitos da comunicação. Razón y Palabra, v. 53, p. 1. 78 Dena, C. (2007). Patterns in Cross-Media interaction design: It’s much more than a URL. In Proceedings of 1st International Conference on Crossmedia Interaction Design, pp. 4–10, Hemavan, Sweden. Denny, M. (2003). Ontology building: A http://www.xml.com/lpt/a/2002/11/06/ontologies.html. survey of editing tools. EclipseFoundation (2009). Eclipse modeling project. http://www.eclipse.org/modeling/. Fach, P. W. (2001). Design reuse through frameworks and patterns. IEEE Softw., 18(5):71–76. Fernandez, O. (2007). Agile dsl development http://www.infoq.com/presentations/agile-dsl-development-in-ruby. in ruby. Filgueiras, L. (2007). X-gov: mídia cruzada em serviços de governo. Plano de Trabalho LTS2007.PR.029.00, PCS: Departamento de Engenharia de Computação e Sistemas digitais – Escola Politécnica da USP. Filgueiras, L. V. L., Correa, D. O., Neto, J. S. O., e Facis, R. P. (2008). X-gov planning: How to apply cross media to government services. In ICDS, pp. 140–145. IEEE Computer Society. Ford, N. (2008). Advanced dsls in ruby. http://rubyconf2008.confreaks.com/advanceddsls-in-ruby.html. Fowler, M. (2008). Domain specific languages. http://martinfowler.com/dslwip/. Freed, N. e Borenstein, N. (1996). RFC2046: Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types. RFC Editor United States. Freeman, S. e Pryce, N. (2006). Evolving an embedded domain-specific language in java. In OOPSLA ’06: Companion to the 21st ACM SIGPLAN symposium on Object-oriented programming systems, languages, and applications, pp. 855–865, New York, NY, USA. ACM. Gamma, E., Helm, R., Johnson, R., e Vlissides, J. (1995). Design patterns: elements of reusable object-oriented software. Addison-Wesley Professional. Greenfield, J. e Short, K. (2003). Software factories: assembling applications with patterns, models, frameworks and tools. In OOPSLA ’03: Companion of the 18th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications, pp. 16–27, New York, NY, USA. ACM. Groenewegen, D. M., Hemel, Z., Kats, L. C., e Visser, E. (2008). Webdsl: a domain79 specific language for dynamic web applications. In OOPSLA Companion ’08: Companion to the 23rd ACM SIGPLAN conference on Object-oriented programming systems languages and applications, pp. 779–780, New York, NY, USA. ACM. Hudak, P. (1996). Building domain-specific embedded languages. ACM Comput. Surv. 196, p. Ivkovic, I. e Kontogiannis, K. (2004). Model synchronization as a problem of maximizing model dependencies. In OOPSLA ’04: Companion to the 19th annual ACM SIGPLAN conference on Object-oriented programming systems, languages, and applications, pp. 222–223, New York, NY, USA. ACM. Johnson, R. E. (1997). How frameworks compare to other object-oriented reuse techniques. frameworks = (components + patterns. In in ’Communications of the ACM, pp. 39–42. Jones, C. (1996). Spr programming languages http://www.theadvisors.com/langcomparison.htm. table release 8.2. Kelly, S. e Tolvanen, J.-P. (2008). Domain-Specific Modeling: Enabling Full Code Generation. Wiley-IEEE Computer Society Pr. Kiczales, G. e Rivieres, J. D. (1991). The Art of the Metaobject Protocol. MIT Press, Cambridge, MA, USA. Kilmer, R. (2008). Ruby and the art of domain http://www.infoq.com/presentations/kilmer-ruby-dsls. specific languages. Knuth, D. E. (1984). Literate programming. 27(2):97–111. Krueger, C. W. (1992). Software reuse. ACM Comput. Surv., 24(2):131–183. Laird, P. e Barrett, S. (2009). Towards context sensitive domain specific languages. In CAMS ’09: Proceedings of the 1st International Workshop on Context-Aware Middleware and Services, pp. 31–36, New York, NY, USA. ACM. Lima, V. A. (2001). Mídia: Teoria e Política. Number 8586469602. Fundação Perseu Abramo. Martin, J. (1985). Fourth-generation languages. Volume I: principles. Prentice-Hall, Inc., Upper Saddle River, NJ, USA. Mernik, M., Heering, J., e Sloane, A. M. (2005). When and how to develop domainspecific languages. ACM Comput. Surv., 37(4):316–344. 80 Microsoft (2009). code name for microsoft’s next generation application development platform. http://msdn.microsoft.com/en-us/oslo/default.aspx. Miyamaru, F., Leite, L., Bertuzzi, A., e Filgueiras, L. (2008a). Mídia cruzada em serviços de governo: conceito e aplicaç ao. In IHC ’08: Proceedings of the VIII Brazilian Symposium on Human Factors in Computing Systems, pp. 330–331, Porto Alegre, Brazil, Brazil. Sociedade Brasileira de Computaç ao. Miyamaru, F., Leite, L., Bertuzzi, A., e Filgueiras, L. (2008b). Task patterns for egovernment services. In IHC ’08: Proceedings of the VIII Brazilian Symposium on Human Factors in Computing Systems, pp. 276–279, Porto Alegre, Brazil, Brazil. Sociedade Brasileira de Computaç ao. Nardi, B. A. (1993). A small matter of programming: perspectives on end user computing. MIT Press, Cambridge, MA, USA. Netbeans (2009). Generic languages framework. http://languages.netbeans.org/. Neto, J. J., Ramos, M. V. M., e Ítalo Santiago Veja (2009). Linguagens Formais: Teoria, Modelagem e Implementação. bookman, 1 edition. OpenArchitectureWare (2009). Xtext. http://wiki.eclipse.org/Xtext. Parr, T. (2007). The Complete Antlr Reference Guide. Pragmatic Bookshelf. Sammet, J. E. (1969). Programming Languages: History and Fundamentals. PrenticeHall, Inc., Upper Saddle River, NJ, USA. Schmidt, D. C. (2006). Guest editor’s introduction: Model-driven engineering. Computer, 39(2):25–31. Sharp, H., Rogers, Y., e Preece, J. (2007). Interaction Design: Beyond HumanComputer Interaction. John Wiley & Sons Ltd, 2 edition. Steele, Jr., G. L. (1998). Growing a language. In OOPSLA ’98 Addendum: Addendum to the 1998 proceedings of the conference on Object-oriented programming, systems, languages, and applications (Addendum), New York, NY, USA. ACM. Subramaniam, V. (2008). Programming Groovy: Dynamic Productivity for the Java Developer. Pragmatic Bookshelf. van Deursen, A., Klint, P., e Visser, J. (2000). Domain-specific languages: an annotated bibliography. SIGPLAN Not., 35(6):26–36. Wexelblat, R. L. (1981). History of Programming Languages. Academic Press, Inc., 81 Orlando, FL. Wiberg, C., Bodén, J., e Jegers, K. (2007). Cross-Media interaction design. In HCI and New Media Arts: Methodology andEvaluation, San Jose, CA, USA. Wile, D. S. (2001). Supporting the dsl spectrum. J. Comput. Inform. 82 Apêndice A Exemplos de DSLs A.1 jMock Exemplo sem pontuação e parênteses da sintaxe java: 1 2 mainframe expects once method ‘‘buy’’ with eq QUANTITY will return value TICKET De volta com a notação da linguagem Java: 1 2 3 4 5 6 7 8 9 10 11 Mock mainframe = mock(Mainframe.class); Mock auditing = mock(Auditing.class); Agent agent = new Agent( QUANTITY, (Mainframe)mainframe.proxy(), (Auditing)auditing.proxy() ); public void testBuysWhenPriceEqualsThreshold() { mainframe.expects(once()) .method(‘‘buy’’).with(eq(QUANTITY)) .will(returnValue(TICKET)); ,auditing.expects(once()) .method(‘‘bought’’).with(same(TICKET)); ,agent.onPriceChange(THRESHOLD); } 12 13 14 15 16 17 18 public void testDoesNotBuyIfMainframeUnavailable() { mainframe.stubs().method(‘‘buy’’) .will(throwException(new NotAvailableException()); auditing.expects(never()).method(‘‘bought’’); agent.onPriceChange(THRESHOLD); } 83 A.2 API Fluente Implementação de uma API usada de forma imperativa: 1 2 3 4 Processor p = new Processor(2, Processor.Type.i386); Disk d1 = new Disk(150, Disk.UNKNOWN_SIZE, null); Disk d2 = new Disk(75, 7200, Disk.Interface.SATA); return new Computer(p, d1, d2); Usando encadeamento de métodos: 1 2 3 4 5 6 7 8 9 10 11 computer() .processor() .cores(2) .i386() .disk() .size(150) .disk() .size(75) .speed(7200) .sata() .end(); Sequenciamento de funções: 1 2 3 4 5 6 7 8 9 10 computer(); processor(); cores(2); processorType(i386); disk(); diskSize(150); disk(); diskSize(75); diskSpeed(7200); diskInterface(SATA); Funções aninhadas: 1 2 3 4 5 6 7 8 9 computer( processor( cores(2), Processor.Type.i386 ), disk( size(150) ), disk( 84 size(75), speed(7200), Disk.Interface.SATA 10 11 12 13 14 ) ); 85 Apêndice B Framework X-Gov B.1 Diagrama de Classes do FrameworkLibrary 86 87 Figura B.1: Exemplo de classes de componentes Figura B.2: Componentes FindEntityInfo para TV, Mobile e Web 88 Figura B.3: Componente GetPreServiceInfo para TV, Mobile e Web Figura B.4: Classes de Transição 89 Apêndice C Implementação da CroMeL C.1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Regras Léxicas e Sintáticas da CroMeL grammar CroMeL ; /************************************************ * PARSER RULES * ************************************************/ prog : var * service + ; service : ’ service ’ service_name ? ’{ ’ decl ’} ’ ; decl : task + transition * web_navigation * ; task : ’ task ’ task_name ’of ’ pattern_name ’{ ’ media + ’} ’ ; media : MEDIA params ; transition : ’ transition ’ transition_type navigation params ; web_navigation : ’ navigation ’ label navigation ; navigation : ’[ ’ begin ’->’ end ’] ’ ; 90 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 params : ’( ’ assign ’) ’ ; assign : ID ’= ’ expr ( ’ , ’ ID ’= ’ expr ) * ; var : assign ; begin : REF ; end : REF ; expr : | | | | ; STRING INT BOOLEAN QID // substituir ID por valor em memória REF // substituir ID por número gerado pela Task . media // parametro opcional n~ a o utilizado service_name : STRING ; // pode restringir aos nomes de padr~ o es de tarefas conhecidos pattern_name : ID ; // pode restringir aos tipos de transiç~ o es conhecidos transition_type : ID ; // label da navegacao label : STRING ; // nome do servico serve como chave para navegaç~ a o / transiç~ ao task_name : ID ; /************************************************ * LEXER RULES * ************************************************/ MEDIA : ( ’ mobile ’ | ’web ’ | ’tv ’) ; BOOLEAN : ( ’ true ’| ’ false ’) ; INT : ’0 ’.. ’9 ’+ ; ID : ( ’a ’.. ’ z ’| ’A ’.. ’ Z ’| ’_ ’) ( ’a ’.. ’ z ’| ’A ’.. ’ Z ’| ’0 ’.. ’9 ’| ’ _ ’) * ; // uma referencia de uma variável ( usada para recuperar seu valor ) 91 70 71 72 73 74 75 76 77 78 79 80 81 82 QID : ’$ ’ ID ; // uma referencia do tipo Task . media ( usado para identificar componentes ) REF : ’\& ’ ID ( ’. ’ MEDIA ) ; STRING : ’" ’ .* ’" ’ | ’\ ’ ’ ~( ’\\ ’| ’\ ’ ’| ’\* ’) * ’\ ’ ’ ; // espaços em branco WS : ( ’ ’| ’\t ’| ’\ r ’| ’\ n ’) { $channel = HIDDEN ;} ; // comentários CMT : ’# ’ ~( ’\ n ’| ’\ r ’) * ’\r ’? ’\n ’ { $channel = HIDDEN ;}; COMMENT : ’/* ’ .* ’*/ ’ { $channel = HIDDEN ;} ; Listagem C.1: Gramatica C.2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Regras Semânticas da CroMeL grammar CroMeL ; @header { import java . util . Map ; import java . util . HashMap ; import java . util . List ; import java . util . ArrayList ; import java . util . regex . Matcher ; import java . util . regex . Pattern ; } @members { // Classe que armazena os dados de um componente class ComponentDTO { public String type ; public Map parameters ; } class TransitionDTO { public String type ; public Map parameters ; public Integer begin , end ; } class NavigationDTO { public String label ; public Integer begin , end ; } class CodeDTO { 92 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public CodeDTO ( String comment , String code ) { this . comment = comment ; this . code = code ; } public String comment ; public String code ; } // lista de componentes , transicoes e navegacoes declaradas List < ComponentDTO > components = new ArrayList < ComponentDTO >() ; List < TransitionDTO > transitions = new ArrayList < TransitionDTO >() ; List < NavigationDTO > navigations = new ArrayList < NavigationDTO >() ; // memória para as variáveis locais Map memory = new HashMap () ; // lista com todos identificadores de componentes Map componentIds = new HashMap () ; // metodo para buscar o id de um componente ( usado na definicao de parametros e navegacao ) public Integer getComponentId ( String componentName ) { // busca valor na memória ( eliminando o & que nao foi colocado na tabela ) Object v = componentIds . get ( componentName . substring (1) ) ; // se encontrado seta o valor de retorno , caso contrário imprime erro if ( v != null ) { System . out . println (" - resoluç~ a o da refer^ e ncia id = "+ v ) ; return new Integer ( v . toString () ) ; } else { System . err . println (" Erro : refer^ e ncia indefinida "+ componentName ) ; return null ; } } } /************************************************ * PARSER RULES * ************************************************/ prog : var * service + ; // declaraç~ a o de variáveis para usar como valor nas propriedades 93 71 72 73 74 75 76 77 78 79 80 81 82 83 var : assign { System . out . println (" - declaraç~ a o da variável : "+ $assign . n +"="+ $assign . v ) ; memory . put ( $assign .n , $assign . v ) ; }; service scope { // contador usado para atribuir um ID para cada componente em um serviço int componentId ; } @after { System . out . println (" Execuç~ a o após processamento da entrada !") ; 84 85 // Cria os componentes da CroMeL e seta seus parametros por reflexao for ( ComponentDTO component : components ) { System . out . println (" Criando componente "+ component . type ) ; System . out . println ("\ tarmazenamento de "+ component . parameters . size () +" parametros ") ; } 86 87 88 89 90 91 // Cria os objetos de transicao e seta seus parametros por reflexao for ( TransitionDTO transition : transitions ) { System . out . println (" Criando transiç~ a o "+ transition . type ) ; System . out . println ("\ tarmazenamento de "+ transition . parameters . size () +" parametros ") ; System . out . println ("\ ttransiç~ a o entre os componentes "+ transition . begin +" e "+ transition . end ) ; } 92 93 94 95 96 97 98 99 100 // Cria os objetos de navegacao for ( NavigationDTO navigation : navigations ) { System . out . println (" Criando navegaç~ a o "+ navigation . label ) ; System . out . println ("\ tnavegaç~ a o entre os componentes "+ navigation . begin +" e "+ navigation . end ) ; } 101 102 103 } 94 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 : { $service :: componentId =1; } // inicializacao do contador ’ service ’ service_name ? ’{ ’ decl ’} ’ ; decl : task + transition * web_navigation * ; // criar objetos para cada midia e setar os parametros ( chamada da API de reflexao ) task : ’ task ’ task_name { System . out . println (" Declaraç~ a o da atividade :"+ $task_name . text ) ; } ’of ’ pattern_name ’{ ’ media [ $task_name . text , $pattern_name . text ]+ ( lc = literate_code { // Executa as regras definidas em um serviço System . out . println (" Executa código embutido : "+ $lc . comment ) ; System . out . println ("\ t "+ $lc . code ) ; } ) * ’} ’ ; // retornar o componente com os parametros para a task media [ String taskName , String patternName ] : m = MEDIA params { // atribui um id ( setar na propriedade da superclasse ) e guarda para referencia int componentId = $service :: componentId ++; String media = $m . text ; String componentName = $taskName +"."+ media ; componentIds . put ( componentName , componentId ) ; // define o tipo do componente String componentType = $patternName +"."+ media ; System . out . println (" Novo componente do tipo "+ componentType +" [ id ="+ componentId +"]") ; // parametros do componente System . out . println ("\ tparametros ="+ $params . p ) ; // guarda o componente na lista // TODO : incluir ID na lista de par^ a metros ComponentDTO dto = new ComponentDTO () ; dto . type = componentType ; 95 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 dto . parameters = $params . p ; components . add ( dto ) ; }; // criar objeto de transicao e setar os parametros transition : ’ transition ’ transition_type navigation params { System . out . println (" Nova transiç~ a o do tipo "+ $transition_type . text ) ; System . out . println ("\ tparametros ="+ $params . p ) ; TransitionDTO dto = new TransitionDTO () ; dto . type = $transition_type . text ; dto . parameters = $params . p ; dto . begin = $navigation . b ; dto . end = $navigation . e ; transitions . add ( dto ) ; }; // criar objeto de navegacao web e seta o label web_navigation : ’ navigation ’ label navigation { NavigationDTO dto = new NavigationDTO () ; dto . label = $label . text ; dto . begin = $navigation . b ; dto . end = $navigation . e ; navigations . add ( dto ) ; }; // recupera o ID do begin e do end navigation returns [ int b , int e ] : ’[ ’ begin ’->’ end ’] ’ { $b = $begin . id ; $e = $end . id ; System . out . println (" Navegaç~ a o do componente ["+ $begin . id +"] -> ["+ $end . id +"]") ; }; // guardar os parametros em um HashMap ( nome , valor ) passado pela regra params returns [ Map p ] @init { p = new HashMap () ; 96 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 } : ’( ’ a1 = assign { p . put ( $a1 .n , $a1 . v ) ; } ( ’ , ’ a2 = assign { p . put ( $a2 .n , $a2 . v ) ; } ) * ’) ’; // retorna um par nome - valor assign returns [ String n , Object v ] : ID ’= ’ expr { $n = $ID . text ; $v = $expr . value ; }; begin returns [ Integer id ] : REF { $id = getComponentId ( $REF . text ) ; }; end returns [ Integer id ] : REF { $id = getComponentId ( $REF . text ) ; }; // regra que determina o tipo de dado por infer^ e ncia expr returns [ Object value ] : STRING { $value = $STRING . text ; } | INT { $value = Integer . parseInt ( $INT . text ) ; } | BOOLEAN { $value = Boolean . parseBoolean ( $BOOLEAN . text ) ; } | QID // substituir ID por valor em memória { // busca valor na memória ( eliminando o $ que nao foi colocado na tabela ) Object v = memory . get ( $QID . text . substring (1) ) ; // se encontrado seta o valor de retorno , caso contrário imprime erro if ( v != null ) { $value = v ; System . out . println (" - resoluç~ a o da variável "+ $QID . text +"="+ v ) ; } else System . err . println (" Erro : variável indefinida "+ $QID . text ) ; } | REF // substituir ID por numero gerado pela Task . media { $value = getComponentId ( $REF . text ) ; } 97 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 ; // parametro opcional nao utilizado service_name : STRING ; // pode restringir aos nomes de padr~ o es de tarefas conhecidos pattern_name : ID ; // pode restringir aos tipos de transicoes conhecidos transition_type : ID ; // label da navegacao label : STRING ; // nome do servico serve como chave para navegacao / transicao task_name : ID ; literate_code returns [ String comment , String code ] : CODE { String pattern = " < <(\\ w +) > >=(.*) @ "; Pattern p = Pattern . compile ( pattern , Pattern . MULTILINE ) ; Matcher m = p . matcher ( $CODE . text ) ; if ( m . find () ) { $comment = m . group (1) ; $code = m . group (2) ; System . out . println ( $comment ) ; System . out . println ( $code ) ; } else { System . out . println (" Erro : código inválido ") ; } 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 }; /************************************************ * LEXER RULES * ************************************************/ CODE : ’<<’ .* ’@ ’; MEDIA : ( ’ mobile ’ | ’web ’ | ’tv ’) ; BOOLEAN : ( ’ true ’| ’ false ’) ; 98 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 INT : ’0 ’.. ’9 ’+ ; ID : ( ’a ’.. ’ z ’| ’A ’.. ’ Z ’| ’_ ’) ( ’a ’.. ’ z ’| ’A ’.. ’ Z ’| ’0 ’.. ’9 ’| ’ _ ’) * ; // uma referencia de uma variavel ( usada para recuperar seu valor ) QID : ’$ ’ ID ; // uma referencia do tipo Task . media ( usado para identificar componentes ) REF : ’\& ’ ID ( ’. ’ MEDIA ) ; STRING : ’" ’ .* ’" ’ | ’\ ’ ’ ~( ’\\ ’| ’\ ’ ’| ’\* ’) * ’\ ’ ’ ; // NEWLINE : ’\r ’? ’\n ’ ; // espaço em branco WS : ( ’ ’| ’\t ’| ’\ r ’| ’\ n ’) { $channel = HIDDEN ;} ; // comentários CMT : ’# ’ ~( ’\ n ’| ’\ r ’) * ’\r ’? ’\n ’ { $channel = HIDDEN ;}; COMMENT : ’/* ’ .* ’*/ ’ { $channel = HIDDEN ;} ; Listagem C.2: Semantica C.3 Diagramas de Sintaxe Figura C.1: Diagrama de sintaxe da raiz da gramática Figura C.2: Diagrama da sintaxe de declaração de um serviço Figura C.3: Diagrama da sintaxe dos elementos que pertencem a um serviço 99 Figura C.4: Diagrama da sintaxe de uma atividade Figura C.5: Diagrama da sintaxe de declaração de parametros Figura C.6: Diagrama de sintaxe de transições Figura C.7: Diagrama de sintaxe de navegação 100 C.4 Autômato Finito Determinístico Figura C.8: DFA reconhecedor dos Tokens da linguagem CroMeL 101 C.5 ANTLRWorks Figura C.9: Ferramenta ANTLRWorks no desenvolvimento da CroMeL C.6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 CroMeL XML <? xml version ="1.0" encoding =" utf -8"? > < service > <! - - Initial information --> < task taskId ="1" pattern =" GetPreServiceInfo " > < name > Basic Information about exams schedule . </ name > < executedBy > Citizen </ executedBy > <web > < componentId >11 </ componentId > < componentName > Basic Information </ componentName > < description > For more information about the medical examination service use the menu on the side </ description > < uriCalled > webExameInfo </ uriCalled > </ web > < mobile > < componentId >12 </ componentId > < componentName > Informations </ componentName > < uriCalled > mobExamInfo </ uriCalled > < welcomeMessage > Welcome to the X - Media Service </ welcomeMessage > </ mobile > 102 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <tv > < componentId >13 </ componentId > < componentName > Basic Information about exams schedule . </ componentName > < uriCalled > tvExamInfo </ uriCalled > < first > true </ first > </ tv > </ task > <! - - User ’ s Exam List --> < task taskId ="2" pattern =" FindPrivateInfo " > < name > Exams List </ name > < executedBy > Citizen </ executedBy > <web > < componentId >21 </ componentId > < componentName > My Exams List </ componentName > < authenticationCompId >71 </ authenticationCompId > < uriCalled > webExamList </ uriCalled > < dataUrl > http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx </ dataUrl > < getFullEntitiesListWebMethod > GWSGetPermittedExams </ getFullEntitiesListWebMethod > < getEntityInformationWebMethod > GWSGetExamInformation </ getEntityInformationWebMethod > < scheduleCompId >31 </ scheduleCompId > </ web > < mobile type =" SearchByOptionList " > < componentId >22 </ componentId > < componentName > My Exams List </ componentName > < authenticationCompId >72 </ authenticationCompId > < uriCalled > mobExamList </ uriCalled > < instructionText > Select an exam : </ instructionText > < listName > Exams Requested </ listName > < dataUrl > http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx </ dataUrl > < getFullEntitiesListWebMethod > GWSGetPermittedExams </ getFullEntitiesListWebMethod > < getEntityInformationWebMethod > GWSGetExamInformation </ getEntityInformationWebMethod > </ mobile > <tv > < componentId >23 </ componentId > < componentName > My Exams List </ componentName > < entityType > Exam </ entityType > < compAuthId >73 </ compAuthId > < uriCalled > tvExamList </ uriCalled > < dataUrl > http ://143.107.102.15/ govside / G W S F i n d P r i v a t e I n f o r m a t i o n / GWSFindPrivateInfo . asmx </ dataUrl > 103 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 < getFullEntitiesListWebMethod > GWSGetPermittedExams </ getFullEntitiesListWebMethod > < getEntityInformationWebMethod > GWSGetExamInformation </ getEntityInformationWebMethod > </ tv > </ task > < transition class =" BarCode " > < BarCodeType > QRCode </ BarCodeType > < OriginComponentId >13 </ OriginComponentId > < DestinationComponentId >22 </ DestinationComponentId > < BaseUrl > http ://143.107.102.15/ poc3xgov / Mobile_Comp / mobile / mobFindPrivExam </ BaseUrl > < ErrorCorrection >M </ ErrorCorrection > < ImageSize >5 </ ImageSize > < LabelMessage > Use this QRCode to access next service step . </ LabelMessage > < TransitionId >7 </ TransitionId > < TransitionName > QRCODE teste web -& gt ; mob </ TransitionName > </ transition > < navigation > < originComponent >11 </ originComponent > < endComponent >21 </ endComponent > < label > See your exam list </ label > </ navigation > < navigation > < originComponent >21 </ originComponent > < endComponent >31 </ endComponent > < label > Schedule an exam </ label > </ navigation > </ service > Listagem C.3: XML C.7 1 2 3 4 5 6 7 8 9 10 11 using using using using using using using using using using using CromelService para Interpretador na versão C# System ; System . Collections . Generic ; System . Linq ; System . Text ; System . Xml . Linq ; System . IO ; log4net ; FrameworkLibrary ; System . Xml ; System . Net ; System . Configuration ; 104 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 using using using using XTransitionLibrary ; Newtonsoft . Json ; System . Reflection ; System . Web . Hosting ; namespace X WSCompon entMana ger { public class CromelService { private static readonly ILog log = LogManager . GetLogger ( typeof ( CromelService ) ) ; public static void RunCromelScript ( string scriptComment , string scriptCode ) { var runtime = IronRuby . Ruby . CreateRuntime () ; var engine = runtime . GetEngine (" rb ") ; // Run embedded code in CroMeL script var result = engine . Execute ( cromelScript ) ; log . Info ( String . Format (" Running {0} with result : {1}." , scriptComment , result ) ) ; return result . ToString () ; } public static void CreateNavigations ( List < NavigationDTO > navigations ) { log . Info ( String . Format ("{0} navigations found ." , navigations . Count () ) ) ; // component list to add in the configuration manager List < ComponentConnection > list = new List < ComponentConnection >() ; // this constructor because mappings of the classes and properties are known for C omponen tConnec tion ComponentFactory cf = new ComponentFactory () ; foreach ( NavigationDTO nav in navigations ) { Comp onentCo nnection cc = ( Compone ntConne ction ) cf . createObject (" FrameworkLibrary " , " Compone ntConne ction ") ; cf . setProperty ( cc , " originComponent " , nav . Begin ) ; cf . setProperty ( cc , " endComponent " , nav . End ) ; cf . setProperty ( cc , " label " , nav . Label ) ; 105 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 } int i = 0; foreach ( Compone ntConne ction cc in list ) { // Verify if connected components exist if ( Global . ComponentList . Exists ( c = > c . ComponentId == cc . OriginComponentId ) ) { if ( Global . ComponentList . Exists ( c = > c . ComponentId == cc . Com pon en tCo nn ect ed Id ) ) { if ( Global . ComponentList . Single ( c = > c . ComponentId == cc . OriginComponentId ) . Medium == Global . ComponentList . Single ( c = > c . ComponentId == cc . C omp one nt Con ne cte dId ) . Medium ) { // Insert connection to component . Global . ComponentList . Single ( c = > c . ComponentId == cc . OriginComponentId ) . I n s e r t C o m p o n e n t C o n n e c t i o n ( cc ) ; i ++; } else { log . Error (" Components " + cc . OriginComponentId . ToString () + " and " + cc . C omp on ent Co nne ct edI d . ToString () + " are not from the same medium !") ; } } else { log . Error (" There is no component with id : " + cc . Co mp one nt Con nec te dId . ToString () + " to end a connection .") ; } } else { log . Error (" There is no component with id : " + cc . OriginComponentId . ToString () + " to start a connection .") ; } } log . Info ( i . ToString () + " connections created .") ; 106 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 } public static void CreateComponents ( List < ComponentDTO > components ) { log . Info ( String . Format ("{0} components found ." , components . Count () ) ) ; // component list to add in the configuration manager List < Component > componentsCreated = new List < Component >() ; Dictionary < String , String > mappingClasses = loadMappingClasses (" classNames . mapping ") ; Dictionary < String , String > mappingProperties = l oa dM a pp i ng Pr o pe rt i es (" propertyNames . mapping ") ; // mapping null because the names of the classes are known ComponentFactory cf = new ComponentFactory ( mappingClasses , mappingProperties ) ; foreach ( ComponentDTO component in components ) { String type = component . Type ; Hashtable params = component . parameters ; // create a new component and add to the list Component component = ( Component ) cf . createComponent ( type ); if ( component != null ) { componentsCreated . Add ( component ) ; foreach ( DictionaryEntry de in parameters ) { cf . setProperty ( component , de . Key () , de . Value () ) ; } } else { log . Warn (" Component not found , please verify the component mapping .") ; } log . Info ( String . Format ("{0} components created ." , componentsCreated . Count () ) ) ; // Atualiza o Global Component List ( TODO : poderia utilizar o AddRange ( componentsCreated ) mas necessita testar primeiro ) foreach ( var comp in componentsCreated ) { Global . ComponentList . Add ( comp ) ; 107 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 } } } public static void CreateTransitions ( List < TransitionDTO > transitions ) { log . Info ( String . Format ("{0} transitions found ." , transitions . Count () ) ) ; TransitionFactory tf = new TransitionFactory () ; tf . L oa d T r a ns i t i on A s s e mb l y () ; foreach ( TransitionDTO transitionElement in transitions ) { String transitionClass = transitionElement . Type ; Hashtable parameters = transitionElement . parameters ; log . Info (" New transition element found : " + transitionClass ) ; Object transitionObject = null ; try { transitionObject = tf . Cr e a t e Tr a n s it i o n O bj e c t ( transitionClass ) ; } catch ( Exception ) { log . Error (" Could not instantiate class : " + transitionClass + ".") ; log . Info (" Skipping this transition element ..") ; continue ; } log . Debug (" Configuring transition parameters : " + transitionClass ) ; foreach ( DictionaryEntry de in parameters ) { try { cf . setProperty ( transitionObject , de . Key () , de . Value () ) ; } catch ( Exception e ) { log . Error ( e ) ; log . Info (" Skipping this transition property ..") ; continue ; } 108 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 } Int32 originTaskId = 0; Int32 destinationTaskId = 0; Int32 transitionId = 0; try { originTaskId = transitionElment . Begin ; destinationTaskId = transitionElement . End ; if ( tf . TransitionExists ( originTaskId , destinationTaskId , transitionClass ) ) { try { tf . S e t T r a n s i t i o n O b j e c t P r o p e r t y ( transitionObject , " TransitionId " , tf . GetTransitionId ( originTaskId , destinationTaskId , transitionClass ) . ToString () ) ; tf . E di t E x i st i n g Tr a n s i ti o n ( transitionObject , transitionClass ) ; transitionId = tf . GetTransitionId ( originTaskId , destinationTaskId , transitionClass ) ; log . Info (" Existent transition id was caught .") ; } catch ( Exception e ) { log . Error (" Error while editing existent transition ." , e ) ; log . Error (" Skipping this transition element ..") ; continue ; } } else { try { transitionId = tf . CreateNewTransitionThroughWebService ( transitionObject , transitionClass , originTaskId , destinationTaskId ) ; log . Info (" New transition id was received .") ; } catch ( Exception e ) { log . Error (" Error while creating new transition : " + transitionClass , e ) ; log . Error (" Skipping this transition element ..") ; continue ; } } } catch ( Exception e ) { 109 191 log . Error (" Could not verify if the transition already exists ." , e ) ; log . Error (" Skipping this transition element ..") ; continue ; 192 193 194 195 196 197 } // Edit object with new transition id try { tf . S e t T r a n s i t i o n O b j e c t P r o p e r t y ( transitionObject , " TransitionId " , transitionId . ToString () ) ; log . Debug (" TransitionId property was sucessfully setted . (" + transitionId . ToString () + ") .") ; } catch ( Exception e ) { log . Error (" Could not set value : " + transitionId + " to TransitionId property ." , e ) ; log . Error (" Skipping this transition element ..") ; continue ; } // Sending object to memory try { tf . Sa ve C om po n en t In Me m or y ( transitionClass , transitionId , originTaskId ) ; log . Debug (" Transition successfully added to component .") ; } catch ( Exception e ) { log . Error (" Error when adding transition to component ." , e ) ; continue ; } 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 } } .... } Listagem C.4: Cromel Service C.8 ComponentFactory para Interpretador na versão C# 1 2 3 4 5 6 7 using using using using using using using System ; System . Collections . Generic ; System . Linq ; System . Text ; System . Reflection ; FrameworkLibrary ; log4net ; 110 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 using System . Web . Hosting ; namespace X WSCompon entMana ger { /// < summary > /// This class uses reflection to instantiate dynamically the components from FrameworkLibrary /// </ summary > class ComponentFactory { private static readonly ILog log = LogManager . GetLogger ( typeof ( ComponentFactory ) ) ; private Assembly assembly ; private Dictionary < String , String > mappingClasses ; private Dictionary < String , String > mappingProperties ; /// < summary > /// Used to create a ComponentFactory for FrameworkLibrary assembly without a dictionary to bind the properties /// </ summary > public ComponentFactory () : this (" FrameworkLibrary . dll ") {} /// < summary > /// Create a ComponentFactory for FrameworkLibrary with a dictionary used to bind the properties to names /// </ summary > /// < param name =" mappingClasses " > Dictionary to lookup the name of the classes </ param > /// < param name =" mappingProperties " > Dictionary to lookup the name of the properties </ param > public ComponentFactory ( Dictionary < String , String > mappingClasses , Dictionary < String , String > mappingProperties ) : this (" FrameworkLibrary . dll ") { this . mappingProperties = mappingProperties ; this . mappingClasses = mappingClasses ; } /// < summary > /// Used to create a ComponentFactory for an assembly without a dictionary to bind the properties /// </ summary > /// < param name =" assembly " > The name of the assembly ( e . g . FrameworkLibrary . dll ) </ param > public ComponentFactory ( String assembly ) { try 111 45 46 { String assemblyWithPath = HostingEnvironment . A p p l i c a t i o n P h y s i c a l P a t h + @ " bin \"+ assembly ; log . Debug (" FrameworkLibrary path : " + assemblyWithPath ) ; this . assembly = Assembly . LoadFrom ( assemblyWithPath ) ; // this . assembly = AppDomain . CurrentDomain . Load ( assembly ) ; 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 } catch ( Exception e ) { log . Error (" Could not load assembly ( dll or exe ) , verify path : " + assembly , e ) ; } } /// < summary > /// Creates a new object from a namespace of the assembly /// </ summary > /// < param name =" namespaceName " > Name of the namespace or namespace . subnamespace </ param > /// < param name =" className " > Name of the class that belongs to the namespace </ param > /// < returns > </ returns > public Object createObject ( String namespaceName , String className ) { // Create component by parametrized constructor // MyClass myObj = ( MyClass ) myAssembly . CreateInstance (" R e fl e c t i on T e s t As s e m bl y . MyClass " , // false , BindingFlags . Default , null , // new object [] { 5 } , null , null ) ; Object newObject = null ; // Lookup in the dictionary for class names if (( mappingClasses != null ) && mappingClasses . ContainsKey ( className ) ) { className = mappingClasses [ className ]; } try { newObject = ( Object ) assembly . CreateInstance ( namespaceName + "." + className ) ; if ( newObject == null ) throw new C o m p o n e n t F a c t o r y E x c e p t i o n (" Creating class "+ className ) ; 112 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 } catch ( Exception e ) { log . Warn (" Can ’ t instantiate the component : " + className , e); } return newObject ; } /// < summary > /// Creates a new object from FrameworkLibrary namespace /// </ summary > /// < param name =" objectName " > Name of the class </ param > /// < returns > New Object instance </ returns > public Object createObject ( String objectName ) { return this . createObject (" FrameworkLibrary " , objectName ) ; } /// < summary > /// Creates a new component from FrameworkLibrary namespace /// </ summary > /// < param name =" componentName " > Name of the class </ param > /// < returns > New Component instance </ returns > public Component createComponent ( String componentName ) { return ( Component ) this . createObject (" FrameworkLibrary " , componentName ) ; } /// < summary > /// Set the property of a object . If you have a ComponentFactory created with a dictionary /// it will try to avoid the Mi s s i n gM e t h od E x c e pt i o n using the key of the dictionary for lookup /// </ summary > /// < param name =" target " > The object that will be set a property value </ param > /// < param name =" property " > The name of the property </ param > /// < param name =" value " > The value of the property ( any datatype as Object ) </ param > public void setProperty ( Object target , String property , Object value ) { try { 113 121 122 // Lookup in the dictionary for property names if (( mappingProperties != null ) && mappingProperties . ContainsKey ( property ) ) { property = mappingProperties [ property ]; } 123 124 125 126 127 128 // transfor 1 st char in upcase ( convention in C #) property = StringExtension . ToUpperFirstLetter (( String ) property ) ; 129 130 131 132 Type componentType = target . GetType () ; // if int datatype is passed as string will have a M e th o d M i ss i n g E xc e p t io n because it should be converted int iValue = 0; bool bValue = false ; if ( value is String && Int32 . TryParse ( value . ToString () , out iValue ) ) { // int value componentType . InvokeMember ( property , BindingFlags . SetProperty , null , target , new object [] { iValue }) ; } else { // if bool datatype is passed as string , will have a M e th o d M i ss i n g E xc e p t io n because it should be converted if ( value is String && Boolean . TryParse ( value . ToString () , out bValue ) ) { // bool value componentType . InvokeMember ( property , BindingFlags . SetProperty , null , target , new object [] { bValue }) ; } else { // string or object value componentType . InvokeMember ( property , BindingFlags . SetProperty , null , target , new object [] { value }) ; } } 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 } 114 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 catch ( Exception e ) { log . Warn ( String . Format (" Can ’ t setProperty : {0} = {1} ({2}) " , property , value , value . GetType () ) , e ) ; } } /// < summary > /// Call a method on the target object with parameters /// </ summary > /// < param name =" target " > The object to call the method </ param > /// < param name =" methodName " > The name of the method </ param > /// < param name =" parameters " > list of parameters </ param > public void callMethod ( Object target , String methodName , Object parameters ) { try { // Lookup in the dictionary for property names if (( mappingProperties != null ) && mappingProperties . ContainsKey ( methodName ) ) { methodName = mappingProperties [ methodName ]; } 175 176 177 178 179 180 // transfor 1 st char in upcase ( convention in C #) methodName = StringExtension . ToUpperFirstLetter (( String ) methodName ) ; 181 182 183 184 185 Type componentType = target . GetType () ; // call the method componentType . InvokeMember ( methodName , BindingFlags . InvokeMethod , null , target , new object [] { parameters } ); 186 187 188 189 190 191 192 193 194 } catch ( Exception e ) { log . Warn ( String . Format (" Can ’ t call the method {0} with parameter {1}" , methodName , parameters ) , e ) ; } } /// < summary > 115 195 /// Ainda nao foi usado para nada , mas serve para inspecionar um assembly . /// </ summary > /// < param name =" assembly " > nome completo do assembly </ param > public static void printTypes ( String assembly ) { if ( assembly == null ) { assembly = " FrameworkLibrary . dll "; } 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 // Load an assembly from file Assembly myAssembly = Assembly . LoadFrom ( assembly ) ; // Get the types contained in the assembly and print their names Type [] types = myAssembly . GetTypes () ; foreach ( Type type in types ) { log . Debug ( type . FullName ) ; } } } /// < summary > /// Utiity class for string manipulation /// </ summary > public static class StringExtension { // string extension method ToUpperFirstLetter public static string ToUpperFirstLetter ( this string source ) { if ( string . IsNullOrEmpty ( source ) ) return string . Empty ; // convert to char array of the string char [] letters = source . ToCharArray () ; // upper case the first char letters [0] = char . ToUpper ( letters [0]) ; // return the array made of the new char array return new string ( letters ) ; } } /// < summary > /// Used to show that something is wrong in the factory /// </ summary > class C o m p o n e n t F a c t o r y E x c e p t i o n : Exception { public C o m p o n e n t F a c t o r y E x c e p t i o n ( String msg ) : base ( msg ) { } 116 240 241 } } Listagem C.5: Component Factory 117 Este documento foi preparado com o formatador de textos LATEX .