SOLID (Parte 2) - Single Responsibility Principle (SRP)
Published: 2023-01-19 13:52:03

O princípio de Responsabilidade Única (SRP, do inglês Single Responsibility Principle) diz que cada classe ou módulo deve ter apenas uma responsabilidade, veja o código abaixo.

```java

public class OrderService {

    private OrderRepository orderRepository;
    private InventoryService inventoryService;

    public OrderService(OrderRepository orderRepository, InventoryService inventoryService) {
        this.orderRepository = orderRepository;
        this.inventoryService = inventoryService;
    }

    public Order createOrder(Order order) {
        // Salva a ordem no banco de dados
        orderRepository.save(order);
        // Atualiza o estoque
        inventoryService.updateInventory(order.getItems());
        // Calcula o preço total da ordem
        order.setTotalPrice(calculateTotalPrice(order.getItems()));
        // Envia um e-mail de confirmação para o cliente
        sendConfirmationEmail(order.getCustomer().getEmail());
    }

    private void sendConfirmationEmail(String email) {
        // Código para enviar o e-mail
    }

    private double calculateTotalPrice(List<Item> items) {
        // Código para calcular o preço total
    }
}
``` 

Neste exemplo, a classe OrderService tem quatro responsabilidades diferentes: salvar a ordem no banco de dados, atualizar o estoque, calcular o preço total da ordem e enviar um e-mail de confirmação para o cliente. Isso viola o SRP pois a classe estaria realizando múltiplas tarefas, essa classe poderia ser dividida em outras classes cada uma com sua responsabilidade específica.

Abaixo você pode ver um exemplo de como isso pode ser feito:

```java
public class CreateOrderGatewayImp implements CreateOrderGateway{
    
    private OrderRepository orderRepository;

    public CreateOrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    public Order execute(Order order) {
        return orderRepository.save(order);
    }
```
Note que eu estou retornando a ordem que foi salva e a mesma geralmento volta com um id que é gerado pelo banco de dados, essas informações podem ser usadas como fontes de dados para execução de métodos em outras classes que estejam no fluxo. 

Talvez você possa estar se perguntando o motivo dessa classe ser uma implementação, vou falar mais sobre isso em outro artigo.

## Princípio de agregação de responsabilidade

Mas em algum momento precisarei chamar os métodos das classes que forem implementadas, quando isso vai acontecer?

Você tem razão, em algum momento pode ser necessário chamar esses métodos em sequência, como no exemplo que eu dei na primeira impementação, onde é necessário salvar a ordem no banco de dados antes de atualizar o estoque, e calcular o preço total antes de enviar o e-mail de confirmação.

Uma maneira de lidar com isso é usar o princípio de agregação de responsabilidade, esse princípio não faz parte dos princípios do SOLID diretamente, no entanto, ele é frequentemente usado como uma técnica para aplicar o princípio de Responsabilidade Única (SRP).Isso significa que, em vez de ter uma única classe responsável por todas as tarefas relacionadas à criação de uma ordem, você pode ter várias classes, cada uma responsável por uma tarefa específica e, em seguida, agregá-las para formar uma classe intermediária que chama essas classes de forma sequencial.

Por exemplo, você pode criar uma classe OrderCreatorService que tem como responsabilidade única criar uma ordem e chama as classes CreateOrderGateway, InventoryUpdater, PriceCalculator e ConfirmationEmailSender, e assim por diante, cada uma dessas classes tem sua responsabilidade específica.

```java
public class CreateOrderService {
    private CreateOrderGateway CreateOrderGateway;
    private InventoryUpdaterService inventoryUpdaterService;
    private PriceCalculatorService priceCalculatorService;
    private ConfirmationEmailSenderService confirmationEmailSenderService;

    public OrderCreator(CreateOrderGateway CreateOrderGateway, InventoryUpdaterService inventoryUpdaterService, PriceCalculatorService priceCalculatorService, ConfirmationEmailSenderService confirmationEmailSenderService) {
        this.CreateOrderGateway = CreateOrderGateway;
        this.inventoryUpdaterService = inventoryUpdaterService;
        this.priceCalculatorService = priceCalculatorService;
        this.confirmationEmailSenderService = confirmationEmailSenderService;
    }

    public void execute(Order order) {
        Order savedOrder = CreateOrderGateway.execute(order);
        inventoryUpdaterService.execute(savedOrder.getItems());
        savedOrder.setTotalPrice(priceCalculatorService.execute(savedOrder.getItems()));
        confirmationEmailSenderService.execute(savedOrder.getCustomer().getEmail());
    }
}
```
Vamos ficando por aqui, qualque dúvida ficarei feliz em responder.

(continua)