Olá! Este é o post da Seça Cooperasharp E, Desta Vez, Vamos Examinar OSafio Sobre Explosão de Dependênia. Vamos Lá! Como possível ver neste post temos um servijo com diversas dependem injetadas, o que cria o que chamamos de explosão de dependincias nenhum construtor (explosão de dependência do construtor em inglês). Este servijo executa Uma Série de Passos para Tornar Possível uma Criaza de Um Pedido. Está abordagem é Ruim porque, Além de Já Conter inúmeras Dependênias, Ainda Pode adicionar mais caso o Processo de Torne Maior, O que LeVARIA A UMA Explosão Ainda Maior, TornandO O Quase Like Container Depende Dece Depende Dece Depende Dece Depende Dece Depende Dece Decentin.. Aqui o Trecho do Códão Ruim: Public Class PedidoService {Private ReadOnly ICliEreePository _CliENTeRePository; Private ReadOnly IPEDIDOREPOSIITY _PEDIDOREPOSIENTY; Private ReadOnly IestoService _estoService; Private readonly ipagamentoService _pagamentoService; Private ReadOnly ImailService _EmailService; Private readonly inotificACaService _NotificAcAoservice; Private ReadOnly ILogger _Logger; Private readonly ifreteService _FretService; Private ReadOnly IMAPPER _MAPPER; Private ReadOnly Iauditoriaservice _auditoriaservice; public PedidoService( IClienteRepository clienteRepository, IPedidoRepository pedidoRepository, IEstoqueService estoqueService, IPagamentoService pagamentoService, IEmailService emailService, INotificacaoService notificacaoService, ILogger logger, IFreteService freteService, IMapper mapper, IAuditoriaService Auditoriaservice) {_cliEreRePository = clientERePository; _pedIDOROREPOSIITY = PEDIDOREPOSIITY; _estoQueService = EstoqueService; _pagamentoService = pagamentoService; _emailService = emailService; _NotificACaService = notificACaService; _logger = logger; _FreTeService = FretService; _mapper = mapeador; _Auditoriaservice = auditoriaservice; } public void Processarpedido (pedidodto dto) {var cliente = _clientarePository.obterporid (dto.clienteid); if (cliente == null) {_logger.log (“Cliente Não Encontrado”); retornar; } var pedido = _mapper.map(dto); _estoQueService.Reservaritens (Pedido.itens); var valorfrete = _freteService.CalCularFrete (dto.endecoentrega); pedido.adicionarfrete (valorfrete); var pagamentook = _pagamentoService.processar (pedido); if (! Pagentook) {_NotificAcAoservice.enviar (“falha no pagamento”); retornar; } _pedidorepository.salvar (pedido); _emailservice.enviarconfirmacao (cliente.email); _Auditoriaservice.registrar (“pedido criado”, pedido.id.toString ()); }} Digite o modo de tela de tela completa Modo de tela completa Uma das soluções que o codor vírus menciona o momento é um de trabalhar com eventos e deixar cada handler se prontificar um resolver uma parte do processo, fazendo com o pedidoss. Serria Uma Solução Interessante Se Não Fosse por UM DeTALHE: REPARE NESTE TRECHO: _ESTOQUESERVICE.RESERVARITENS (Pedido.itens); var valorfrete = _freteService.CalCularFrete (dto.endecoentrega); pedido.adicionarfrete (valorfrete); Digite Modo de tela cheia de saída Modo de tela cheia o quecontece se Houver Uma Exceção No Serviço de Frete? Pois é! O estroque permanece com os reservatórios de reservas ainda que o processo não é Geral Falhe. ISSO leva uma UMA inconsistente no estado da Aplicação, podndo imedir que usto pedido seja feito por falta de estroque. Primanto, precisamos Pensar Numa forma de Tornar Possível que AÇões compensa compensações como uma libertação dos itens Seja Seja Possível. E aí entra uma solução que Encontrei para o Desafio. SE Pensarmes Bem, Este Processo ToDO é uma transmissão. Se um passo Dela Falhar, Todas Devem Falhar, Execando UM Rollback E Revertendo um Mudança de Estado que Eventualmente Tenha Provisto. Então Entra em Cena Um Mecanismo de Transaca em Cadeia, Inspirado Nenhuma cadeia de responsabilidade Sobre o posto de ninho da FALO. Vamos Conhecer O Códão! Em Primeiro Lugar, Precisamos se Capazes de Descrever os passos da Nossa Transacão E, para ISSO, Foram Criados OS TransactionSteps, Como Podmos ver ABAIXO: Interface pública ItransactionStepPep onde tinput: notnull {resultado Executar (entrada de tinut de referência); Resultado Reversão (resultado erro); } Public Resumo Class TransactionStepBase(ItransactionStep? Próximo): ItransactionStep onde tinput: notnull {resultado público Execute (entrada de tonal de ref) {var resultado = executeinternal (entrada de ref); if (resultado && a seguir não for nulo) retorne a seguir. se (o próximo é o resultado de retorno nulo; reversão de retorno (resultado); } resultado abstrato protegido ExecuteInternal (entrada de tinúnculo de ref); resultado abstrato público Reversão (resultado erro); } Digite o modo de tela completa Sair do modo de tela completa aqui temos uma interface que vai demarcar a anatomia de um passo transacional e, também, uma clase abstrata que deverá ser implementada por cada passo. REPARE que CADA PASSO DA TRANSAÇÃO, TAL QUANDO CADEIA DE Responserabilidades, Recebe uma referência para o Passo Seguinte. Uma reversão de DiFerença Está no Método, Que Será Invocado Caso Hava UM Resultado Negativo do Passo implementação. Há, tamboma, uma verifica ã do próximo passo a fim de sabre se alcançamos de fim da cadeia. AGORA VAMOS VER Um implementação de um dos passos, o de verificações da existência de um cliente: Classe Public selado(Próximo) {Resultado de substituição protegida ExecuteInternal (entrada de saco de referência de referência) {try {var CustomerDataDataAccess.getById (input.request.customerId); if (cliente) {input.customer = cliente.get (); resultado de retorno.OK(); } Retornar resultado.Error (novo erro ($ “cliente com id {input.request.customerid} não encontrado”)); } catch (exceção ex) {return rollback (novo erro (ex.Message)); }} Resultado de substituição pública Reversão (resultado erro) => erro; } Enter fullscreen mode Exit fullscreen mode Repare que aqui temos três possíveis desfechos para a execução deste passo: O cliente existe e é incluído em uma OrderSubmissionBag que contém uma referência para a requisição recebida pelo servidor, uma para o cliente e outra para o pedido. NESTE DESFECHO O PASSO SEGUINTO É EXECURADO, O ORDERSTOCKREVERVERVIÇÃO, Respovel POR RESERVAR OS ITENS DO PEDIDO NÃO ESTOQUE. O cliente não existe e é retornado um erro indicando que o Id Informado Não foi Encontrado. Há uma Exceção em algum ponto do fluxo eo método rollback é acionado. NESTE CASO, POR Tratar-Se de Uma Consulta, Não Há Um Reverter necessado de Estado da Aplicação, ontanto APENAS UM ERRO SERA RETORNADO, Interrop, um Execuça da Cadeia Transacional. Para -se o transactor de Execução, é necessário, que Funciona Apenas como iniciador do Processo.Veja o Código ABAIXO: Public selado OrdensionTranTor OrdersissionTor (CustomValidationStep Step) {Resultado Público Resultado Processo (saco de saco de pedidos de referência) => step.execute (saco de ref); } Entre no modo de tela cheia de saída de tela cheia de tela completa com, como pode ser visto no repositório da solução, Todos os passos da transação podem ser executados em sequenncia e novos podem serncadeados, injetopugues a dependente
[Route(“api/[controller]”)]
[ApiController]
classe pública SubmitorDerController (OrderSubmissionTransActor Transactor): ControllerBase {
[HttpPost]
submissor público de iaCtionResult ([FromBody] OrdesUbmissionRequest Solicy) {var resultado = transactor.process (new Ordersubmissionbag {request = solicitação, cliente = null, order = null}); Resultado de retorno? OK (): StatusCode (500, “Não foi possível enviar seu pedido. Tente novamente mais tarde.”); } } Enter fullscreen mode Exit fullscreen mode Evitar a explosão de dependências é interessante para manter o código legível e, também, evitar o que alguns chamam de God Classes ou Megazords, classes que respondem por muitas atividades e cuja legibilidade geralmente é baixa, assim como é sua Testabilidade – Imagine Criar e injetar 10 instântácias reais para testar esta classe, ou pior, utilizar zombar para isso! Com uma solução que proponho, Cada Passo do Processo Está AutoContido, Poranto Coso, Não TEM CONHECIMENTO DOS Demais, Exceto Pelo Paso imediatament Seguinte, eliminamos a explosão dependente e, tambemica, tambemica, tambemica, tambemica, tambemica, tambemica, tambemica, tambemica, tambemica, tambemica, tambemica, antaata. Aparentemente Uma Vitória! Gostou? Me Deixe Saber Pelos indicadores ou por Minhas Redes Sociais. Muito ObriGado por Ler Até Aqui, E Até O Próximo Post!
Fonte