<?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: Guilherme Ferreira</title>
    <description>The latest articles on DEV Community by Guilherme Ferreira (@gsferreira).</description>
    <link>https://dev.to/gsferreira</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%2F260870%2Fc0d8fb82-be12-4f4e-a022-86bc55e1f08d.jpg</url>
      <title>DEV Community: Guilherme Ferreira</title>
      <link>https://dev.to/gsferreira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gsferreira"/>
    <language>en</language>
    <item>
      <title>Embedding dotnet format in your development cycle</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Fri, 11 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/embedding-dotnet-format-in-your-development-cycle-8ih</link>
      <guid>https://dev.to/gsferreira/embedding-dotnet-format-in-your-development-cycle-8ih</guid>
      <description>&lt;p&gt;I have to confess. I've spent more time than acceptable during code reviews, looking into C# code formatting issues. It's such dumb work. I should focus on other things rather than watching if a colleague forgot to format the code or if someone is using a different editor with different rules.&lt;/p&gt;

&lt;p&gt;That's one thing that that I miss when writing C# in Visual Studio if I compare it to writing JS in Visual Studio Code. It's so beautiful when Prettier auto-format when I save the file. You define rules in your &lt;code&gt;.editorconfig&lt;/code&gt; and BOOOM! 💥 No more nitpicking on indentation or whitespaces. You can even enforce other rules like having the System using directives first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# .editorconfig Example
# Organize using directives
&lt;/span&gt;&lt;span class="py"&gt;dotnet_sort_system_directives_first&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;dotnet_separate_import_directive_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can bring the same experience with &lt;strong&gt;dotnet format&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;.NET CLI has introduced a &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-format"&gt;new command to format&lt;/a&gt;. &lt;a href="https://github.com/dotnet/format"&gt;"dotnet format"&lt;/a&gt; was an existing dotnet tool, but now (.NET 6.x SDK and later versions) it's integrated into the CLI. You install the CLI, and you have it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can I use it?
&lt;/h2&gt;

&lt;p&gt;It is a simple command-line tool, so you can integrate it into your CI/CD toolchain.&lt;/p&gt;

&lt;p&gt;One interesting "dotnet format" option is to verify if changes should be performed with &lt;code&gt;--verify-no-changes&lt;/code&gt;. Besides that, you can include only some files in the verification with &lt;code&gt;--include&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet format --verify-no-changes --include src\Infrastructure\CustomerRepository.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, those two arguments are perfect for a CI pipeline.&lt;br&gt;
Every time a PR (Pull Request) is open, you can verify any broken format rule during build time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Runing dotnet format with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;You can run it in your prefered build system, being TeamCity, Jenkins, Azure DevOps, etc., but here I will use GitHub Actions.&lt;/p&gt;

&lt;p&gt;The process is quite simple. If you go to &lt;a href="https://github.com/marketplace?type=actions"&gt;GitHub Actions Marketplace&lt;/a&gt;, you will find some extensions to run dotnet format. I will be using &lt;a href="https://github.com/marketplace/actions/dotnet-format"&gt;"xt0rted/dotnet-format"&lt;/a&gt; by &lt;a href="https://github.com/xt0rted"&gt;Brian Surowiec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, I added a step to my workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run dotnet format&lt;/span&gt;
      &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xt0rted/dotnet-format@v1&lt;/span&gt;
      &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;only-changed-files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.NET&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup .NET&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-dotnet@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;dotnet-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;6.0.x&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run dotnet format&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xt0rted/dotnet-format@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;only-changed-files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restore dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet restore&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet build --no-restore&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet test --no-build --verbosity normal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when a PR is open, dotnet format will run to check the changed files. If someone edits a file without formatting, the build will fail.&lt;/p&gt;

&lt;p&gt;That is pretty cool, but I would prefer to prevent build attempts because somebody forgot to format a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  dotnet format and Git Hooks
&lt;/h2&gt;

&lt;p&gt;So, how can I prevent commits if I forget to format the code?&lt;/p&gt;

&lt;p&gt;The answer to that is &lt;a href="https://githooks.com/"&gt;Git Hooks&lt;/a&gt;.&lt;br&gt;
Git gives you a way to hook in some git steps. So, you can run your code on pre-commit.&lt;/p&gt;

&lt;p&gt;You can do that in many ways (see &lt;a href="https://github.com/dotnet/format/blob/main/docs/integrations.md"&gt;here&lt;/a&gt;), but I prefer to use &lt;a href="https://pre-commit.com/"&gt;"pre-commit"&lt;/a&gt;. Pre-commit simplifies your process and offers you an easy way to adopt new hooks. Go take a look. It's pretty cool!&lt;/p&gt;
&lt;h3&gt;
  
  
  How to configure pre-commit
&lt;/h3&gt;

