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

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/>

### 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.

### Benefícios

- 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/>

### DebitService

``` 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/