Como fazer uma Modularização dinâmica em Java com OSGi

O conceito de modularização dinâmica para a tecnologia Java, proposto pela iniciativa OSGi, vem sendo adotado há um bom tempo por soluções de software cuja execução não deve ser interrompida, seja devido à necessidade de instalação de novos módulos, seja para alcançar resiliência quanto à disponibilidade da aplicação. Independentemente disso, existem ótimos benefícios pela escolha de uma arquitetura modular, e o framework OSGi é o caminho para alcançar tais vantagens. Com base nisso, este artigo tem como objetivo apresentar o contexto no qual a especificação OSGi foi concebid, bem como um exemplo prático para o entendimento dos principais conceitos.

Pode-se dizer que os conceitos fundamentais para o desenvolvimento de um software baseiam-se na busca pela flexibilidade, robustez e reutilização. Assim, características como coesão, acoplamento, modularização e extensibilidade costumam estar no topo do checklist de arquitetos que queiram que o código de uma determinada solução de software seja definitivamente de boa qualidade.

Nesse contexto, enquanto as ferramentas que apoiam o desenvolvimento de software, bem como os meios nos quais o mesmo é executado, mudaram significativamente, os princípios básicos para o desenvolvimento de uma boa arquitetura continuam os mesmos. A título de exemplo, observamos todos os novos recursos disponíveis em IDEs e na Java Virtual Machine (JVM), que apoiam o desenvolvimento, e também a evolução proporcionada pelo ecossistema baseado em Cloud Computing, no qual muitos softwares são executados.

No entanto, os conceitos que moldam a qualidade na construção de um sistema não sofrem mudanças significativas há pelo menos vinte e cinco anos. Isso se mostra evidente ao lembrar que, mesmo antes da publicação do livro "Design Patterns: Elements of Reusable Object-Oriented Software", em 1994 — cujos autores ficaram conhecidos como “Gangue dos Quatros” (Gang Of Four, frequentemente abreviado como "GoF") —, os engenheiros Kent Beck e Ward Cunningham iniciaram, em 1987, um experimento para aplicar padrões baseados em ordem, organização e forma nas linguagens de programação. Tal experimento foi baseado na obra do arquiteto e matemático Christopher Alexander, denominada “Notes on the Synthesis of Form”, publicada em 1964. Curiosamente, Alexander também influenciou na criação do famoso jogo “SimCity”, a partir de sua obra “A Pattern Language”, conforme declarado pelo próprio Will Wright, designer do jogo e co-fundador da Electronic Arts. Voltando ao experimento de Beck e Cunningham, eles apresentaram seus resultados no mesmo ano de 1987 em uma conferência anual dedicada à pesquisa e desenvolvimento de linguagens orientadas a objetos, conhecidas como OOPSLA, que naquele ano ocorreu em Orlando (Flórida, EUA). Tais resultados contribuíram para o início de um movimento para a busca por padrões de projetos na área da ciência computacional, que finalmente ganhou popularidade a partir da publicação do livro pelos membros do GoF, em 1994.

Depois disso, poucas publicações alcançaram tamanha popularidade como a obra do GoF. É claro que surgiram novos Design Patterns nos últimos anos, mas os princípios nos quais esses se apoiam continuam os mesmos. Entre os princípios mais conhecidos, é possível citar cinco que atualmente delineiam os parâmetros qualitativos na engenharia de um sistema. São eles: Princípio da Responsabilidade Única (Single Responsibility Principle — SRP); Princípio da Segregação de Interfaces (Interface Segregation Principle — ISP); Princípio da Substituição de Liskov (Liskov Substitution Principle — LSP); Princípio da Inversão de Dependências (Dependency Inversion Principle — DIP) e o Princípio do Aberto Fechado (Open Closed Principle — OCP).

Não está no escopo deste artigo se aprofundar sobre cada um desses conceitos. Contudo, vale dizer que três deles, o SRP, DIP e o ISP, estão diretamente ligados à determinação por um código modular. Não por acaso a modularização oferece excelentes benefícios quando se pretende alcançar uma arquitetura com índices de manutenibilidade e reusabilidade satisfatórios.

