<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Willian Menezes</title>
    <description>The latest articles on DEV Community by Willian Menezes (@wmscode).</description>
    <link>https://dev.to/wmscode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628990%2F799be51d-bc23-4c13-9cce-351cc130a634.jpeg</url>
      <title>DEV Community: Willian Menezes</title>
      <link>https://dev.to/wmscode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wmscode"/>
    <language>en</language>
    <item>
      <title>Entendendo o que são middlewares em uma aplicação ASP.NET</title>
      <dc:creator>Willian Menezes</dc:creator>
      <pubDate>Tue, 02 Jan 2024 05:19:35 +0000</pubDate>
      <link>https://dev.to/wmscode/entendendo-o-que-sao-middlewares-em-uma-aplicacao-aspnet-5gm0</link>
      <guid>https://dev.to/wmscode/entendendo-o-que-sao-middlewares-em-uma-aplicacao-aspnet-5gm0</guid>
      <description>&lt;h2&gt;
  
  
  O que é um middleware?
&lt;/h2&gt;

&lt;p&gt;Um middleware nada mais é do que um componente que está contido em uma pipeline de uma aplicação capaz de lidar com requests e responses de uma solicitação HTTP, ou seja, todo o percurso que uma request percorre dentro da aplicação passa por um middleware, desde a recepção até sua resposta.&lt;/p&gt;

&lt;p&gt;Quando criamos um middleware em .NET estamos criando nada mais nada menos do que um delegate, ou seja, estamos criando um ponteiro para uma função de forma segura.&lt;/p&gt;




&lt;h2&gt;
  
  
  Como funcionam os middlewares em uma aplicação WEB?
&lt;/h2&gt;

&lt;p&gt;Uma aplicação &lt;a href="http://ASP.NET"&gt;ASP.NET&lt;/a&gt; contem uma sequencia de delegates ou melhor dizendo middlewares que são chamados um após o outro.&lt;/p&gt;

&lt;p&gt;Um diagrama clássico que sempre vemos quando falamos de middleware é este aqui:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm3eb3byn3di3vf2nrkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm3eb3byn3di3vf2nrkw.png" alt="Diagrama mostrando o fluxo de uma request com vários middlewares configurados" width="600" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A seta preta indica o caminho que ocorre o processamento, cada middleware pode executar operações antes ou depois do próximo middleware.&lt;/p&gt;

&lt;p&gt;É aqui que as coisas começam a ficar legais, dependendo do tipo de processamento que queremos realizar, podemos configurar um middleware no começo da pipeline ou no final, tudo depende da funcionalidade que estamos criando.&lt;/p&gt;

&lt;p&gt;Uma coisa importante que devemos nos atentar quando estamos trabalhando com middlewares em uma aplicação &lt;a href="http://ASP.NET"&gt;ASP.NET&lt;/a&gt; é a ordem de configuração dos middlewares.&lt;/p&gt;

&lt;p&gt;A ordem que configuramos os middlewares é extremamente importante é ela quem define a ordem em que eles serão executados na request e consequentemente a ordem inversa em sua response.&lt;/p&gt;

&lt;p&gt;Um exemplo clássico de middleware seria um handler de erro global, nesse caso o recomendado é que esse middleware de erro seja o primeiro a ser executado, dessa forma, conseguiremos capturar todos os erros que ocorrem na aplicação.&lt;/p&gt;

&lt;p&gt;Hummmmm, serio Willian? Porque? &lt;/p&gt;

&lt;p&gt;Pensa comigo e vamos olhar o diagrama novamente, o primeiro middleware do pipeline pode ou não executar alguma ação, depois disso ele é encarregado de chamar o próximo middleware através do metodo next(), dessa forma ele fica esperando o próximo middleware encerrar a sua execução e retornar alguma resposta. &lt;/p&gt;

&lt;p&gt;O próximo middleware pode chamar outro e o próximo chamar outro e por ai vai…&lt;/p&gt;

&lt;p&gt;Deu para perceber porque um middleware de erro deve ser o primeiro da pipeline? Quando todos os middleware forem executados o nosso middleware de erro vai ser o ultimo da cadeia de execução, dessa forma ele vai ser capas de “capturar”, todas as exceções que ocorrerem durante a pipeline de execução da request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Aprendendo a criar middlewares
&lt;/h2&gt;

&lt;p&gt;Vamos começar criando nossa aplicação. Acessando a sua IDE favorita (Aqui eu uso o JetBrains Rider) crie uma aplicação ASP.NET Web API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmd59de5ac40pxlzebt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmd59de5ac40pxlzebt3.png" alt="Tela do jetbrains rider criando uma aplicação asp.net web api" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com o projeto aberto vamos criar nosso middleware de erro customizado. Essa classe é igual a qualquer outra classe em C#, mas para ela funcionar corretamente precisamos nos atentar a alguns nomes e propriedades, vou explicar cada uma a frente.&lt;/p&gt;

