Arquitetura para aplicações REST com express (node.js) #01: Cada escolha uma renúncia
Tags: express, node, rest, api
Published: 2020-02-19 21:22:40

Iniciar um projeto de `API REST` usando `Node.js` geralmente é algo rápido e relativamente fácil. Você escolhe um framework, lê um artigo e mete bronca no `hello world`. Simples assim :thumbsup:.

![Feliz](https://media.giphy.com/media/l3g00YU1xZnn0P3Og/giphy.gif)

Porém, algo não muito difundido no mundo "javascripteiro" do `Node.js` é que, ao escolher um framework para trabalhar você meio que escolhe automaticamente uma filosofia de arquitetura para seguir. Mesmo que, no caso do `Express`, a escolha seja não ter arquitetura :eyes:.

É complicado entender a necessidade de algo que não temos, nunca vimos ou ouvimos falar. Para termos o que comparar, vou apresentar um conceito que é um dos pilares do famoso e super desenvolvido `Ruby on Rails`.

## Convenção sobre configuração

Por definição:

> Convenção sobre configuração ou programação por convenção (do inglês `Convention over configuration - CoC`) é um modelo de desenvolvimento de software que busca *diminuir o número de decisões* que os desenvolvedores precisam tomar. Visa ganhar simplicidade sem perder flexibilidade.

Fonte: [wikipedia](https://pt.wikipedia.org/wiki/Conven%C3%A7%C3%A3o_sobre_configura%C3%A7%C3%A3o)

## Aplicação do conceito no mundo Rails

Diferente do processo padrão (que você aprende em tutoriais pela internet a fora), para iniciar uma `API` usando `Express`, ao iniciar um projeto usando `Ruby on Rails` você roda a ferramenta de linha de comando e faz `scaffolding` da base do projeto. Onde já temos toda a estrutura de pastas, padrões de nomenclatura e comunicação entre módulos pré definidos pelo framework:

```sh
$ rails new projeto
```


> OBS: O exemplo abaixo é um resumo simplificado da estrutura do `Rails`. Para uma explicação melhor consulte a [documentação oficial](https://guides.rubyonrails.org/getting_started.html).


	.
	├── app/
	|  ├-- assets/
	|  ├── controllers/
	|  ├── helpers/
	|  ├── mailers/
	|  ├── models/
	|  └── views/
	├── bin/
	├── config/
	├── db/
	├── public/
	├── test/
	├── tmp/
	├── vendor/
	└── assets/


Isso traz algumas vantagens e desvantagens:

### Vantagens

Como descrito na definição do conceito, ao ter uma arquitetura pré definida, o desenvolvedor não gasta seu tempo e energia decidindo coisas que não influenciam nas regras de negócio do projeto. Ou seja... Você consegue focar "no que importa" e ganha de brinde uma ótima arquitetura, testada por milhares de pessoas e amplamente documentada.

#### Exemplo da vida real

Imagine que você estude `Ruby on Rails` por cerca de 1 ano. Após esse período você inicia em um trabalho novo onde sua tarefa é ajudar no produto da empresa (que usa `Ruby on Rails`).

Eu garanto que, em poucos minutos, você consegue (a partir do seu conhecimento prévio) saber exatamente o que cada tipo de arquivo faz, como estão organizados e cada comando para executar o projeto.

Nesse cenário, você consegue "pular" a etapa de entender o projeto e consegue partir para uma entrega de valor em um tempo bem curto.

![Eu gosto disso](https://media.giphy.com/media/3owzVVlSXEXpScinio/giphy.gif)

### Desvantagens

#### Posso ser radical e dizer coisas como:

Em regimes ditatoriais é tirado o poder de escolha da população em prol de coisas como sua segurança e eficiência :thumbsdown:.

Na China, por exemplo, a população escolheu abrir mão da própria "liberdade" em favor da segurança. Isso é uma boa troca? Para nosso caso é irrelevante! Mas entender que tirar o poder de escolha de alguém em prol de um ganho qualquer, sempre gera uma troca. Se vale a pena adotar essa escolha, só você pode responder :scream:.

#### Sendo mais amigável posso dizer coisas como:

A partir do momento em que você aceita usar uma arquitetura pré pronta, você aceita uma listinha de desvantagens que vem junto. Temos como a mais notável a seguinte afirmação:

> Cada projeto é um projeto, assumir que a mesma fórmula atende todos os casos é no mínimo *ingenuidade* :expressionless:.

## E o Express com isso?

Basicamente aprendemos a criar uma `API` de forma muito simples em um único arquivo ou, no máximo, com dois ou três tipos de arquivos (geralmente seguindo um `MVC`) que nos apresenta à uma filosofia totalmente oposta à escolhida pelo `Rails`. Finalmente lhes apresento o que torna a curva de aprendizado do `Express` tão interessante:

Definição do `Express`:

> Express is a *minimal and flexible* `Node.js` web application framework that provides a robust set of features for web and mobile applications.

fonte: [expressjs.com](https://expressjs.com/)

ou seja,

Aqui temos um framework totalmente **flexível, que permite e estimula que o desenvolvedor crie e implemente** sua própria arquitetura. Não importa o tamanho ou objetivo do projeto, você tem as ferramentas para organizar seu projeto da forma que melhor te atende.

Instale o Express:

```sh
$ npm install express
```

Crie um arquivo `index.js`:

```js
const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(3000, () => {
  console.log('Example app listening on port 3000!')
})
```

Execute o projeto:

```sh
$ node index.js
```

Pronto, temos uma `API` rodando plenamente.

> OBS: Existe [uma ferramenta de linha de comando](https://expressjs.com/pt-br/starter/generator.html) que faz `scaffolding` no `Express`, porém ela não é focada em `APIs` e quase não é utilizada.

Com `Express` você tem o poder de fazer do seu jeito. Isso é incrível! Mas é aqui que mora o principal problema:

### Desvantagens

Ter o poder de fazer as coisas do seu jeito, pode ser lido como: "Ter o poder de fazer merda" :shit:.

![Fazendo besteira](https://media.giphy.com/media/Ddab9zJPtaEmI/giphy.gif)

Sim, é isso mesmo que você leu, a partir do momento em que você não delegou o trabalho de arquitetura para alguém que sabe o que está fazendo (mesmo que no caso do `Rails` tentando ser genérico para atender a todos os casos), fica muito fácil construir uma aplicação sem levar em consideração vários aspectos estruturais que são extremamente importantes. Principalmente se você pretende dar manutenção no projeto a longo prazo e em equipe.

#### Exemplo da vida real:

Imagine que você estude `Express` por cerca de 1 ano, após esse período, você inicia em um trabalho novo onde sua tarefa é ajudar no produto da empresa (que usa `Express`).

Eu garanto que o projeto está organizado de forma diferente do que você fez durante seus estudos, o que aumenta muito a curva de aprendizado para entregar algo de valor.

### Vantagens

Obviamente, se você entende do que está fazendo, o poder de construir uma aplicação da forma que quiser é extremamente eficiente. É possível criar verdadeiras obras de arte em forma de arquitetura que vão poupar muitas horas e "dinheiros" a longo prazo. Isso inclui uma boa documentação, o que vai diminuir muito a curva de aprendizado de alguém novo no projeto, mitigando a principal desvantagem de um arquitetura "personalizada" :green_heart:.

Claramente esse processo não é trivial, o que nos leva ao próximo tópico:

## Requisitos

Chegamos à conclusão de que precisamos estudar bastante para entender o que estamos fazendo a nível de arquitetura.

Para criar um projeto que atende aos requisitos estruturais de uma boa arquitetura, primeiro precisamos saber quais são esses requisitos.

Vou compartilhar com vocês alguns dos meus objetivos ao criar um novo projeto:

- **Escalabilidade**
  - Separação de responsabilidades.
  - Responsabilidade única.
- **Manutenibilidade**
  - Maior facilidade para criação de `error handlers`.
  - Maior facilidade para escrita de `testes automatizados`.
- **Controllers isolados**
  - Todos os `controllers` são `assíncronos`.
  - Facilidade para escrever validações.
- **Iterações em serviços de forma isolada**
  - Serviços `síncronos` e `assíncronos`.
  - Múltiplos serviços para diferentes `bancos de dados`.
- **Error handler automático para todas as rotas**

Essa listinha já é um bom ponto de partida para criar uma
aplicação com excelente qualidade (a de nível de arquitetura).

![OK](https://media.giphy.com/media/3o7abB06u9bNzA8lu8/giphy.gif)

Agora precisamos entender cada um desses requisitos e como implementá-los na prática usando `Express`. Mas como esse texto já está muito longo vamos deixar isso para a parte 2.

## Conclusão

"Cada escolha uma renúncia" é uma ótima frase para explicar esses processos de decisão.

Espero que eu tenha conseguido trazer algo de relevante para você que chegou até esse momento da leitura :grin:.

Se você ficou animado ao ler esse artigo, deixe um comentário e um :heart: para eu saber que tem alguém interessado e que vale a pena continuar a compartilhar esse tipo de conteúdo.

![Adeus](https://media.giphy.com/media/j44gNTTN0F4By/giphy.gif)

Um abraço e até a próxima.