Entre os benefícios obtidos pelo desenho de um código modular, observamos a facilidade com que componentes independentes podem ser extraídos a partir dele. Tal vantagem mostrou-se muito importante no ecossistema do desenvolvimento de software. Isso porque a produção de códigos modulares, empacotados em componentes — na forma de bibliotecas do tipo JAR, por exemplo —, promoveu o reuso genuíno além das fronteiras de um ou outro grupo de desenvolvedores. Desse modo, centenas de frameworks foram construídos, compartilhados e combinados, como num lego, com o objetivo de alavancar o desenvolvimento de sistemas complexos com um esforço relativamente reduzido frente ao que seria necessário para construí-los inteiramente do zero. Assim, grande parte da comunidade de desenvolvedores beneficiou-se (e vem se beneficiando) da contribuição mútua de código reutilizável, muitas vezes chamados de frameworks, como o JUnit, SLF4J, Log4j, Google Guava, Apache Commons, Spring, Hibernate e milhares de outros.

Entretanto, não foi por acaso que tal modelo para construção de código modular encaixou-se perfeitamente na tecnologia Java. A forte aderência dessa linguagem de programação aos princípios da Orientação a Objetos tornou a aplicação desse modelo muito efetiva, e, como já foi dito nos parágrafos anteriores, bibliotecas empacotadas em arquivos JAR se proliferaram, permitindo a forte reutilização de seus módulos.

O uso de um software denominado Maven também alavancou a prática de reuso de componentes, que são disponibilizados em centenas de repositórios públicos. Tal comportamento também tem sido observado em outras tecnologias, como o JavaScript, que foi marcado pelo surgimento da plataforma Node.js. Essa plataforma possui um gerenciador de pacotes denominado npm, o qual disponibiliza também repositórios públicos contendo componentes que podem ser reutilizados. Tal gerenciador é mantido pela empresa NPM Inc.

Pode-se dizer que um grande percentual das aplicações construídas em JavaScript atualmente são dependentes desse modelo. Para se ter uma ideia, em março de 2016, o programador Azer Koçulu removeu cerca de 250 módulos que havia compartilhado no npm, isso porque se enfezou quando a equipe da NPM Inc., juntamente com advogados de uma empresa responsável por um aplicativo de mensagens instantâneas, denominado Kik, solicitou que ele alterasse o nome de um de seus componentes, também batizado de Kik, alegando direitos autorais sobre esse nome. O problema é que, entre os módulos removidos, estava o popular “left-pad”, composto somente por onze linhas de código. A remoção desse módulo comprometeu milhares de aplicações na web que o possuíam como dependência, entre elas o Facebook, Netflix, Airbnb e milhares de outras. Assim, tais aplicações ficaram indisponíveis por um curto período de tempo até que a NPM Inc. conseguiu reestabelecer tal dependência. Tal episódio levantou inclusive uma discussão sobre esse tipo de fragilidade dos sistemas web.

No caso da tecnologia Java, o modelo de reutilização baseado em componentes empacotados em JARs possui um detalhe que pode vir a se tornar uma desvantagem dependendo do tipo de sistema a ser construído. Esse detalhe é a necessidade de reinicialização da Máquina Virtual Java (JVM) para os casos de inclusão, remoção ou atualização dos componentes que compreendem a aplicação. Tal fato pode ser um problema para aplicações construídas para servirem outras aplicações, como o WebLogic, JBoss AS, GlassFish, TomEE, etc., e para plataformas para o desenvolvimento de sistemas, onde é preciso gerenciar a instalação de plugins e extensões, como o Eclipse IDE. Para esses tipos de sistemas, é necessário que sejam implantados módulos em tempo de execução e que os mesmos possam ser removidos e atualizados sem a necessidade de reinício da JVM, ou seja, um modelo de modularização dinâmico.

Diante dessa latente necessidade, surgiu a especificação OSGi (Open Services Gateway initiative), também conhecida por Dynamic Module System for Java, desenhada por uma organização denominada OSGi Alliance. Essa organização foi fundada em março de 1999, por um consórci ...

Quer ler esse conteúdo completo? Tenha acesso completo