<?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: Italo Fernandes</title>
    <description>The latest articles on DEV Community by Italo Fernandes (@italofernandez).</description>
    <link>https://dev.to/italofernandez</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%2F448133%2Fb91dc2ef-03a1-43f3-a72d-c9fef48d2f30.png</url>
      <title>DEV Community: Italo Fernandes</title>
      <link>https://dev.to/italofernandez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/italofernandez"/>
    <language>en</language>
    <item>
      <title>Tratar validações de domínio com o lançamento de exceções é uma boa opção?</title>
      <dc:creator>Italo Fernandes</dc:creator>
      <pubDate>Sun, 11 Jul 2021 21:57:02 +0000</pubDate>
      <link>https://dev.to/italofernandez/voce-nao-deveria-tratar-validacao-de-dominio-com-lancamento-de-excecoes-4cgj</link>
      <guid>https://dev.to/italofernandez/voce-nao-deveria-tratar-validacao-de-dominio-com-lancamento-de-excecoes-4cgj</guid>
      <description>&lt;h2&gt;
  
  
  O que diz a &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1#minimize-exceptions" rel="noopener noreferrer"&gt;documentação&lt;/a&gt; 🤔?
&lt;/h2&gt;

&lt;p&gt;"&lt;strong&gt;Exceptions should be rare.&lt;/strong&gt; Throwing and catching exceptions is slow relative to other code flow patterns. Because of this, exceptions shouldn't be used to control normal program flow."&lt;/p&gt;

&lt;p&gt;Bem, de acordo com a documentação do framework, você deveria evitar, ao máximo, o lançamento de exceções para controlar o fluxo normal do seu código, pois esta abordagem pode &lt;strong&gt;comprometer a performance&lt;/strong&gt; (&lt;em&gt;tempo de resposta&lt;/em&gt;) da sua aplicação.&lt;/p&gt;

&lt;p&gt;Principalmente dentro dos &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1#understand-hot-code-paths" rel="noopener noreferrer"&gt;hot code paths&lt;/a&gt;, que são, basicamente, trechos (fluxos) da sua aplicação que são executados com muita frequência, como por exemplo: &lt;strong&gt;validações&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um cenário comum
&lt;/h2&gt;

&lt;p&gt;Para exemplificar, vamos imaginar que você precise construir uma web api, que deve verificar cada requisição recebida e validar se a mesma atende ou não às suas regras de negócio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo&lt;/strong&gt;: Ao receber uma requisição para cadastrar um novo usuário, a aplicação deve verificar se o email enviado é válido. Caso o email seja inválido, esta requisição deverá ser invalidada e aplicação &lt;strong&gt;não&lt;/strong&gt; deve seguir com o seu processamento.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Este é o ponto onde muitos desenvolvedores fazem uso do lançamento de exceções.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Então você deve está se perguntando: &lt;em&gt;"Certo, mas qual o problema de lançar exceções já que estou capturando essas exceções mais a frente?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A seguir, vamos entrar em detalhes de como você pode evitar essa má prática, mas primeiramente, gostaria de fazer algumas observações: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Você &lt;strong&gt;pode&lt;/strong&gt; trabalhar com exceções e até mesmo criar as suas próprias exceptions, desde que façam sentido para a sua aplicação.&lt;/li&gt;
&lt;li&gt;O problema abordado neste post é a &lt;strong&gt;perda de performance&lt;/strong&gt; causada pelo &lt;strong&gt;lançamento de exceções&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para exemplificar como seria a maneira "errada" (menos performática) de tratar validações, vamos usar o cenário citado anteriormente:&lt;/p&gt;

&lt;h2&gt;
  
  
  Com lançamento de exceções
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;INVALID_EMAIL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"invalid_email#123"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;ThrowingException&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CreateUserRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INVALID_EMAIL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ValidateAndThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&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;return&lt;/span&gt; &lt;span class="nf"&gt;BadRequest&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="n"&gt;Message&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sem lançamento de exceções
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;INVALID_EMAIL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"invalid_email#123"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;NotThrowingException&lt;/span&gt;&lt;span class="p"&gt;()&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;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CreateUserRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INVALID_EMAIL&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;validationResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validationResult&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;h2&gt;
  
  
  Vejamos os resultados
&lt;/h2&gt;

&lt;h3&gt;
  
  
  BenchmarkDotNet
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fitalofernandez%2Fexpensive-exceptions%2Fmain%2Fimages%2Fbenchmark_dotnet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fitalofernandez%2Fexpensive-exceptions%2Fmain%2Fimages%2Fbenchmark_dotnet.png" alt="BenchmarkDotNet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  K6 - Load Testing
&lt;/h3&gt;

&lt;p&gt;A seguir vemos o resultado de um simples teste de carga em nossa api, utilizando o &lt;a href="//k6.io"&gt;k6.io&lt;/a&gt; com duração de 1 minuto e 100 &lt;a href="https://k6.io/docs/using-k6/options/#vus" rel="noopener noreferrer"&gt;Virtual Users&lt;/a&gt; (VUs).&lt;/p&gt;

&lt;p&gt;À &lt;strong&gt;esquerda&lt;/strong&gt; o endpoint que faz o lançamento de uma exceção, e à &lt;strong&gt;direita&lt;/strong&gt; os resultados do endpoint trata a validação sem lançar exceções.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fitalofernandez%2Fexpensive-exceptions%2Fmain%2Fimages%2Fk6_loading_tests.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fitalofernandez%2Fexpensive-exceptions%2Fmain%2Fimages%2Fk6_loading_tests.png" alt="K6 - Load Testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Após analisar os resultados, não é difícil perceber que o lançamento de exceções gera uma degradação considerável na performance da sua aplicação, então use-as com cuidado. 😋&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1#minimize-exceptions" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1#minimize-exceptions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.thecodebuzz.com/best-practices-for-handling-exception-in-net-core-2-1/" rel="noopener noreferrer"&gt;https://www.thecodebuzz.com/best-practices-for-handling-exception-in-net-core-2-1/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackify.com/finding-hidden-exceptions-application-performance-problems-apm/" rel="noopener noreferrer"&gt;https://stackify.com/finding-hidden-exceptions-application-performance-problems-apm/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/AlbertoMonteiro/c5f4da035c8c9cf9b32b1da2006b4400" rel="noopener noreferrer"&gt;https://gist.github.com/AlbertoMonteiro/c5f4da035c8c9cf9b32b1da2006b4400&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>performance</category>
      <category>aspnetcore</category>
      <category>exceptionhandling</category>
    </item>
  </channel>
</rss>