&lt;p&gt;Segue classe do nosso middleware de tratamento de erros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Middlewares&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorHandlerMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;RequestDelegate&lt;/span&gt; &lt;span class="n"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ErrorHandlerMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RequestDelegate&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;InvokeAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;httpContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;HandlerErrorAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;HandlerErrorAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContentType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensagemErro&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;ArgumentException&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="n"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;mensagemErro&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Argumentos inválidos"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;HttpStatusCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;mensagemErro&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Opa, um erro inesperado aconteceu no servidor"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mensagemErro&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesta classe temos duas coisas extremamente importantes, a propriedade RequestDelegate e o método InvokeAsync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RequestDelegate:&lt;/strong&gt; Essa propriedade é responsável por armazenar uma referencia para o próximo middleware. Em todo middleware que criamos, temos a opção de chamar o proximo middleware após executar uma operação ou não. A propriedade RequestDelegate é gerenciada pelo próprio framework que fornece toda a estrutura de pipeline de middlewares.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;InvokeAsync:&lt;/strong&gt; Método principal que é responsável por executar o processamento do middleware. Este método é chamado automaticamente pelo ASP.NET quando uma solicitação HTTP é executada, ou seja, não precisamos chamar esse método de forma explicita, ele será invocado no momento necessário durante o processamento de uma pipeline de middlewares.&lt;/p&gt;

&lt;p&gt;Repare tambem que colocamos um trycat quando chamamos o próximo middleware, fazendo isso conseguimos garantir que qualquer exception que acontecer nos próximos middleware vamos conseguir capturar.&lt;/p&gt;

&lt;p&gt;Mas Willian, o que ganhamos com isso? &lt;/p&gt;

&lt;p&gt;Já viu aqueles códigos onde existem vários trycat para tratar cenário de erros? &lt;/p&gt;

&lt;p&gt;Muitas vezes fazer os tratamentos de forma individual em cada parte do código torna a nossa aplicação muito complexa, com baixa legibilidade e possivelmente com varios pontos de manutenção.&lt;/p&gt;

&lt;p&gt;Criando um middleware para tratamento de excessões, todo esse código pode ficar centralizado em uma unica classe responsável por tratar erros, com isso temos muito mais semântica, uma legibilidade melhor, menos complexidade ciclomática e por ai vai... O código fica muito melhor.&lt;/p&gt;

&lt;p&gt;Mas cuidado hein não é bala de prata, analise seu caso e se fizer sentido, acredito que esse post te ajude a implementar.&lt;/p&gt;




&lt;p&gt;É muito comum quando se criar um middleware em uma aplicação ASP.NET criar um método de extensão para podermos configurar o middleware, isso garante um pouco mais de organização e legibilidade de código na nossa classe Program e alguns outros benefícios quando temos que configurar mais algumas coisas, vamos implementar essa classe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MiddlewareExtension&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="nf"&gt;UseGlobalErrorHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseMiddleware&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ErrorHandlerMiddleware&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso basta chamar esse método de extensão na classe Program. Lembre-se a ordem que configuramos um middleware é extremamente importante e para esse nosso cenário de erro ele deve estar configurado como primeiro middleware do pipeline de execução.&lt;/p&gt;

&lt;p&gt;Segue a implementação na classe Program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Middlewares&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSwaggerGen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseGlobalErrorHandler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSwagger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSwaggerUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/middleware/erro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/middleware"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Sucesso"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOpenApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repare tambem que criamos dois endpoint com minimal API para testar os cenários de erro e de sucesso para a execução dos nossos testes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Executando a aplicação
&lt;/h2&gt;

&lt;p&gt;Vamos executar a aplicação e reparar o que acontece com o middleware que criamos e configuramos em nossa aplicação.&lt;/p&gt;

&lt;p&gt;Ao inicar a aplicação sera aberta uma pagina do swagger com dois endpoints configurados:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkwd7swzaqimsbq1tpx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkwd7swzaqimsbq1tpx1.png" alt="Imagem do swagger com dois endpoints do tipo GET criados" width="792" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos abrir nossa IDE e colocar um breakpoint para visualizar o que acontece com a aplicação quando realizamos uma chamada HTTP.&lt;/p&gt;

&lt;p&gt;Abra o nosso middleware customizado e coloque o breakpoint na linha 22 onde capturamos a exception no catch do metodo InvokeAsync.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv83gy6our1cs4xfrxdz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv83gy6our1cs4xfrxdz0.png" alt="Código demonstrando o breakpoint na linha 22" width="798" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reparem que ao chamar o endpoint com a rota "middleware" ele apenas executa e retorna sucesso na requisição, ou seja, nenhuma exception foi lançada na nossa aplicação, o middleware de erro que criamos apenas chamou o proximo e na resposta da nossa solicitação ele apenas retornou a informção, sem executar processamento algum nesse cenário de sucesso. &lt;/p&gt;

