Front End

22 fev, 2013

Arquitetura baseada em evento: getting decoupled

Publicidade

Todo desenvolvedor de JavaScript sabe que eventos são bastante normais na linguagem e que um sistema baseado em eventos pode ser muito divertido e simples de usar. A maioria usa mecanismos de eventos quase toda vez que escreve JavaScript, mas você já tentou levá-lo ao extremo? Qual a aparência dele quando você possui uma arquitetura de aplicativo que raramente tem dois objetos que se comunicam diretamente com o outro?

Sério, você já experimentou? No meu último artigo, eu falei sobre a injeção de dependência e a parte final dele era sobre como eu a usei no meu projeto mais recente. Expliquei que estou usando um objeto de aplicativo central como um hub de eventos, mas em vez de objetos fazerem referência a ele diretamente, eu estava injetando-o através de constructors. Bem, aqui eu vou falar um pouco mais sobre como eu estou usando esse hub de eventos e, provavelmente, muito pouco sobre injeção de dependência.

Hub de eventos

Para o novo gerenciador de servidor Minecraft, eu decidi experimentar Marionette, que estende o Backbone para oferecer algumas novas funcionalidades e eliminar uma grande quantidade de código clichê (especialmente a partir de views). Vou fazer uma extensa série sobre ele em outra ocasião, mas por agora eu vou apenas apontar alguns componentes menores, particularmente Application e EventAggregator.

O Marionette apresenta o Application, que é um objeto projetado para ser o hub central de um aplicativo Backbone que implementa um sistema de módulos e muitas outras peças interessantes. Eu só uso o EventAggregator que é construído como a propriedade vent. O EventAggregator é basicamente só uma forma avançada de eventos de Backbone.

Eu uso o Application.vent como o local onde todos os meus módulos se comunicam uns com os outros. Esse não é o único meio de comunicação entre os componentes, mas, se ele pode ajudar a fazer algo mais reutilizável, então eu tento usar isso em vez de acoplar objetos diretamente. Falarei sobre isso mais tarde.

System-Wide Events

Desde que nosso hub de eventos esteja anexado a uma parte do aplicativo que é conhecida em todo o sistema, podemos transmitir mensagens para quase qualquer parte do sistema. Eu sinto que o maior desafio com isso é a escolha de quais eventos emitir e nomear.

Isso pode ser muito simples. Basta escolher os eventos sobre os quais você saiba algo mais, e o sistema terá que responder. Mas isso significa que quando você expandir o sistema, você pode precisar adicionar mais eventos nele. Pessoalmente, eu tento pensar mais para frente para ver se existem eventos que queiram usar algo mais no futuro. Essa é a parte que pode ser um pouco difícil, mas, para quem deseja ampliar o sistema, vai ter valido a pena. Você pode considerar esses eventos como “ganchos” para que outros possam plugar sua própria funcionalidade sem ter que modificar muito a base de código existente.

A nomeação só é difícil se você realmente se importar, o que você deve fazer. A consistência em nomes é extremamente importante para a leitura do código e os nomes de todo o sistema de eventos são tão importantes, se não mais importantes, do que o nome de uma propriedade ou de um método de um objeto.

Exemplos

Por que não mostrar um exemplo ou dois do que eu estou falando? No gerenciador de servidor Minecraft, eu uso WebSockets para a comunicação entre o servidor e os clientes sobre as coisas que estão acontecendo com os servidores Minecraft. Eu tenho um único módulo que lida com essas comunicações com o back-end.

Se um cliente pede um servidor Minecraft para começar a executar, então o back-end irá alertar todos os clientes que o servidor está em execução. O objeto acima receberá a notificação e usará o hub de eventos para deixar o resto do mundo saber. Outro componente ouve esse evento e adiciona o novo servidor em execução a uma coleção que detém especificamente os servidores em execução. Esse componente, em seguida, dispara um evento que permite que o sistema saiba que um servidor é iniciado. O gerente de guia ouve sobre esse evento e cria uma nova guia para esse servidor.

Você acabou de ouvir sobre vários componentes que se comunicavam uns com os outros, mas nenhum deles tinha qualquer pista de que o outro existia. Sua comunicação foi inteiramente baseada em eventos controlados pelo hub de eventos. Você pode remover completamente as peças desse sistema e não haverá erros (mas também muito pouca funcionalidade), porque não há dependências, exceto no hub de eventos, que é injetado, assim você pode usar qualquer sistema de eventos que tem um método on, off e trigger. Se o sistema de eventos que você deseja instalar não tiver essa interface, você pode sempre criar um adaptador.

***

Texto original disponível em http://www.joezimjs.com/javascript/event-based-architecture-getting-decoupled/