---
# System prepended metadata

title: Pipeline pattern

---

# Pipeline pattern

## O que é
<br/>
<br/>


![](https://i.imgur.com/wJKeRs9.png)


Pipeline patter permite o processamento em uma série de etapas, fornecendo uma entrada inicial e passando a saída processada para ser usada pelos próximos estágios.

1 - Organização de processos computacionais como sequencia
2 - A saída de um processo é a entrada do próximo processo

<br/>
<br/>
<br/>


## Usamos mais do que imaginamos

<br/>
<br/>

![](https://i.imgur.com/a5X46Oz.png)

### Streams

1 - O streams nos fornece uma forma de forma de fazer diversas etapas sequenciais onde 

Parte da DOC de Stream:

> Um fluxo não é uma estrutura de dados que armazena elementos; em vez disso, ele transmite elementos de uma fonte, como uma estrutura de dados, uma matriz, uma função geradora ou um canal de I/O, por meio de um pipeline de operações computacionais.

![](https://i.imgur.com/6csxZun.png)

### Benefícios 

![](https://i.imgur.com/a8N0Msy.png)


- Execute estágios individuais que geram um valor final.
- Adicione legibilidade à sequência complexa de operações fornecendo um construtor fluente como uma interface.
- Melhore a testabilidade do código, pois os processos provavelmente farão uma única coisa, em conformidade com o Princípio de Responsabilidade Única (SRP)




## Real life


<br/><br/>


![](https://i.imgur.com/smw0ycn.png)

### DebitService

![](https://i.imgur.com/9KXknMo.png)

``` java
@Slf4j
@Service
@AllArgsConstructor
@ConditionalOnProperty(value="service.debit-service", havingValue = "v2")
public class DebitService implements IDebitService {

    private final PixConfig pixConfig;
    private final MetricsService metricsService;

    private final PipelineImpl pipelineProcessPayment;
    private final SetEntryValueToCreditorIfExistsStepOnSuccess setEntryValueToCreditorIfExistsStep;
    private final GetOriginTransactionStepOnSuccess getOriginTransactionStep;
    private final SetTransactionIdIfEmptyStepOnSuccess setTransactionIdIfEmptyStep;
    private final SetGeolocationIfNullStepOnSuccess setGeolocationIfNullStep;
    private final SetEndToEndIdIfNullStepOnSuccess setEndToEndIdIfNullStep;
    private final ValidateAndSaveInEndToEndIdCacheStepOnSuccess validateAndSaveInEndToEndIdCacheStep;
    private final SetPaymentTypeToManualIfNullStepOnSuccess setPaymentTypeToManualIfNullStep;
    private final SetNatureTypeToRealTimeIfNullStepOnSuccess setNatureTypeToRealTimeIfNullStep;
    private final ValidateIfIsNotMedOperationStepOnSuccess validateIfIsNotMedOperationStep;
    private final RemoveSpecialCharacteresOfDescriptionStepOnSuccess removeSpecialCharacteresOfDescriptionStep;
    private final ValidateIfIsQrCodeStepOnSuccess validateIfIsQrCodeStep;
    private final UpdateAccountNumberAliasStepOnSuccess updateAccountNumberAliasStep;
    private final GetCoreBankingStepOnSuccess getCoreBankingStep;
    private final ValidateTransactionStepOnSuccessStep validateTransactionStep;
    private final ValidateTransactionLimitStepOnSuccess validateTransactionLimitStep;
    private final SendToCoreStepOnSuccess sendToCoreStep;
    private final SaveTransactionStepOnSuccess saveTransactionStep;
    private final ProcessPaymentStep processPaymentStep;

    private final PipelineImpl pipelineErrorHandler;
    private final DeleteConstrainStep deleteConstrainStep;

    @Override
    public CreateTransferResponse sendPayment(CreateTransferDTO request) {
        metricsService.increaseCounter("pagamento_iniciado");
        log.info("Iniciando transação de débito para {}", request);

        if (BooleanUtils.isFalse(pixConfig.isDebitEnabled())) {
            final String errorMessage = "error.disabledDebit";
            metricsService.increaseCounter("pagamento_erro", "error_message", errorMessage);
            throw new BusinessException(errorMessage);
        }

        try {
            pipelineProcessPayment
                    .addStep(setEntryValueToCreditorIfExistsStep)
                    .addStep(getOriginTransactionStep)
                    .addStep(setTransactionIdIfEmptyStep)
                    .addStep(setGeolocationIfNullStep)
                    .addStep(setEndToEndIdIfNullStep)
                    .addStep(validateAndSaveInEndToEndIdCacheStep)
                    .addStep(setPaymentTypeToManualIfNullStep)
                    .addStep(setNatureTypeToRealTimeIfNullStep)
                    .addStep(validateIfIsNotMedOperationStep)
                    .addStep(removeSpecialCharacteresOfDescriptionStep)
                    .addStep(validateIfIsQrCodeStep)
                    .addStep(updateAccountNumberAliasStep)
                    .addStep(getCoreBankingStep)
                    .addStep(validateTransactionStep)
                    .addStep(validateTransactionLimitStep)
                    .addStep(sendToCoreStep)
                    .addStep(saveTransactionStep)
                    .addStep(processPaymentStep)
                    .execute(request);

            final CreateTransferResponse response = new CreateTransferResponse(request.getTransactionId(), request.getEndToEndId());
            log.info("Transação concluída com sucesso: {}", response);
            return response;
        } catch (Exception exception) {
            pipelineErrorHandler
                    .addStep(deleteConstrainStep)
                    .execute(request, exception);
            throw exception;
        }
    }


}

```
---

#### Referências :

https://martinfowler.com/articles/collection-pipeline/
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
https://java-design-patterns.com/patterns/pipeline/