&lt;p&gt;Agora reparem que ao executar o endpoint "middleware/erro" uma excessão é lançada:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facvu5iv5yvpopnaeomhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facvu5iv5yvpopnaeomhm.png" alt="Excessão de argumentexception" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como não criamos nenhum trycat nesse ponto, essa execessão vai percorrer a aplicação até encontrar um trycat que possa captura-lá. No nosso caso esse tryecat esta na nossa classe de midleware de erro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjgxsuowl9jx1vz2mjsa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjgxsuowl9jx1vz2mjsa.png" alt="Excessão capturada no trycat" width="763" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que a execução esta pausada no método "HandlerErrorAsync", método que criamos para tratar as excessões da nossa aplicação.&lt;/p&gt;

&lt;p&gt;Ao executar a aplicação passo a passo, vamos reparar que a excessão será tratada como uma "ArgumentException" e retornar um erro 400 com uma mensagem "Argumentos Inválidos".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegy8y17yxvivprs0c3dm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegy8y17yxvivprs0c3dm.png" alt='Erro 400 com mensagem de erro "argumentos inválidos"' width="753" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Encerrando e considerações finais
&lt;/h2&gt;

&lt;p&gt;Ao longo desse post conseguimos entender o que é um middleware em ASP.NET, como criar um middleware, quais os pontos que devemos ter atenção no momento de criação e de quebra vimos uma solução simples, mas muito funcional sobre tratamento de erro de forma global.&lt;/p&gt;

&lt;p&gt;Claro que a implementação foi bem simples afim de facilitar o entendimento dos conceitos que foram abordados, mas com certeza podemos evoluir esse post em vários outros assuntos.&lt;/p&gt;




&lt;p&gt;Aqui vai um desafio, eu tenho vários vídeos sobre injeção de dependencia em .NET no meu canal do &lt;a href="https://www.youtube.com/playlist?list=PLelKrgw43Tu1jVd6Hr9coPT-AYMC32il1"&gt;youtube&lt;/a&gt;, um middleware em ASP.NET ele tem o tempo de vida da aplicação, se injetar uma dependencia configurada como sccoped em um middleware, como essa dependecia irá se comportar? &lt;/p&gt;

&lt;p&gt;Deixa ai nos comentários o que vocês acham que vai acontecer, mais pra frente vamos abordar essa assunto com um post mais detalhado.&lt;/p&gt;

&lt;p&gt;Não se esqueçam de me seguir em minhas redes sociais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UC0Vo6yL26XaraIjak87jDww"&gt;youtube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://instagram.com/wmscode/"&gt;instagram&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/willianmenezes"&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qualquer dúvida é só deixar nos comentários, abraços e até a próxima.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Abstract Factory — Implementando o Padrão de Projeto com ASP.NET 5 WEB API</title>
      <dc:creator>Willian Menezes</dc:creator>
      <pubDate>Fri, 10 Sep 2021 15:16:11 +0000</pubDate>
      <link>https://dev.to/wmscode/abstract-factory-implementando-o-padrao-de-projeto-com-asp-net-5-web-api-498h</link>
      <guid>https://dev.to/wmscode/abstract-factory-implementando-o-padrao-de-projeto-com-asp-net-5-web-api-498h</guid>
      <description>&lt;p&gt;Olá pessoal, hoje vamos abordar um assunto bem legal dentro do mundo de programação. Vou colocar aqui e também em meu canal no &lt;a href="https://www.youtube.com/channel/UC0Vo6yL26XaraIjak87jDww"&gt;youtube&lt;/a&gt; uma série de artigos e vídeos sobre &lt;strong&gt;Padrões de Projeto ou Design Patterns.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Neste artigo vamos abordar como implementar o Padrão de Projeto &lt;strong&gt;“Abstract Factory”&lt;/strong&gt; em uma API Rest utilizando o C# como linguagem de programação.&lt;/p&gt;

&lt;p&gt;Antes de mais nada, é super importante que vocês estejam confortáveis com os conceitos do paradigma de &lt;strong&gt;Programação Orientada a Objetos e SOLID.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Caso queiram entender e praticar os conceitos de SOLID, podem assistir esse vídeo &lt;a href="https://www.eduardopires.net.br/2015/01/solid-teoria-e-pratica/"&gt;aqui&lt;/a&gt; do Eduardo Pires.&lt;/p&gt;

&lt;p&gt;Bom pessoal, sem mais delongas, vamos lá!&lt;/p&gt;

&lt;p&gt;O que é o padrão de projeto &lt;strong&gt;Abstract Factory?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O Abstract Factory faz parte da família de padrões &lt;a href="https://refactoring.guru/pt-br/design-patterns/creational-patterns"&gt;“criacionais”&lt;/a&gt;. Um padrão de projeto criacional nos permite fazer uso de mecanismos para a criação de objetos, aumentando a flexibilidade e reutilização do nosso código, nos ajuda também a alcançar uma alta coesão e baixo acoplamento.&lt;/p&gt;

&lt;p&gt;Em termos técnicos o Abstract Factory nos permite criar familias de objetos relacionados ou dependentes, sem a necessidade de especificar suas classes concretas.&lt;/p&gt;

