Suba o nível do seu código aplicando o S do S.O.L.I.D.
Tags: javascript, architecture, programming, carrer
Published: 2021-06-03 02:41:33



# TL;DR

> every module, class or function in a computer program should have responsibility over a single part of that program's functionality.

Em outras palavras, cada função, arquivo, componente ou classe da sua aplicação, deve ser responsável por apenas, e unicamente, **UMA** funcionalidade do seu programa. 

# Para começar...

Primeiramente, muito prazer me chamo José Bezerra, dev fullstack desde que me entendo por gente, fundador&CTO das falecidas Propi e Vestibulando e hoje eu vou compartilhar com você **uma dica que transformou a minha forma de pensar software.**

Antes de qualquer coisa, pra melhorar a qualidade do teu código e subir o nível dos teus jobs me segue lá no instagram @josebezerra12 pra acompanhar as dicas que saem.

Todos nós, em algum momento da nossa carreira, escrevemos um servidor ou aplicativo achando que estava **MEGA** organizado (só na nossa cabeça) e a medida que as funcionalidades cresciam, o projeto ficava cada vez mais **impossível** **de se manter organizado**. Parece que pra cada bug resolvido, 2 outros outros aparecem. 😂

Pra resolver esse tipo problema, código acoplado, confuso, difícil de entender e manter existe o famoso **S.O.L.I.D.** Sigla que postula cinco princípios para escrever um código desacoplado, manutenível e mais robusto.

**S —** Single responsibility principle

**O —** Open closed principle

**L —** Liskov substitution principle

**I —** Interface segregation principle

**D —** Dependency Inversion principle

Hoje nós não falaremos sobre tudo, mas sim como aplicar **de forma prática** o principio que eu acredito ser o mais importante, o **S do SOLID,** o **Princípio da Responsabilidade Única**. Seguindo este entendimento, em muito dos casos ja é o suficiente para você **subir o nível dos seus projetos.**

# Princípio da responsabilidade única

> every module, class or function in a computer program should have responsibility over a single part of that program's functionality.

Em outras palavras, cada função, arquivo, componente ou classe da sua aplicação, deve ser responsável por apenas, e unicamente, **UMA** funcionalidade do seu programa. 

## Explorando o problema

Como um código vale mais que mil palavras, aqui está um exemplo de um servidor em express a **não** ser seguido:

```jsx
const LISTEN_PORT = 3333;
const app = express();

app.get('/user/:id', async (request, response) => {
    const { id } = request.params;
    const user = await User.findOne({ id })
    if (!user) {
        throw new Error('Usuário não existente.')
    }

    return response.status(200).json({ user });
});

app.listen(LISTEN_PORT, () => {
  console.log('🚀 Server started on port 3333');
});
```

Repare que estou utilizando o express para criar as rotas de nosso servidor, e o mongoose para buscar um usuário em nosso banco de dados **(Linha 6)**.

Para começar a destrinchar esse princípio, aviso que podemos aplicá-lo em diferentes profundidades, ou seja, até qual nível faz sentido refatorar seu código é relativo a sua necessidade.

Indo direto ao ponto, perceba que em um mesmo arquivo, possuímos diferentes responsabilidades da aplicação:

- **Em primeiro lugar**, a instância e configurações de servidor.
- **Em segundo lugar**, todas as rotas da aplicação.
- **Em terceiro lugar**, as regras de negócio de nossa rota.

## Mas qual é o real problema?

O problema é que aqui temos um belo exemplo de código extremamente acoplado. Semanticamente, nós **não conseguimos saber onde começa uma parte de nosso software e acaba outra.** Uma outra forma de enxergar isso é se perguntar:

- **qual arquivo altero a porta de nosso servidor?** server.js
- **qual arquivo altero o nome de minha rota?** server.js
- **qual arquivo mudo a query feita pelo banco?** server.js
- **qual arquivo acrescento uma regra de negócio na rota?** server.js

Respondido? Aqui temos um problema... não podemos atribuir tantas responsabilidades a apenas uma camada em nossa aplicação, apenas nesse trechinho de código, a longo prazo caso as configurações de nosso servidor ou as regras de negócio mudem, ou a quantidade de rotas cresça, pelo forte casamento de todas essas partes, teremos um código com um alto custo para ser alterado, com grande potencial para bugs e difícil correção para erros.

Por exemplo, se pensarmos em fazer rotas de **CRUD** para os usuários e outro para agendamentos, ja teremos pelo menos 8 rotas, de diferentes áreas de nosso sistema, com diferentes regras de negócios, no mesmo lugar. O código não possui semântica, ele não se auto-explica.

