NodeJS e Padrões de Desenvolvimento

Recentemente temos utilizado muitos projetos menores com NodeJS. Como venho do mundo Java e Spring para desenvolvimento de Backends sempre estranhei o formato de desenvolvimento com NodeJS em respeito a padrões.

Minha pouca experiência nos tutoriais e projetos, e leituras sobre, eu vi muita gente usando de vários jeitos distintos. E sempre senti falta de uma boa estrutura com programação orientada a objetos, e uma boa estrutura na gerência das dependências entre os diversos arquivos dos projetos.

Lendo mais sobre, eu descobri o Typescript, que pareceu resolver boa parte dos problemas em relação a estrutura orientada a objetos que eu sentia falta.

A linguagem oferece:

  • Tipagem dinâmica, e forte.
  • Classes, Interfaces, e Enumerações
  • Generics
  • Decorators

Essa combinação de coisas já deixam a programação em NodeJS bem mais estruturada, é como deixar o Javascript um pouco mais completo.

Mas ainda tem um problema, como gerenciar de forma efetiva as dependências do projeto, garantir de uma forma limpa que cada objeto da aplicação esteja lá na hora certa, e etc…

Foi então que eu descobri o Inversify, esse projeto resolve esse problema muito bem. Ele oferece um container par IoC, que funciona de uma maneira bem elegante com o Typescript.

Algo mais ou menos assim:

Capturar

E como isso é util para o meu projeto ?

“Bem. O container que vai gerenciar as dependências no Inversify tem diversas configurações, para suprir todas as necessidades no projeto. Ele vai tirar do desenvolvimento o trabalho de se preocupar com o ciclo de vida dos objetos da aplicação.”

Isso é feito da seguinte maneira:Capturar

A partir desse momento, os objetos podem ser acessados através do decorator @inject(), identificando os tipos através das constantes definidas em TYPES.

A partir desse conjunto de Typescript e Inversify eu comecei a estruturar os meus projetos mais perto do padrão definido no Spring, que já sou um pouco mais familiarizado, eu deixo o projeto organizado da forma em que cada classe e arquivo tenha sua responsabilidade bem definida.

Organização de um projeto

Com isso tenho organizado meus projetos da seguinte maneira:

Em módulos, contendo as seguintes responsabilidades:

  • Module
  • Service
  • Domain
  • Repository
  • Controller

E no módulo principal ou core adiciono os tipos definidos utilizados, em uma constante TYPES, e as demais dependências no Container principal da aplicação.

Vou explicar e exemplificar a responsabilidade de cada um, e como esse conjunto de Typescript e Inversify ajudou e muito a estrutura dos meus projetos, e garantiu com que eu conseguisse definir bem a responsabilidade de cada bloco do meu código.

Primeiro vamos com o coração da aplicação, os Modules. A ideia do Inversify, além de garantir uma boa gerência de dependências da aplicação, além de também modularizar bem a aplicação, por exemplo, eu tenho um módulo especifico para lidar com os usuários da minha aplicação.

Como eu faço isso ?

O Inversify permite que eu declare Containers modulares, e também trabalhe com eles de forma assíncrona.

Dessa forma eu posso simplesmente definir em um arquivo especifico do módulo todos os objetos contidos no próprio módulo.Capturar

Minha camada de Domain eu uso para definir os objetos transacionados entre o módulo. Outra biblioteca interessante que gosto de utilizar para isso é a Validator.ts.Capturar

Para a camada de repositório, como estamos utilizando os Containers, a gente pode definir objetos de acesso aos dados conforme a necessidade. Para esse exemplo vou usar um objeto db de acesso a um MongoDB.Capturar

Dessa forma, com essa organização a camada de Serviço pode continuar da mesma maneira apresentada anteriormente. Lembrando que a responsabilidade da camada de Serviço é de garantir as regras de negócio do sistema, para esse exemplo a única regra de negócio é registrar um usuário válido.Capturar

Por fim a Controller tem a responsabilidade de mapear as rotas da nossa API, a partir da nossa camada de Service. Para isso utilizamos o ExpressJS, o mais interessante é que o próprio inversify nos libera uma biblioteca auxiliar justamente para facilitar nossa vida nesse caso.

Dessa forma o nosso UserController fica da seguinte maneiraCapturar

Finalizando os Containers

Por fim eu defino uma classe principal da aplicação, que irá conter cada modulo registrado em um container principal, bem como os objetos principais da aplicação (como o acesso ao BD).CapturarCapturar

E por fim no script principal da aplicação eu inicializo minha classe UserApplicationCapturar

Finalizando

Ótimo, agora temos uma idéia de como organizar melhor nosso projeto, com cada objeto com sua responsabilidade, sem se preocupar com o ciclo de vida dos nossos objetos, organizando bem nossa aplicação em blocos bem definidos.

Os últimos detalhes são, organizar a compilação e execução da aplicação. Outro ponto importante é que o Inversify necessita da reflect-metadata.

Para ajustar a compilação do nosso projeto precisamos definir um tsconfig.json com alguns detalhes específicos do Inversify.Capturar

Essa configuração permite alguns módulos específicos úteis para trabalhar tanto com o Validator.ts, quanto com o Inversify.

Por fim, para quem ainda não é familiarizado com o Typescript precisamos instalar ele como um pacote global, e usar o comando de compilação no nosso projeto.

npm install -g typescript

E depois para a compilação

tsc

Conforme a compilação definida no nosso tsconfig.json o nosso projeto vai ser gerado os arquivos na pasta dist, então podemos simplesmente rodar com.

node dist/Index.js

Ou simplesmente definir em nosso npm startCapturar

Além disso existem algumas utilidades legais para auxiliar nos projetos, como por exemplo o uso do Gulp e do Nodemon, que também funcionam muito bem no Typescript.

Para quem quiser o Projeto Completo está no meu Github

Fonte: Rodney Nogueira – MEDIUM 

Fonte Imagem: Wikipedia

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s