&lt;p&gt;Calma, para alguns pode ser um pouco confuso entender o que exatamente esse padrão de projeto faz, mas vamos aos poucos. O Abstract Factory possui alguns participantes, vamos entender cada um deles e suas responsabilidades.&lt;/p&gt;

&lt;p&gt;Os participantes são:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract Factory:&lt;/strong&gt; Conhecido como “Fábrica de produtos abstratos”, este é responsável por criar classes/produtos abstratos. Ou seja, dentro dessa classe criaremos métodos abstratos que retornam para quem o chama uma classe/produto abstrato.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concrete Factory:&lt;/strong&gt; Conhecido como “Fábrica de produtos concretos”, este é responsável por criar classes/produtos concretos. Ou seja, dentro dessa classe implementaremos os métodos herdados da nossa fábrica abstrata, mas ao invés de retornar uma classe/produto abstrato, retornaremos uma classe/produto concreto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract product:&lt;/strong&gt; Conhecido como “Produto abstrato”, este é apenas uma classe/produto abstrata que definimos para exemplificar alguma coisa do mundo real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concrete product:&lt;/strong&gt; Conhecido como “Produto concreto”, este é apenas uma classe/produto concreto, onde implementamos uma classe/produto abstrata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client:&lt;/strong&gt; Este entendemos como consumidor, porém, essa classe apenas consome os produtos abstratos gerados a partir de nossas fabricas abstratas. O Client não é obrigado a saber como as coisas estão sendo implementadas, por isso ele consome apenas a fábrica abstrata e produtos abstratos.&lt;/p&gt;

&lt;p&gt;Esses diagramas abaixo, são utilizados para exemplificar esses participantes, veja:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3dmtwsa7gy9dp8p0omk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3dmtwsa7gy9dp8p0omk.png" alt="Alt Text" width="720" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;a href="https://refactoring.guru/pt-br/design-patterns/abstract-factory"&gt;Referência&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;Temos também este aqui:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fb1x5y6iwaz3otg51au.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fb1x5y6iwaz3otg51au.png" alt="Alt Text" width="437" height="471"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;a href="https://www.dofactory.com/net/abstract-factory-design-pattern"&gt;Referência&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;Bom, depois de toda essa teoria sobre o Abstract Factory, vocês devem estar se perguntando: “Tá, e ai? Como implementar isso na prática?”.&lt;/p&gt;

&lt;p&gt;Eu criei uma demo de uma API utilizando ASP.NET 5 e C#.&lt;/p&gt;

&lt;p&gt;Vamos lá!!!!&lt;/p&gt;

&lt;p&gt;É importante termos instalado na máquina o &lt;a href="https://visualstudio.microsoft.com/pt-br/vs/community/"&gt;Visual Studio Community&lt;/a&gt; e também o &lt;a href="https://dotnet.microsoft.com/download"&gt;SDK do .NET 5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vamos criar um novo projeto no Visual Studio do tipo ASP.NET Core Web API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihwbijzhaale8i21h2yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihwbijzhaale8i21h2yb.png" alt="Alt Text" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Escolha um nome para seu projeto e o local onde será salvo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9y2czztaolxjl3amn0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9y2czztaolxjl3amn0a.png" alt="Alt Text" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E por último e selecione a versão do .NET 5, caso vocês tenha outras versões.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7527t2765t5ju4o4kqr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7527t2765t5ju4o4kqr.png" alt="Alt Text" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Legal, com o nosso projeto criado podemos agora começar a implementar de fato o nosso padrão de projeto. Primeiramente vamos remover as classes que são criadas automaticamente para nós. Podemos excluir os arquivos “WeatherForecast.cs” e “WeatherForecastController.cs”.&lt;/p&gt;

&lt;p&gt;Ótimo, agora podemos começar a criar os diretórios para separar a nossa aplicação em responsabilidades especificas. Vamos lá, no seu Visual Studio crie as seguintes pastas (Clients, Domain, Factories) conforme imagem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdll90w1e6kdp9fi0drb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdll90w1e6kdp9fi0drb4.png" alt="Alt Text" width="344" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora de fato vamos começar a colocar a mão na massa e aplicar o padrão de projeto. Mas antes, gostaria apenas de explicar qual vai ser o nosso cenário.&lt;/p&gt;

&lt;p&gt;Imaginem que vocês tem um cliente que possui uma loja de alimentos e esta loja é especialista na venda de alimentos/embalagens orgânicas e inorgânicas. A partir disso, o cliente pediu que fosse construida uma API Rest para retornar uma lista de produtos de acordo com o tipo que ele especificar na chamada HTTP, podendo ele ser “Orgânico” ou “Inorgânico”.&lt;/p&gt;

&lt;p&gt;Ótimo, depois de entender a necessidade… bora meter a mão no código.&lt;/p&gt;

&lt;p&gt;Vamos criar primeiramente os nossos produtos abstratos, pensando no contexto da nossa aplicação os nossos produtos inicialmente serão: “Food” e “Packing”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6druriwnh59ustjujrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6druriwnh59ustjujrq.png" alt="Alt Text" width="342" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como esses caras vão ser nossos produtos abstratos, que serão herdados por produtos concretos e utilizados na nossa fábrica abstrata, criei uma pasta “Base” e coloquei as classes lá dentro.&lt;/p&gt;