## Aplicando o princípio da responsabilidade única

Para resolver, dividiremos o nosso código utilizando uma pequena "arquitetura", com o fim de separar cada funcionalidade em uma camada diferente.  

- A instância de nosso servidor ficará em server.js
- As rotas de nossa aplicação ficará em /routes/user.routes.js
- As nossas regras de negócio ficarão em /services/GetUserService.js

![download](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jyhf5ktscvudjb9n38rx.png)
 

**Sem muita enrolação, vamos ao código!**

### A camada do servidor

```jsx
import express from 'express';
import userRoute from './user.routes';

const LISTEN_PORT = 3333;

const app = express();
app.use(express.json());
app.use(userRoute);

app.listen(LISTEN_PORT, () => {
  console.log('🚀 Server started on port 3333');
});
```

Aqui temos a camada de nosso **servidor**, propriamente dito. Todas as configurações de nosso servidor está isolado e desacoplado do resto, chamamos o express, fazemos as suas configurações de uso, json(), as rotas e instanciamos o nosso servidor.

### A camada das rotas

```jsx
import { Router } from 'express';

import GetUserService from '../services/GetUserService';

const userRouter = Router();
userRouter.get('/user/:id', async (request, response) => {
    const { id } = request.params;
    const getUser = new GetUserService();
    const user = getUser.execute({ id });
    return response.status(200).json({ user });
});

export default userRouter;
```

Aqui, a diferença pode ser sutil, mas extremamente poderosa. A nossa camada de **rotas** está responsável apenas por receber o request nos endpoints, **repassar** os dados do request para a camada lógica (logo abaixo) e responder este request com o respectivo **response**. 

Repare que toda a funcionalidade de **capturar e processar as entradas** do request, e responder o request que foi processado fica nessa camada.

### A camada das regras de negócio

```jsx
class GetUserService {
  public async execute({ id }) {
    const user = await User.findOne({ id });

    if (!user) {
        throw new Error('Usuário não existente.')
    }

    return user;
  }
}

export default GetUserService;
```

Por último, finalmente temos as nossas regras de negócio isoladas em uma classe, uma classe  para cada "ação" do nosso sistema, ou como estamos chamando aqui, **serviço**. 

Normalmente cada endpoint de nosso servidor fará uso de pelo menos 1 serviço, onde cada serviço **isola a lógica de negócio do "pedido" feito pelo request.** Neste exemplo, estamos chamando de serviço **o ato de "pegar" de um usuário no banco.**

Exemplo de outros serviços seriam, **UpdateUserService**, **ChangePasswordUserService**, **BookAppointmentService**, enfim, isso é papo para outro artigo.  Posteriormente posso falar mais sobre **Service-Oriented-Architecture** se vocês quiserem.

# Pensamentos finais

Claro, tudo que fizemos aqui depende do tamanho e o propósito do projeto que você está escrevendo. Cada caso é um caso e não adianta escrever o melhor código do mundo para um projeto que com **poucas funcionalidades** que possivelmente irá morrer em breve.

Lembre-se que cada alteração tem o propósito de tornar o código cada vez mais **desacoplado**, **claro** e **coeso**. Este princípio pode ser aplicado de diferentes formas, lembre-se que o que mostrei é a aplicação prática do **Single Responsibility Principle**, e não uma arquitetura específica. O exemplo que trouxe é pra deixar claro uma maneira de aplicar esta poderosa filosofia na prática.

Para mais informações, você pode ler estes artigos:

- [https://medium.com/@cramirez92/s-o-l-i-d-the-first-5-priciples-of-object-oriented-design-with-javascript-790f6ac9b9fa](https://medium.com/@cramirez92/s-o-l-i-d-the-first-5-priciples-of-object-oriented-design-with-javascript-790f6ac9b9fa)
- [https://blog.logrocket.com/solid-principles-single-responsibility-in-javascript-frameworks/#whatarethesolidprinciples](https://blog.logrocket.com/solid-principles-single-responsibility-in-javascript-frameworks/#whatarethesolidprinciples)
- [https://en.wikipedia.org/wiki/Single-responsibility_principle](https://en.wikipedia.org/wiki/Single-responsibility_principle)

**Ou fala comigo que vai ser mais fácil.**

**Dúvidas? Feedbacks? Sugestões? me manda la no @josebezerra12.** 🚀