Classe de serviços Centralizada VS Separada por Ações
Tags: patterns, poo, structuralpattern
Published: 2022-05-07 22:06:34

## Overview

Fala pessoal , espero que esteja tudo bem com vocês. Estou fazendo esse post para tentar mostrar um pouco sobre duas abordagens quando utilizando Serviços como uma forma de separar a lógica de negócios do controller , assim , deixando o controller somente com a responsabilidade de orquestrar todo fluxo , como deveria ser.

## Porque eu decidi abordar tal assunto?
<img width="70%"src="https://media.giphy.com/media/2xwWl4iiaR0UKIiiRQ/giphy.gif">

Você pode estar se perguntando , porque diabos você vai abordar esse assunto? , e bom , tudo surgiu quando eu aprendi sobre as classes de Serviço, e como elas nos ajudam a separar a responsabilidade de aplicar uma lógica de negócios fora do nosso Controller.

Da forma que aprendi , uma classe de serviço tinha centralizado todos os métodos e funções que condiziam com aquela entidade. 

Ex : o método **_searchAvailableHotels_** estar na mesma classe de Serviço que o método **_getHotelRoomDetails_** , pois ambos fazem parte da regra de negócios da entidade **Hotel , que utiliza um _HotelService_**. 

Porém , a medida em que a aplicação for crescendo , mais e mais métodos serão criados dentro desse serviço. E assim tornando difícil se localizar no workflow, no meio de tantas funções.

<img width="70%"src="https://media.giphy.com/media/Yq2SKEsscV85lPRJdu/giphy.gif">

Sendo assim , lembrei que em algumas linguagens como TypeScript, os devs costumam criar várias classes de serviços, separando seus módulos por pastas , e sendo **cada classe de serviço de um módulo específico performando sua principal ação**.

Também me lembrei que no Framework Laravel existe algo semelhante ,uma abordagem  chamada **Actions**, que se assemelha a uma classe Job , onde a classe tem um construtor para inicializar as dependências  necessárias , e um método **execute**, que executa a ação imposta sobre aquela action.

Para saber mais sobre actions acesse [esse post](https://freek.dev/1371-refactoring-to-actions) do Freek , demonstrando como se utiliza as tão famosas actions.

Sendo assim, decidi abordar esse assunto, por conta dessa “dor” que tive com as classes de Serviço. Então sem mais delongas irei falar um pouco sobre cada abordagem , e quando utiliza-las (na minha visão :p).


## Centralizada

Uma classe de serviço centralizada geralmente é criada com uma separação por entidades. Então se tenho as entidades Hotel e Guest na minha aplicação , eu deveria ter uma classe **HotelService** , e **GuestService** para lidar com a aplicação das regras de negócios.

### Prós
* Todas as funções relacionadas as regras de negócio de uma determinada entidade ficam centralizadas em um local específico , tornando assim mais fácil de debugar o código , e de seguir um workflow.

### Contras

* Ao mesmo tempo , as funções estando centralizadas em uma só classe, dependendo da aplicação pode se tornar maçante , por conter inúmeras linhas de código, tornando assim fácil de se perder , e correndo um maior risco de ter efeitos colaterais ( um exemplo prático seria a mudança em uma variavel declarada no escopo da classe , e que é modificada por uma ou duas funções em um determinado workflow, podendo gerar erros).


## Separadas por ações

Uma classe de Serviços separada por ações , geralmente é separada por módulos assim como na centralizada , porém , a grande diferença é que agora , para cada fluxo ou ação , criamos uma classe de serviço especifico.

Então agora , se antes tinhamos uma classe **HotelService** , contendo várias funções relacionadas a entidade Hotel , utilizando essa abordagem teremos **uma classe de serviço para cada ação da entidade Hotel**. 
Um exemplo seriam os serviços **SearchAvailableHotels** e **GetHotelRoomDetails**.

### Prós

* Maior abstração/separação de responsabilidades.
* Classes menores e com maior facilidade de se localizar.
* Uncle Bob ficaria feliz por saber que estaríamos seguindo a letra S do Solid , o princípio da responsabilidade única.


### Contras

* Dependendo do sistema e da complexidade teríamos muitas classes , tornando  não o código , mas a estruturação um pouco mais complexa , tendo em vista que teremos várias classes de serviço em um módulo. Mas mesmo assim , em sistemas complexos eu ainda prefiro essa abordagem.

* Não vale a pena utilizar em sistemas menores que não possuem tantas funções relacionadas a regra de negócio da entidade.

#Conclusão

Então quando devemos utilizar uma abordagem ou outra? , e a resposta é bem comum na nossa área... **DEPENDE**!.
Se na sua visão , a sua aplicação não irá precisar de implementar mais métodos e verificações no futuro , e que não há a chance de se tornar um projeto complexo , utilize a abordagem de Serviço centralizado. Senão , se você sabe que a aplicação irá crescer junto com o número de features requisitadas por seus clientes , se tornando algo complexo , recomendo utilizar a abordagem de serviços separados por ações/fluxos.

Espero que tenham gostado desse post , e principalmente espero que ele seja útil para alguém. Falei algo errado? , pensa de um modo diferente ou conhece uma abordagem melhor? , comenta aí :) , Um grande abrç a todos , e até a proxima!

<img width="70%"src="https://media.giphy.com/media/Hw5QkgfUPxgjWaSnWA/giphy.gif">