&lt;p&gt;Food e Packing vão ficar assim, respectivamente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiaya0zkewpi2zgs6696a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiaya0zkewpi2zgs6696a.png" alt="Alt Text" width="568" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwqal5nupyp9xkmecq5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwqal5nupyp9xkmecq5d.png" alt="Alt Text" width="610" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos criar também o enum “TypeProduct” que identifica qual o tipo de produto. A classe ficaria assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdeaspaf02tvsvyb5776q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdeaspaf02tvsvyb5776q.png" alt="Alt Text" width="222" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8dossng73kl32wxbm1wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8dossng73kl32wxbm1wl.png" alt="Alt Text" width="475" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos aproveitar e já criar também os nossos produtos concretos, ou seja, as classes que vão implementar nossos produtos abstratos. Se pararmos para pensar um pouco, os nossos produtos concretos vão ser: “FoodOrganic”, “FoodInorganic”, “PackingOrganic” e “PackingInorganic”. Bora implementar essas classes.&lt;/p&gt;

&lt;p&gt;Primeiramente crie os arquivos na pasta Domain, dessa forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flguypdhrlu8qb5s7qoxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flguypdhrlu8qb5s7qoxh.png" alt="Alt Text" width="252" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E agora as implementações das nossas classes/produtos concretos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllzvqgqe776b7uc6la8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllzvqgqe776b7uc6la8o.png" alt="Alt Text" width="716" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feob21y2lwq651eb9gr3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feob21y2lwq651eb9gr3s.png" alt="Alt Text" width="716" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx0jrliuswu12rjd6ju40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx0jrliuswu12rjd6ju40.png" alt="Alt Text" width="739" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsj7wtsgkj0pbe39ifka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsj7wtsgkj0pbe39ifka.png" alt="Alt Text" width="716" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de criarmos os nossos produtos abstratos e também os produtos concretos, podemos começar a pensar em como vai ficar a nossa fábrica abstrata. Temos em mente que a nossa fábrica é responsável por criar produtos abstratos, então, já sabemos que ela vai ser responsável por criar para nós os produtos Food e Packing.&lt;/p&gt;

&lt;p&gt;Vamos a criação da classe, dentro do diretório Factories crie um outro diretório chamado “AbstractFactories” e dentro dele crie a classe “ProductFactory”, vamos criar nessa classe dois métodos abstratos responsáveis por criar nossos produtos abstratos Food e Packing.&lt;/p&gt;

&lt;p&gt;Localização do arquivo nos diretórios:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklz3k4ntaw51btflc13v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklz3k4ntaw51btflc13v.png" alt="Alt Text" width="269" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nossa fábrica ficará assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsb4vbl60tvetzpkfz8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsb4vbl60tvetzpkfz8r.png" alt="Alt Text" width="609" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beleza pessoal, chegamos até aqui, não vamos desistir hein… Bom, depois criar nossas fábricas abstratas nos resta implementar nossas fábricas concretas, essas que serão responsáveis por criar nossos produtos concretos “FoodInorganic”, “FoodOrganic”, “PackingInorganic ”e “PackingOrganic”.&lt;/p&gt;

&lt;p&gt;Vamos lá!&lt;/p&gt;

&lt;p&gt;Dentro do diretório “Factories ” crie duas classes com os seguintes nomes: “ProductOrganicFactory” e “ProductInorganicFactory”. Não podemos esquecer de que nossas fábricas concretas vão herdar de nossa fábrica abstrata, com isso vamos ter a responsabilidade de implementar os métodos abstratos da nossa fábrica abstrata, ou seja, vamos especializar esses carinhas em nossas fábricas concretas.&lt;/p&gt;

&lt;p&gt;Localização dos arquivos no diretório:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjd7ucgbwfrl8y207iy2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjd7ucgbwfrl8y207iy2s.png" alt="Alt Text" width="269" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nossas fábricas ficarão assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pfvz36udyl8cxp7quah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pfvz36udyl8cxp7quah.png" alt="Alt Text" width="640" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxp4l6j17mlmvshgmobx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxp4l6j17mlmvshgmobx.png" alt="Alt Text" width="634" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de implementar nossos produtos e fabricas, sendo eles abstratos e concretos só nos falta implementar nosso “Client”. Vamos nessa!&lt;/p&gt;

&lt;p&gt;Dentro do diretório “Clients” crie a classe “ProductClient”, vou explicar a implementação do nosso client em partes para ficar mais fácil de apresentar o que foi feito.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0nkzmstfv44bqg6f3vf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0nkzmstfv44bqg6f3vf.png" alt="Alt Text" width="793" height="881"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Primeiramente criamos duas propriedades na nossa classes dos nossos produtos abstratos. Ficando assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xfmg3izxx2o6zshtasr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xfmg3izxx2o6zshtasr.png" alt="Alt Text" width="347" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois criamos o nosso construtor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszdyqh0hgkn4w80tklkl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszdyqh0hgkn4w80tklkl.png" alt="Alt Text" width="533" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que o nosso construtor esta um pouco diferente do que normalmente fazemos com a famosa injeção de dependência hahaha, mas calma, vamos entender o porque estamos fazendo assim.&lt;/p&gt;