&lt;p&gt;First, you need to install pre-commit (see &lt;a href="https://pre-commit.com/#install"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;After installed, create a file &lt;code&gt;".pre-commit-config.yaml"&lt;/code&gt; in the root folder.&lt;/p&gt;

&lt;p&gt;Add the following snippet there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/dotnet/format&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet-format&lt;/span&gt;
        &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;--folder&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;--include&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, install your git hook script:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pre-commit install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After this, dotnet format will run every time you &lt;code&gt;git commit&lt;/code&gt;! 😍&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m6pMZqVy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/dotnet/dotnet-format-result.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m6pMZqVy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/dotnet/dotnet-format-result.png" alt="dotnet format result" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Obviously, one of your teammates may not install "pre-commit" and keep editing files with Sublime, Vim or Notepad 🤷. That's why is important to do it not only as a pre-commit but also as part of the build. One works as a Guard and the other as a feedback cycle improver.&lt;/p&gt;

&lt;p&gt;It's quite a simple process, so it's worth trying.&lt;/p&gt;

&lt;p&gt;I hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Looking into C# Property Patterns Performance</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/looking-into-c-property-patterns-performance-hop</link>
      <guid>https://dev.to/gsferreira/looking-into-c-property-patterns-performance-hop</guid>
      <description>&lt;p&gt;Property Patterns is one of those things that rapidly changed how I write code. I love how the code looks clear and expressive (see what I've written about it &lt;a href="https://dev.to/gsferreira/expressive-c-code-with-property-patterns-gpo"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In that spirit, I recently tweeted and posted to LinkedIn how I loved simple things like implementing a Guard Clause on collections. See the tweet below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D28-o4U7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/tweets/property-patterns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D28-o4U7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/tweets/property-patterns.png" alt="Tweet / Property Patterns" width="800" height="977"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://twitter.com/gsferreira/status/1486625607895109635"&gt;(here)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was aware that this is not for the taste of everyone, and obviously, most comments were from people that prefer other conventional ways of expressing it.&lt;/p&gt;

&lt;p&gt;One of the comments was the usual when you post .NET related content: &lt;em&gt;"What about performance?"&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance 🚀
&lt;/h2&gt;

&lt;p&gt;So, I decided to go on a journey to understand how performant Guard clauses with Property Patterns can be.&lt;/p&gt;

&lt;p&gt;To do that, I decided to compare the multiple suggestions received with my loved Property Patterns.&lt;/p&gt;

&lt;p&gt;So, the candidates were:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (list is null || !list.Any()) 
    return false;
return true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option B
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (list?.Any() == false) 
    return false;
return true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option C
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (list == null || list.Length == 0) 
    return false;
return true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option D
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (list is not { Length: &amp;gt; 0 }) 
    return false;
return true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option E
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (list is null or { Length: 0 }) 
    return false;
return true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running a benchmark, I got the following results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--by2ggvLq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/csharp/property-patterns-guard-benchmark-results.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--by2ggvLq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/csharp/property-patterns-guard-benchmark-results.png" alt="Property Patterns Benchmark Results" width="800" height="737"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That was an excellent result.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can they do that? 🤔
&lt;/h2&gt;

&lt;p&gt;As you can see, Property Patterns aren't the most performant, but they are close enough. How?&lt;/p&gt;

&lt;p&gt;If you pick option D or E and lower it using &lt;a href="https://sharplab.io/"&gt;SharpLab&lt;/a&gt;, you will see that the Property Patterns lowered version is quite close to Option C, the most performant option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WINisg_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/csharp/lowered-property-patterns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WINisg_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/csharp/lowered-property-patterns.png" alt="SharpLab / Lowered Property Patterns" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So what? 🙄
&lt;/h2&gt;

&lt;p&gt;Now what? Why should I use Property Patterns when there's a most efficient option?&lt;/p&gt;

&lt;p&gt;That is true. On the other hand, Property Patterns are expressive (my opinion), but also &lt;strong&gt;they guide you to better decisions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As an example, you can't use LINQ with Property Patterns. You can see from benchmark results that it is a good constraint to have. Anything that can set you on the path of success is a good thing to do.&lt;/p&gt;

&lt;p&gt;After this journey, this is just one more reason to keep using it. I know it may feel strange for an experienced .NET developer, but give it a try.&lt;/p&gt;

&lt;p&gt;🔗 You can find the source code used &lt;a href="https://github.com/gsferreira/dotnet-playground/tree/main/Optimizations/PropertyPatternsBenchmark"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Taking control over xUnit test names</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Mon, 24 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/taking-control-over-xunit-test-names-3mel</link>
      <guid>https://dev.to/gsferreira/taking-control-over-xunit-test-names-3mel</guid>
      <description>&lt;p&gt;Unit Testing naming conventions are almost as conflicting as spaces versus tabs. I've never worked on a project where everyone has the same preferences.&lt;/p&gt;

&lt;p&gt;Often, you even find multiple practices in the same codebase. They go from &lt;em&gt;Given_When_Then&lt;/em&gt; to &lt;em&gt;MethodUnderTest_Scenario_ExpectedResult&lt;/em&gt; or even variances where one person may use Pascal and another Snake case.&lt;/p&gt;

&lt;p&gt;Often, we forget that &lt;strong&gt;the most important thing is expressing clearly the test intent&lt;/strong&gt;. So, it's the question of how to make the most of those shapes or forms.&lt;/p&gt;

&lt;h2&gt;
  
  
  xUnit Test name customization
&lt;/h2&gt;

&lt;p&gt;The good news is that you have some ways to control xUnit behaviour in terms of test display names.&lt;/p&gt;

&lt;p&gt;The simplest one is defining a custom Display Name through the Fact attribute.&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="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DisplayName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Get the max number of an array"&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;void&lt;/span&gt; &lt;span class="nf"&gt;GivenAnArray_WhenApplyMax_ThenGetThenBiggerOne&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Max&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&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;That will give you a higher degree of freedom, but it's an extra effort, difficult to keep consistent across the code. We already need to craft a meaningful method name, so having an extra-label may lead to out of sync text. We already know what happens to code comments. We don't need to deal with the same problem in tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what can we do?
&lt;/h2&gt;

&lt;p&gt;One interesting thing from xUnit is the &lt;a href="https://xunit.net/docs/configuration-files"&gt;configuration files&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There, you can find many options to change the default behaviours of xUnit. One of them is related to Display Name.&lt;/p&gt;

&lt;p&gt;xUnit in .net will display names based on class and method name by default. With the configuration file, you can define the &lt;a href="https://xunit.net/docs/configuration-files#methodDisplay"&gt;display name&lt;/a&gt; to be the Method name.&lt;/p&gt;

&lt;p&gt;To do it, create a &lt;em&gt;&lt;code&gt;xunit.runner.json&lt;/code&gt;&lt;/em&gt; file in the xUnit project root, make sure it's included and add the following snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://xunit.net/schema/current/xunit.runner.schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"methodDisplay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"method"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To include, add to the &lt;em&gt;csproj&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Content&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"xunit.runner.json"&lt;/span&gt; &lt;span class="na"&gt;CopyToOutputDirectory=&lt;/span&gt;&lt;span class="s"&gt;"PreserveNewest"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides that, the most interesting thing is the &lt;a href="https://xunit.net/docs/configuration-files#methodDisplayOptions"&gt;method display name options&lt;/a&gt;, where you can find options to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace underscores with spaces;&lt;/li&gt;
&lt;li&gt;Replace operators with matching symbols (example: &lt;code&gt;eq becomes =&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;Replace periods with a comma and a space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To enable them, go to the &lt;em&gt;&lt;code&gt;xunit.runner.json&lt;/code&gt;&lt;/em&gt; file and add a new key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"methodDisplayOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replaceUnderscoreWithSpace,useOperatorMonikers"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, for the following tests:&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;class&lt;/span&gt; &lt;span class="nc"&gt;DisplayNameTests&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&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;void&lt;/span&gt; &lt;span class="nf"&gt;Given10_WhenMultiplyBy2_ThenGet20&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;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20&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="n"&gt;Fact&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;void&lt;/span&gt; &lt;span class="nf"&gt;Is_20_gt_10&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;BeGreaterThan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&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;p&gt;Once you run the tests, you will see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0veT3hhz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/xunit/xunit-configuration-method-name-after.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0veT3hhz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/xunit/xunit-configuration-method-name-after.png" alt="xUnit / Result after changing method display name configuration" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0PsGTLfG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/xunit/xunit-configuration-method-name-before.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0PsGTLfG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/xunit/xunit-configuration-method-name-before.png" alt="xUnit / Result before changing method display name configuration" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I don't say you must use this, but knowing that these features exist may be helpful to improve the readability of your tests when analysing the results. In some cases, the existing conventions may help achieve better results, like if you are using Snake casing, enabling the "&lt;em&gt;replaceUnderscoreWithSpace&lt;/em&gt;" is a quick improvement.&lt;/p&gt;

&lt;p&gt;Now it's time to take a look into your codebase, look into the existing configuration options, and you may find a quick win.&lt;/p&gt;

&lt;p&gt;🔗 You can find the source code used &lt;a href="https://github.com/gsferreira/dotnet-playground/tree/main/Tests/xUnit/xUnitDisplayName"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>xunit</category>
    </item>
    <item>
      <title>Expressive C# code with Property Patterns</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Mon, 20 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/expressive-c-code-with-property-patterns-gpo</link>
      <guid>https://dev.to/gsferreira/expressive-c-code-with-property-patterns-gpo</guid>
      <description>&lt;p&gt;C# has been growing with F# inspired features.&lt;/p&gt;

&lt;p&gt;One that is most exciting is &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern"&gt;Pattern Matching&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The introduction of Pattern matching led to Property Patterns.&lt;/p&gt;

&lt;p&gt;Property patterns deserve close attention. Since they were included on C# 8, they have been evolving, with improvements either on C# 9 but also in C# 10.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property Patterns are interesting ways to make the code more expressive, and in this post, we will see how.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Property Pattern
&lt;/h2&gt;

&lt;p&gt;You use a property pattern to match expression properties to nested patterns.&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;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsFirstOfTheMonth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, with Property Patterns, you can go from this:&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;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isValid&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;reason&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;Note&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;)&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;note&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&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;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note&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;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Title should be 5 to 50 char long"&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;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Content is required"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&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;To this:&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;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isValid&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;reason&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;Note&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;50&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;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Title should be 5 to 50 char long"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&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;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Content is required"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&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;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&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;
  
  
  Where can you use them
&lt;/h2&gt;

&lt;p&gt;It's common to see the Property Pattern being used with switch expressions, but don't limit it to there.&lt;/p&gt;

&lt;p&gt;Property Patterns can be used in the context of switch case guards, if's, boolean assignments, catch a condition, etc.&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;try&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;NpgsqlException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"42P01"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nested patterns
&lt;/h2&gt;

&lt;p&gt;Property Patterns can be used to not only test properties but also nested ones. With &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/extended-property-patterns"&gt;C# 10 Extended property patterns&lt;/a&gt;, that becomes even simpler.&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Student&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CountryCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PT"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Precedence
&lt;/h2&gt;

&lt;p&gt;With Property Patterns you will not be using "&amp;amp;&amp;amp;", "||" or "!", instead, you can use "and", "or", "not".&lt;/p&gt;

&lt;p&gt;You can also use parentheses to specify the precedence.&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="n"&gt;person&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nf"&gt;Student&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CountryCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PT"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CountryCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ES"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Next time you need to write a boolean expression, give what you have learned here a try. I know that at the moment, this is not that common in C# code bases, which increases the required cognitive load. It's a different way to write code if you are a long time C# Developer, but in the end, the code becomes more expressive in my opinion. What do you think?&lt;/p&gt;

&lt;p&gt;I hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Where to place C#10 Global Usings</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Sat, 11 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/where-to-place-c10-global-usings-5e07</link>
      <guid>https://dev.to/gsferreira/where-to-place-c10-global-usings-5e07</guid>
      <description>&lt;p&gt;The new C# 10 is packed with quality of life features. One that I'm definitively using is &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#global-modifier"&gt;Global Usings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In simple terms, Global Usings is a way to declare usings at the project level, so you don't need to declare them in every single file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I care?
&lt;/h2&gt;

&lt;p&gt;That's a fair question, especially in the days where IDE's do most of the work for us.&lt;/p&gt;

&lt;p&gt;Even then, declaring them at the project level will result in tidier source files. Let's be honest, how many times do you import &lt;code&gt;System.Linq&lt;/code&gt; or your own Extensions namespace?&lt;/p&gt;

&lt;h2&gt;
  
  
  How can I do it?
&lt;/h2&gt;

&lt;p&gt;Global Usings are simple to use. Simply add the &lt;code&gt;global&lt;/code&gt; modifier to the &lt;code&gt;using&lt;/code&gt; you want.&lt;/p&gt;

&lt;p&gt;Adding the &lt;code&gt;global&lt;/code&gt; modifier is the same as adding the same &lt;code&gt;using&lt;/code&gt; directive to every source file in your project.&lt;/p&gt;

&lt;p&gt;That leads to the question: &lt;em&gt;Where should I declare my global usings?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was facing that same question. 🤔&lt;/p&gt;

&lt;p&gt;One thing was obvious to me. I should have a central place for it. Even &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#global-modifier"&gt;Microsoft Docs&lt;/a&gt; say so:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may add global using directives to any source file. Typically, you'll want to keep them in a single location. The order of global using directives doesn't matter, either in a single file, or between files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But, where? In a Web or Console project, you may use "Program.cs" for it, but rapidly it may become cluttered. And if it is a Class Library?! There are no "Program.cs".&lt;/p&gt;

&lt;h3&gt;
  
  
  So I asked my Twitter friends what would they do.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PPx-2Ajp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/tweets/global-usings-where-to-place-question.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PPx-2Ajp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/tweets/global-usings-where-to-place-question.png" alt="Tweet / Where to add gloabal usings." width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://twitter.com/gsferreira/status/1464293275511177217"&gt;(here)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you take a look at the comments, you will see many good suggestions around adding a file to the root of the project. Name suggestions vary as you can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Globals.cs&lt;/li&gt;
&lt;li&gt;GlobalUsings.cs&lt;/li&gt;
&lt;li&gt;Imports.cs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That seems a good approach, but there was a comment by &lt;a href="https://twitter.com/martin_costello"&gt;Martin Costello&lt;/a&gt; that made my mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  My prefered way
&lt;/h2&gt;

&lt;p&gt;Before going into Martin suggestion, it's important to say that you can not only declare &lt;code&gt;global usings&lt;/code&gt; in a &lt;code&gt;.cs&lt;/code&gt; file but also at the project file.&lt;/p&gt;

&lt;p&gt;That can be done by adding a &lt;code&gt;&amp;lt;Using&amp;gt;&lt;/code&gt; item to your project file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ItemGroup&amp;gt;
 &amp;lt;Using Include="MyAwesomeApp.Extensions" /&amp;gt;
&amp;lt;/ItemGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In principle, I would prefer to declare my usings in C#. I don't love to edit my &lt;code&gt;csproj&lt;/code&gt; files, but Martin remembered me that I can do it in a &lt;code&gt;Directory.Build.props&lt;/code&gt; file (if you want to know more about this file, take a look at &lt;a href="https://gsferreira.com/archive/2018/06/versioning-net-core-applications-using-cake/"&gt;this post&lt;/a&gt; that I've written to see the potential).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ViXvM_U8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/tweets/global-usings-where-to-place-question-directory-build-props.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ViXvM_U8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/tweets/global-usings-where-to-place-question-directory-build-props.png" alt="Tweet / Global Usings - Directory Build Props" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://twitter.com/martin_costello/status/1464498288061816838"&gt;(here)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So, what's the beauty of it?
&lt;/h3&gt;

&lt;p&gt;The beauty of it is that if you place &lt;code&gt;Directory.Build.props&lt;/code&gt; in the root folder that contains your source code, when MSBuild runs will add to every project the properties defined in the &lt;code&gt;Directory.Build.props&lt;/code&gt;. So, if you want to do it Solution wise or even only for your Test folder, you can do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I will be using &lt;code&gt;Directory.Build.props&lt;/code&gt; for sure. At least until we see a new standard way to declare global usings emerging in the community.&lt;/p&gt;

&lt;p&gt;I hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Uploading files with ASP.NET Minimal APIs</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Wed, 24 Nov 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/uploading-files-with-aspnet-minimal-apis-2036</link>
      <guid>https://dev.to/gsferreira/uploading-files-with-aspnet-minimal-apis-2036</guid>
      <description>&lt;p&gt;With the .net 6 release, I was extremely excited to play with &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0"&gt;Minimal APIs&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One of the first things that I've done was to move an existing project to .net 6 and convert my Controllers into a Minimal API.&lt;/p&gt;

&lt;p&gt;I've found the process easy, but &lt;strong&gt;I was surprised when the tests for an Upload endpoint failed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My implementation after converting into Minimal API Endpoint was this. 👇&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/upload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;IFormFile&lt;/span&gt; &lt;span class="n"&gt;request&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;if&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="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&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;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stream&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="nf"&gt;OpenReadStream&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;reader&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;StreamReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&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;text&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;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadToEndAsync&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;Results&lt;/span&gt;&lt;span class="p"&gt;.&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;text&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;And the test this. 👇&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;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;application&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;Application&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;formData&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;MultipartFormDataContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text.txt"&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;streamContent&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;StreamContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text.txt"&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;response&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PostAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/upload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;formData&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="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Be&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;OK&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;data&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\"Hello World!\""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected &lt;em&gt;200 OK&lt;/em&gt; status code was now a &lt;em&gt;415 Unsupported Media Type&lt;/em&gt; 🤔&lt;/p&gt;

&lt;p&gt;That was strange. My first thought was that I was missing to define the content type accepted by that endpoint.&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Accepts&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFormFile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"multipart/form-data"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I realized I was stupid by thinking that since the code above is just about adding OpenAPI Metadata. 😅&lt;/p&gt;

&lt;p&gt;Then, finally, I got it. Minimal APIs will try to bind attributes with the assumption that content is JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, how do I handle it?
&lt;/h2&gt;

&lt;p&gt;I had to &lt;strong&gt;receive the HttpRequest request as an argument&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then, I was able to read the Form and look for files.&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/upload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&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;if&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="n"&gt;HasFormContentType&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;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BadRequest&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;form&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadFormAsync&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;formFile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"file"&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;formFile&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;formFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&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;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenReadStream&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;reader&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;StreamReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&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;text&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;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadToEndAsync&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;Results&lt;/span&gt;&lt;span class="p"&gt;.&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;text&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;In the end, it requires a lit bit of extra effort, but it's not a big deal. Maybe in a future version, we may have a simple way of accomplishing it.&lt;/p&gt;

&lt;p&gt;I hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>dotnet6</category>
    </item>
    <item>
      <title>React components doing too much (and how to simplify them)</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Mon, 16 Nov 2020 10:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/react-components-doing-too-much-and-how-to-simplify-them-4cnd</link>
      <guid>https://dev.to/gsferreira/react-components-doing-too-much-and-how-to-simplify-them-4cnd</guid>
      <description>&lt;p&gt;Do you have the feeling that some of your components are doing too much?&lt;/p&gt;

&lt;p&gt;Do you remember that time you added a new boolean prop to act as a flag to condition the render? That happens a lot, but those small changes sometimes can have huge impacts in the future.&lt;/p&gt;

&lt;p&gt;Feature after feature, change after change, components tend to become more complex. If we are not watching for it, they will be out of control, and that will lead us to be afraid of change.&lt;/p&gt;

&lt;p&gt;That's why &lt;strong&gt;we need to be careful with component contracts&lt;/strong&gt;. That contract is expressed through props by the way.&lt;/p&gt;

&lt;p&gt;One way to spot eventual problems is to look for boolean props &lt;a href="https://gsferreira.com/archive/2020/05/that-flag-argument-is-yelling-at-you/"&gt;(they will yell at you as you can read here)&lt;/a&gt;. A usual case is to have boolean props used as a way to condition the render.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5jieIJBq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/react/bool-props.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5jieIJBq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/archive/react/bool-props.png" alt="React component boolean props definition" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a few problems with that approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The component contract can become complex and the state of the component difficult to evaluate.&lt;/li&gt;
&lt;li&gt;It can be a symptom that the component is doing too much.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complex Contract
&lt;/h2&gt;

&lt;p&gt;Imagine that you have to create a login Component where the user can log in using username.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Login&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Username:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Log In"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One day, you have to review the login Component so the consumer can decide if the user will log in using username or email. A quick fix to achieve that is to create a component with a boolean prop in case the consumer prefers email:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;usingEmail&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;usingEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Username:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;usingEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Log In"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;usingEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine that one day, users can also log in with phone number. Now you have a problem.&lt;/p&gt;

&lt;p&gt;The boolean flag isn't extensible to support three variants, and following the same strategy, we would get contradicting boolean props. The consumer of the component would be capable of configuring the Component with a username and phone login, for example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;usingEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;usingPhoneNumber&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;usingEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usingPhoneNumber&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Phone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Username:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;usingEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usingPhoneNumber&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Log In"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;usingEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;usingPhoneNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contracts with boolean flags are complex and deliver a bad UX to the consumer.&lt;/p&gt;

&lt;p&gt;It complicates component signature, yelling that this component does more than one thing. It does one thing if the flag is "True" and another if the flag is "False". In the example, the worst is that the consumer doesn't know what to expect when both props are "True".&lt;/p&gt;

&lt;h3&gt;
  
  
  So, what to do?
&lt;/h3&gt;

&lt;p&gt;A simple solution would be to &lt;strong&gt;prefer Enums over booleans.&lt;/strong&gt; A boolean is extensible and describes a clear intention.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_IDENTIFIFICATION_TYPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;USERNAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;EMAIL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;PHONENUMBER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;phone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userIdentificationType&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldUseEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;userIdentificationType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;USER_IDENTIFIFICATION_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldUsePhone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;userIdentificationType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;USER_IDENTIFIFICATION_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PHONENUMBER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;shouldUseEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shouldUsePhone&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Phone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Username:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;shouldUseEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shouldUsePhone&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Log In"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userIdentificationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;oneOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;USER_IDENTIFIFICATION_TYPES&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="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userIdentificationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;USER_IDENTIFIFICATION_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we fix the problem of the contract, but this component is doing too much.&lt;/p&gt;

&lt;h2&gt;
  
  
  God Components
&lt;/h2&gt;

&lt;p&gt;Besides contract complexity, &lt;strong&gt;boolean props are a symptom that the component may be a God Component&lt;/strong&gt; , doing too much.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, what to do?
&lt;/h3&gt;

&lt;p&gt;If you notice that you are in the presence of a God Component, you should split the component.&lt;/p&gt;

&lt;p&gt;In this login component example, you could create three components, for instance, to encapsulate inner details, something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UsernameLogin&lt;/li&gt;
&lt;li&gt;EmailLogin&lt;/li&gt;
&lt;li&gt;PhoneNumberLogin&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Base Login Component
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prop-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Log In"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Username Login Component
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UsernameLogin&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Username:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Login&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UsernameLogin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Email Login Component
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;EmailLogin&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;EmailLogin:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Login&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;EmailLogin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Phone Login Component
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PhoneNumberLogin&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Phone:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tel"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Login&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;PhoneNumberLogin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, your components will &lt;strong&gt;do one thing and do it well&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Hope that this was useful! To get more tips like this, follow me on &lt;a href="https://twitter.com/gsferreira"&gt;Twitter (@gsferreira)&lt;/a&gt; and let's keep in touch!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Eleventy - The Simplest Static Site Generator</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Fri, 24 Jul 2020 21:47:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/eleventy-the-simplest-static-site-generator-3bl0</link>
      <guid>https://dev.to/gsferreira/eleventy-the-simplest-static-site-generator-3bl0</guid>
      <description>&lt;p&gt;Eleventy is the simplest Static Site Generator that I know. I know that this is a bold statement and you can prove me wrong. But &lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;Eleventy (11ty)&lt;/a&gt; was the simplest static site generator that I found when I needed to migrate my blog. Eleventy may not be the best or the powerful one but is beautifully simple.&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%2Fgsferreira.com%2Fimages%2Farchive%2Feleventy%2Flogo.jpg" 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%2Fgsferreira.com%2Fimages%2Farchive%2Feleventy%2Flogo.jpg" alt="Eleventy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;I have been thinking about moving my blog to a different framework. I was using &lt;a href="https://dev.to/gsferreira/reasons-to-blogging-with-github-pages-and-sandra-snow-4nhg-temp-slug-42844"&gt;Sandra.Snow&lt;/a&gt;, that not have been updated recently.&lt;/p&gt;

&lt;p&gt;My goal was to keep using a Static Blog, hosting on GitHub Pages. I want to write using markdown. It was also important to be able to keep the same URLs and migrate all the content to the new framework. I also would like the blog not need JavaScript to display the blog posts. Those are the requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The obvious choices
&lt;/h2&gt;

&lt;p&gt;In the top of my mind, I knew that &lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; and &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt; were able to do the job. I was more inclined to try out Gatsby since there are many starters to create a blog. I don't have experience with Gatsby or NextJS, so, it was important to me to not need to much time to do the work. So, the learning curve was also an important factor.&lt;/p&gt;

&lt;p&gt;My first attempt was with Gatsby. I installed the &lt;a href="https://www.gatsbyjs.org/starters/gatsbyjs/gatsby-starter-blog/" rel="noopener noreferrer"&gt;starter blog&lt;/a&gt; and I tried to migrate my content to Gatsby. I have to confess that after a few hours I was stuck. I couldn't accomplish my task without investing to much time to learn the framework. After a few problems, I was finding myself searching through the web to have a clue of what should I do.&lt;/p&gt;

&lt;p&gt;Gatsby was taking so much time that I decided to take a bet on NextJS. I knew beforehand that I didn't have so many starters/templates as in the Gatsby ecosystem. Even so, I was expecting to have results faster.&lt;/p&gt;

&lt;p&gt;I picked &lt;a href="https://telmo.im/writings/open-sourcing-blog" rel="noopener noreferrer"&gt;Telmo blog&lt;/a&gt; as a starting point and I tried to move my content. The results show up faster!&lt;/p&gt;

&lt;p&gt;But, there was something that I didn't like and I didn't find a way to overcome. Even with the &lt;a href="https://nextjs.org/docs/advanced-features/static-html-export" rel="noopener noreferrer"&gt;static HTML export&lt;/a&gt; build, I needed JavaScript enabled to display the content. Probably was because of my lack of knowledge, but after a few hours, I didn't have a clue of what should I do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eleventy
&lt;/h2&gt;

&lt;p&gt;I was tired of fighting with Gatsby and NextJS. Something simpler was needed. I recall seeing a blog post from &lt;a href="https://reverentgeek.com/" rel="noopener noreferrer"&gt;David Neal&lt;/a&gt; about moving his blog to a different technology. The technology is Eleventy. You can read his blog post &lt;a href="https://reverentgeek.com/moving-from-ghost-to-eleventy/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After reading a few things, I start feeling excited. Eleventy seems simple and quick to learn. The learning curve doesn't seem to steep. It feels natural to create pages with it. I see it as Templating Language on steroids.&lt;/p&gt;

&lt;p&gt;So, I start working to move my blog into Eleventy. I started with the &lt;a href="https://github.com/marcfilleul/mf-blogstarter" rel="noopener noreferrer"&gt;MF Blog Starter Template&lt;/a&gt;. After a few hours, I had most of the job done. Without tricks and without needing to search the web to find what I want. The &lt;a href="https://www.11ty.dev/docs/" rel="noopener noreferrer"&gt;Eleventy documentation&lt;/a&gt; was just enough.&lt;/p&gt;

&lt;p&gt;I can't recommend it more. If you are planning to use a Static Site Generator, give Eleventy a try. Probably something simple is enough.&lt;/p&gt;

&lt;p&gt;You can find &lt;a href="https://github.com/gsferreira/gsferreira.github.com" rel="noopener noreferrer"&gt;here the source code for my blog&lt;/a&gt;. I hope it can be helpful.&lt;/p&gt;

</description>
      <category>eleventy</category>
      <category>jamstack</category>
      <category>webdev</category>
      <category>staticsites</category>
    </item>
    <item>
      <title>Speaking at a Virtual Conference</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Wed, 08 Jul 2020 20:40:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/speaking-at-a-virtual-conference-1af4</link>
      <guid>https://dev.to/gsferreira/speaking-at-a-virtual-conference-1af4</guid>
      <description>&lt;p&gt;I had the honour of having one of my talks selected to &lt;a href="https://ndcoslo.com" rel="noopener noreferrer"&gt;NDC Oslo 2020&lt;/a&gt;. I was looking forward to speaking at Oslo Spektrum for the first time. This has been a wish for a long time.&lt;/p&gt;

&lt;p&gt;Unfortunately, Coronavirus has destroyed those plans. NDC was converted into an Online Conference. With that, I was facing a new and different challenge: Virtual Conference Speaking.&lt;/p&gt;

&lt;p&gt;If you had the chance of speaking in a virtual conference, you know that it's not the same experience. Even if you are an experienced Speaker, you will find yourself with strange feelings.&lt;/p&gt;

&lt;p&gt;Fortunately, my talk went really well. So, this post serves to share what I have done to prepare myself. If you will be speaking in a virtual conference, this may be useful to you. My goal here is to describe what I've done and what I've learned. Hope it can be helpful to you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Video
&lt;/h3&gt;

&lt;p&gt;To me, image is an important part, and I didn't want to seem sloppy or unprofessional. Having a good camera is a must, but there are other things to consider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Camera
&lt;/h3&gt;

&lt;p&gt;I bought a &lt;a href="https://secure.logitech.com/en-gb/product/hd-pro-webcam-c920?crid=34" rel="noopener noreferrer"&gt;Logitech C920&lt;/a&gt;. The image improved when comparing to the laptop webcam. Besides that fact, I'm able to use a tripod to hold the camera and align it with my eyes.&lt;/p&gt;

&lt;p&gt;Aligning the camera with your eyes is useful. You will be speaking to a camera, so it's good to have it in the correct position. Level it with your eyes. It will feel more natural to you and to those that are watching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lighting
&lt;/h3&gt;

&lt;p&gt;Lighting is a small investment that makes a huge difference in the result. You can always use natural light. In my case, I bought a simple &lt;a href="https://www.aliexpress.com/item/33020816527.html" rel="noopener noreferrer"&gt;light ring from AliExpress&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;If you don't have a green screen, you need to take care of your background. Having a lot of things happening in the background can be quite distracting. Remember that your goal is to get the attention of the audience. They are at home, on their computer, and they can easily be distracted when compared to a conference room. &lt;/p&gt;

&lt;p&gt;I didn't want to give them another good reason for distraction by having shiny objects on the background.&lt;/p&gt;

&lt;p&gt;So, I tried to create a minimalist background with a small décor to have a better look and feel than a white wall. I also used a led strip that I had at home to have a backlight.&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%2Fgsferreira.com%2Fimages%2Fspeaking-at-a-virtual-conference-background.jpg" 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%2Fgsferreira.com%2Fimages%2Fspeaking-at-a-virtual-conference-background.jpg" alt="Background"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Microphone
&lt;/h3&gt;

&lt;p&gt;A decent microphone is a must. Using the laptop microphone is terrible. &lt;a href="https://dylanbeattie.net/2020/05/12/microphones.html" rel="noopener noreferrer"&gt;Dylan Beatie crafted an excellent blog post&lt;/a&gt; that can help. There you can also see the difference between different microphones.&lt;/p&gt;

&lt;p&gt;In my case, the microphone was a concern, especially because I live in a noisy place with a ton of traffic. It's impossible not to listen to background noise in my house. So, I decided to invest in a USB Dynamic Microphone (&lt;a href="http://www.samsontech.com/samson/products/microphones/usb-microphones/q2u/" rel="noopener noreferrer"&gt;SAMSON q2u&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So, I recommend you to find the quietest place you can and use a good microphone. At least, something other than your laptop microphone. If you don't have background noise, an inexpensive Condenser Microphone can improve your sound quality a lot.&lt;/p&gt;

&lt;p&gt;I've found really good information about Microphones, Cameras and Lighting &lt;a href="https://mattstauffer.com/blog/setting-up-your-webcam-lights-and-audio-for-remote-work-podcasting-videos-and-streaming" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Glare on Glasses
&lt;/h3&gt;

&lt;p&gt;If you use glasses like me, Lighting and positioning can be quite difficult. &lt;/p&gt;

&lt;p&gt;Facing direct light or bright screens was reflecting everything on my glasses.&lt;/p&gt;

&lt;p&gt;Light and screen reflexes can be quite distracting and don't feel natural. To overcome it, I position my screens on a diagonal line and the light ring from top to bottom. Besides that, I reduced the brightness of my screens. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=9NWAcK-wM80" rel="noopener noreferrer"&gt;This video&lt;/a&gt; was really helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stand-up
&lt;/h3&gt;

&lt;p&gt;By standing up, you will see that your voice will be clear and you will have a better posture. If not have a standing desk, improvise. I managed the same result by stacking up my kitchen table with my daughter´s playing table. &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%2Fgsferreira.com%2Fimages%2Fspeaking-at-a-virtual-conference-setup-macro.jpg" 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%2Fgsferreira.com%2Fimages%2Fspeaking-at-a-virtual-conference-setup-macro.jpg" alt="Setup - Stand-up"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Preparing
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rehearse&lt;/strong&gt; in the same environment and with the same setup that you will be using.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Record it and share it with your friends and colleagues. Ask for  &lt;a href="https://gsferreira.com/archive/2019/07/leading-improvement-through-honest-feedback/" rel="noopener noreferrer"&gt;honest feedback&lt;/a&gt;. Use the feedback to improve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rehearse&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that you have a Plan B&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What if your computer fails?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will you use a pointer? Do you have extra batteries?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rehearse&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rehearse&lt;/strong&gt; with the same software that you will be using in the day. Make yourself comfortable with it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No. Rehearse written so many times isn't a mistake. Honestly, &lt;strong&gt;the most important thing that you can do is rehearse&lt;/strong&gt;. Rehearse in the same conditions. Over and over again. By doing that you will feel more comfortable speaking to a camera.&lt;/p&gt;




&lt;h2&gt;
  
  
  The day
&lt;/h2&gt;

&lt;p&gt;The day has been really pleasant to me. After multiple hours of rehearsing, I have found that my muscle memory kicked in. I didn't have the chance to feel stressed. I was feeling prepared. It was showtime and I was enjoying it. Nevertheless, there are a few things that helped me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dress-up
&lt;/h3&gt;

&lt;p&gt;This will signal to your brain that it's time to do important stuff. &lt;/p&gt;

&lt;h3&gt;
  
  
  Barefoot
&lt;/h3&gt;

&lt;p&gt;Barefoot or use socks. You will find yourself more relaxed. You will also make less background noise with your feet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shutdown your doorbell
&lt;/h3&gt;

&lt;p&gt;Make the possible not to be interrupted. Delivery man ringing the doorbell, your partner walking by, your dog barking... Try to find a way to reduce the probability of something like that to happen. But, if it happens, embrace it. Play with it. Prepare a joke if you can.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hydrate
&lt;/h3&gt;

&lt;p&gt;Have a glass of water nearby. Do not forget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect to the audience
&lt;/h3&gt;

&lt;p&gt;You can't move around, so try to make your hands visible and use them to communicate. Use different tones of voice to keep people connected. Ask for feedback in the chat and try to keep an eye on the chat in case you are looking for a more interactive talk.&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%2Fgsferreira.com%2Fimages%2Fspeaking-at-a-virtual-conference-micro.jpg" 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%2Fgsferreira.com%2Fimages%2Fspeaking-at-a-virtual-conference-micro.jpg" alt="Setup - closeup"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Always remember that those attending, are there because they want to learn from you. So enjoy!&lt;/p&gt;

</description>
      <category>speaking</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>That flag argument is yelling at you</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Wed, 27 May 2020 23:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/that-flag-argument-is-yelling-at-you-3jl3</link>
      <guid>https://dev.to/gsferreira/that-flag-argument-is-yelling-at-you-3jl3</guid>
      <description>&lt;p&gt;Sometimes the code yells at you trying to warn you that something is wrong.&lt;/p&gt;

&lt;p&gt;Flag arguments are one of those cases. Adding a Boolean argument to condition the execution is an easy fix, but we are doing the wrong thing.&lt;/p&gt;

&lt;p&gt;By adding a flag argument to a function, it's clear that we are ignoring the Single Responsibility Principle. The code is yelling at us, trying to explain that. No doubt.&lt;/p&gt;

&lt;p&gt;Let's take a look. When a function has a flag argument, we will find something like this (or even worse) in the implementation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JC1-Lez3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/that-flag-argument-is-yelling-at-you-flag-argument.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JC1-Lez3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/that-flag-argument-is-yelling-at-you-flag-argument.png" alt="Flag Argument" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wouldn't be better to have something like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VzVI7LYT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/that-flag-argument-is-yelling-at-you-refactor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VzVI7LYT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/that-flag-argument-is-yelling-at-you-refactor.png" alt="Flag Argument Refactor" width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When writing code, remember that the goal is to simplify our client's life.&lt;/p&gt;

</description>
      <category>refactoring</category>
      <category>improvement</category>
      <category>cleancode</category>
      <category>simplicity</category>
    </item>
    <item>
      <title>Don't comment what your code is doing, comment the Why</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Thu, 21 May 2020 23:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/don-t-comment-what-your-code-is-doing-comment-the-why-4f24</link>
      <guid>https://dev.to/gsferreira/don-t-comment-what-your-code-is-doing-comment-the-why-4f24</guid>
      <description>&lt;p&gt;Code comments are a common topic of love/hate discussions. It's particularly interesting to see developers shifting opinion while experience grows.&lt;/p&gt;

&lt;p&gt;Code Comments are a good idea because we are writing them down to help others. Even to help the future self. But we use a lot of comments that don't help. This explains the Comments bad reputation nowadays.&lt;/p&gt;

&lt;p&gt;So, what can we do to improve our comments?&lt;/p&gt;

&lt;p&gt;I use a simple rule: &lt;strong&gt;Explain the Why, not the What.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I see a lot of Comments that are explaining what the code is doing. That doesn't help. &lt;br&gt;
The effort that we put to write a Comment must be invested refactoring the code (&lt;a href="https://gsferreira.com/archive/2019/10/a-simple-tip-to-improve-your-code-maintainability-decompose-if-statements-into-methods"&gt;this is a good starting point&lt;/a&gt;). &lt;br&gt;
&lt;strong&gt;When we need to describe the What is because the code isn't readable at all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's also pretty common to have obvious Comments. All we have seen that &lt;em&gt;"// Get a Customer"&lt;/em&gt; comment in a &lt;em&gt;"GetCustomer"&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;Those comments don't bring value. They raise the cognitive load required to read and maintain the code.&lt;/p&gt;

&lt;p&gt;So, the idea is to &lt;strong&gt;let the code speak for himself&lt;/strong&gt;. We only write comments, when we need to explain Why we have done something.&lt;/p&gt;

&lt;p&gt;It's useful to understand why a piece of code was written in a certain way. &lt;br&gt;
Those Why comments can help us out to understand that there's a particular corner case, or the reason for the followed approach, or that, because of a bug (Link the bug from the comment), we need to do that. &lt;br&gt;
Those are a few examples, but you get the point.&lt;/p&gt;

&lt;p&gt;Our code must be self-describing, but sometimes, we need to explain the Why.&lt;/p&gt;

&lt;p&gt;And remember: &lt;strong&gt;don't Comment the code that you don't need anymore. Throw it away.&lt;/strong&gt; In case you need it, it will be at the source control.&lt;/p&gt;

</description>
      <category>refactoring</category>
      <category>improvement</category>
      <category>cleancode</category>
      <category>simplicity</category>
    </item>
    <item>
      <title>Manage your code as a successful restaurant</title>
      <dc:creator>Guilherme Ferreira</dc:creator>
      <pubDate>Fri, 15 May 2020 05:00:00 +0000</pubDate>
      <link>https://dev.to/gsferreira/manage-your-code-as-a-successful-restaurant-48ca</link>
      <guid>https://dev.to/gsferreira/manage-your-code-as-a-successful-restaurant-48ca</guid>
      <description>&lt;p&gt;Have you ever noticed that a successful restaurant has a shorter menu? Especially when compared to those who are struggling.&lt;/p&gt;

&lt;p&gt;Why?! &lt;strong&gt;Simplicity!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you keep things simple, you focus on fewer things. You give your best and you can focus your effort. You can try to improve and perfect all details.&lt;/p&gt;

&lt;p&gt;But, when life doesn't work as we expect, we start throwing new dishes into the menu. Expecting to please everyone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3n1_CEfB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/manage-your-code-as-a-successful-restaurant-complex-menu.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3n1_CEfB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gsferreira.com/images/manage-your-code-as-a-successful-restaurant-complex-menu.jpeg" alt="Complex menu" width="714" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Spoiler alert: When you build something to everyone, you build it to nobody.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't just the restaurants' reality. We see that in software too. When trying to convince new customers, throwing features into a product is usually the way to go. And it's hard to find a Product Owner who doesn't fight to have the team focused on new features.&lt;/p&gt;

&lt;p&gt;What we should all be doing is to &lt;strong&gt;focus on what we have and what customers love.&lt;/strong&gt; Those features have a margin to improve. &lt;strong&gt;Don't bring a new feature into the product just because a customer needs it. Bring it because is inevitable.&lt;/strong&gt; Because it's obvious that your software will be so much better. Because you believe that you are in an especial condition and nobody can do it better than you. And don't forget to throw away stuff that doesn't "spark joy". &lt;/p&gt;

&lt;p&gt;We can expand this concept to multiple software parts. High level, to a low level. Decompose the code in smaller objects or functions. Create focused "restaurants" specialized in one task. If you want Mexican food, you don't look for an Italian restaurant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat your code as a garden, which deserves care and dedication.&lt;/strong&gt; Don't write it and ignore it until a bug arises. &lt;/p&gt;

&lt;p&gt;A chef who creates new dishes every single night will create a few stunning dishes for sure. But also, a vast number of massive failures.&lt;/p&gt;

&lt;p&gt;Having a continuous improvement mindset is what makes us better than the rest.&lt;/p&gt;

</description>
      <category>improvement</category>
      <category>cleancode</category>
      <category>simplicity</category>
    </item>
  </channel>
</rss>