&lt;p&gt;Nós temos dentro da nossa classe “ProductClient” duas propriedades privadas somente leitura, essas propriedades representam os nossos produtos abstratos.&lt;/p&gt;

&lt;p&gt;No nosso construtor estamos recebendo como parâmetro o “ProductFactory”, que nada mais é do que nossa fábrica abstrata e dentro do nosso método construtor estamos criando as instâncias para os nossos produtos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mas porque não podemos dar um “new” logo em cada produto e já criar a instância que queremos?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Porque se fizermos isso, vamos perder todos os poderes que esse padrão de projeto nos oferece (alta coesão, baixo acoplamento), entre outras coisas.&lt;/p&gt;

&lt;p&gt;Lembre-se, o nosso cliente não tem a obrigação e nem deve saber como as coisas estão sendo implementadas, ele apenas consome os produtos e fábricas abstratas.&lt;/p&gt;

&lt;p&gt;Continuando…&lt;/p&gt;

&lt;p&gt;Para facilicar a criação de nossas fábricas concretas, vamos criar um método estático dentro da classe “ProductClient” que será responsável por retornar para nós uma instância do nosso client já com a fábrica concreta que precisamos.&lt;/p&gt;

&lt;p&gt;O nosso método ficará dessa forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxgyhjcyfyjcjd8yrw4jp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxgyhjcyfyjcjd8yrw4jp.png" alt="Alt Text" width="658" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ainda dentro da classe “ProductClient” vamos criar mais dois métodos que retornarão para nós uma lista de “Food” e “Packing”, já temos esses métodos criados dentro dos nossos produtos abstratos, vamos apenas dar um return nesses métodos das nossas classes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs65iglhzhna6b191q4so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs65iglhzhna6b191q4so.png" alt="Alt Text" width="414" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ótimo pessoal, já temos todo o padrão de projeto “Abstract Factory” implementado, só nos resta agora ver ele na prática, funcionando.&lt;/p&gt;

&lt;p&gt;Como comentamos no começo desse artigo, a proposta era implementar esse padrão de projeto utilizando uma API, vamos fazer isso.&lt;/p&gt;

&lt;p&gt;Dentro do diretório “Controllers” crie uma classe chamada “ProductsController”, ficando asssim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcypeu0rqxclrqvbxwk7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcypeu0rqxclrqvbxwk7b.png" alt="Alt Text" width="245" height="65"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjsi3awkp5pngwbjarup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjsi3awkp5pngwbjarup.png" alt="Alt Text" width="743" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Olha que legal pessoal, dentro da nossa controller vamos criar dois métodos, um para buscar “food”e outro para buscar “packing”, via &lt;a href="https://en.wikipedia.org/wiki/Query_string"&gt;query params&lt;/a&gt; estamos recebendo o tipo de produto que queremos pesquisar, esse tipo é o mesmo dos nossos produtos abstratos.&lt;/p&gt;

&lt;p&gt;Quando chamamos qualquer um desses métodos, a primeira ação que executamos é a chamada do método estático “CreateProductClient” e passamos o tipo que está vindo da nossa requisição.&lt;/p&gt;

&lt;p&gt;Se o usuário passar para nosso método “SearchFood” o tipo “Organic”, será criada uma instância no nosso “ProductClient” e a fábrica concreta que será criada no construtor nesse caso é a “ProductOrganicFactory”.&lt;/p&gt;

&lt;p&gt;Veja o exemplo em debug na imagem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth4shuxxld8if4maft5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth4shuxxld8if4maft5e.png" alt="Alt Text" width="710" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No nosso construtor a instancia que esta sendo passada é da nossa fábrica concreta “ProductOrganicFactory”, isso só é possível por conta da herança que realizamos da nossa fábrica abstrata “ProductFactory”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iisn0t1gbdng1f27vga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iisn0t1gbdng1f27vga.png" alt="Alt Text" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logo abaixo, chamamos o método “SearchFood” e se pararmos para analisar, nosso “client” está chamando esse método do nosso produto abstrato “Food” que declaramos no inicio da classe. E agora vem a pergunta:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;E como que a nossa aplicação sabe que ela tem que retornar uma lista de “Food” do tipo “Organic”?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Simples, através da herança que utilizamos em nossas fabricas e produtos concretos(as).&lt;/p&gt;

&lt;p&gt;Quando o método “SearchFood” ser acionado, a implementação dele vai estar no nosso produto concreto “ProductOrganic” porque a fábrica que criou o produto foi a fábrica concreta “ProductOrganicFactory”. As imagens a seguir mostram o fluxo da aplicação quando chamamos o método “SearchFood” da nossa controller.&lt;/p&gt;

&lt;p&gt;Recebendo o tipo “Organic” no nosso método de buscar “foods”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmoeh2jjioqeb3pufs6sh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmoeh2jjioqeb3pufs6sh.png" alt="Alt Text" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Criando uma instância de “ProductClient” e passando no construtor uma instância da fábrica “ProductOrganicFactory” de acordo com o tipo recebido.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flrqkweapx72zxv6o3hfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flrqkweapx72zxv6o3hfu.png" alt="Alt Text" width="701" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No construtor de “ProductClient” estamos criando produtos concretos de “Food” e “Packing” através na nossa fábrica concreta “ProductOrganicFactory” recebida no construtor, ou seja, esta sendo criado instâncias de “FoodOrganic” e “PackingOrganic”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nsuwfst8g56dznve1ne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nsuwfst8g56dznve1ne.png" alt="Alt Text" width="491" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8ggk9j7dg8cmsn3b4b6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8ggk9j7dg8cmsn3b4b6.png" alt="Alt Text" width="496" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando chamamos o método “SearchFood”, a lista que será retornada é uma lista do tipo “List”, ou seja, a execução deste carinha esta ocorrendo dentro do nosso produto concreto “FoodOrganic”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjlu43n2rhw0oy8c671k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjlu43n2rhw0oy8c671k.png" alt="Alt Text" width="554" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No nosso navegador vamos ter o seguinte retorno para o tipo que passamos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F856datpd4yyx4jm0mejd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F856datpd4yyx4jm0mejd.png" alt="Alt Text" width="297" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se fosse solicitado o tipo “Inorganic”, seria este o retorno apresentado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi0mm5ypa3eu1nlo58jc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi0mm5ypa3eu1nlo58jc.png" alt="Alt Text" width="260" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enfim, terminamos pessoal. Mas antes gostaria de fazer algumas observações.&lt;/p&gt;

&lt;p&gt;Com a implementação desse padrão de projeto, conseguimos atender algumas das recomendações do SOLID, sendo elas:&lt;/p&gt;

&lt;p&gt;SRP, onde cada classe tem a sua responsabilidade, não dependendo e nem implementando coisas que seriam responsabilidade de outras classes.&lt;/p&gt;

&lt;p&gt;OCP, esse princípio é atendido quando criamos as classes abstratatas “Food” e “Packing”, que podem ser herdadas e especializadas. Se por um acaso, um dia surgir um novo tipo de produto como “Industrial”, podemos especializar essas classes como, “FoodIndustrial” e “PackingIndustrial” por exemplo.&lt;/p&gt;

&lt;p&gt;LSP, quando criamos nossas abstrações de fábricas abstratas e fábricas concretas, estamos garantindo que este principio seja atendido.&lt;/p&gt;

&lt;p&gt;Os outros dois princípios não foram implementados neste exemplo, mas fica aberto para discussão e melhorias caso localizem algo que poderia ser implementado.&lt;/p&gt;

&lt;p&gt;O padrão de diretórios criado foi apenas um exemplo para demostrar como implementar este padrão de projeto, caso veja a necessidade de utilizar esse padrão, lembre-se de adequar a implementação a arquitetura que voce está utilizando.&lt;/p&gt;

&lt;p&gt;Este exemplo não é uma receita de bolo que pode ser seguida e copiada sempre, busque abstrair o que foi passado aqui e implemente de acordo com com a necessidade e arquitetura do seu projeto.&lt;/p&gt;

&lt;p&gt;Dessa vez é isso pessoal, muito obrigado pra quem chegou até aqui.&lt;/p&gt;

&lt;p&gt;Curta e compartilhe com seus amigos que estão aprendendo sobre este padrão de projeto, é sempre bom ter uma visão diferente de como fazer as coisas.&lt;/p&gt;

&lt;p&gt;Críticas construtivas são sempre bem vindas, caso localizem algo que possa ser melhorado, deixa ai nos comentários ou me mande uma mensagem.&lt;/p&gt;

&lt;p&gt;Logo vou postar um vídeo no youtube mostrando o passo a passo da nossa demo. Pra quem curte conteúdo em vídeo, vai ser legal.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;p&gt;Projeto no github: &lt;a href="https://github.com/willianmenezes/abstract-factory-dy"&gt;aqui&lt;/a&gt;&lt;br&gt;
Vídeo no youtube: &lt;a href="https://www.youtube.com/watch?v=8FtfHvlxG5g"&gt;aqui&lt;/a&gt;&lt;br&gt;
Twitter: &lt;a href="https://twitter.com/wmscode"&gt;aqui&lt;/a&gt;&lt;br&gt;
youtube: &lt;a href="https://www.youtube.com/channel/UC0Vo6yL26XaraIjak87jDww"&gt;aqui&lt;/a&gt;&lt;br&gt;
polywork: &lt;a href="https://www.polywork.com/wmscode"&gt;aqui&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Organizando a Startup de uma aplicação ASP.NET Core Web Application.</title>
      <dc:creator>Willian Menezes</dc:creator>
      <pubDate>Mon, 23 Aug 2021 20:55:39 +0000</pubDate>
      <link>https://dev.to/wmscode/organizando-a-startup-de-uma-aplicacao-asp-net-core-web-application-1lfa</link>
      <guid>https://dev.to/wmscode/organizando-a-startup-de-uma-aplicacao-asp-net-core-web-application-1lfa</guid>
      <description>&lt;p&gt;Neste pequeno artigo abordarei um assunto simples, mas que pode ajudar inúmeros desenvolvedores a deixar a sua aplicação um pouco mais organizada. Com o uso de &lt;a href="https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-and-call-a-custom-extension-method"&gt;Métodos de extensão&lt;/a&gt; podemos deixar nossa classe Startup de uma aplicação em ASP.NET Core bem organizada e fácil de entender.&lt;/p&gt;

&lt;p&gt;Vou utilizar nos exemplos a seguir, uma API criada em ASP.NET Core 3.1.&lt;/p&gt;

&lt;p&gt;Quando iniciamos um projeto, seja ele para um cliente especifico, testes para empresas ou uso pessoal, precisamos configurar uma serie de serviços na classe Startup.cs, um exemplo clássico é a configuração do Entity Framework um ORM (Object Relational Mapping), que nos ajuda na abstração entre a aplicação e o banco de dados, explicando de uma forma “BEM RESUMIDA”.&lt;/p&gt;

&lt;p&gt;Um exemplo de configuração seria este:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4e9pdxtviyqd0ey6bplg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4e9pdxtviyqd0ey6bplg.png" alt="Imagem mostrando a a classe estartup configurando uma connection string de banco de dados" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dentro do método &lt;strong&gt;ConfigureServices&lt;/strong&gt; na classe Startup registramos nosso contexto de banco de dados, indicando que estamos utilizando o MySQL e apontando para nossa string de conexão chamada &lt;strong&gt;DefaultConnection&lt;/strong&gt; que está localizada no arquivo &lt;strong&gt;appsettings.json.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Até ai tudo bem, temos apenas um serviço sendo registrado, mas e quando isso começar a escalar? O que podemos fazer?&lt;/p&gt;

&lt;p&gt;Imaginem um cenário onde nós temos uma aplicação divida em camadas, sendo elas, uma camada de “Data”, “Business” e “App”, onde cada uma terá sua responsabilidade. Na camada de “Data” nós temos todas as nossas classes de repositórios e suas respectivas interfaces, logo precisamos registrar na aplicação esses repositórios para utiliza-los com &lt;strong&gt;injeção de dependência.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Na classe Startup.cs a injeção de dependência desses repositórios ficariam dessa forma(não necessariamente é a única forma de se fazer):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxe32ucvp8w59jg37xl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxe32ucvp8w59jg37xl1.png" alt="Alt Text" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se por necessidade nossa aplicação conter muitas classes de repositórios, a classe Startup.cs começa a ficar muito grande, dificultando seu entendimento e possíveis manutenção.&lt;/p&gt;

&lt;p&gt;Uma solução muito interessante para resolver isso é removendo essa implementação da classe Startup.cs, utilizando de &lt;strong&gt;Métodos de extensão.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Criaremos um local próprio na nossa aplicação, que terá a responsabilidade de registrar e configurar os serviços que forem necessários.&lt;/p&gt;

&lt;p&gt;Inicialmente precisamos criar uma classe de configuração. Conforme o exemplo a seguir.&lt;/p&gt;

&lt;p&gt;Na camada de aplicação criei uma classe chamada &lt;strong&gt;DependecyInjectionConfiguration,&lt;/strong&gt; nela implementei um método de extensão da interface &lt;strong&gt;IServiceCollection,&lt;/strong&gt; encapsulando a injeção de dependência dos repositórios, ficando da seguinte forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55l12yg7rsisp2qfmlrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55l12yg7rsisp2qfmlrf.png" alt="Alt Text" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na classe Startup.cs dentro do método ConfigureServices precisamos apenas chamar este método da seguinte maneira:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y6ids69ydk7b4jqkxbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y6ids69ydk7b4jqkxbm.png" alt="Alt Text" width="517" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É isso pessoal, esse foi meu primeiro artigo e espero que possa ajudar o máximo de pessoas possível.&lt;/p&gt;

&lt;p&gt;Aceito toda e qualquer crítica construtiva que possa ajudar a trazer um conteúdo de melhor qualidade.&lt;/p&gt;

&lt;p&gt;Me segue lá no &lt;a href="https://www.youtube.com/channel/UC0Vo6yL26XaraIjak87jDww?view_as=subscriber"&gt;YouTube&lt;/a&gt; e no &lt;a href="https://twitter.com/wmscode"&gt;Twitter&lt;/a&gt; que logo vou começar a postar vídeos sobre programação com ASP.NET Core, Angular e entre outras coisas.&lt;/p&gt;

&lt;p&gt;Obrigado! Fui e &lt;strong&gt;#boraaaaaaa!&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
