Gui FerreiraSoftware Architect and a minimalist aspirant. passionate by product development and a continuous improvement enthusiast.2023-12-19T00:00:00-00:00https://guiferreira.me/Gui Ferreiragui@guiferreira.me3 KafkaFlow Features Hard to Ignore2023-12-19T00:00:00-00:00https://guiferreira.me/archive/2023/3-kafkaflow-features-hard-to-ignore/<p>https://www.youtube.com/watch?v=v-aFkzlBVpE</p>
<p>If you are a .NET developer working with <a href="https://kafka.apache.org/">Apache Kafka</a>, <a href="https://github.com/farfetch/kafkaflow">KafkaFlow</a> is a framework worth exploring.</p>
<p>Here, you can find three compelling features that make KafkaFlow stand out and deserve your attention.</p>
<h2>1️⃣ Multi-Threaded Consumers</h2>
<p>In the typical Apache Kafka infrastructure, you will find topics with multiple partitions. If you observe a lag and need to increase the consumption throughput, you will do it by bringing new consumers into the consumer group. That strategy will work up to a point. The number of partitions works as an upper limit, and having more consumers in a consumer group than the number of partitions is useless. However, traditional single-threaded consumers may result in underutilized infrastructure resources.</p>
<p>KafkaFlow addresses this by offering <a href="https://farfetch.github.io/kafkaflow/docs/guides/consumers/">multi-threading within a single consumer</a>. This feature allows your consumer to delegate work to multiple workers, enabling parallel processing.</p>
<p>If that didn't catch your attention, let me tell you that even with multiple workers, KafkaFlow maintains message order. And all of that is perfectly encapsulated under a simple configuration.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// KafkaFlow Configuration</span><br>services<span class="token punctuation">.</span><span class="token function">AddKafka</span><span class="token punctuation">(</span>kafka <span class="token operator">=></span> kafka<br> <span class="token punctuation">.</span><span class="token function">AddCluster</span><span class="token punctuation">(</span>cluster <span class="token operator">=></span> cluster<br> <span class="token punctuation">.</span><span class="token function">WithBrokers</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token string">"localhost:9092"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddConsumer</span><span class="token punctuation">(</span>consumer <span class="token operator">=></span> consumer<br> <span class="token punctuation">.</span><span class="token function">Topic</span><span class="token punctuation">(</span><span class="token string">"topic-name"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithGroupId</span><span class="token punctuation">(</span><span class="token string">"group-name"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithBufferSize</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithWorkersCount</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span> <span class="token comment">// Define the number of workers</span><br> <span class="token range operator">..</span><span class="token punctuation">.</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">)</span><br><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This feature offers another option to scale consumption and use the infrastructure efficiently.</p>
<h2>2️⃣ Administration API and Dashboard</h2>
<p>KafkaFlow offers an <a href="https://farfetch.github.io/kafkaflow/docs/guides/admin/">Administration API and a Dashboard</a>, providing a convenient way to manage your Apache Kafka consumers.</p>
<p><img src="https://guiferreira.me/images/archive/kafkaflow/kafkaflow-dashboard-consumer-group.png" alt="KafkaFlow / Dashboard - Consumer Group"></p>
<p>To set up the Dashboard, install the <a href="https://farfetch.github.io/kafkaflow/docs/guides/admin/dashboard#adding-the-dashboard">KafkaFlow Dashboard package</a>, define the topic for administration messages, and call the <code>UseKafkaFlowDashboard</code> method in your web application.</p>
<pre class="language-csharp"><code class="language-csharp">builder<span class="token punctuation">.</span>Services<br> <span class="token punctuation">.</span><span class="token function">AddKafka</span><span class="token punctuation">(</span>kafka <span class="token operator">=></span> kafka<br> <span class="token punctuation">.</span><span class="token function">AddCluster</span><span class="token punctuation">(</span>cluster <span class="token operator">=></span> cluster<br> <span class="token punctuation">.</span><span class="token function">WithBrokers</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token string">"localhost:9092"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddConsumer</span><span class="token punctuation">(</span>consumer <span class="token operator">=></span> consumer<br> <span class="token range operator">..</span><span class="token punctuation">.</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">EnableAdminMessages</span><span class="token punctuation">(</span><span class="token string">"kafka-flow.admin"</span><span class="token punctuation">)</span> <span class="token comment">// Administration messages topic</span><br> <span class="token punctuation">.</span><span class="token function">EnableTelemetry</span><span class="token punctuation">(</span><span class="token string">"kafka-flow.admin"</span><span class="token punctuation">)</span><br> <span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddControllers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> app <span class="token operator">=</span> builder<span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>app<span class="token punctuation">.</span><span class="token function">MapControllers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>app<span class="token punctuation">.</span><span class="token function">UseKafkaFlowDashboard</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Enable Dashboard</span></code></pre>
<p>Accessing the Dashboard through a web application allows you to administrate consumers. The API exposes endpoints for various actions, such as pausing, starting, and stopping consumers, making it a valuable operational tool. All those actions are not only available through the Dashboard UI but also through a <a href="https://farfetch.github.io/kafkaflow/docs/guides/admin/web-api#consumers">C# client</a>.</p>
<h2>3️⃣ Batch Consuming</h2>
<p>While Kafka is excellent for handling real-time systems, processing one message at a time may not always be ideal. KafkaFlow introduces <a href="https://farfetch.github.io/kafkaflow/docs/guides/middlewares/batch-consume-middleware">Batch Consuming</a>, a useful feature in scenarios such as when you have devices producing numerous events and need to process them in bulk.</p>
<p>To enable Batch Consuming, install the corresponding package and add a middleware in your consumer configuration. Specify the batch size and batch timeout to control when the batch should be forwarded to the next middleware.</p>
<pre class="language-csharp"><code class="language-csharp">services<span class="token punctuation">.</span><span class="token function">AddKafka</span><span class="token punctuation">(</span>kafka <span class="token operator">=></span> kafka<br> <span class="token punctuation">.</span><span class="token function">AddCluster</span><span class="token punctuation">(</span>cluster <span class="token operator">=></span> cluster<br> <span class="token punctuation">.</span><span class="token function">WithBrokers</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token string">"localhost:9092"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddConsumer</span><span class="token punctuation">(</span><br> consumerBuilder <span class="token operator">=></span> consumerBuilder<br> <span class="token range operator">..</span><span class="token punctuation">.</span><br> <span class="token punctuation">.</span><span class="token function">AddMiddlewares</span><span class="token punctuation">(</span><br> middlewares <span class="token operator">=></span> middlewares<br> <span class="token range operator">..</span><span class="token punctuation">.</span><br> <span class="token punctuation">.</span><span class="token function">AddBatching</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// Configuration of the BatchConsumeMiddleware</span><br> <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Add</span><span class="token generic class-name"><span class="token punctuation"><</span>HandlingMiddleware<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Middleware to process the batch</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">)</span><br><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This feature allows KafkaFlow to collect messages until either the batch size or the defined time is reached, forwarding the batch to the next middleware. It is particularly handy for scenarios where you want to store events in a file or a database in a bulk change.</p>
<p>In conclusion, KafkaFlow brings valuable features for .NET developers working with Apache Kafka. Whether you need multi-threaded consumers, an Administration API with a Dashboard, or Batch-consuming capabilities, KafkaFlow provides a user-friendly and powerful solution. Consider adopting KafkaFlow as your .NET Kafka client to simplify your Kafka-based applications.</p>
A BETTER Way to Kafka Event-Driven Applications with C#2023-12-13T00:00:00-00:00https://guiferreira.me/archive/2023/a-better-way-to-kafka-event-driven-applications-with-csharp/<p>https://youtu.be/4e18DZkf-m0?si=QMgwWgQFKFZqRbD3</p>
<p>Building event-driven applications on top of Apache Kafka can be hard.
Using the <a href="https://github.com/confluentinc/confluent-kafka-dotnet">.NET client library by Confluent</a> can give a lot of work.</p>
<p>There are many patterns in this type of application and I want to show you a framework that will help you build your event-driven applications on top of Apache Kafka in a simple and maintainable way.</p>
<p>The framework that I want to show you is <a href="https://github.com/farfetch/kafkaflow">KafkaFlow</a> which is an Open-Source project developed by <a href="https://farfetchtechblog.com/">FARFETCH</a>.</p>
<p>KafkaFlow will help us simplify the process of building event-driven applications on Apache Kafka in a straightforward and maintainable manner.</p>
<h2>Introduction to KafkaFlow</h2>
<p>KafkaFlow is built on top of the Confluent Kafka client, providing a set of features to enhance the development of event-driven applications. These features simplify working with the Confluent client library, making your development process more efficient and maintainable.</p>
<h3>Key Features of KafkaFlow</h3>
<p>Before diving into the code, let's explore some of the key features offered by KafkaFlow, as outlined in the documentation:</p>
<ul>
<li><strong>Dependency Injection:</strong> KafkaFlow allows you to define the configuration of your relationship with Kafka through dependency injection, streamlining the setup process.</li>
<li><strong>Middleware:</strong> KafkaFlow introduces the concept of middleware, offering a way to apply serialization and other processing logic when publishing or consuming messages.</li>
<li><strong>Batch Consume:</strong> A useful feature for consuming messages in batches, allowing efficient processing and reducing the overhead of handling individual messages.</li>
<li><strong>Multithreaded Consumer:</strong> KafkaFlow supports multithreaded consumers, enabling parallel processing and scalability within a single application instance.</li>
<li><strong>Management API and Dashboard:</strong> KafkaFlow provides a management API and a dashboard for monitoring and managing your Kafka-based applications.</li>
</ul>
<p>Now, let's dive into a practical example to see how KafkaFlow can be applied to build a simple event-driven application.</p>
<h2>Building a Task Management Application</h2>
<p>In this example, we'll create a task management application with a REST API that will produce messages and two consumer applications for handling statistics and notifications.</p>
<p><em><strong>Note:</strong> This is not an extensive tutorial. We will focus on how to use KafkaFlow.</em></p>
<h3>Setting Up KafkaFlow</h3>
<p>To get started, create a simple ASP.NET API with an endpoint to create tasks.</p>
<p>You can find here how to do it using <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis">Minimal APIs</a>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// Map endpoint</span><br>app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">"/add"</span><span class="token punctuation">,</span> RequestHandler<span class="token punctuation">.</span>HandleAsync<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Request</span><br><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">AddTaskRequest</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> Title<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">?</span></span> Description<span class="token punctuation">,</span> <span class="token class-name">DateOnly<span class="token punctuation">?</span></span> DueDate<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Handler</span><br><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">RequestHandler</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IResult<span class="token punctuation">></span></span> <span class="token function">HandleAsync</span><span class="token punctuation">(</span><br> <span class="token class-name">AddTaskRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">CancellationToken</span> cancellationToken<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token comment">// TODO</span><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Accepted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now, let's move on to produce a new Kafka message when that endpoint is invoked.</p>
<p>To get started, install the KafkaFlow NuGet packages.</p>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> package KafkaFlow --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.LogHandler.Microsoft --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.Microsoft.DependencyInjection --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.Serializer.JsonCore --version <span class="token number">3.0</span>.1</code></pre>
<p>Configure KafkaFlow through dependency injection, defining the Kafka cluster's brokers and the topic to be used.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// Program.cs (or Startup.cs)</span><br>builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddKafka</span><span class="token punctuation">(</span><br> kafka <span class="token operator">=></span> kafka<br> <span class="token punctuation">.</span><span class="token function">AddCluster</span><span class="token punctuation">(</span>cluster<span class="token operator">=></span><br> <span class="token punctuation">{</span><br> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> topicName <span class="token operator">=</span> <span class="token string">"tasks"</span><span class="token punctuation">;</span><br> cluster<br> <span class="token punctuation">.</span><span class="token function">WithBrokers</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token string">"localhost:9092"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">CreateTopicIfNotExists</span><span class="token punctuation">(</span>topicName<span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddProducer</span><span class="token punctuation">(</span><br> <span class="token string">"publish-task"</span><span class="token punctuation">,</span><br> producer <span class="token operator">=></span> producer<br> <span class="token punctuation">.</span><span class="token function">DefaultTopic</span><span class="token punctuation">(</span>topicName<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddMiddlewares</span><span class="token punctuation">(</span>middlewares<span class="token operator">=></span><br> middlewares<br> <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddSerializer</span><span class="token generic class-name"><span class="token punctuation"><</span>JsonCoreSerializer<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><br><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>In this configuration, we've defined a Kafka cluster with a producer named "publish-task". We are also defining the target topic and using <code>System.Text.Json</code> to serialize the message.</p>
<h3>Implementing the Task API (Producer)</h3>
<p>Next, let's update our API endpoint for producing task messages. This API will act as the producer, publishing messages to the Kafka topic.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// RequestHandler.cs</span><br><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">RequestHandler</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IResult<span class="token punctuation">></span></span> <span class="token function">HandleAsync</span><span class="token punctuation">(</span><br> <span class="token class-name">IProducerAccessor</span> producerAccessor<span class="token punctuation">,</span><br> <span class="token class-name">AddTaskRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">CancellationToken</span> cancellationToken<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> producer <span class="token operator">=</span> producerAccessor<span class="token punctuation">.</span><span class="token function">GetProducer</span><span class="token punctuation">(</span><span class="token string">"publish-task"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">await</span> producer<span class="token punctuation">.</span><span class="token function">ProduceAsync</span><span class="token punctuation">(</span><br> <span class="token keyword">null</span><span class="token punctuation">,</span><br> request<br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Accepted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>In this example, the <code>RequestHandler</code> uses the KafkaFlow <code>IProducerAccessor</code> to get the configured producer by name and then publish messages to the Kafka topic when a new task is added.</p>
<h3>Implementing a Notifications Consumer</h3>
<p>Start by creating a simple console application.</p>
<p>Now, install KafkaFlow packages.</p>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> package KafkaFlow --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.Extensions.Hosting --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.LogHandler.Microsoft --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.Microsoft.DependencyInjection --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.Serializer.JsonCore --version <span class="token number">3.0</span>.1<br>dotnet <span class="token function">add</span> package KafkaFlow.TypedHandler --version <span class="token number">3.0</span>.1<br><br>dotnet <span class="token function">add</span> package Microsoft.Extensions.Logging.Console</code></pre>
<p>Now, let's add a reference to the Tasks API, so we can share the message contract.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ItemGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ProjectReference</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..\TaskApi\TaskApi.csproj<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ItemGroup</span><span class="token punctuation">></span></span></code></pre>
<p>Let's start by defining the boilerplate of our <code>Program.cs</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>Extensions<span class="token punctuation">.</span>DependencyInjection</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>Extensions<span class="token punctuation">.</span>Logging</span><span class="token punctuation">;</span><br><br><span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> topicName <span class="token operator">=</span> <span class="token string">"tasks"</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> services <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ServiceCollection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>services<span class="token punctuation">.</span><span class="token function">AddLogging</span><span class="token punctuation">(</span>configure <span class="token operator">=></span> configure<span class="token punctuation">.</span><span class="token function">AddConsole</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// TODO - KafkaFlow configuration</span><br><br>Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Press key to exit"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>Console<span class="token punctuation">.</span><span class="token function">ReadKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now we can configure the consumer.</p>
<pre class="language-csharp"><code class="language-csharp">services<span class="token punctuation">.</span><span class="token function">AddKafkaFlowHostedService</span><span class="token punctuation">(</span><br> kafka <span class="token operator">=></span> kafka<br> <span class="token punctuation">.</span><span class="token function">UseMicrosoftLog</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddCluster</span><span class="token punctuation">(</span>cluster <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> cluster<br> <span class="token punctuation">.</span><span class="token function">WithBrokers</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token string">"localhost:9092"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddConsumer</span><span class="token punctuation">(</span>consumer <span class="token operator">=></span><br> consumer<br> <span class="token punctuation">.</span><span class="token function">Topic</span><span class="token punctuation">(</span>topicName<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithGroupId</span><span class="token punctuation">(</span><span class="token string">"notifications"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithBufferSize</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithWorkersCount</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithAutoOffsetReset</span><span class="token punctuation">(</span>KafkaFlow<span class="token punctuation">.</span>AutoOffsetReset<span class="token punctuation">.</span>Earliest<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddMiddlewares</span><span class="token punctuation">(</span>middlewares <span class="token operator">=></span> middlewares<br> <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddDeserializer</span><span class="token generic class-name"><span class="token punctuation"><</span>JsonCoreDeserializer<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddTypedHandlers</span><span class="token punctuation">(</span>handlers <span class="token operator">=></span><br> handlers<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddHandler</span><span class="token generic class-name"><span class="token punctuation"><</span>AddTaskHandler<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><br><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Notice that in this example we are using the method <code>AddKafkaFlowHostedService</code>. This will register a hosted service for us.</p>
<p>One interesting part of it is the concept of Middlewares. KafkaFlow uses Middlewares as a kind of Chain of Responsibility. Each Middleware can handle, transform or delegate a message. In this case, we are first transforming the message by deserializing it, and then we forward it to a Typed Handler middleware. If you are familiar with MediatR, you automatically know what Typed Handlers are. The middleware will try to find a Handler capable of handling that message type.</p>
<p>That takes us to the next step. Creating the handler. So, create a new class and implement the <code>IMessageHandler</code> interface.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// AddTaskHandler.cs</span><br><span class="token keyword">using</span> <span class="token namespace">KafkaFlow</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">KafkaFlow<span class="token punctuation">.</span>TypedHandler</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>Extensions<span class="token punctuation">.</span>Logging</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AddTaskHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IMessageHandler<span class="token punctuation"><</span>AddTaskRequest<span class="token punctuation">></span></span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">ILogger<span class="token punctuation"><</span>AddTaskHandler<span class="token punctuation">></span></span> _logger<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token function">AddTaskHandler</span><span class="token punctuation">(</span><span class="token class-name">ILogger<span class="token punctuation"><</span>AddTaskHandler<span class="token punctuation">></span></span> logger<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _logger <span class="token operator">=</span> logger<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">Task</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">IMessageContext</span> context<span class="token punctuation">,</span> <span class="token class-name">AddTaskRequest</span> message<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>message<span class="token punctuation">.</span>DueDate<span class="token punctuation">.</span>HasValue<span class="token punctuation">)</span><br> _logger<span class="token punctuation">.</span><span class="token function">LogInformation</span><span class="token punctuation">(</span><span class="token string">"New Task {Title} scheduled to {DueDate}"</span><span class="token punctuation">,</span><br> message<span class="token punctuation">.</span>Title<span class="token punctuation">,</span><br> message<span class="token punctuation">.</span>DueDate<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> Task<span class="token punctuation">.</span>CompletedTask<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>The <code>Handle</code> method is invoked whenever a message received is deserialized to the type <code>AddTaskRequest</code>.</p>
<h3>Running the Application</h3>
<p>To run the application, build the service provider, create a bus, and start the bus.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// Program.cs</span><br><br><span class="token comment">// after adding KafkaFlow configuration...</span><br><span class="token class-name"><span class="token keyword">var</span></span> provider <span class="token operator">=</span> services<span class="token punctuation">.</span><span class="token function">BuildServiceProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> bus <span class="token operator">=</span> provider<span class="token punctuation">.</span><span class="token function">CreateKafkaBus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">await</span> bus<span class="token punctuation">.</span><span class="token function">StartAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Press key to exit"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>Console<span class="token punctuation">.</span><span class="token function">ReadKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This code ensures that the KafkaFlow message bus is started, allowing the application to send and receive messages.</p>
<h3>Implementing a Statistics Consumer</h3>
<p>I want to show you one more KafkaFlow feature.
So, create a new console application for Statistics. Add the same packages you added to the Notifications application. And update the <code>Program.cs</code> with the following example.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">KafkaFlow</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">KafkaFlow<span class="token punctuation">.</span>Serializer</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>Extensions<span class="token punctuation">.</span>DependencyInjection</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>Extensions<span class="token punctuation">.</span>Logging</span><span class="token punctuation">;</span><br><br><span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> topicName <span class="token operator">=</span> <span class="token string">"tasks"</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> services <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ServiceCollection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>services<span class="token punctuation">.</span><span class="token function">AddLogging</span><span class="token punctuation">(</span>configure <span class="token operator">=></span> configure<span class="token punctuation">.</span><span class="token function">AddConsole</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>services<span class="token punctuation">.</span><span class="token function">AddKafkaFlowHostedService</span><span class="token punctuation">(</span><br> kafka <span class="token operator">=></span> kafka<br> <span class="token punctuation">.</span><span class="token function">UseMicrosoftLog</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddCluster</span><span class="token punctuation">(</span>cluster <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> cluster<br> <span class="token punctuation">.</span><span class="token function">WithBrokers</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token string">"localhost:9092"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddConsumer</span><span class="token punctuation">(</span>consumer <span class="token operator">=></span><br> consumer<br> <span class="token punctuation">.</span><span class="token function">Topic</span><span class="token punctuation">(</span>topicName<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithGroupId</span><span class="token punctuation">(</span><span class="token string">"statistics"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithBufferSize</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithWorkersCount</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithAutoOffsetReset</span><span class="token punctuation">(</span>KafkaFlow<span class="token punctuation">.</span>AutoOffsetReset<span class="token punctuation">.</span>Earliest<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddMiddlewares</span><span class="token punctuation">(</span>middlewares <span class="token operator">=></span> middlewares<br> <span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddDeserializer</span><span class="token generic class-name"><span class="token punctuation"><</span>JsonCoreDeserializer<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token comment">// TODO</span><br> <span class="token punctuation">)</span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><br><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> provider <span class="token operator">=</span> services<span class="token punctuation">.</span><span class="token function">BuildServiceProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> bus <span class="token operator">=</span> provider<span class="token punctuation">.</span><span class="token function">CreateKafkaBus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">await</span> bus<span class="token punctuation">.</span><span class="token function">StartAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Press key to exit"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>Console<span class="token punctuation">.</span><span class="token function">ReadKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4>Implementing a Batch Consumer</h4>
<p>Now, let's take a look into other interesting Feature. Batch consuming.
In many use cases, it's worth processing messages in batch to optimize the system.</p>
<p>KafkaFlow gives you an easy way to do that through a middleware.</p>
<p>Go ahead and install the BatchConsume package.</p>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> package KafkaFlow.BatchConsume --version <span class="token number">3.0</span>.1</code></pre>
<p>Now, let's go back to the <code>Program.cs</code> and right after the <code>AddDeserializer</code> middleware, we will configure batching.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">.</span><span class="token function">AddBatching</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Add</span><span class="token generic class-name"><span class="token punctuation"><</span>StatisticsMiddleware<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>You do it by configuring the batch size and the maximum time to wait. Now, KafkaFlow will forward to the next middleware, the <code>StatisticsMiddleware</code> a batch of messages, every 5 seconds or every time the batch has 100 messages.</p>
<p>Once you have that, you can process the batch at once.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">KafkaFlow</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">KafkaFlow<span class="token punctuation">.</span>BatchConsume</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">StatisticsMiddleware</span><span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IMessageMiddleware</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name"><span class="token keyword">int</span></span> _total <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">Task</span> <span class="token function">Invoke</span><span class="token punctuation">(</span><span class="token class-name">IMessageContext</span> context<span class="token punctuation">,</span> <span class="token class-name">MiddlewareDelegate</span> next<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> batch <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">GetMessagesBatch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> _total <span class="token operator">+=</span> batch<span class="token punctuation">.</span>Count<span class="token punctuation">;</span><br><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"Current Total: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">_total</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> Task<span class="token punctuation">.</span>CompletedTask<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now we can run our applications and send an HTTP request to the Tasks API, adding tasks to the system. Monitor the console output of the consumers (notifications and statistics) to observe the processing of messages.</p>
<h2>Conclusion</h2>
<p>In this tutorial, we explored the KafkaFlow framework to simplify the development of event-driven applications on Apache Kafka. We have seen how simple it is to configure it through the fluent API.</p>
<p>We have also seen how to take advantage of some advanced features like batching.
Consider exploring additional features of KafkaFlow, such as the Administration Dashboard and API. As you delve deeper into KafkaFlow, you'll find it to be a valuable tool for building robust and efficient event-driven applications.</p>
<p>Remember to check the KafkaFlow documentation for more in-depth information on its features and capabilities.</p>
Refactoring C# Code with the Chain of Responsibility Design Pattern2023-05-26T00:00:00-00:00https://guiferreira.me/archive/2023/refactoring-csharp-code-with-the-chain-of-responsibility-design-pattern/<p>https://www.youtube.com/watch?v=SF305UAQTXI</p>
<p>Imagine calling a support line and being transferred to multiple people until your problem is resolved. This everyday concept of "passing the responsibility" also exists in the world of programming as a <a href="https://refactoring.guru/design-patterns/behavioral-patterns">behavioral design pattern</a> called the Chain of Responsibility. <strong>This pattern is particularly useful when refactoring code, as it helps with decoupling and segregation of responsibilities.</strong></p>
<p>By the way, if you've worked with ASP.NET, you might already be familiar with the Chain of Responsibility pattern.</p>
<p>In this blog post, I will share with you how to apply the Chain of Responsibility design pattern to refactor C# code. Hopefully 🤞, we will end up with more maintainable code. We will focus on a specific scenario where we have a function responsible for determining if an order qualifies for a discount. This function is used by a sales team to apply discounts within a specific screen of an application.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">double</span></span> proposedDiscount<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>_vipClients<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Client<span class="token punctuation">.</span>Code<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>_stockClearanceProducts<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Code<span class="token punctuation">)</span> <span class="token operator">&&</span> proposedDiscount <span class="token operator"><</span> <span class="token number">0.80</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span><span class="token punctuation">(</span>proposedDiscount <span class="token operator"><</span> <span class="token number">0.30</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2>Understanding the Need for the Chain of Responsibility Design Pattern</h2>
<p><strong>As the business grows and more discount rules are added, the code becomes harder to maintain</strong>. The Class responsible for discount approval becomes overloaded with responsibilities, making it difficult for developers to modify it. This is where the Chain of Responsibility design pattern comes into play. It helps segregate responsibilities and decouples the discount approval engine from the consumers.</p>
<p>To illustrate the application of the pattern, let's consider a discount approval process involving multiple rules.</p>
<ul>
<li>First, we check if the customer is a VIP client.</li>
<li>Then, we verify if the product is part of a stock clearance and if the discount is below a specified value.</li>
<li>Finally, we evaluate an overall discount rule.</li>
</ul>
<p>During this process, we can return and break the cycle at any point, avoiding the need to check subsequent rules. Each handler in the chain performs its task and delegates the request to the next handler.</p>
<h2>Refactoring with the Chain of Responsibility Pattern</h2>
<p>To begin refactoring the code using the Chain of Responsibility pattern, we'll follow a structured approach.</p>
<p>First, we create a folder named <code>Approvals</code> to organize the source code related to the chain of responsibility. This organization helps developers locate and understand the code easily.</p>
<p>Next, we create a base class named <code>DiscountApproval</code>. In this example, we will do it in a different namespace to minimize changes in the existing code.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DiscountApproval</span><br><span class="token punctuation">{</span><br><br><span class="token punctuation">}</span></code></pre>
<p>This base class will manage the request and establish guidelines for the handlers implementing it. We add a <code>SetNext</code> method and a field to store the next element in the chain.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DiscountApproval</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token class-name">DiscountApproval<span class="token punctuation">?</span></span> _nextHandler<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">DiscountApproval</span> <span class="token function">SetNext</span><span class="token punctuation">(</span><span class="token class-name">DiscountApproval</span> handler<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _nextHandler <span class="token operator">=</span> handler<span class="token punctuation">;</span><br> <span class="token keyword">return</span> handler<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Additionally, we implement a method to handle the discount approval request based on the order information.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DiscountApproval</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token class-name">DiscountApproval<span class="token punctuation">?</span></span> _nextHandler<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">DiscountApproval</span> <span class="token function">SetNext</span><span class="token punctuation">(</span><span class="token class-name">DiscountApproval</span> handler<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _nextHandler <span class="token operator">=</span> handler<span class="token punctuation">;</span><br> <span class="token keyword">return</span> handler<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">double</span></span> proposedDiscount<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token comment">// ...</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>The key concept of the Chain of Responsibility pattern is that each handler performs its task and delegates the request to the next handler in the chain.</p>
<p>In the base class, we define the behavior for handling the next element. If there is a next element, it delegates the request to that element; otherwise, it returns false to indicate that the discount is not approved.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DiscountApproval</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token class-name">DiscountApproval<span class="token punctuation">?</span></span> _nextHandler<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">DiscountApproval</span> <span class="token function">SetNext</span><span class="token punctuation">(</span><span class="token class-name">DiscountApproval</span> handler<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _nextHandler <span class="token operator">=</span> handler<span class="token punctuation">;</span><br> <span class="token keyword">return</span> handler<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">double</span></span> proposedDiscount<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> _nextHandler<span class="token punctuation">?.</span><span class="token function">Handle</span><span class="token punctuation">(</span>order<span class="token punctuation">,</span> proposedDiscount<span class="token punctuation">)</span> <span class="token operator">??</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Once the base class is established, we proceed to implement specific discount approval rules. For example, we create a new class for VIP client discount approval by inheriting from the base class and overriding the handle method. We copy the relevant code from the old source code into the new handler. The handler checks the rule and breaks the chain if the rule matches, approving the discount. If the rule doesn't match, it delegates the execution to the next handler.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">VipDiscountApproval</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">DiscountApproval</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">HashSet<span class="token punctuation"><</span><span class="token keyword">string</span><span class="token punctuation">></span></span> _vipClients <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token comment">//...</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">double</span></span> proposedDiscount<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>_vipClients<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Client<span class="token punctuation">.</span>Code<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">Handle</span><span class="token punctuation">(</span>order<span class="token punctuation">,</span> proposedDiscount<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Similarly, we implement handlers for other discount approval rules, such as stock clearance discounts and global discounts. Each handler overrides the base class, copies the relevant source code, and follows the chain of responsibility pattern.</p>
<h2>Enhancing Code Efficiency and Flexibility</h2>
<p>After refactoring the code, we remove the old approach by deleting the old file. This might cause the tests to fail, but since we used the same naming under a separate namespace, fixing the tests is straightforward.</p>
<p>However, you will notice that some tests related to the "reject" scenario pass while others fail. This is because, in the given chain, when there is no subsequent element, it returns <code>false</code>.</p>
<p>Next, we configure the responsibility chain to ensure that all discount approval rules are evaluated. In the chain, we set the next element to the VIP discount handler. After the execution of the VIP discount handler, if the approval hasn't been granted yet, the request is forwarded to the stock clearance handler. Finally, if none of the previous handlers approve the discount, the request is passed to the global discount handler.</p>
<pre class="language-csharp"><code class="language-csharp">_handler <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">DiscountApproval</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>_handler<br> <span class="token punctuation">.</span><span class="token function">SetNext</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">VipDiscountApproval</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">SetNext</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">StockClearanceDiscountApproval</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">SetNext</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">GlobalDiscountApproval</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>This approach provides flexibility to introduce new handlers in the evaluation chain, change their order, load them dynamically, and perform various tasks without constantly rewriting the source code.</strong></p>
<h2>Wrapping Up</h2>
<p>The Chain of Responsibility design pattern is a powerful tool for improving code efficiency and managing complex scenarios like a rule engine.</p>
<p>By applying this pattern, we achieve better decoupling and segregation of responsibilities, resulting in a more maintainable and flexible code.</p>
<p>In our refactoring example, we demonstrated how to implement the Chain of Responsibility pattern to manage discount approval in a C# codebase. Each discount rule is encapsulated within a separate handler, and the responsibility is passed from one handler to another until the discount is approved or rejected.</p>
<p>If you have experience using the Chain of Responsibility pattern or other design patterns in your projects, I would love to hear your thoughts and insights.</p>
<p>Keep it Simple 🌱</p>
Discover an Easy Trick to Simplify Your C# Test Assertions!2023-05-19T00:00:00-00:00https://guiferreira.me/archive/2023/discover-an-easy-trick-to-simplify-your-csharp-test-assertions/<p>https://www.youtube.com/watch?v=vERw8hyTiQk</p>
<p>Can we all agree that this test assertion is beautiful and easy to read?</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContainProduct</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>And<br> <span class="token punctuation">.</span><span class="token function">ContainProduct</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>But how can we reach this level of clarity when starting from something like this?</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Contain</span><span class="token punctuation">(</span>line<span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name <span class="token operator">==</span> <span class="token string">"Shoes"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Which<br> <span class="token punctuation">.</span>Quantity<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Contain</span><span class="token punctuation">(</span>line<span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name <span class="token operator">==</span> <span class="token string">"T-Shirt"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Which<br> <span class="token punctuation">.</span>Quantity<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The key to achieving this lies in <strong>expressing the assertion using domain-specific concepts</strong>. Once you have figured out the domain-specific expression, it's just a matter of implementing it using your assertion library.</p>
<p>As a huge fan of <a href="https://fluentassertions.com/">Fluent Assertions</a>, I can vouch for its high accessibility, making it the perfect choice for crafting elegant and easy-to-read test assertions.</p>
<p>In this example, we will refactor a test assertion to simplify its various components. The test uses <a href="https://xunit.net/">xUnit.net</a> and has a model containing an Order, Order Line, and Product. The test ensures that when the <code>AddProduct</code> method is called within the Order, each product is correctly added as an order line with the appropriate quantity. The complex assertion shown checks the lines for a specific product name and verifies the corresponding quantity is accurate.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Order</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">Order</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> number<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Number <span class="token operator">=</span> number<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">List<span class="token punctuation"><</span>OrderLine<span class="token punctuation">></span></span> _lines <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> Number <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">IReadOnlyCollection<span class="token punctuation"><</span>OrderLine<span class="token punctuation">></span></span> Lines <span class="token operator">=></span> _lines<span class="token punctuation">.</span><span class="token function">AsReadOnly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> TotalAmount <span class="token operator">=></span> _lines<span class="token punctuation">.</span><span class="token function">Sum</span><span class="token punctuation">(</span>line <span class="token operator">=></span> line<span class="token punctuation">.</span>Amount <span class="token operator">*</span> line<span class="token punctuation">.</span>Quantity<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token class-name">Product</span> product<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> quantity<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderLine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Product <span class="token operator">=</span> product<span class="token punctuation">,</span><br> Amount <span class="token operator">=</span> product<span class="token punctuation">.</span>Amount<span class="token punctuation">,</span><br> Quantity <span class="token operator">=</span> quantity<br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderLine</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">Product</span> Product <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> Quantity <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> Amount <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Product</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">Product</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> name<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">decimal</span></span> amount<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Name <span class="token operator">=</span> name<span class="token punctuation">;</span><br> Amount <span class="token operator">=</span> amount<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> Amount <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br></code></pre>
<h2>Fluent Custom Assertions</h2>
<p>In this example, we'll create a new test to refactor the test assertion, keeping both the original and refactored versions for comparison. The refactored test uses the same setup as the original.</p>
<p><strong>While Fluent Assertions already offers great readability, we can further enhance it by creating custom methods tailored to our domain-specific needs.</strong></p>
<p>When utilizing Fluent Assertions, the first step is to call the <code>Should</code> method, which grants us access to various assertions. The question is: <em>How can we extend that list further?</em></p>
<p>Fortunately, Fluent Assertions offers a <a href="https://fluentassertions.com/extensibility/#building-your-own-extensions">Custom Extensions</a> feature that we can leverage.</p>
<p>Let's create an extension for the Order class.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">OrderExtensions</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">OrderAssertions</span> <span class="token function">Should</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">Order</span> instance<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderAssertions</span><span class="token punctuation">(</span>instance<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>You might have noticed that we are returning a <code>OrderAssertions</code> type. Now, let's define that type.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderAssertions</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">Order</span> _instance<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token function">OrderAssertions</span><span class="token punctuation">(</span><span class="token class-name">Order</span> instance<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _instance <span class="token operator">=</span> instance<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br><span class="token punctuation">}</span></code></pre>
<p>This class should have a constructor that receives the order object as a parameter and a field to store it.</p>
<p>Within this type, we can finally implement our custom method, which will express the assertion using domain concepts.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderAssertions</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">Order</span> _instance<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token function">OrderAssertions</span><span class="token punctuation">(</span><span class="token class-name">Order</span> instance<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _instance <span class="token operator">=</span> instance<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span> <span class="token function">ContainProduct</span><span class="token punctuation">(</span><br> <span class="token class-name"><span class="token keyword">string</span></span> productName<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> quantity<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> because <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token keyword">params</span> <span class="token class-name"><span class="token keyword">object</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> becauseArgs<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br><span class="token punctuation">}</span></code></pre>
<p>By creating this custom method, we have further enhanced the readability and expressiveness of our test assertions, making it easier for developers to understand and maintain the code.
By using the <code>AndConstraint</code> as the return type, we can chain multiple assertions together.</p>
<p>Now, let's write our assertion.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContainProduct</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>And<br> <span class="token punctuation">.</span><span class="token function">ContainProduct</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>However, if we attempt to use one of the out-of-the-box assertions like <code>ShouldNotBeNull</code>, we encounter a compilation error. Let's bring those back into play.</p>
<p>To achieve this, we need to go back to the <code>OrderAssertions</code> class and make it inherit from <code>ReferenceTypeAssertions</code>.</p>
<p>To implement this change, simply inherit from <code>ReferenceTypeAssertions</code>, remove the private read-only field, and update the constructor accordingly.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderAssertions</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ReferenceTypeAssertions<span class="token punctuation"><</span>Order<span class="token punctuation">,</span> OrderAssertions<span class="token punctuation">></span></span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">OrderAssertions</span><span class="token punctuation">(</span><span class="token class-name">Order</span> instance<span class="token punctuation">)</span><br> <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>instance<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span> <span class="token function">ContainProduct</span><span class="token punctuation">(</span><br> <span class="token class-name"><span class="token keyword">string</span></span> productName<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> quantity<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> because <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token keyword">params</span> <span class="token class-name"><span class="token keyword">object</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> becauseArgs<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Identifier <span class="token operator">=></span> <span class="token string">"order"</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>Now, it compiles successfully. We can not only use our custom assertions but also the default ones.</p>
<p>Now, let's make our assertion do something meaningful. Here, we can define conditions and a failure message.
To utilize Fluent Assertions' engine for our custom <code>ContainProduct</code> method, we can access the <code>Execute.Assertion</code> property. This will allow us to inject our desired constraints or conditions.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderAssertions</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ReferenceTypeAssertions<span class="token punctuation"><</span>Order<span class="token punctuation">,</span> OrderAssertions<span class="token punctuation">></span></span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">OrderAssertions</span><span class="token punctuation">(</span><span class="token class-name">Order</span> instance<span class="token punctuation">)</span><br> <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>instance<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span> <span class="token function">ContainProduct</span><span class="token punctuation">(</span><br> <span class="token class-name"><span class="token keyword">string</span></span> productName<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> quantity<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> because <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token keyword">params</span> <span class="token class-name"><span class="token keyword">object</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> becauseArgs<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br><br> Execute<span class="token punctuation">.</span>Assertion<br> <span class="token punctuation">.</span><span class="token function">BecauseOf</span><span class="token punctuation">(</span>because<span class="token punctuation">,</span> becauseArgs<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ForCondition</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>productName<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">FailWith</span><span class="token punctuation">(</span><span class="token string">"You can't assert a product exist if you don't pass a proper name"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Identifier <span class="token operator">=></span> <span class="token string">"order"</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>The exciting part is that we can chain multiple conditions here.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderAssertions</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ReferenceTypeAssertions<span class="token punctuation"><</span>Order<span class="token punctuation">,</span> OrderAssertions<span class="token punctuation">></span></span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">OrderAssertions</span><span class="token punctuation">(</span><span class="token class-name">Order</span> instance<span class="token punctuation">)</span><br> <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>instance<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span> <span class="token function">ContainProduct</span><span class="token punctuation">(</span><br> <span class="token class-name"><span class="token keyword">string</span></span> productName<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> quantity<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> because <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token keyword">params</span> <span class="token class-name"><span class="token keyword">object</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> becauseArgs<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br><br> Execute<span class="token punctuation">.</span>Assertion<br> <span class="token punctuation">.</span><span class="token function">BecauseOf</span><span class="token punctuation">(</span>because<span class="token punctuation">,</span> becauseArgs<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ForCondition</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>productName<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">FailWith</span><span class="token punctuation">(</span><span class="token string">"You can't assert a product exist if you don't pass a proper name"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Then<br> <span class="token punctuation">.</span><span class="token function">ForCondition</span><span class="token punctuation">(</span>Subject<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">FailWith</span><span class="token punctuation">(</span><span class="token string">"Expecting Products added to the Order"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Then<br> <span class="token punctuation">.</span><span class="token function">Given</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> Subject<span class="token punctuation">.</span>Lines<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ForCondition</span><span class="token punctuation">(</span>lines <span class="token operator">=></span> lines<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>line <span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name<span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>productName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">FailWith</span><span class="token punctuation">(</span><span class="token string">"Expected {context:order} to contain {0}{reason}, but found {1}."</span><span class="token punctuation">,</span><br> _ <span class="token operator">=></span> productName<span class="token punctuation">,</span> lines <span class="token operator">=></span> lines<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>line <span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Then<br> <span class="token punctuation">.</span><span class="token function">Given</span><span class="token punctuation">(</span>_ <span class="token operator">=></span> Subject<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">First</span><span class="token punctuation">(</span>line <span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name <span class="token operator">==</span> productName<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ForCondition</span><span class="token punctuation">(</span>line <span class="token operator">=></span> line<span class="token punctuation">.</span>Quantity <span class="token operator">==</span> quantity<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">FailWith</span><span class="token punctuation">(</span><span class="token string">"Expected {context:order} to contain {0}{reason}, but found {1}."</span><span class="token punctuation">,</span><br> _ <span class="token operator">=></span> quantity<span class="token punctuation">,</span> line <span class="token operator">=></span> line<span class="token punctuation">.</span>Quantity<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AndConstraint<span class="token punctuation"><</span>OrderAssertions<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Identifier <span class="token operator">=></span> <span class="token string">"order"</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>And we're done!</p>
<p>But before we conclude, let's take another look at the before and after versions.</p>
<p>Before:</p>
<pre class="language-csharp"><code class="language-csharp">order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Contain</span><span class="token punctuation">(</span>line<span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name <span class="token operator">==</span> <span class="token string">"Shoes"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Which<br> <span class="token punctuation">.</span>Quantity<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Contain</span><span class="token punctuation">(</span>line<span class="token operator">=></span> line<span class="token punctuation">.</span>Product<span class="token punctuation">.</span>Name <span class="token operator">==</span> <span class="token string">"T-Shirt"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Which<br> <span class="token punctuation">.</span>Quantity<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>After:</p>
<pre class="language-csharp"><code class="language-csharp">order<br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>order<br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContainProduct</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>And<br> <span class="token punctuation">.</span><span class="token function">ContainProduct</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Don't you think it's much better now?</p>
<p>Keep it Simple 🌱</p>
DTOs - The Good, The Bad, and The Tradeoff2023-05-05T00:00:00-00:00https://guiferreira.me/archive/2023/dtos-the-good-the-bad-and-the-tradeoff/<p>https://www.youtube.com/watch?v=aCMJWOXwT0k</p>
<p>Data Transfer Objects, also known as DTOs.</p>
<ul>
<li>Show we use them?</li>
<li>Should we avoid them?</li>
<li>When should we use them?</li>
</ul>
<p>All of those are valid questions.</p>
<p>This article will explore the good, the bad, and the tradeoff of using DTOs.</p>
<h2>What is a DTO</h2>
<p><strong>A DTO is a pure representation of data.</strong></p>
<p>One definition I like is <a href="https://martinfowler.com/eaaCatalog/dataTransferObject.html"><em>"An object that carries data between processes to reduce the number of methods calls"</em> by Martin Fowler</a>. From this explanation, we see that a DTO lives on the boundaries of our systems.</p>
<p>It's important to note that DTOs are not only objects with a DTO suffix. They can also be view models, message contracts, commands, or events.</p>
<p>Not everybody falls in love with DTOs. Some will love them and overuse them sometimes. Others hate them and try to avoid them at all costs. The decision is a tradeoff, as are many other decisions in our field.</p>
<h2>The Good Parts</h2>
<p>Let's look into the following snippet.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">namespace</span> <span class="token namespace">DTOsTradeoffs<span class="token punctuation">.</span>Controllers</span><span class="token punctuation">;</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">ApiController</span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Route</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"[controller]"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TaskController</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ControllerBase</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">ILogger<span class="token punctuation"><</span>TaskController<span class="token punctuation">></span></span> _logger<span class="token punctuation">;</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">TasksDbContext</span> _dbContext<span class="token punctuation">;</span><br><br><br> <span class="token keyword">public</span> <span class="token function">TaskController</span><span class="token punctuation">(</span><span class="token class-name">ILogger<span class="token punctuation"><</span>TaskController<span class="token punctuation">></span></span> logger<span class="token punctuation">,</span> <span class="token class-name">TasksDbContext</span> dbContext<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _logger <span class="token operator">=</span> logger<span class="token punctuation">;</span><br> _dbContext <span class="token operator">=</span> dbContext<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">HttpGet</span><span class="token attribute-arguments"><span class="token punctuation">(</span>Name <span class="token operator">=</span> <span class="token string">"GetTasks"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IEnumerable<span class="token punctuation"><</span>Model<span class="token punctuation">.</span>Task<span class="token punctuation">></span><span class="token punctuation">></span></span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">await</span> _dbContext<span class="token punctuation">.</span>Tasks<span class="token punctuation">.</span><span class="token function">AsNoTracking</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToListAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">HttpPost</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IActionResult<span class="token punctuation">></span></span> <span class="token function">Post</span><span class="token punctuation">(</span><span class="token class-name">Model<span class="token punctuation">.</span>Task</span> request<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _dbContext<span class="token punctuation">.</span>Tasks<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">await</span> _dbContext<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token function">Created</span><span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">,</span> request<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<pre class="language-csharp"><code class="language-csharp"><br><span class="token keyword">namespace</span> <span class="token namespace">DTOsTradeoffs<span class="token punctuation">.</span>Infrastructure</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TasksDbContext</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">DbContext</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">TasksDbContext</span><span class="token punctuation">(</span><span class="token class-name">DbContextOptions<span class="token punctuation"><</span>TasksDbContext<span class="token punctuation">></span></span> options<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">DbSet<span class="token punctuation"><</span>Task<span class="token punctuation">></span></span> Tasks <span class="token operator">=></span> <span class="token generic-method"><span class="token function">Set</span><span class="token generic class-name"><span class="token punctuation"><</span>Task<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">namespace</span> <span class="token namespace">DTOsTradeoffs<span class="token punctuation">.</span>Model</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Task</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">Task</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Id <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">Guid</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> required <span class="token return-type class-name"><span class="token keyword">string</span></span> Title <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span><span class="token punctuation">?</span></span> Description <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>This example uses a shared representation of what a Task is. Both the Controller and Entity Framework depend on it.</p>
<p>One problem with using a shared representation in this example is that the API GET contract is the same as the POST contract. This means that the client can send an ID. What if the ID is system generated? That will confuse our consumers.</p>
<p><strong>That's one of the advantages of using DTOs. We can craft specific contracts per endpoint.</strong></p>
<p>The other benefit is that once I have the DTO in place, <strong>I can change my Model without impacting my consumers</strong>. The goal is to avoid internal implementations being a contract with the outside, so we can safely evolve and maintain them. Not only that, but DTOs avoid overexposure. And we know that <strong>once something becomes public, it is a contract</strong>.</p>
<p>Can you imagine all the pain involved in changing the name of the <code>Title</code> property in the example above?</p>
<p>In case you start thinking as if DTOs are just about our APIs, sorry for the misunderstanding. DTOs are also useful for our system dependencies.</p>
<p>Take a look at the following interface:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">namespace</span> <span class="token namespace">DTOsTradeoffs<span class="token punctuation">.</span>Infrastructure</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ITaskEventPublisher</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">Task</span> <span class="token function">PublishAsync</span><span class="token punctuation">(</span><span class="token class-name">Model<span class="token punctuation">.</span>Task</span> task<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>The interface implementation publishes the task as an event somewhere (Kafka, Rabbit, you name it.).</p>
<p>Now, imagine that once again I change the name of a property on my model. What happens to anyone consuming those events?</p>
<p>In a nutshell, <strong>a DTO is extremely useful on the inbound and outbound system boundaries</strong>.</p>
<h2>The Bad Parts</h2>
<p>DTOs are extremely useful, but... there are no free lunches.</p>
<p><strong>Once I bring my DTOs into the inbound and outbound, I will have a ton of duplication.</strong></p>
<p>If I'm building a new feature that adds a new property to Tasks, now I need to go to several classes to apply this change. In the example that I have a GET Endpoint DTO, a POST Endpoint DTO, and an Event DTO, it means that I need to keep 4 classes in sync. <strong>If I introduce duplication, I reduce maintainability.</strong></p>
<p><strong>The other problem with DTOs is overuse</strong>. Have you never seen multi-layer architectures where each layer has its DTOs? I do. And let me tell you: it's no fun.</p>
<h2>The Tradeoff</h2>
<p>We have concluded that using <strong>a DTO is a tradeoff</strong>.</p>
<p>On one hand, <strong>by introducing a DTO we decrease the coupling, so we increase the maintainability</strong>. On the other hand, <strong>introducing a DTO, increase the duplication, so we decrease the maintainability</strong>.</p>
<h2>What to do?</h2>
<p>Don't trust anyone who says <em>"Always use DTOs!"</em> or <em>"Don't use DTOs!"</em>. That's the biggest lesson.</p>
<p>So, next time, take a look into the tradeoff and evaluate complexity, third-party dependencies, risk of change, etc.</p>
<p>As an expensive consultant would tell you: It depends!</p>
<p>Keep it Simple 🌱</p>
Moving from Controllers to .NET Minimal APIs2023-04-28T00:00:00-00:00https://guiferreira.me/archive/2023/moving-from-controllers-to-dotnet-minimal-apis/<p>https://www.youtube.com/watch?v=MuecFu7CCMQ</p>
<p>How can you refactor your API Controllers code to embrace <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis">Minimal APIs</a>?</p>
<p>With .NET's recent push towards more Minimal APIs, now is the perfect time to consider refactoring your Controllers for a Minimal API approach. In this blog post, we'll explore how to make this transition.</p>
<h2>Context</h2>
<p>As the baseline for this refactoring, we will be using the <a href="https://github.com/jasontaylordev/CleanArchitecture">Clean Architecture Template</a> by <a href="https://jasontaylor.dev/">Jason Taylor</a>.</p>
<p>We will refactor some of the controllers that you can find in the <em>WebUI</em> project into Minimal APIs endpoints. We will not only do that, but we will also structure the project into a Feature Driven organization.</p>
<p>We will do this refactoring manually, without bringing tools or frameworks, so you can understand how it works under the wood. However, by the end, I will reference a Framework that might be useful.</p>
<h2>Refactoring Pre-conditions</h2>
<p>Refactoring can be a daunting task, but having proper tests in place can provide peace of mind and confidence in your changes.</p>
<p>Ensure your tests cover the API to catch any regressions as you make the transition to Minimal APIs. <strong>I would not start the refactoring without a safety net.</strong></p>
<h2>A Simple Case: Weather Controller</h2>
<p>Let's begin our refactoring journey with a straightforward example: the Weather Controller.</p>
<p>The first step is to add a new directory <code>WeatherForecast</code>.
Inside, let's add a static class <code>GetEndpoint</code>.</p>
<p>The <code>GetEndpoint</code> class will have 2 methods. One for endpoint mapping and the other one to handle the request. Let's start with the Map.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">GetEndpoint</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">WebApplication</span> <span class="token function">MapGetWeatherForecastEndpoint</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">WebApplication</span> app<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token comment">//...</span><br> <span class="token punctuation">}</span><br><br><span class="token punctuation">}</span></code></pre>
<p>To define the route, we take advantage of the existing conventions on the Controller. So the code will be like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">WebApplication</span> <span class="token function">MapGetWeatherForecastEndpoint</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">WebApplication</span> app<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">"api/WeatherForecast"</span><span class="token punctuation">,</span> GetAsync<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> app<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>For the Handle method, we need to review the Input and Output types.
Then, we copy and paste the code from the Controller.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">GetEndpoint</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">WebApplication</span> <span class="token function">MapGetWeatherForecastEndpoint</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">WebApplication</span> app<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">"api/WeatherForecast"</span><span class="token punctuation">,</span> GetAsync<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> app<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IEnumerable<span class="token punctuation"><</span>ControllersToMinimalApis<span class="token punctuation">.</span>Application<span class="token punctuation">.</span>WeatherForecasts<span class="token punctuation">.</span>Queries<span class="token punctuation">.</span>GetWeatherForecasts<span class="token punctuation">.</span>WeatherForecast<span class="token punctuation">></span><span class="token punctuation">></span></span> <span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">await</span> mediator<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">GetWeatherForecastsQuery</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>If the Controller has constructor parameters, the Minimal API endpoint needs method parameters (<a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/parameter-binding?view=aspnetcore-7.0#parameter-binding-with-dependency-injection">see here</a>). The <code>ISender mediator</code> is one of those.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">GetEndpoint</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">WebApplication</span> <span class="token function">MapGetWeatherForecastEndpoint</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">WebApplication</span> app<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">"api/WeatherForecast"</span><span class="token punctuation">,</span> GetAsync<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> app<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IEnumerable<span class="token punctuation"><</span>ControllersToMinimalApis<span class="token punctuation">.</span>Application<span class="token punctuation">.</span>WeatherForecasts<span class="token punctuation">.</span>Queries<span class="token punctuation">.</span>GetWeatherForecasts<span class="token punctuation">.</span>WeatherForecast<span class="token punctuation">></span><span class="token punctuation">></span></span> <span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token class-name">ISender</span> mediator<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">await</span> mediator<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">GetWeatherForecastsQuery</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now, go to <code>Program.cs</code> and call the map method.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// ...</span><br>app<span class="token punctuation">.</span><span class="token function">MapControllerRoute</span><span class="token punctuation">(</span><br> <span class="token named-parameter punctuation">name</span><span class="token punctuation">:</span> <span class="token string">"default"</span><span class="token punctuation">,</span><br> <span class="token named-parameter punctuation">pattern</span><span class="token punctuation">:</span> <span class="token string">"{controller}/{action=Index}/{id?}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// HERE 👇</span><br>app<span class="token punctuation">.</span><span class="token function">MapGetWeatherForecastEndpoint</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>app<span class="token punctuation">.</span><span class="token function">MapRazorPages</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>app<span class="token punctuation">.</span><span class="token function">MapFallbackToFile</span><span class="token punctuation">(</span><span class="token string">"index.html"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">;</span><br><br>app<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br></code></pre>
<p>Remove the old Controller, and run your tests/application.</p>
<h2>When a Controller Has Many Hats</h2>
<p>Let's tackle a more complex case: the Todos Controller. This Controller has multiple routes for creating, retrieving, updating, and deleting todos. Let's see how to approach a case like this, replacing a single controller with many Minimal API endpoints.</p>
<p>Let's do this in a Feature Driven way. So, let's first create a folder. <code>TodoLists</code>. Inside it, let's create a <code>GetTodoList</code> folder. This will be the home of our Todo list endpoint.</p>
<p>Now, let's create a static class <code>Endpoint</code>. The process will be the same as we have done for the Weather Controller.</p>
<p>So, the migrated code will be:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Endpoint</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">WebApplication</span> <span class="token function">MapGetTodoListEndpoint</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">WebApplication</span> app<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">"api/TodoLists"</span><span class="token punctuation">,</span> GetAsync<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">RequireAuthorization</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> app<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>TodosVm<span class="token punctuation">></span></span> <span class="token function">GetAsync</span><span class="token punctuation">(</span><span class="token class-name">ISender</span> mediator<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">await</span> mediator<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">GetTodosQuery</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>The difference is that you will find an <code>Authorization</code> Attribute on the Controller. To apply that, you call the <code>RequireAuthorization</code> method on the Mapping.</p>
<pre class="language-csharp"><code class="language-csharp">app<span class="token punctuation">.</span><span class="token function">MapGet</span><span class="token punctuation">(</span><span class="token string">"api/TodoLists"</span><span class="token punctuation">,</span> GetAsync<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">RequireAuthorization</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>And it's done.</p>
<p>Let's do one more. Let's take a look into the Update.</p>
<p>On the Update Action, you see that the result might be a Bad Request, Not Found, or OK. That's why the return type is <code>ActionResult</code>. While on the Minimal API Endpoint, we need to return <code>IResult</code>. We do it using methods like <code>Results.BadRequest</code> or <code>Results.NotFound</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Endpoint</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">WebApplication</span> <span class="token function">MapUpdateTodoListEndpoint</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">WebApplication</span> app<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> app<span class="token punctuation">.</span><span class="token function">MapPut</span><span class="token punctuation">(</span><span class="token string">"api/TodoLists/{id:int}"</span><span class="token punctuation">,</span> UpdateAsync<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">RequireAuthorization</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> app<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>IResult<span class="token punctuation">></span></span> <span class="token function">UpdateAsync</span><span class="token punctuation">(</span><span class="token class-name">ISender</span> mediator<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> id<span class="token punctuation">,</span> <span class="token class-name">UpdateTodoListCommand</span> command<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>id <span class="token operator">!=</span> command<span class="token punctuation">.</span>Id<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">await</span> mediator<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">NoContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now, call the mapping method on <code>Program.cs</code>, remove the old Controller, and voilá.</p>
<h2>A Helpful Tool</h2>
<p>If you have been holding to API Controllers due to the convention-based approach, and you don't want to do this "tidying" by hand, you can use <a href="https://fast-endpoints.com/">FastEndpoints</a>. FastEndpoints is a framework that will simplify your work and nudge you in the right direction.</p>
<h2>Summary</h2>
<p>Embracing Minimal APIs in .NET can lead to more streamlined, efficient code. If you are looking for those performance gains, I hope this example helps you understand how to approach refactoring. And with tools like Fast Endpoints, transitioning to Minimal APIs can be even more accessible.</p>
<p>Keep it Simple 🌱</p>
.NET Integration Testing with Docker Compose2023-04-21T00:00:00-00:00https://guiferreira.me/archive/2023/dotnet-integration-testing-with-docker-compose/<p>https://www.youtube.com/watch?v=zhPFMyMMw4A</p>
<p>Test Containers are fantastic, but <strong>I often find myself updating my container definition twice</strong>: once in the <code>docker-compose</code> file and then again in the C# tests. It's like dressing twins to look identical.</p>
<p>So, I wondered: <strong>Is it possible to use docker-compose for Integration Testing?</strong></p>
<h2>The Problem</h2>
<p>In numerous projects, it's common to have a set of resources required to boot your application. Nowadays, we manage these resources using a <code>docker-compose</code> file. This file is utilized for various purposes, such as manual testing in a developer's environment, where the developer runs the docker-compose before starting the application.</p>
<p>The same resources are needed to run Integration Tests. Thankfully, we now have <a href="https://dotnet.testcontainers.org/">Test-containers</a>, which allow us to do precisely that. <strong>Test-containers enable us to use a Fluent API to define the necessary docker infrastructure</strong>. However, <strong>this leads to two separate infrastructure definitions</strong>: one in the Integration Tests and another in the <code>docker-compose</code>. <strong>Duplicated configurations can result in not only extra work when changes are needed but also inconsistencies</strong>.</p>
<p>So, why not use the same <code>docker-compose</code> file for Integration Testing?
Regrettably, <strong>this is currently not possible with Test-containers for .NET</strong>. Although it might become feasible to use Test-containers with docker-compose in the future, similar to <a href="https://www.testcontainers.org/modules/docker_compose/">Java</a>.</p>
<h2>Fluently Running docker-compose</h2>
<p>The good news is that there's already a solution for .NET: <a href="https://github.com/mariotoffia/FluentDocker">FluentDocker</a>. FluentDocker is an open-source library that enables interactions with Docker and docker-compose using a Fluent API. It even has some testing features. However, those features don't support Docker Compose Fixtures. But don't worry, we can easily address that. Let's see how.</p>
<p>You can install FluentDocker using NuGet.</p>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> package Ductus.FluentDocker</code></pre>
<h3>Test Base</h3>
<p>The first thing we need to do is create an abstract Test Base. This class will be responsible for finding a host, building the composite service, and disposing of it. It will serve as the foundation for our Test Fixture.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Ductus<span class="token punctuation">.</span>FluentDocker<span class="token punctuation">.</span>Services</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">DockerComposeTestBase</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IDisposable</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">protected</span> <span class="token class-name">ICompositeService</span> CompositeService<span class="token punctuation">;</span><br> <span class="token keyword">protected</span> <span class="token class-name">IHostService<span class="token punctuation">?</span></span> DockerHost<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token function">DockerComposeTestBase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token function">EnsureDockerHost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> CompositeService <span class="token operator">=</span> <span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">try</span><br> <span class="token punctuation">{</span><br> CompositeService<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">catch</span><br> <span class="token punctuation">{</span><br> CompositeService<span class="token punctuation">.</span><span class="token function">Dispose</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">throw</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token function">OnContainerInitialized</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Dispose</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token function">OnContainerTearDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> compositeService <span class="token operator">=</span> CompositeService<span class="token punctuation">;</span><br> CompositeService <span class="token operator">=</span> <span class="token keyword">null</span><span class="token operator">!</span><span class="token punctuation">;</span><br> <span class="token keyword">try</span><br> <span class="token punctuation">{</span><br> compositeService<span class="token punctuation">?.</span><span class="token function">Dispose</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">catch</span><br> <span class="token punctuation">{</span><br> <span class="token comment">// ignored</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">abstract</span> <span class="token return-type class-name">ICompositeService</span> <span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnContainerTearDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">virtual</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnContainerInitialized</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">EnsureDockerHost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>DockerHost<span class="token punctuation">?.</span>State <span class="token operator">==</span> ServiceRunningState<span class="token punctuation">.</span>Running<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> hosts <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Hosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Discover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> DockerHost <span class="token operator">=</span> hosts<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>IsNative<span class="token punctuation">)</span> <span class="token operator">??</span> hosts<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Name <span class="token operator">==</span> <span class="token string">"default"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">!=</span> DockerHost<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>DockerHost<span class="token punctuation">.</span>State <span class="token operator">!=</span> ServiceRunningState<span class="token punctuation">.</span>Running<span class="token punctuation">)</span> DockerHost<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>hosts<span class="token punctuation">.</span>Count <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> DockerHost <span class="token operator">=</span> hosts<span class="token punctuation">.</span><span class="token function">First</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">!=</span> DockerHost<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span><br><br> <span class="token function">EnsureDockerHost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<h3>Fixture</h3>
<p>Since you don't want to start the infrastructure for every single test, you'll need to create a Test Fixture. In this example, we'll use <a href="https://xunit.net/">xUnit.net</a>.</p>
<p>The Fixture will inherit from the Test Base class mentioned earlier.</p>
<p>In the Fixture, we can override the Build method, where we'll define the path to the <code>docker-compose</code> file.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Ductus<span class="token punctuation">.</span>FluentDocker<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Common</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Ductus<span class="token punctuation">.</span>FluentDocker<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Compose</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Ductus<span class="token punctuation">.</span>FluentDocker<span class="token punctuation">.</span>Services</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Ductus<span class="token punctuation">.</span>FluentDocker<span class="token punctuation">.</span>Services<span class="token punctuation">.</span>Impl</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>Extensions<span class="token punctuation">.</span>DependencyInjection</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyTestFixture</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">DockerComposeTestBase</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">MyTestFixture</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token return-type class-name">ICompositeService</span> <span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> file <span class="token operator">=</span> Path<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>Directory<span class="token punctuation">.</span><span class="token function">GetCurrentDirectory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br> <span class="token punctuation">(</span>TemplateString<span class="token punctuation">)</span><span class="token string">"Fixture/docker-compose.yml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">DockerComposeCompositeService</span><span class="token punctuation">(</span><br> DockerHost<span class="token punctuation">,</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">DockerComposeConfig</span><br> <span class="token punctuation">{</span><br> ComposeFilePath <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">List<span class="token punctuation"><</span><span class="token keyword">string</span><span class="token punctuation">></span></span> <span class="token punctuation">{</span> file <span class="token punctuation">}</span><span class="token punctuation">,</span><br> ForceRecreate <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br> RemoveOrphans <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br> StopOnDispose <span class="token operator">=</span> <span class="token boolean">true</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now, you can use the Fixture in your tests as you normally would, and when the tests run, the <code>docker-compose</code> will start the necessary infrastructure.</p>
<h2>Summary</h2>
<p>Although FluentDocker lacks built-in Test Fixtures for docker-compose, it still provides a more unified approach for defining and managing container configurations. Give this method a try, and let us know what you think in the comments! If you have any doubts about how to do this, be sure to watch the linked video.</p>
<p>Keep it Simple 🌱</p>
My Simple Testing Stack (for .NET developers) [2023]2023-04-18T00:00:00-00:00https://guiferreira.me/archive/2023/my-simple-testing-stack-for-dotnet-developers-2023/<p>https://www.youtube.com/watch?v=j7cBRtloLDE</p>
<p>Discover the tools I use for my .NET test projects!</p>
<p>Not only will you get an inside look at my current testing stack, but you'll also get a sneak peek at the tools I'm planning to try out. Stick around to the end to uncover these hidden gems!</p>
<h2>🧰 What I Use</h2>
<h3><a href="https://xunit.net/">xUnit.net</a></h3>
<p>xUnit is my go-to framework for unit testing in .NET applications. I love its clean and straightforward syntax. Besides that, it's the most used testing framework in the .NET space.</p>
<h3><a href="https://fluentassertions.com/">Fluent Assertions</a></h3>
<p>Fluent Assertions is a powerful library that elevates the expressiveness of my test assertions. Tests should reveal the intent as clearly as possible. Fluent Assertions are the perfect tool for that.</p>
<h3><a href="https://github.com/moq/moq4">Moq</a></h3>
<p>Moq is the most commonly used mocking library for .NET.
However, I confess that I have been looking into other options. Moq is a powerful tool but sacrifices simplicity, and I don't use advanced features.</p>
<h3><a href="https://github.com/mariotoffia/FluentDocker">FluentDocker</a></h3>
<p>FluentDocker is a fantastic library. With its fluent API, I can quickly spin up docker containers to create isolated testing environments that mimic real-world scenarios. I've started using it because Test-containers didn't support spinning up containers based on a docker-compose file, and FluentDocker does. That might change in the future.</p>
<h3><a href="https://k6.io/">K6</a></h3>
<p>If you don't have a go-to load-testing, soak-testing, or smoke-testing tool, you will want K6 as part of your testing toolkit.
You don't write tests using .NET. You do it with JavaScript. But trust me, it's simple and expressive.</p>
<h3><a href="https://www.cypress.io/">Cypress</a></h3>
<p>Cypress is my choice for end-to-end testing of web applications. If you have ever used Selenium, you will love this.</p>
<h2>🔮 What I Plan to Use</h2>
<h3><a href="https://nsubstitute.github.io/">NSubstitute</a></h3>
<p>I'm looking forward to trying NSubstitute as an alternative to Moq for creating mock objects. I have seen so many great things about it. The simplicity of NSubstitute is what seduces me.</p>
<h3><a href="https://github.com/bchavez/Bogus">Bogus</a></h3>
<p>I'm eager to explore Bogus for generating realistic test data in my .NET projects. I find it especially exciting for E2E tests. A side benefit would be using it to seed demo data.</p>
<h3><a href="https://playwright.dev/dotnet/">Playwright</a></h3>
<p>Playwright is another tool I'm excited to try out. With .NET support, it's difficult to find arguments to not try to replace Cypress.</p>
<h2>👋 Wrap up</h2>
<p>As a developer, having a reliable and efficient testing stack is crucial for ensuring the quality of your projects. If you are looking for a testing stack, copy this one and start with it. And before we go, I would love to know if you have any other tools to recommend.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Keep it Simple 🌱</p>
Why I Don't Use Loops on My Tests2023-04-06T00:00:00-00:00https://guiferreira.me/archive/2023/why-i-dont-use-loops-on-my-tests/<p>https://www.youtube.com/watch?v=NJ07Ly0XfLA</p>
<p>Ditch the Fors, Foreachs, Whiles, and so on. Why? Because <strong>I avoid iterating on tests</strong>. The secret lies in the power of Zero, One, or Many. Intrigued? Let's dive in and explore this approach.</p>
<h2>🔄 The Problem</h2>
<p>In this scenario, we'll demonstrate the impact of writing loops in your tests and how you can achieve the same results without resorting to loops.</p>
<p>Let's start by examining the code under test.</p>
<p>We'll use a straightforward scenario to illustrate how people typically write tests with Fors, Whiles, and Foreachs, and then demonstrate how we can rewrite these tests to avoid such loops.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Order</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">IList<span class="token punctuation"><</span>OrderItem<span class="token punctuation">></span></span> Lines <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">List<span class="token punctuation"><</span>OrderItem<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">OrderItem<span class="token punctuation">?</span></span> <span class="token function">MostExpensive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token operator">=></span> Lines<span class="token punctuation">.</span><span class="token function">MaxBy</span><span class="token punctuation">(</span>item <span class="token operator">=></span> item<span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">OrderItem<span class="token punctuation">?</span></span> <span class="token function">Cheapest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token operator">=></span> Lines<span class="token punctuation">.</span><span class="token function">MinBy</span><span class="token punctuation">(</span>item <span class="token operator">=></span> item<span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderItem</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">double</span></span> Amount <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br></code></pre>
<p>Our example involves an object containing a list of lines.</p>
<p>The Order Lines possess certain functions (<code>MostExpensive</code> and <code>Cheapest</code>) that allow us to extract data from them, and it's these functions that we'll be testing.</p>
<p>In the example, we have a basic collection—a list of order lines. An order line is a simple object consisting of a name and an amount.</p>
<p>Our goal is to implement two functions: one to return the most expensive item in the order and another to return the least expensive item in the same order.</p>
<p>Now, let's take a look at the test cases.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">NoLoopTests</span><br><span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Given10Items_WhenGetMostExpensiveItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><br> order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token interpolation-string"><span class="token string">$"PRODUCT-</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">i</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">,</span> Amount <span class="token operator">=</span> i <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> order<span class="token punctuation">.</span><span class="token function">MostExpensive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">!</span><span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Given10Items_WhenGetCheapestItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><br> order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token interpolation-string"><span class="token string">$"PRODUCT-</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">i</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">,</span> Amount <span class="token operator">=</span> i <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> order<span class="token punctuation">.</span><span class="token function">Cheapest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">!</span><span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Often, when creating tests, it's necessary to set up a collection to perform the test. In the Arrange phase, you'll manipulate a list, populating it with data to test your methods. That's what's happening here.</p>
<p>I have two simple use cases here to demonstrate the approach most take when writing these tests. In this scenario, I create an order and iterate through a list of numbers from 1 to 10. I then populate the order lines with a new order, assigning a given name and an amount. Afterward, I assert that if I'm iterating from 1 to 10, the most expensive item should be 10.</p>
<p>Conversely, when seeking the cheapest one, I follow the same process. By the end, I call the function to find the cheapest item, which should have 1 as the amount, since I start with an index of 1.</p>
<p>Upon running these tests (<code>dotnet test</code>), we can see that they are successful. 🟢</p>
<p>Using <a href="https://stryker-mutator.io/docs/stryker-net/introduction/">Striker.NET</a> to evaluate the tests, we observe that they are in good shape.</p>
<pre class="language-bash"><code class="language-bash">dotnet stryker</code></pre>
<p>For those unfamiliar with <a href="https://stryker-mutator.io/docs/stryker-net/introduction/">Striker.NET</a>, it's an impressive <a href="https://en.wikipedia.org/wiki/Mutation_testing">mutation testing</a> tool for .NET. You can find a <a href="https://www.youtube.com/watch?v=sGwfwtkaDfk">video here</a> by <a href="https://nickchapsas.com/courses/">Nick Chapsas</a>, which thoroughly explains its capabilities.</p>
<p>After running Striker, the results indicate a final mutation score of 100, which means the tests are performing exactly as intended, ensuring nothing has been overlooked in the testing process.</p>
<p><strong>Why would I avoid writing tests like these if they are effective?</strong></p>
<h2>↗️ No Loops</h2>
<p>To demonstrate the difference between using a loop and not using one, I will duplicate one of these tests and place them side by side.</p>
<p>Before rewriting the test, it's important to understand that when testing collections, we typically only need to test three scenarios:</p>
<ul>
<li>Zero</li>
<li>One</li>
<li>Two (which represents 'many' in the scenarios we're considering)</li>
</ul>
<p><strong>Instead of iterating through 10 items, we can simply test with two.</strong> While it may be tempting to refactor the existing test, it's more effective to simplify it. With only two items, we can easily rewrite the test to include the two lines of code corresponding to the desired values.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">NoLoopTests</span><br><span class="token punctuation">{</span><br> <span class="token comment">// [Fact]</span><br> <span class="token comment">// public void Given10Items_WhenGetMostExpensiveItem()</span><br> <span class="token comment">// {</span><br> <span class="token comment">// var order = new Order();</span><br> <span class="token comment">// for (var i = 1; i <= 10; i++)</span><br> <span class="token comment">// order.Lines.Add(new OrderItem() { Name = $"PRODUCT-{i}", Amount = i });</span><br><br> <span class="token comment">// Assert.Equal(10, order.MostExpensive()!.Amount);</span><br> <span class="token comment">// }</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Given2Items_WhenGetMostExpensiveItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"PRODUCT-1"</span><span class="token punctuation">,</span> Amount <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"PRODUCT-2"</span><span class="token punctuation">,</span> Amount <span class="token operator">=</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> order<span class="token punctuation">.</span><span class="token function">MostExpensive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">!</span><span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token comment">// ...</span><br><span class="token punctuation">}</span></code></pre>
<p>In this case, we expect an outcome of 10. To test this, we can simply input 10 and run the test.</p>
<p>The results show that both tests are successful, but the simplified version is more descriptive and easier to understand. <strong>This reduced cognitive load is important, as it allows for a clearer view of the test's purpose</strong>. When writing tests, <strong>aim for a cyclomatic complexity of one, avoiding the use of loops and conditional statements</strong> whenever possible.</p>
<p>You might wonder if the simplified test is truly equivalent to the original. To prove it, let's comment out the first test, duplicate the test for the cheapest item, and apply the same simplification strategy. We'll convert the loop into direct calls to add lines.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">NoLoopTests</span><br><span class="token punctuation">{</span><br> <span class="token comment">// ...</span><br><br> <span class="token comment">// [Fact]</span><br> <span class="token comment">// public void Given10Items_WhenGetCheapestItem()</span><br> <span class="token comment">// {</span><br> <span class="token comment">// var order = new Order();</span><br> <span class="token comment">// for (var i = 1; i <= 10; i++)</span><br> <span class="token comment">// order.Lines.Add(new OrderItem() { Name = $"PRODUCT-{i}", Amount = i });</span><br><br> <span class="token comment">// Assert.Equal(1, order.Cheapest()!.Amount);</span><br> <span class="token comment">// }</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Given2Items_WhenGetCheapestItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"PRODUCT-10"</span><span class="token punctuation">,</span> Amount <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> order<span class="token punctuation">.</span>Lines<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"PRODUCT-30"</span><span class="token punctuation">,</span> Amount <span class="token operator">=</span> <span class="token number">30</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> Assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> order<span class="token punctuation">.</span><span class="token function">Cheapest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">!</span><span class="token punctuation">.</span>Amount<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>With these two tests in place and the original ones commented out, let's run Stryker.NET once again.</p>
<p>The results confirm that the mutation score remains at 100%. This indicates that the simpler code achieves the same outcomes as the more complex version.</p>
<p><strong>The streamlined test is cleaner and easier to understand, saving time and mental effort.</strong> So, the next time you're about to use a loop or conditional statement in your test code, pause and consider this approach with just two entries. <strong>You might find that it's equally effective while reducing cognitive load.</strong></p>
<p>Another technique to minimize test complexity is to avoid over-applying the DRY (Don't Repeat Yourself) principle. To learn more about striking the right balance, check out <a href="https://guiferreira.me/archive/2022/how-dry-can-damage-your-tests/">this article</a>.</p>
<p>Until next time, remember to keep your test code simple and straightforward.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Keep it Simple 🌱</p>
3 TDD Techniques Most People Don’t Know2023-03-31T00:00:00-00:00https://guiferreira.me/archive/2023/3-tdd-techniques-most-people-dont-know/<p>https://www.youtube.com/watch?v=ga6i2i_ynYE</p>
<p>There are <strong>3 techniques to help you move from Red 🔴 to Green 🟢</strong>. Even if you already know about <a href="https://wikipedia.org/wiki/Test-driven_development">Test Driven Development (TDD)</a>, you may only be familiar with one of these techniques. However, this may lead you to believe that the <a href="https://www.codecademy.com/article/tdd-red-green-refactor">Red-Green-Refactor process</a> is useless.</p>
<p>To explain the differences between these techniques, let's use a straightforward example like multiplication. I believe it will demonstrate the three techniques clearly. <em>If you want to see these techniques applied in a more complicated example, please reach out.</em></p>
<p><em>Important: I will be using <a href="https://xunit.net/">xUnit.net</a> and <a href="https://fluentassertions.com/">Fluent Assertions</a>.</em></p>
<h2>Fake It</h2>
<p>The first technique is the "Fake It" technique. Also known as <em>"Fake it until you make it"</em>. And how do you do it?
So, let's start creating our code.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br><br><span class="token punctuation">}</span></code></pre>
<p>We are writing our tests, and now we start that process of daydreaming about what the solution will be.</p>
<p>We can imagine something like this, a static Class <em>Calculator</em> with a static method <em>Multiply</em> that will receive two integers as arguments.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>We can provide <code>2</code> and <code>3</code> and expect an int as a Result.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>The first step is to make this code compile. So, let's generate this code, create a static Class <code>Calculator</code>, and create the <code>Multiply</code> method.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">NotImplementedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>What we want to do now is our assertion.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>So, <code>results</code> (in case you are asking, I'm using <a href="https://fluentassertions.com/">Fluent Assertions</a>) should be <code>2</code> times <code>3</code>. It means <code>6</code> is what we want.</p>
<p>Let's run the test to see what happens.</p>
<p>The test is failing due to the exception that I'm throwing.</p>
<p>So, now let's start the process of <em>Faking Until We Make It</em>.</p>
<p>If we know that <code>6</code> will fix it, let's return the <code>6</code>, and when we run it, we have a green test.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token number">6</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>We are now in a green state, and we start refactoring this code to find the final solution.</p>
<p>In this scenario, we have a <code>6</code> on the test and a <code>6</code> on the code under the test. We want to avoid this duplication, am I right? So what can we do next? Don't worry, we're dealing with multiplication, so it might sound silly, but bear with me and trust the process.</p>
<p><strong>Since we want to avoid that duplication, what we can do is that we know that <code>2</code> times <code>3</code> will return <code>6</code>, right? So, that is the next obvious step. Just replace this with two times three.</strong></p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token number">2</span> <span class="token operator">*</span> <span class="token number">3</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>We execute the test again. The tests are green once again. Perfect! So, we can keep iterating on this.</p>
<p>The duplication has been moved from the return <code>6</code> to the two parameters.</p>
<p>So, what we do now is we will keep faking one of them, but we swap the other one with the correct implementation.</p>
<p>Let's change the <code>3</code> by the <code>b</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token number">2</span> <span class="token operator">*</span> b<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Run the tests, and see the green state.</p>
<p>Now we swap the <code>2</code> by the <code>a</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> a <span class="token operator">*</span> b<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>We run the tests, and it's green once again.</p>
<p>So, the <em>"faking until we make it"</em> process is simple as this.</p>
<p><strong>We start with the dumbest thing we can do to fulfil that assertion and then start swapping things slowly. One at a time until we find the solution.</strong></p>
<p>If you feel that this one seems stupid, you will like the next one because it's the one that usually no one tells you can do on TDD.</p>
<h2>Obvious implementation</h2>
<p>This technique is what I consider a practical approach. It's the one I use frequently, and I've noticed many others adopting it as well. Some may view it as not truly TDD, but it is. Even <a href="https://www.kentbeck.com/">Kent Beck's</a> <a href="https://www.goodreads.com/en/book/show/387190">TDD by Example book</a> includes this approach.</p>
<p>Let's look once again at the same case. We have <code>2</code> times <code>3</code> equals <code>6</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>What can we do now? We know that it is <code>2</code> times <code>3</code>. We know it's multiplication. So if it's easy, <strong>why don't we do this right away and run the tests?</strong></p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> a <span class="token operator">*</span> b<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>They should be green. Voila!</p>
<p><strong>TDD doesn't mean that you need to do always the <em>stupid</em> thing.</strong></p>
<p>Just go to techniques like the <em>"fake it until you make it"</em> when you are not confident about the approach or when it's not obvious what you should do. You need to mix and match these techniques that I'm showing you.</p>
<h2>Triangulate</h2>
<p>This one comes from the radar triangulation concept, where you can use two radars to find the position of a third device. We can apply the same principle to tests.</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span><br> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">,</span><br> <span class="token class-name"><span class="token keyword">int</span></span> expectedResult<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span></code></pre>
<p>We changed the code to instead of being a Fact to be a Theory and used InlineData to provide these values as arguments.</p>
<p>Next, we implemented the simplest solution by returning <code>6</code> since we know that providing <code>6</code> as input results in success.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token number">6</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>We run the tests, and they succeeded, so everything worked perfectly.</p>
<p>What we can do now is provide a new set of values. We need to find a position using a data set, so let's change the first parameter to <code>1</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span><br> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">,</span><br> <span class="token class-name"><span class="token keyword">int</span></span> expectedResult<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>Now we expect the result to be <code>3</code>. When we execute tests again, one test succeeds, and the other fails.</p>
<p>We can start thinking of ways to achieve the desired result with just two test cases. For example, we can return a different number if a given number is received or multiply a by three (for now). After making these changes, we run the tests, and they succeed.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> a <span class="token operator">*</span> <span class="token number">3</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>We can now bring in another option and change the second argument.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ShouldMultiplyTwoNumbers</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span><br> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">,</span><br> <span class="token class-name"><span class="token keyword">int</span></span> expectedResult<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> Calculator<span class="token punctuation">.</span><span class="token function">Multiply</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>expectedResult<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>After running the tests, one of them fails. However, <strong>by triangulating the three test scenarios, we can deduce that the solution must meet all three conditions, allowing us to identify a pattern</strong>. It's crystal clear the solution is <code>a</code> times <code>b</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Calculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> b<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> a <span class="token operator">*</span> b<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>We run all the tests, and they succeed.</p>
<p>If you are familiar with these three techniques, let me know which one you use.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Keep it Simple 🌱</p>
Why I Always Avoid InternalsVisibleTo in .NET, Unless...2023-03-21T00:00:00-00:00https://guiferreira.me/archive/2023/why-i-always-avoid-internalsvisibleto-in-dotnet-unless/<p>https://www.youtube.com/watch?v=O9GiOIw5XYc</p>
<p>Please don't hate me, but I have to confess that <strong>I don't like to use <a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.internalsvisibletoattribute?view=net-8.0"><code>InternalsVisibleTo</code></a> in my .NET applications just for the sake of testing</strong>. Unless I'm in a specific scenario (don't worry, I will let you know later in this article).</p>
<h2>🤔 Why?</h2>
<p>Let me show you.</p>
<p>What do I have here? I have two projects; one with the source code that will be under test and the other with the test code.</p>
<pre class="language-bash"><code class="language-bash">dotnet new sln -n InternalsVisibleToDemo<br>dotnet new classlib -n InternalsVisibleToDemo<br>dotnet new xunit -n InternalsVisibleToDemo.Tests<br>dotnet <span class="token function">add</span> InternalsVisibleToDemo.Tests reference InternalsVisibleToDemo</code></pre>
<p>In the code under test, I have a simple class that does nothing special. It's a simple method call.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AddCustomerService</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Add</span><span class="token punctuation">(</span><span class="token class-name">Customer</span> customer<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">IsValid</span><span class="token punctuation">(</span>customer<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">InvalidDataException</span><span class="token punctuation">(</span><span class="token string">"Invalid Customer data"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token comment">// ...</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">internal</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">IsValid</span><span class="token punctuation">(</span><span class="token class-name">Customer</span> customer<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>customer<span class="token punctuation">.</span>Name <span class="token keyword">is</span> <span class="token punctuation">{</span> Length<span class="token punctuation">:</span> <span class="token operator"><</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>customer<span class="token punctuation">.</span>Email<span class="token punctuation">.</span><span class="token function">IsValidEmail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><br> <span class="token comment">//...</span><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>The goal of the public method is to add a customer, and the only thing that I'm doing here right now is calling <code>IsValid</code>.</p>
<p>Obviously, in a real-world scenario, we will do extra stuff here. I want to make a point, just that.</p>
<p><code>IsValid</code> is simply performing two checks on top of this customer object. But, usually, this will be almost as complex as the Game of Thrones story plot. So since this is a different method, what I see a lot of people doing is that they use this as an 'internal' for the sake of testing.</p>
<p>Since usually, this type of validator tends to have a bit of logic, some <strong>people prefer to expose them and test this validation in specific</strong>.</p>
<p>So what do you do in those cases? You can go to your <code>csproj</code> or have an attribute tag to your project. Nick Chapsas has <a href="https://www.youtube.com/watch?v=6WeT-JQBI98">this cool video</a> that explains all the options that you can do.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ItemGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>InternalsVisibleTo</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>InternalsVisibleToDemo.Tests<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ItemGroup</span><span class="token punctuation">></span></span></code></pre>
<p><strong>On the <code>csproj</code>, we add the <code>InternalsVisibleTo</code> to enable my test project to access anything internal on this project.</strong></p>
<p>What does this mean? It means that anything internal, from methods to classes, can be accessed by that specific project.</p>
<p>Now, you can write tests like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenValidCustomer_WhenCheckIfIsValid_ReturnTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> service <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AddCustomerService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> isValid <span class="token operator">=</span> service<span class="token punctuation">.</span><span class="token function">IsValid</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Customer</span><span class="token punctuation">(</span><span class="token string">"Guilherme"</span><span class="token punctuation">,</span> <span class="token string">"gui@guiferreira.me"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> isValid<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenInvalidCustomer_WhenCheckIfIsValid_ReturnFalse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> service <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AddCustomerService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> isValid <span class="token operator">=</span> service<span class="token punctuation">.</span><span class="token function">IsValid</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Customer</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">,</span> <span class="token string">"gui@guiferreira.me"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> isValid<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeFalse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>As you can see, I am invoking <code>IsValid</code>, an internal method. I'm asserting that if I provide a valid customer, it should return "True". So, if I provide an invalid customer, for example, sending an empty name, it should be "False".</p>
<p>If we run the tests, they will succeed.</p>
<p>But now, let's go back and refactor some code.</p>
<p>Let's imagine I want <strong>to perform a refactoring on the <code>IsValid</code> because the method has been growing and becoming too hard to maintain</strong>.</p>
<p>Now you feel that this <strong>method should go to a different Class</strong>. Maybe this Class will be used in another place of your application, for example. So, what will you be doing in that case?</p>
<p>Let's move this into a different Class. I will create a new Class with the name <code>CustomerValidator</code>. This Class will be Internal as well, and I will copy the method into that. Cut and paste.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">class</span> <span class="token class-name">CustomerValidator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">internal</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">IsValid</span><span class="token punctuation">(</span><span class="token class-name">Customer</span> customer<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>customer<span class="token punctuation">.</span>Name <span class="token keyword">is</span> <span class="token punctuation">{</span> Length<span class="token punctuation">:</span> <span class="token operator"><</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>customer<span class="token punctuation">.</span>Email<span class="token punctuation">.</span><span class="token function">IsValidEmail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><br> <span class="token comment">//...</span><br><br> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now we can update the <code>AddCustomerService</code> to:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AddCustomerService</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">CustomerValidator</span> _customerValidator <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Add</span><span class="token punctuation">(</span><span class="token class-name">Customer</span> customer<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>_customerValidator<span class="token punctuation">.</span><span class="token function">IsValid</span><span class="token punctuation">(</span>customer<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">InvalidDataException</span><span class="token punctuation">(</span><span class="token string">"Invalid Customer data"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token comment">// ...</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p><strong>We have to agree that this refactoring has not changed any application behavior. So, in theory, my test should still be Green, am I right? But in fact, they are not.</strong> They will not even compile <strong>because I changed the structure of my application</strong>.</p>
<h2>🔀 What's the alternative?</h2>
<p>What if the tests were like this?</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Alternative_GivenValidCustomer_WhenCheckIfIsValid_ReturnTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> service <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AddCustomerService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> action <span class="token operator">=</span><br> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> service<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Customer</span><span class="token punctuation">(</span><span class="token string">"Guilherme"</span><span class="token punctuation">,</span> <span class="token string">"gui@guiferreira.me"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> action<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">NotThrow</span><span class="token generic class-name"><span class="token punctuation"><</span>InvalidDataException<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Alternative_GivenInvalidCustomer_WhenCheckIfIsValid_ReturnFalse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> service <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AddCustomerService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> action <span class="token operator">=</span><br> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> service<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Customer</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">,</span> <span class="token string">"gui@guiferreira.me"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> action<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Throw</span><span class="token generic class-name"><span class="token punctuation"><</span>InvalidDataException<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>They are performing the same assertion. Better than that, our refactoring didn't break them.
<strong>These tests, instead of depending on internal methods, are going through the public interface.</strong></p>
<p>And why do I do this? Because <strong>any change to internal things should have no reflection on the outside behavior through the public contracts</strong>. And while <strong>changing the public Contract may be a tremendous problem</strong> for you, <strong>changes to Internal and Private things should be frictionless</strong>.</p>
<p>My point is that when you use the <code>InternalsVisibleTo</code> for the sake of testing, more often than not, you will be structure dependent. You are testing the code structure instead of the behavior of your application.</p>
<h2>📦 The exception to the rule</h2>
<p><strong>There's one scenario that I believe <code>InternalsVisibleTo</code> may be useful</strong>, and let me explain why.</p>
<p>Let's look into this open-source project, <a href="https://github.com/octokit/octokit.net">octokit.net</a>. It's a GitHub API client.
Let's take a look at this example.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> github <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">GitHubClient</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">ProductHeaderValue</span><span class="token punctuation">(</span><span class="token string">"MyAmazingApp"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">await</span> github<span class="token punctuation">.</span>User<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">"half-ogre"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>Followers <span class="token operator">+</span> <span class="token string">" folks love the half ogre!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Here you can see how you can use it. If you look into this snippet, you can see that what we'll be doing if we want to use this code is that we simply instantiate the GitHub client.</p>
<p>So what does this mean? It means that when you call the <code>User.Get</code>, there's an HTTP request to the GitHub API.</p>
<p>So what's the relationship between this I'm showing you and the <code>InternalsVisibleTo</code>?</p>
<p>In a scenario like this, <strong>I might want to define a clear and strict contract with the outside world to publish a library. So, I don't want to expose extra things. I want to provide a lean public contract to optimize the consumer developer experience.</strong></p>
<p>So, to test my library, the GitHub Client, I may struggle to avoid invoking the real API or run a fake/mock server to test it. So, in some cases like this, <strong>when exposing a library, it may be super useful to have the <code>InternalsVisibleTo</code> to do a kind of subcutaneous test where you don't use the real API.</strong></p>
<p>For most of the tests, you want to be sure they run fast. So, you can go through this approach.</p>
<p>It's common to see people advocating for the <code>InternalsVisibleTo</code>, saying that even Microsoft on the .NET repos uses this a lot (which is true). However, it's true because Microsoft is building libraries and frameworks like this GitHub Client API. So, they need to do that, so we don't suffer as consumers. <strong>In public libraries, the friction of adoption is an important concern</strong>. We need to think about developer experience.</p>
<p>And now, do you agree with me? Will you keep using <code>InternalsVisibleTo</code>?</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
3 Types of Unit Tests (for C# Developers)2022-12-22T00:00:00-00:00https://guiferreira.me/archive/2022/3-types-of-unit-tests-for-csharp-developers/<p>You can group your unit tests into 3 types. Knowing those 3 types will guide you to simple and maintainable tests.</p>
<p>Those types are based on the outcome the test wants to assert.</p>
<p>They are <strong>Result</strong>, <strong>State</strong>, and <strong>Component Interaction</strong>.</p>
<p>Let's see it in action.</p>
<h2>1️⃣ Result</h2>
<p>A Result Test is when a <strong>test asserts a behavior based on the result value or exception</strong>.</p>
<p>This is the most common type of test.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Result</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> TextTools<span class="token punctuation">.</span><span class="token function">CountWords</span><span class="token punctuation">(</span><span class="token string">"Hello World"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2>2️⃣ State</h2>
<p>A State Test is when <strong>to assert a behavior after calling a method, needs to assert state changes on an object</strong>.</p>
<p>It's usual to see this type of test when facing strong domain models.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">State</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"Shoes"</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> order<span class="token punctuation">.</span><span class="token function">AddProduct</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Product</span><span class="token punctuation">(</span><span class="token string">"T-Shirt"</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> order<span class="token punctuation">.</span>TotalAmount<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">110</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2>3️⃣ Component interaction</h2>
<p>A Component Interaction Test is <strong>when the outcome of a behavior it's indirectly observed by observing the impact on external dependencies</strong>.</p>
<p>This type of test is common when testing Services or Command Handlers that need to call underlying data stores.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task</span> <span class="token function">ComponentInteraction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> fakeOrderRepository <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">FakeOrderRepository</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> service <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderService</span><span class="token punctuation">(</span>fakeOrderRepository<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">await</span> service<span class="token punctuation">.</span><span class="token function">ProcessNewOrder</span><span class="token punctuation">(</span>order<span class="token punctuation">,</span> <span class="token keyword">default</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token keyword">await</span> fakeOrderRepository<span class="token punctuation">.</span><span class="token function">GetAsync</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Number<span class="token punctuation">)</span><span class="token punctuation">;</span><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">NotBeNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>But Component Interaction Tests can be dangerous.
So, I highly recommend checking <a href="https://guiferreira.me/archive/2022/how-structure-sensitive-tests-make-refactorings-fail/">this article</a>.</p>
<p>https://www.youtube.com/watch?v=KaW1HNnhOME</p>
<p>Let me know what you think about it. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
3 Fluent Assertions Features You Should be Using2022-12-07T00:00:00-00:00https://guiferreira.me/archive/2022/3-fluent-assertions-features-you-should-be-using/<p>I love <a href="https://fluentassertions.com/">Fluent Assertions</a> 💖. And you should too.</p>
<p>Even if you are using it, maybe you don't know some lesser-known features of it.</p>
<p>But don't worry. I'm here to change that 💪.</p>
<p>Here are 3 features you should know if you are using Fluent Assertions.</p>
<h2>1️⃣ Assertion Scopes</h2>
<p>Take a look into the following test:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> Code <span class="token operator">=</span> <span class="token string">"GF"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token function">Process</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>result<span class="token punctuation">.</span>Successful<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>result<span class="token punctuation">.</span>ErrorCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeNullOrEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>To assert a given behavior this test executes two assertions through Fluent Assertions, as you can see.</p>
<pre class="language-csharp"><code class="language-csharp">result<span class="token punctuation">.</span>Successful<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>result<span class="token punctuation">.</span>ErrorCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeNullOrEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>If you execute this test and the first assertion fail, you will not know if there's any problem with the following one.</p>
<pre class="language-bash"><code class="language-bash">Xunit.Sdk.XunitException<br>Expected result.Successful to be true, but found False.</code></pre>
<p>Assertion Scopes solve that. When you use assertion scopes, all the assertions execute before returning the result.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> Code <span class="token operator">=</span> <span class="token string">"GF"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token function">Process</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">using</span> <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">AssertionScope</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> result<span class="token punctuation">.</span>Successful<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> result<span class="token punctuation">.</span>ErrorCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeNullOrEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>So, the result would be:</p>
<pre class="language-bash"><code class="language-bash">Xunit.Sdk.XunitException<br>Expected result.Successful to be true, but found False.<br>Expected result.ErrorCode to be <span class="token operator"><</span>null<span class="token operator">></span> or empty, but found <span class="token string">"invalid_code"</span><span class="token builtin class-name">.</span></code></pre>
<h2>2️⃣ HttpResponseMessages</h2>
<p>Do you write tests against APIs? So, this one is for you.</p>
<p>When we assert the result of a HTTP call, it's common to check the HTTP Status Code.
You may be doing it like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">HttpRequestAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>BadRequest<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>With Fluent Assertions, you can simply convert it into this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">HttpRequestAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>response<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">HaveStatusCode</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>BadRequest<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>What if you want to test if it was a success request (Status Code in the 2xx range)?
With Fluent Assertions, you can do it in this elegant way:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">HttpRequestAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">//2xx</span><br>response<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeSuccessful</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The same applies to Client Errors (4xx) or Server Errors (5xx).</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">HttpRequestAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">//2xx</span><br>response<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeSuccessful</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token comment">//4xx</span><br>response<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">HaveClientError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token comment">//5xx</span><br>response<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">HaveServerError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>3️⃣ DateTime Features</h2>
<p>Date and Time assertions is so elegant.</p>
<p>Take a look into this little details.</p>
<p>If you want to define an expected date, you can do it like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// instead of: new DateTime(2022, 12, 25);</span><br><span class="token class-name"><span class="token keyword">var</span></span> expectedDate <span class="token operator">=</span> <span class="token number">25</span><span class="token punctuation">.</span><span class="token function">December</span><span class="token punctuation">(</span><span class="token number">2022</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Do you want to define the time? No problem:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// instead of: new DateTime(2022, 12, 25, 20, 00, 00);</span><br><span class="token class-name"><span class="token keyword">var</span></span> expectedDate <span class="token operator">=</span> <span class="token number">25</span><span class="token punctuation">.</span><span class="token function">December</span><span class="token punctuation">(</span><span class="token number">2022</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">At</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">00</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>What about checking if the date is Greater or Equal to an expected date?</p>
<pre class="language-csharp"><code class="language-csharp">date<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeOnOrAfter</span><span class="token punctuation">(</span>expectedDate<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Is the DateTime in Local Time or UTC?</p>
<pre class="language-csharp"><code class="language-csharp">expectedDate<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeIn</span><span class="token punctuation">(</span>DateTimeKind<span class="token punctuation">.</span>Utc<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This are just a few examples of what you can do with DateTimes in Fluent Assertions.</p>
<h2>⭐️ Bonus Feature</h2>
<p>There's a bonus feature that you should know.
Do you know you can implement architecture tests with Fluent Assertions?
Take a look at <a href="https://youtu.be/e4w2qePKcTE">this video</a> to see how to apply it.</p>
<p>If you want to see them in action, take a look at this video 👇</p>
<p>https://www.youtube.com/watch?v=7ROVlJ1cQWs</p>
<p>Let me know what you think about it. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
How to Organize your .NET Dependency Injection Configuration2022-12-02T00:00:00-00:00https://guiferreira.me/archive/2022/how-to-organize-your-net-dependency-injection-configuration/<p>How big is your dependency injection configuration file?</p>
<p>Too big? Is your <code>Program.cs</code> or <code>Startup.cs</code> so huge that you can't find anything without using Search 🔎?</p>
<p>Don't worry. We have all been there.</p>
<p>The good news is that we can fix that quickly with a simple technique.</p>
<p>Here is a way to break it down.</p>
<h2>📜 The Existing Convention</h2>
<p>Have you noticed that ASP.NET uses a convention to register components on Dependency Injection? If not, I bet you have been using them for sure.</p>
<p><strong>Methods like <code>AddControllers</code> or <code>AddEndpoints</code> follow a convention.</strong>
According to the convention, similar things are added to Dependency Configuration using an "Add Something" extension method.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">IMvcBuilder</span> <span class="token function">AddControllers</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">IServiceCollection</span> services<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token comment">//...</span><br><span class="token punctuation">}</span></code></pre>
<p>This idea is the root of my preferred approach. But I don't take it to the letter.</p>
<h2>📦 Solution</h2>
<p>My approach goes in a different direction, because <strong>I don't group by similarity. I prefer to group by Feature.</strong></p>
<p>What does that mean? It means that instead of having an <code>AddServices</code>, <code>AddRepositories</code>, or <code>AddCommandHandlers</code>, I prefer to have an <code>AddCancelOrderFeature</code> that contains Services, Repositories, Commands, Command Handlers, etc.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">DependencyInjectionExtensions</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">IServiceCollection</span> <span class="token function">AddFeatureAddBookRead</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">IServiceCollection</span> serviceCollection<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> serviceCollection<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddScoped</span><span class="token generic class-name"><span class="token punctuation"><</span>IAddBookRead<span class="token punctuation">,</span> AddBookRead<span class="token punctuation">.</span>AddBookRead<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> serviceCollection<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">DependencyInjectionExtensions</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">IServiceCollection</span> <span class="token function">AddPostgreBookReadStore</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">IServiceCollection</span> serviceCollection<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> serviceCollection<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">TryAddTransient</span><span class="token generic class-name"><span class="token punctuation"><</span>IDbConnection<span class="token punctuation">></span></span></span><span class="token punctuation">(</span>sp<br> <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">NpgsqlConnection</span><span class="token punctuation">(</span><span class="token string">"connectionString"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> serviceCollection<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddScoped</span><span class="token generic class-name"><span class="token punctuation"><</span>IBookReadStore<span class="token punctuation">,</span> PostgreBookReadStore<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> serviceCollection<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>I added this code as an extension method to the Project/Adapter they are part of.</p>
<p>Now, you can replace many lines of your <code>Program.cs</code> or <code>Startup.cs</code> with something as simple as this:</p>
<pre class="language-csharp"><code class="language-csharp">builder<span class="token punctuation">.</span>Services<br> <span class="token punctuation">.</span><span class="token function">AddFeatureAddBookRead</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddPostgreBookReadStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>The configuration becomes extremely clear and maintainable.</strong></p>
<p>Another benefit of this approach is that swapping adapters becomes really simple.
As an example, on the example above, changing the existing store from PostgreSQL to DynamoDB would mean invoking a different method on the configuration. That can even be behind a feature flag.</p>
<h2>🔀 Other Ways</h2>
<p>There are two other common ways that people use to break it down.</p>
<p>One is extracting methods inside the <code>Program.cs</code> or <code>Startup.cs</code>. Why don't I do it? Because even being a better way than having everything on the <code>ConfigureServices</code>, we still have a massive unmanageable class. Besides that, I believe each adapter is responsible for providing easy and simple configuration methods that the Dependency Configuration can use.</p>
<p>The other common approach is relying on dependency auto-discovery. In this approach, you will dynamically find dependencies on your assemblies to configure. You can use a library like <a href="https://github.com/khellang/Scrutor">Scrutor</a> to achieve that.
Even knowing that this approach throws away much of the code needed to configure dependencies, <strong>I prefer to avoid "magic".</strong> I like when something as dependency becomes explicit because I've seen systems not behaving as expected because the incorrect dependency was injected on runtime. And magic, my friends, it's hard to review on a Pull Request.</p>
<h2>👋 Wrapping up</h2>
<p>There's only one open question. What should we call these extension methods? You can find the answer in <a href="https://guiferreira.me/archive/2022/the-missing-project-that-fixes-everything-in-dotnet/">this blog post</a>.</p>
<p>If you want to see me refactoring towards this solution, take a look at this video 👇</p>
<p>https://www.youtube.com/watch?v=huFpOOtBdvU</p>
<p>Let me know what you think about it. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
How Structure Sensitive Tests Make Refactoring's Fail2022-11-23T00:00:00-00:00https://guiferreira.me/archive/2022/how-structure-sensitive-tests-make-refactorings-fail/<p><strong>Why do most refactoring attempts fail?</strong></p>
<p>You refactor your code, and hundreds of tests go Red.</p>
<p>Even then, you know that the system is still working as expected. You didn't change its behavior.</p>
<p>This is when developers start mistrusting tests.</p>
<p>And <strong>it all happens due to Structure Sensitive Tests</strong>.</p>
<h2>Structure Sensitive Tests</h2>
<p>Take a look at the following code.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IPremiumClientDiscountCalculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> <span class="token function">Calculate</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">decimal</span></span> totalValue<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">class</span> <span class="token class-name">PremiumClientDiscountCalculator</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IPremiumClientDiscountCalculator</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> <span class="token function">Calculate</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">decimal</span></span> totalValue<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> totalValue <span class="token operator">>=</span> <span class="token number">1000</span> <span class="token punctuation">?</span> <span class="token number">.12M</span> <span class="token punctuation">:</span> <span class="token number">.10M</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderDiscountCalculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">IPremiumClientDiscountCalculator</span> _premiumClientDiscount<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token function">OrderDiscountCalculator</span><span class="token punctuation">(</span><span class="token class-name">IPremiumClientDiscountCalculator</span> premiumClientDiscount<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _premiumClientDiscount <span class="token operator">=</span> premiumClientDiscount<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> <span class="token function">Calculate</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>Client<span class="token punctuation">.</span>Tier <span class="token keyword">is</span> <span class="token class-name">Client<span class="token punctuation">.</span>Tiers<span class="token punctuation">.</span>Premium</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> _premiumClientDiscount<span class="token punctuation">.</span><span class="token function">Calculate</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Total<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">decimal</span><span class="token punctuation">)</span><span class="token number">0.12</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now consider the following test.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenPremiumClientAndTotalAbove1000_ThenReturns12PercentDiscount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> premiumClientDiscountMock <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Mock<span class="token punctuation"><</span>IPremiumClientDiscountCalculator<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> premiumClientDiscountMock<span class="token punctuation">.</span><span class="token function">Setup</span><span class="token punctuation">(</span>m <span class="token operator">=></span> m<span class="token punctuation">.</span><span class="token function">Calculate</span><span class="token punctuation">(</span>It<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">IsAny</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">decimal</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Returns</span><span class="token punctuation">(</span><span class="token number">.12M</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Verifiable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> calculator <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderDiscountCalculator</span><span class="token punctuation">(</span>premiumClientDiscountMock<span class="token punctuation">.</span>Object<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Client <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Client</span> <span class="token punctuation">{</span> Tier <span class="token operator">=</span> Client<span class="token punctuation">.</span>Tiers<span class="token punctuation">.</span>Premium <span class="token punctuation">}</span><span class="token punctuation">,</span><br> Total <span class="token operator">=</span> <span class="token number">1001</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> discount <span class="token operator">=</span> calculator<span class="token punctuation">.</span><span class="token function">Calculate</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> discount<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">.12M</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> premiumClientDiscountMock<span class="token punctuation">.</span><span class="token function">VerifyAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>Did you notice the <code>Verify</code> on the test? That <code>Verify</code> ensures that the Mock is being used.</p>
<p>If you decide to refactor the implementation and copy the Premium Discount Logic into the Calculator, like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderDiscountCalculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">IPremiumClientDiscountCalculator</span> _premiumClientDiscount<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token function">OrderDiscountCalculator</span><span class="token punctuation">(</span><span class="token class-name">IPremiumClientDiscountCalculator</span> premiumClientDiscount<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _premiumClientDiscount <span class="token operator">=</span> premiumClientDiscount<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> <span class="token function">Calculate</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>Client<span class="token punctuation">.</span>Tier <span class="token keyword">is</span> <span class="token class-name">Client<span class="token punctuation">.</span>Tiers<span class="token punctuation">.</span>Premium</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> order<span class="token punctuation">.</span>Total <span class="token operator">>=</span> <span class="token number">1000</span> <span class="token punctuation">?</span> <span class="token number">.12M</span> <span class="token punctuation">:</span> <span class="token number">.10M</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">decimal</span><span class="token punctuation">)</span><span class="token number">0.12</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Once we run the tests, what do you think will happen? This time they will fail.</p>
<p>The problem is not that they fail. The problem is that they fail but not because the system is wrong.</p>
<h2>Structure Insensitive Tests</h2>
<p>As you know, <strong>a refactor shouldn't break tests</strong>.</p>
<p>Tests should be sensitive to behavior and not structure.</p>
<p>And how to do that? You avoid any checks related to the underlying implementation and you focus on the behaviour.
So, we can instead write a test focused only on the behaviour, as the following:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenPremiumClientAndTotalAbove1000_ThenReturns12PercentDiscount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> calculator <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">OrderDiscountCalculator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> order <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Order</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Client <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Client</span> <span class="token punctuation">{</span> Tier <span class="token operator">=</span> Client<span class="token punctuation">.</span>Tiers<span class="token punctuation">.</span>Premium <span class="token punctuation">}</span><span class="token punctuation">,</span><br> Total <span class="token operator">=</span> <span class="token number">1001</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> discount <span class="token operator">=</span> calculator<span class="token punctuation">.</span><span class="token function">Calculate</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> discount<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">.12M</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>And you can refactor your code like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OrderDiscountCalculator</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">PremiumClientDiscountCalculator</span> _premiumClientDiscount<br> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">decimal</span></span> <span class="token function">Calculate</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>Client<span class="token punctuation">.</span>Tier <span class="token keyword">is</span> <span class="token class-name">Client<span class="token punctuation">.</span>Tiers<span class="token punctuation">.</span>Premium</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> _premiumClientDiscount<span class="token punctuation">.</span><span class="token function">Calculate</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Total<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token number">.05M</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>As you can see, now the test succeeds. We don't use mocks. The <code>PremiumClientDiscountCalculator</code> is an internal design decision, that has no impact on the behaviour. Now, we can refactor the Calculator as we wish.</p>
<p><strong>Structure Insensitive is one of the key properties of a good test.</strong></p>
<p>Readability is another, so you may want to take a look at <a href="https://guiferreira.me/archive/2022/the-missing-project-that-fixes-everything-in-dotnet/">this post</a>.</p>
<p>And remember that when you test internal or private classes/methods, you are likely making your tests Structure Sensitive.</p>
<p>Let me know what you think about it. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
The Biggest Folder Structure Mistake on .NET2022-11-17T00:00:00-00:00https://guiferreira.me/archive/2022/the-biggest-folder-structure-mistake-on-net/<p>If you organize your project folder structure like this, you are making a huge mistake.</p>
<p><img src="https://guiferreira.me/images/archive/architecture/librarian-folder-structure.png" alt="Librarian folder structure approach"></p>
<pre class="language-bash"><code class="language-bash">/CommandHandlers/AddOrderCommandHandler.cs<br>/CommandHandlers/AddProductCommandHandler.cs<br>/CommandHandlers/CancelOrderCommandHandler.cs<br>/Repositories/ProductsRepository.cs<br>/Repositories/OrderRepository.cs<br>/Commands/AddProductCommand.cs<br>/Commands/AddOrderCommand.cs<br>/Commands/CancelOrderCommand.cs<br>/Validators/AddOrderCommandValidator.cs<br>/Validators/AddProductCommandValidator.cs</code></pre>
<p>It's a simple mistake that can cause a lot of frustration, especially to the new joiners.
The good news is that you can go from this to this with a simple technique.</p>
<blockquote>
<p><strong>Don't organize like a Librarian.
Organize by action/utility.</strong></p>
</blockquote>
<p>Let's take a look.</p>
<h2>📚 The Librarian Approach</h2>
<p>It's common to see <strong>projects organized around technical concerns</strong>.</p>
<p>We build buckets like Repositories, Services, Validators, and Mappers and group everything according to that.</p>
<p>The problem is that it <strong>becomes hard to find anything</strong>. Until you are familiar with a code base, it's hard to know where a feature-related code lands. So, <strong>the cognitive load required to perform increments, refactoring's, or navigate the code, is high</strong>.</p>
<p>Grouping that way, <strong>objects naturally will have a vast scope.</strong> For example, a Repository or a Service may be the home of code related to multiple features.</p>
<p><strong>To this, I call a Librarian approach to structure code. When we organize it by category as if code is a book.</strong></p>
<h3>The MVC Problem</h3>
<p>Some templates naturally lead to technological segregation, which reinforces this problem.
Yes, MVC, I'm talking about you.</p>
<p>When we create a new MVC API, we get a Controllers, Models, and Views folder. MVC invites us to organize by technology once again.</p>
<p><img src="https://guiferreira.me/images/archive/architecture/mvc-folder-structure.png" alt="MVC folder structure approach"></p>
<h2>🎯 The Solution</h2>
<p>It's easy to find a book in a Library using the category system. It's even better that we can easily find related books together.</p>
<p>But do we need the same approach in source code? No.</p>
<p>A single feature will have code across files with several responsibilities (categories). <strong>When we access code for maintainability, we do it in the context of a Feature.</strong> That's the most common access pattern. So, how should we organize it instead? The rule is simple.</p>
<blockquote>
<p><strong>Don't organize like a Librarian.
Organize by action/utility.</strong></p>
</blockquote>
<p>What does that mean?</p>
<ul>
<li>We should think about how the code will be used, accessed, and maintained.</li>
<li>We should think about what code will evolve together.</li>
<li>We should think about how to reduce the cognitive load of future actions.</li>
</ul>
<p>This is the Feature Folders concept in a nutshell.
These will lead you to Screaming Architecture from Clean Architecture.</p>
<p>So, the structure that we have seen at the beginning of this post can be refactored into:</p>
<p><img src="https://guiferreira.me/images/archive/architecture/feature-folder-structure.png" alt="Feature folder structure approach"></p>
<pre class="language-bash"><code class="language-bash">/CancelOrder/ICancelOrderRepository.cs<br>/CancelOrder/CancelOrderCommand.cs<br>/CancelOrder/CancelOrderCommandHandler.cs<br>/AddOrder/AddOrderCommandHandler.cs<br>/AddOrder/IAddOrderRepository.cs<br>/AddOrder/AddOrderCommand.cs<br>/AddOrder/AddOrderCommandValidator.cs<br>/AddProduct/AddProductCommand.cs<br>/AddProduct/AddProductCommandHandler.cs<br>/AddProduct/AddProductCommandValidator.cs</code></pre>
<h3>What about MVC?</h3>
<p>If you want to organize your API differently, you have several options:</p>
<ul>
<li>You can adapt <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-7.0">Minimal APIs</a> (my preferred way).</li>
<li>You can use API Endpoints (<a href="https://github.com/ardalis/ApiEndpoints">see here</a>).</li>
<li>You can use Feature Folders (<a href="https://scottsauber.com/2016/04/25/feature-folder-structure-in-asp-net-core/">see here</a>).</li>
</ul>
<h2>🏗 The Structure Besides the Project</h2>
<p>It doesn't mean you should keep adapters to the outside world inside the same folder and project.</p>
<p>Adapters need to be swappable. You can find an in-depth explanation <a href="https://guiferreira.me/archive/2022/how-to-apply-hexagonal-architecture-with-dotnet/">here</a>.</p>
<p>If you want to see me performing the refactoring, take a look at this video 👇</p>
<p>https://www.youtube.com/watch?v=rYnbspEcKJw</p>
<p>Let me know what you think about it. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
I Built the Netflix Intro on a .NET Console, and this is how I've done it2022-11-10T00:00:00-00:00https://guiferreira.me/archive/2022/i-built-the-netflix-intro-on-a-dotnet-console-and-this-is-how-i-have-done-it/<p>I've recreated the Netflix Intro on a .NET Console. 🤯</p>
<p>And I will explain to you how.</p>
<h2>🧐 Why do it?</h2>
<p>I've watched a video of a <a href="https://www.youtube.com/c/kevinparry">Kevin Parry</a> <a href="https://www.youtube.com/watch?v=M1qj21eBzNc">recreating the Netflix Intro using yarn</a>, and I asked myself: <em>Would I be able to do it with .NET on a Terminal?</em></p>
<p>Will I be using it in production? The answer is No.
But it's a fun challenge, and I was curious like a cat 🐱.</p>
<h2>🏔 The challenge</h2>
<p>How can I build an animation using visuals and audio on a <strong>Terminal that looks like the Netflix Intro</strong>?</p>
<p>So, I decided to split the problem in two.</p>
<ol>
<li>How to display an animation.</li>
<li>How to play sound at the same time.</li>
</ol>
<h2>🖥 How to display the animation</h2>
<p>These days, when I think about a good terminal experience and .NET, I think about <a href="https://spectreconsole.net/">Spectre.Console</a>. So, that was where I headed.</p>
<p>Spectre has a <a href="https://spectreconsole.net/widgets/canvas-image">canvas image</a>, and that made me think about GIFs. Spectre Image Canvas will not display a moving GIF, but a GIF isn't much more than a sequence of images. So, can I do the same?</p>
<p>There's a cool library part of the <a href="https://www.mono-project.com/">mono project</a>, <a href="https://github.com/mono/SkiaSharp">SkiaSharp</a>, that can access the metadata of an image. After exploring the samples on GitHub, I realized that SkiaSharp extracts GIF frames and frame duration.</p>
<p>Now, the question was: <em>Now that I have the Frames, how can I display them in movement?</em> I don't want to render frame after frame. They need to render in the same place, the same square, and the same coordinates.</p>
<p>The good news is that Spectre.Console has a <a href="https://spectreconsole.net/live/live-display">Live Display</a> widget.</p>
<p>The <strong>Live Display can update components in place</strong>, so it is perfect for the job.</p>
<h3>👨🎨 Animation in practice</h3>
<p>Now that we have a strategy, the first step is to get a Netflix Intro GIF. A quick google search will do that for me.</p>
<p>Having the GIF, I bring it into a simple .NET Console application. Make sure that the GIF is copied to the output directory.</p>
<p>Install <code>Spectre.Console</code>, <code>SkiaSharp</code>, and I'm ready to go.</p>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> package Spectre.Console<br>dotnet <span class="token function">add</span> package SkiaSharp</code></pre>
<p>The following code will get the frames, iterate through them, and display them on the Terminal.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">SkiaSharp</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Spectre<span class="token punctuation">.</span>Console</span><span class="token punctuation">;</span><br><br><span class="token keyword">await</span> AnsiConsole<span class="token punctuation">.</span><span class="token function">Live</span><span class="token punctuation">(</span>Text<span class="token punctuation">.</span>Empty<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">StartAsync</span><span class="token punctuation">(</span><span class="token keyword">async</span> ctx <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> stream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKManagedStream</span><span class="token punctuation">(</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">FileStream</span><span class="token punctuation">(</span><span class="token string">"netflix.gif"</span><span class="token punctuation">,</span> FileMode<span class="token punctuation">.</span>Open<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> codec <span class="token operator">=</span> SKCodec<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> frames <span class="token operator">=</span> codec<span class="token punctuation">.</span>FrameInfo<span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> info <span class="token operator">=</span> codec<span class="token punctuation">.</span>Info<span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> bitmap <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKBitmap</span><span class="token punctuation">(</span>info<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> frame <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> frame <span class="token operator"><</span> frames<span class="token punctuation">.</span>Length<span class="token punctuation">;</span> frame<span class="token operator">++</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> opts <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKCodecOptions</span><span class="token punctuation">(</span>frame<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>codec<span class="token punctuation">?.</span><span class="token function">GetPixels</span><span class="token punctuation">(</span>info<span class="token punctuation">,</span> bitmap<span class="token punctuation">.</span><span class="token function">GetPixels</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> opts<span class="token punctuation">)</span> <span class="token operator">!=</span> SKCodecResult<span class="token punctuation">.</span>Success<span class="token punctuation">)</span> <span class="token keyword">continue</span><span class="token punctuation">;</span><br><br> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> memStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> wStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKManagedWStream</span><span class="token punctuation">(</span>memStream<span class="token punctuation">)</span><span class="token punctuation">;</span><br> bitmap<span class="token punctuation">.</span><span class="token function">Encode</span><span class="token punctuation">(</span>wStream<span class="token punctuation">,</span> SKEncodedImageFormat<span class="token punctuation">.</span>Jpeg<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> memStream<span class="token punctuation">.</span>Position <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> data <span class="token operator">=</span> memStream<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> canvasImage <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">CanvasImage</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">MaxWidth</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> ctx<span class="token punctuation">.</span><span class="token function">UpdateTarget</span><span class="token punctuation">(</span>canvasImage<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> duration <span class="token operator">=</span> frames<span class="token punctuation">[</span>frame<span class="token punctuation">]</span><span class="token punctuation">.</span>Duration<span class="token punctuation">;</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>duration <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span><br> duration <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">;</span><br> <span class="token keyword">await</span> Task<span class="token punctuation">.</span><span class="token function">Delay</span><span class="token punctuation">(</span>duration<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token punctuation">}</span><br><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>🎧 How to trigger sound</h2>
<p>The visual animation without that famous <em>"Tuduuuummmmmmmmm"</em> doesn't have the same feeling.</p>
<p>Unfortunately, <strong>there's no easy way of triggering it since .NET Core</strong>.</p>
<p><em>It's important to say that I was building it on macOS. The solution I will implement may not be the same on Windows, but the approach would be.</em></p>
<p>Since I couldn't rely on .NET to play the sound, <strong>I decided to trigger a process using an application that could do it</strong>. On macOS, I can run <code>afplay</code> with the path to an audio file, and it will play.</p>
<pre class="language-bash"><code class="language-bash">afplay netflix.mp3</code></pre>
<h3>🎶 Sound in practice</h3>
<p>Once again, the first step is getting the Netflix Intro audio. Nothing that a Google Search can't resolve.</p>
<p>Download the audio file to the project folder and make sure it is copied to the output directory.</p>
<p>To start the process, I decided to use <a href="https://github.com/Tyrrrz/CliWrap">CliWrap</a>, a cool open-source project that simplifies the process.</p>
<p>With CliWrap, it's as simple as 👇</p>
<pre class="language-csharp"><code class="language-csharp">Cli<br> <span class="token punctuation">.</span><span class="token function">Wrap</span><span class="token punctuation">(</span><span class="token string">"afplay"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithArguments</span><span class="token punctuation">(</span><span class="token string">"netflix.mp3"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ExecuteAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now that I have a way to play it, I just need to decide how.</p>
<p>Since I'm going through each frame, one option it's to start it when the first frame is rendered.</p>
<p>So, let's do it.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">CliWrap</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">SkiaSharp</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Spectre<span class="token punctuation">.</span>Console</span><span class="token punctuation">;</span><br><br><span class="token keyword">await</span> AnsiConsole<span class="token punctuation">.</span><span class="token function">Live</span><span class="token punctuation">(</span>Text<span class="token punctuation">.</span>Empty<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">StartAsync</span><span class="token punctuation">(</span><span class="token keyword">async</span> ctx <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> stream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKManagedStream</span><span class="token punctuation">(</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">FileStream</span><span class="token punctuation">(</span><span class="token string">"netflix.gif"</span><span class="token punctuation">,</span> FileMode<span class="token punctuation">.</span>Open<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> codec <span class="token operator">=</span> SKCodec<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> frames <span class="token operator">=</span> codec<span class="token punctuation">.</span>FrameInfo<span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> info <span class="token operator">=</span> codec<span class="token punctuation">.</span>Info<span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> bitmap <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKBitmap</span><span class="token punctuation">(</span>info<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> frame <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> frame <span class="token operator"><</span> frames<span class="token punctuation">.</span>Length<span class="token punctuation">;</span> frame<span class="token operator">++</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> opts <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKCodecOptions</span><span class="token punctuation">(</span>frame<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>codec<span class="token punctuation">?.</span><span class="token function">GetPixels</span><span class="token punctuation">(</span>info<span class="token punctuation">,</span> bitmap<span class="token punctuation">.</span><span class="token function">GetPixels</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> opts<span class="token punctuation">)</span> <span class="token operator">!=</span> SKCodecResult<span class="token punctuation">.</span>Success<span class="token punctuation">)</span> <span class="token keyword">continue</span><span class="token punctuation">;</span><br><br> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> memStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> wStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SKManagedWStream</span><span class="token punctuation">(</span>memStream<span class="token punctuation">)</span><span class="token punctuation">;</span><br> bitmap<span class="token punctuation">.</span><span class="token function">Encode</span><span class="token punctuation">(</span>wStream<span class="token punctuation">,</span> SKEncodedImageFormat<span class="token punctuation">.</span>Jpeg<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> memStream<span class="token punctuation">.</span>Position <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> data <span class="token operator">=</span> memStream<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> canvasImage <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">CanvasImage</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">MaxWidth</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> ctx<span class="token punctuation">.</span><span class="token function">UpdateTarget</span><span class="token punctuation">(</span>canvasImage<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>frame <span class="token keyword">is</span> <span class="token number">0</span><span class="token punctuation">)</span><br> _ <span class="token operator">=</span> Task<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">Play</span><span class="token punctuation">(</span><span class="token string">"netflix.mp3"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> duration <span class="token operator">=</span> frames<span class="token punctuation">[</span>frame<span class="token punctuation">]</span><span class="token punctuation">.</span>Duration<span class="token punctuation">;</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>duration <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span><br> duration <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">;</span><br> <span class="token keyword">await</span> Task<span class="token punctuation">.</span><span class="token function">Delay</span><span class="token punctuation">(</span>duration<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token punctuation">}</span><br><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><br><span class="token keyword">static</span> <span class="token return-type class-name">Task</span> <span class="token function">Play</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> filename<span class="token punctuation">)</span> <span class="token operator">=></span><br> Cli<br> <span class="token punctuation">.</span><span class="token function">Wrap</span><span class="token punctuation">(</span><span class="token string">"afplay"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithArguments</span><span class="token punctuation">(</span>filename<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ExecuteAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>As you can see, the Play method will be invoked only on the first frame. I don't <code>await</code> for the task because I want them running side by side.</p>
<p>Now, it's time to run it.</p>
<p><img src="https://guiferreira.me/images/archive/dotnet/netflix-intro-dotnet-console.png" alt="Netflix Intro on a .NET Console"></p>
<p>If you are curious about the result, and you want to see it in action, I have a video here 👇</p>
<p>https://www.youtube.com/watch?v=fgm2I8aSDNg</p>
<p>Let me know what you think about it. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
DateTimeOffset vs DateTime - What's the difference?2022-10-25T00:00:00-00:00https://guiferreira.me/archive/2022/datetimeoffset-vs-datetime-whats-the-difference/<p>Do you use DateTime everywhere? Do you know that <strong>Microsoft recommends DateTimeOffset as the default option</strong>?</p>
<p><em>"consider DateTimeOffset as the default date and time type for application development."</em>
(<a href="https://learn.microsoft.com/en-us/dotnet/standard/datetime/choosing-between-datetime">here</a>)</p>
<p>But why? We know that DateTime can be risky. Who has never suffered from a missing UTC Conversion?! (crickets sound)</p>
<p>Who has not realized too late in the project that time localization was needed against all the odds?</p>
<h2>What's the problem with DateTime?</h2>
<p>For those who may not know, a <a href="https://learn.microsoft.com/en-us/dotnet/api/system.datetime">DateTime</a> value represents a date and time. There you can find a Kind property that provides data about the Time Zone. The problem is that it is limited. You have 3 possible values: Local (machine time zone), UTC, or Unspecified. That is not enough in a world with more than 40 time zones.</p>
<p><img src="https://guiferreira.me/images/archive/dotnet/datetimekind.png" alt="DateTimeKind"></p>
<p><strong>DateTime can't capture the exact moment of an event.</strong> It's common to enforce that we only deal with UTC inside the system boundaries. The problem is that it requires discipline, which is difficult to enforce after a long period. And besides that, we can't say the original local time anymore.</p>
<h3>Scenario</h3>
<p>Imagine that you are building a monitoring system for your company.</p>
<p>Your company has offices across multiple time zones.</p>
<p>One of the system requirements is that it should notify the person On Call if the alert happens outside of working hours. Alerts are triggered in the time zone where the Owner Team is located.</p>
<p>If you approach this problem by converting all the dates to UTC, you will lose the semantics of the Offset. The Offset is useful to understand if the DateTime is inside working hours or not. So, DateTime will not do the job.</p>
<h2>The solution</h2>
<p>If you value the original local time, you can use the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset">DateTimeOffset</a> structure.</p>
<p>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset">DateTimeOffset</a> structure represents a date and time value, together with an offset that indicates how much that value differs from UTC. Thus, <strong>DateTimeOffset always identifies a single point in time</strong>.</p>
<p>We can say that DateTimeOffset is like DateTime+Offset.</p>
<p><strong>Important:</strong> DateTimeOffset doesn't give you the time zone, only the Offset. Based on the Offset, you can figure out a subset of time zones where it might have happened. If you want to know the exact time zone, you need to store the time zone. Why? Because it's common to have time zones overlapping.</p>
<h2>When is DateTime the solution?</h2>
<p>Imagine that you are building an application to manage alarms. Like the one you have on your phone.</p>
<p>One of the most common use cases will be creating an alarm to wake up every day at 8 am. Simple.</p>
<p>The question is: Is the Offset important? Not really. You need a constant Date and Time. You need it to trigger at 8 am even if you change the time zone or daylight-saving time.</p>
<h2>Rule of thumb</h2>
<p>The Offset doesn't have semantic value for you, or you are sure that you will <strong>never</strong> ever work with time zones, and UTC is enough? You can use DateTime.</p>
<p>Otherwise, use DateTimeOffset.</p>
<p>In case of doubt, use DateTimeOffset.</p>
<p>Let's keep in touch. You can find me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>.</p>
How the DRY Principle can damage your tests (C# Developers)2022-10-18T00:00:00-00:00https://guiferreira.me/archive/2022/how-dry-can-damage-your-tests/<p>Don't Repeat Yourself (DRY) is likely the most famous principle in software development. The first thing you learn to optimize your code is to avoid duplication. As the saying goes, duplication is the root of all evil 😈. <strong>To many this is DRY in a nutshell. Exterminate anything that looks like a clone. And that is how you destroy your test readability.</strong> And I will show you how so you can keep an eye on it.</p>
<p>The DRY principle is more nuanced than it looks. It's like wine 🍷. Many drink wine, but only a few can spot Wood flavors there.</p>
<p><img src="https://guiferreira.me/images/archive/fun/wine-connoisseur.png" alt="Wine Connoisseur - Michael Scott - The Office"></p>
<p>In <a href="https://en.wikipedia.org/wiki/The_Pragmatic_Programmer"><em>The Pragmatic Programmer</em></a> book, <a href="https://en.wikipedia.org/wiki/Andy_Hunt_(author)">Andy Hunt</a> and <a href="https://en.wikipedia.org/wiki/Dave_Thomas_(author)">Dave Thomas</a> stated DRY as <em>"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system"</em>.</p>
<p>What does that mean? That means that <strong>changing a system element should not require a change in unrelated elements.</strong> Let me try to state that differently. If two identical elements can change for different reasons, that means they are not the same element, even if they are identical. Having a doppelganger or even a twin doesn't make you the same person.</p>
<p>So, as you can see, it's easy to go wrong with it. And one of the cases where I have seen it go wrong more often is on Tests. <strong>Tests, by their nature, evolve independently. So, when you read a test, it should be clear what that Test asserts without implying a huge cognitive load. And it's here where DRY can get you in a bad place.</strong> Even though DRY is a good principle to keep in mind, you should always keep an eye on Readability, one of the most important properties of a good Test.</p>
<p>Let's see an example. Hopefully, it will make it clear.</p>
<h2>🎢 Putting it into practice</h2>
<p>Take a look at the following code.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithoutDefinedLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"EN"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithEnglishLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span><span class="token punctuation">,</span> Language <span class="token operator">=</span> <span class="token string">"EN"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"EN"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithPortugueseLanguage_WhenGenerateWelcomeMessage_ReturnsOla</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span><span class="token punctuation">,</span> Language <span class="token operator">=</span> <span class="token string">"PT"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"PT"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Olá Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>What would you refactor here? Can we start by extracting those Language Code magic strings? Ok, let's try it.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> PortugueseLanguage <span class="token operator">=</span> <span class="token string">"PT"</span><span class="token punctuation">;</span><br><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> DefaultLanguage <span class="token operator">=</span> <span class="token string">"EN"</span><span class="token punctuation">;</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithoutDefinedLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>DefaultLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithEnglishLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span><span class="token punctuation">,</span> Language <span class="token operator">=</span> DefaultLanguage <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>DefaultLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithPortugueseLanguage_WhenGenerateWelcomeMessage_ReturnsOla</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span><span class="token punctuation">,</span> Language <span class="token operator">=</span> PortugueseLanguage <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>PortugueseLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Olá Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>Did we de-duplicate? Yes. Did we make it more readable? I don't think so. Can I safely change it? No. A change to the value to satisfy one test may affect the other.</p>
<p>Let's try another one. Let's extract the user creation to a different method.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> PortugueseLanguage <span class="token operator">=</span> <span class="token string">"PT"</span><span class="token punctuation">;</span><br><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> DefaultLanguage <span class="token operator">=</span> <span class="token string">"EN"</span><span class="token punctuation">;</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithoutDefinedLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token function">CreateUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>DefaultLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithEnglishLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token function">CreateUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>DefaultLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithPortugueseLanguage_WhenGenerateWelcomeMessage_ReturnsOla</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token function">CreateUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> user<span class="token punctuation">.</span>Language <span class="token operator">=</span> PortugueseLanguage<span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>PortugueseLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Olá Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token return-type class-name">User</span> <span class="token function">CreateUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token operator">=></span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"Gui"</span><span class="token punctuation">,</span> Language <span class="token operator">=</span> DefaultLanguage <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Did we de-duplicate? Yes. Did we make it more readable? I don't think so.</p>
<p>If you look into the following code, you may ask yourself: <em>"Where does that value come from? Why 'Hello Gui?'"</em>. Why? We <em>DRYed</em> too much.</p>
<p>As you can see, deduplication may impact your code readability, and when we are talking about tests, we are talking about an important property.</p>
<p>So, what can you do instead?</p>
<h2>⭐️ A better solution</h2>
<p>Always ask yourself: <em>"Is it clear what is under test here?"</em> and <em>"Is it really a duplicate? There's any reason to change them independently?"</em>.</p>
<p>Based on that, you could have done something along those lines.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> EnglishLanguage <span class="token operator">=</span> <span class="token string">"EN"</span><span class="token punctuation">;</span><br><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> PortugueseLanguage <span class="token operator">=</span> <span class="token string">"PT"</span><span class="token punctuation">;</span><br><span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> DefaultLanguage <span class="token operator">=</span> EnglishLanguage<span class="token punctuation">;</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithoutDefinedLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">UserBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">"Gui"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>DefaultLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithEnglishLanguage_WhenGenerateWelcomeMessage_ReturnsHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">UserBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">"Gui"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithLanguage</span><span class="token punctuation">(</span>EnglishLanguage<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>EnglishLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenUserWithPortugueseLanguage_WhenGenerateWelcomeMessage_ReturnsOla</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">UserBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">"Gui"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithLanguage</span><span class="token punctuation">(</span>PortugueseLanguage<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> message <span class="token operator">=</span> <span class="token function">WelcomeMessage</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> message<span class="token punctuation">.</span>Language<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>PortugueseLanguage<span class="token punctuation">)</span><span class="token punctuation">;</span><br> message<span class="token punctuation">.</span>Text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Olá Gui!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>As you can see, now the magic string has a name that puts me in the right direction. Besides that, I use the Builder pattern and specify the properties that will impact the assertion result in the Arrange step. Now is clear where the Gui in <em>"Hello Gui!"</em> comes from.</p>
<p>Let me know what you think about it.</p>
<p>I have an in-depth video here 👇</p>
<p>https://www.youtube.com/watch?v=QUj2dRDEWWs</p>
<p>If you want more, be sure to follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>Just keep things Simple 🌱</p>
The missing Project that fixes everything in .NET2022-09-27T00:00:00-00:00https://guiferreira.me/archive/2022/the-missing-project-that-fixes-everything-in-dotnet/<p>https://www.youtube.com/watch?v=jeUHyGjnTwo</p>
<p>It has many names. <a href="http://cleancoder.com/products">Robert C. Martin (AKA Uncle Bob)</a> calls it the Main Component, and Mark Seemann calls it the <a href="https://blog.ploeh.dk/2011/07/28/CompositionRoot/">Composition Root</a>. You may also know it as the Application Host or Startup. Not the same as <em>"Startup.cs"</em>. I'm still trying to find my preferred name, so you may see me using those terms interchangeably.</p>
<p>Robert C. Martin says <strong>it is the Ultimate Detail</strong>. Even then, most seem to not care about it.</p>
<p>Those brave souls who care about it will look into the face of .NET and say: <em>"Not Today!"</em>. <a href="https://gameofthrones.fandom.com/wiki/Arya_Stark">Arya Stark</a> style. They will often do it by:</p>
<ul>
<li>Moving entry points to a Presentation Project. For example, extracting Controllers out of an MVC API.</li>
<li>Load dependencies through dynamic assembly loading using something like <a href="https://learn.microsoft.com/en-us/dotnet/framework/mef/">MEF</a>.</li>
</ul>
<p>I have a slightly different approach, and it's what I want to show you today.</p>
<p>But first, let's see what the Main Component/Composition Root/Application Host/Startup is.</p>
<h2>❓ What is it</h2>
<p>When you apply <a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">Clean Architecture</a>, <a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/">Onion Architecture</a>, <a href="https://guiferreira.me/archive/2022/hexagonal-architecture-for-dotnet-developers-beginners/">Hexagonal Architecture</a>, or any other shape of device-independent architecture, keeping the dependencies independent and respecting the Dependency Rule may be challenging. .NET, you know I'm talking about you. <strong>The Template for an API or Web application is already the host itself.</strong></p>
<p>You need to define the dependencies and configurations of the involved modules/components/projects, which can be challenging when the DI configuration happens inside the adapter. You may do it through a Dependency Injection Container or by Pure DI. But, <strong>the DI responsible project will need to know all the other projects</strong>. Unless you want to do it dynamically. What I don't recommend in most cases.</p>
<p><strong>The dependency management becomes a problem when that Project should be a simple adapter to the Core Application logic.</strong> Once you introduce all the references there, it becomes hard to enforce the Dependency Rule and to spot shortcuts. Once you notice it, you may have an MVC directly inserted into your SQL DB even when it was not supposed to. That's why adapters should be independent of each other.</p>
<p>Robert C. Martin is absolutely right when he says it is the <em>"dirtiest of all the dirty components"</em>. The project is coupled to everyone. But he does it in good faith. Someone has to sacrifice to keep the rest of the family safe.</p>
<h2>🏗 How it sits in the architecture</h2>
<p>The application host/startup is <strong>the initial entry point of the application</strong>.</p>
<p>You can picture it as the outermost circle Onion Architecture or Clean Architecture diagram.</p>
<p>This component will be the one you will start when you run your application. It loads everything, configures it, and hands control to another component.</p>
<h2>👍 The benefits</h2>
<p>Besides the obvious benefit of removing unwanted dependencies from other projects, it will allow you to use multiple configurations, depending on the scenario. So, if you want to use the same application logic as a CLI or an API, you simply have a different host/startup where you do a different configuration. Just that. Do you need a sandbox version with another DB Adapter? You implement another host/startup. Those are just examples.</p>
<h2>📝 How to do it</h2>
<p><em>Note: If you want to follow along, you can find the example <a href="https://guiferreira.me/archive/2022/how-to-apply-hexagonal-architecture-with-dotnet/">here</a>. Then, just run the following script.</em></p>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> src/Adapter.Api/Adapter.Api.csproj reference ./src/Adapter.Kafka/Adapter.Kafka.csproj<br>dotnet <span class="token function">add</span> src/Adapter.Api/Adapter.Api.csproj reference ./src/Adapter.PostgreSQL/Adapter.PostgreSQL.csproj</code></pre>
<p>Before we start, your dependency diagram may look something like this.</p>
<p><img src="https://guiferreira.me/images/archive/hexagonal-architecture/before-startup-project.png" alt="Before Startup project"></p>
<h4>1. Create a new console project</h4>
<pre class="language-bash"><code class="language-bash">dotnet new console -n Application.Api -o src/Application.Api<br>dotnet sln <span class="token function">add</span> src/Application.Api<br></code></pre>
<h4>2. Change old startup project (<em>Adapter.Api</em>) to a library. Edit the <em>.csproj</em> and add the Output Type as a library</h4>
<pre class="language-xml"><code class="language-xml"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>PropertyGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>OutputType</span><span class="token punctuation">></span></span>Library<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>OutputType</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>PropertyGroup</span><span class="token punctuation">></span></span></code></pre>
<h4>3. Remove references to other adapters from old startup project (<em>Adapter.Api</em>).</h4>
<h4>4. Add references to the new project</h4>
<pre class="language-bash"><code class="language-bash">dotnet <span class="token function">add</span> src/Application.Api/Application.Api.csproj reference ./src/Adapter.Kafka/Adapter.Kafka.csproj<br>dotnet <span class="token function">add</span> src/Application.Api/Application.Api.csproj reference ./src/Adapter.PostgreSQL/Adapter.PostgreSQL.csproj<br>dotnet <span class="token function">add</span> src/Application.Api/Application.Api.csproj reference ./src/Adapter.Api/Adapter.Api.csproj</code></pre>
<h4>5. Convert the <em>Program.cs</em> for the old startup project (<em>Adapter.Api</em>) into a class</h4>
<p>I like to split the building from the running.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AdapterApi</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token class-name">WebApplicationBuilder</span> _builder<span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token function">AdapterApi</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _builder <span class="token operator">=</span> WebApplication<span class="token punctuation">.</span><span class="token function">CreateBuilder</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> _builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddControllers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> _builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddEndpointsApiExplorer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> _builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddSwaggerGen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">Task</span> <span class="token function">RunAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> app <span class="token operator">=</span> _builder<span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>app<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span><span class="token function">IsDevelopment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> app<span class="token punctuation">.</span><span class="token function">UseSwagger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> app<span class="token punctuation">.</span><span class="token function">UseSwaggerUI</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> app<span class="token punctuation">.</span><span class="token function">UseHttpsRedirection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> app<span class="token punctuation">.</span><span class="token function">UseAuthorization</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> app<span class="token punctuation">.</span><span class="token function">MapControllers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> app<span class="token punctuation">.</span><span class="token function">RunAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br></code></pre>
<h4>6. Receive the Dependency Injection configuration</h4>
<p>Add an argument to the constructor to receive an Action to configure DI.</p>
<p>Now the constructor will look like this:</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token keyword">public</span> <span class="token function">AdapterApi</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">,</span> <span class="token class-name">Action<span class="token punctuation"><</span>IServiceCollection<span class="token punctuation">></span></span> options<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _builder <span class="token operator">=</span> WebApplication<span class="token punctuation">.</span><span class="token function">CreateBuilder</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> options<span class="token punctuation">.</span><span class="token function">Invoke</span><span class="token punctuation">(</span>_builder<span class="token punctuation">.</span>Services<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> _builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddControllers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> _builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddEndpointsApiExplorer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> _builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddSwaggerGen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span></code></pre>
<h4>7. Setup the adapter and run the application</h4>
<p>Now, in your new startup project (<em>Application.Api</em>) you simply setup your Adapters and run it.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> api <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AdapterApi</span><span class="token punctuation">(</span>args<span class="token punctuation">,</span> options <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> options<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddScoped</span><span class="token generic class-name"><span class="token punctuation"><</span>IAddBookRead<span class="token punctuation">,</span> AddBookRead<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> options<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddScoped</span><span class="token generic class-name"><span class="token punctuation"><</span>IBookReadStore<span class="token punctuation">,</span> PostgreBookReadStore<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> options<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddScoped</span><span class="token generic class-name"><span class="token punctuation"><</span>IBookReadPublisher<span class="token punctuation">,</span> KafkaBookReadPublisher<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">await</span> api<span class="token punctuation">.</span><span class="token function">RunAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now, your diagram will look like this.</p>
<p><img src="https://guiferreira.me/images/archive/hexagonal-architecture/after-startup-project.png" alt="After Startup project"></p>
<p>Take a look at <a href="https://guiferreira.me/archive/2022/how-to-apply-hexagonal-architecture-with-dotnet/">this article</a> if you have any doubts about how to assemble a device-independent solution.</p>
<p>I hope you have found this useful.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
How to apply Hexagonal Architecture with .NET2022-09-19T00:00:00-00:00https://guiferreira.me/archive/2022/how-to-apply-hexagonal-architecture-with-dotnet/<p>Hexagons, Ports, Adapters, you know all of that. What you don't know is how to put it into practice. Don't worry.</p>
<p>That's normal. My hundreds of hours of watching MasterChef don't make me a Chef 🧑🍳. But they served me well to know what a Sous Vide is.</p>
<p>It's what we are going to cover here. Not Sous Vide. Hexagonal Architecture. Let's focus.</p>
<p>If you are not familiar with Hexagonal Architecture, don't worry. I got you covered.</p>
<p>Take a moment to check <a href="https://guiferreira.me/archive/2022/hexagonal-architecture-for-dotnet-developers-beginners/">this post</a> or <a href="https://youtu.be/5ioLmkgJ_28">this video</a> where I explain the concepts. Go and make sure you get back here. This party can't continue without you. 🥳</p>
<p>In this blog post, we will look at the Project Structure for a .NET Solution following Hexagonal Architecture.</p>
<p>For the sake of the exercise, we will be imagining a Book Tracking API that needs to store data on <a href="https://www.postgresql.org/">PostgreSQL</a> and publish events to <a href="https://kafka.apache.org/">Apache Kafka</a> every time a book is read.</p>
<p>Let's start?</p>
<h2>⚠️ Disclaimer</h2>
<p>If you think about it, Hexagonal Architecture is mostly about the Dependency Rule. Dependencies should point inwards.</p>
<p>Knowing that I have an important disclaimer to make. Here it goes.</p>
<p>This post may be about how to structure your solution using Hexagonal Architecture, but <strong>this is not the only way</strong>.
You can achieve Hexagonal Architecture using Projects, Components, Folders, or only files. As far as you respect the dependency rule. Let me say again. <strong>The Folder / Project structure doesn't matter. As far as you respect the dependency rule.</strong></p>
<p>What you find here is my recommended approach. Knowing that Hexagonal Architecture will be most useful on complex projects. But also knowing that mistakes happen. And not every team has a squad of experts or ninjas 🥷 (unless it's a Japanese company). This is a highly opinionated post based on my experience.</p>
<h2>🏗️ Structuring your Project</h2>
<h3>🛣️ Approach</h3>
<p>As I said, Project and Folder structure doesn't matter, but I prefer to use different projects for the Core Application (the Hexagon) and each Adapter technology.</p>
<p>Why? Not because I like to wait for my IDE to load the solution, but because <strong>with different projects in .NET it becomes easier to enforce the dependency rule</strong>.</p>
<p>How?</p>
<ul>
<li>You can easily spot new references on a ".csproj" file during code review;</li>
<li>You can write some architecture/structure tests;</li>
<li>Circular dependencies will be denied by default.</li>
</ul>
<p>You may have noticed that I said: "<strong>each</strong> Adapter" above. Yes, I mean one project per technology Adapter.</p>
<p>In Hexagonal Architecture, <strong>Adapters should not know each other.</strong> Only then it's possible to swap Adapters with confidence. One at a time. So, you don't want your API Adapter calling on your PostgreSQL adapter once a call is received. Your Core Application should always mediate that.</p>
<h3>📦 Application Core Project</h3>
<p>In the center of your application, you will have your Core. The Core doesn't depend on anything. No Adapters or Technologies are known.
<strong>The Application Core (aka Hexagon) will host all business logic and Ports.</strong></p>
<p><em>Note: You may reference utility libraries for sure.</em></p>
<p>So, we create one project on the Core?!
Yes and No. <strong>Hexagonal Architecture says nothing about how the Core should be structured</strong>. We only know that the Core exposes Ports to the outside world. Beyond that is up to you.</p>
<p>Often, 1 is enough (Core). If you want to follow an approach more in line with DDD, you may want to have 2 ("<em>Core.Application</em>"" and "<em>Core.Domain</em>"). I prefer to start with Core and only split if I have a strong Domain or I need to share Domain concepts with other applications.</p>
<p><em>Note: Make sure that you use the Public accessor modifier carefully. Everything you expose becomes a contract with your adapters.</em></p>
<h3>🔌 Adapter Project</h3>
<p>You need to identify the Primary/Driving Adapters and the Secondary/Driven Adapters.</p>
<p>Primary/Driving Adapters are all those Adaptors that enable an actor to communicate with the Core Application through a given port. Examples: REST API, Web Client, CLI, Message Handler, etc.</p>
<p>Secondary/Driven Adapters are all those Adapters that the Core Application calls to communicate with the outside world. Examples: Database, Message Bus, SMTP Server, etc.</p>
<p><strong>Identify those Technologies/Delivery Mechanisms and create a project per each.</strong> To me, this is the right balance between too many projects and too few to implement Hexagonal Architecture.</p>
<p>Make sure you follow a convention when naming Adapters. It's important that when we see an Adapter, we understand his role in a fraction of a second. As explained in <a href="https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html">Screaming Architecture</a>.</p>
<p>If we think about our scenario, we know that we have an <strong>API</strong> that needs to store data on <strong>PostgreSQL</strong> and publish events to <strong>Kafka</strong>, so our adapters will be:</p>
<ol>
<li>Driving Adapters
<ul>
<li>API</li>
</ul>
</li>
<li>Driven Adapters
<ul>
<li>PostgreSQL</li>
<li>Kafka</li>
</ul>
</li>
</ol>
<p>Done ✅</p>
<h3>🧪 The most important part: Tests</h3>
<p>One of the Goals of Hexagonal Architecture is to facilitate tests. So, <strong>It is not Hexagonal Architecture until you have a Test suite in place</strong>.
There's even a rule I like by Alistair: <em>"1 Port. 2 Adapters."</em>. What does that mean? It means that each port should always have 1 Adapter for Testing.</p>
<p>Knowing that you should create one Testing Project for your Core and one per Adapter.</p>
<p>If you want to go deeper on a Testing Strategy, watch my talk at <a href="https://youtu.be/gHSpj2zM9Nw">NDC Porto 2022</a>.</p>
<h3>👀 Show me the code! Or show me the Hexagon!</h3>
<p>What would that solution look like?</p>
<p>Something along the following lines:</p>
<ul>
<li>src
<ul>
<li>src / Core
<ul>
<li>src / Adapters / API</li>
<li>src / Adapters / Kafka</li>
<li>src / Adapters / PostgreSQL</li>
</ul>
</li>
</ul>
</li>
<li>test
<ul>
<li>test / Core Tests
<ul>
<li>test / Adapters / Kafka Tests</li>
<li>test / Adapters / PostgreSQL Tests</li>
<li>test / Adapters / API Tests</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>So, let's run the following script using <a href="https://learn.microsoft.com/en-us/dotnet/core/tools/">dotnet CLI</a>.</p>
<pre class="language-bash"><code class="language-bash">dotnet new sln<br><br>dotnet new classlib -n Core -o src/Core<br>dotnet new xunit -n Core.Tests -o test/Core.Tests<br>dotnet <span class="token function">add</span> test/Core.Tests/Core.Tests.csproj reference ./src/Core/Core.csproj<br>dotnet sln <span class="token function">add</span> src/Core<br>dotnet sln <span class="token function">add</span> test/Core.Tests<br><br>dotnet new webapi -n Adapter.Api -o src/Adapter.Api<br>dotnet new xunit -n Adapter.Api.Tests -o test/Adapter.Api.Tests<br>dotnet <span class="token function">add</span> test/Adapter.Api.Tests/Adapter.Api.Tests.csproj reference ./src/Adapter.Api/Adapter.Api.csproj<br>dotnet <span class="token function">add</span> src/Adapter.Api/Adapter.Api.csproj reference ./src/Core/Core.csproj<br>dotnet sln <span class="token function">add</span> src/Adapter.Api<br>dotnet sln <span class="token function">add</span> test/Adapter.Api.Tests<br><br><br>dotnet new classlib -n Adapter.Kafka -o src/Adapter.Kafka<br>dotnet new xunit -n Adapter.Kafka.Tests -o test/Adapter.Kafka.Tests<br>dotnet <span class="token function">add</span> test/Adapter.Kafka.Tests/Adapter.Kafka.Tests.csproj reference ./src/Adapter.Kafka/Adapter.Kafka.csproj<br>dotnet <span class="token function">add</span> src/Adapter.Kafka/Adapter.Kafka.csproj reference ./src/Core/Core.csproj<br>dotnet sln <span class="token function">add</span> src/Adapter.Kafka<br>dotnet sln <span class="token function">add</span> test/Adapter.Kafka.Tests<br><br>dotnet new classlib -n Adapter.PostgreSQL -o src/Adapter.PostgreSQL<br>dotnet new xunit -n Adapter.PostgreSQL.Tests -o test/Adapter.PostgreSQL.Tests<br>dotnet <span class="token function">add</span> test/Adapter.PostgreSQL.Tests/Adapter.PostgreSQL.Tests.csproj reference ./src/Adapter.PostgreSQL/Adapter.PostgreSQL.csproj<br>dotnet <span class="token function">add</span> src/Adapter.PostgreSQL/Adapter.PostgreSQL.csproj reference ./src/Core/Core.csproj<br>dotnet sln <span class="token function">add</span> src/Adapter.PostgreSQL<br>dotnet sln <span class="token function">add</span> test/Adapter.PostgreSQL.Tests<br></code></pre>
<p>Now, our solution looks like this:</p>
<p><img src="https://guiferreira.me/images/archive/hexagonal-architecture/project-structure-sample.png" alt="Hexagonal Architecture - .NET Project Structure"></p>
<h3>⚠️ The host problem</h3>
<p>Once you start adding your ports and configuring the Dependencies, you will see that your startup project will depend on many projects.</p>
<p>As I explained, Adapters should not know each other. That can be hard for your application Host / <a href="https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/ch26.xhtml">Main Component</a> / <a href="https://blog.ploeh.dk/2011/07/28/CompositionRoot/">Composition Root</a> / Startup. <strong>That project needs to perform the Dependency Configuration, so it needs to know the other projects.</strong> We know that when we create an MVC project, as an example, the startup code will be there. That can make our life harder.</p>
<p>There are a few options to accomplish that, but they bring an extra level of complexity to the solution. I will reserve that for another post. I promise, my friend. In the meanwhile, you can either:</p>
<ul>
<li>Extract the logical part of your host, like Controllers, to a different adapter;</li>
<li>Load dependencies through dynamic assembly loading 🤢;</li>
<li>or you simply be extra careful with dependencies on the Host project and treat it as an adapter.</li>
</ul>
<h3>Wrap up</h3>
<p>I hope you find this post useful and that it contributed to a clear vision of what Hexagonal Architecture is.</p>
<p>Before you go, I have to say this once again: It's not about the Projects. It's about the Dependency Rule.</p>
<p>Let me know if you want to see more about Hexagonal Architecture. You can find me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>.</p>
<p>I will see you soon. In the meanwhile, just keep things simple.</p>
Hexagonal Architecture for .NET Developers (Beginners)2022-09-12T00:00:00-00:00https://guiferreira.me/archive/2022/hexagonal-architecture-for-dotnet-developers-beginners/<p>91.23% of .NET Developers think about Clean Architecture when creating a new Solution.
Less than 20% know Hexagonal Architecture.
Let me tell you that we are failing as a community. Hexagonal Architecture deserves more respect from us.</p>
<p><em>Note: those percentages are based on a study where I was inquired about my own random opinion 😄</em></p>
<h2>⬡ What is Hexagonal Architecture?</h2>
<p>Hexagonal Architecture, also known as Ports & Adapters, has been presented to us by <a href="https://www.linkedin.com/in/alistaircockburn">Alistair Cockburn</a> in 2005.</p>
<p>But why? Why did Alistair share this idea?
Have you ever been in a situation <strong>where it was hard to test your most important code?</strong> Have you ever realized that it was <strong>hard to Test because it was extremely hard to swap a data storage or a client protocol in your software?</strong> All those classical problems of <a href="https://en.wikipedia.org/wiki/Multitier_architecture">Layered Architecture</a>.</p>
<p>The goal of Hexagonal Architecture is to fix that. <strong>With Hexagonal Architecture, you gain the capability of Testing in isolation. And the best is that your software becomes independent of Tools and Delivery Mechanisms.</strong> It is an awesome Architecture to evolve your software. Go ask Netflix (<a href="https://netflixtechblog.com/ready-for-changes-with-hexagonal-architecture-b315ec967749">see here</a>).</p>
<p>So, how does it work? It starts with a simple premise. <strong>Every software has an internal and an external side.</strong> Isn't it? There's no point in having code when there's no impact on the outside world.</p>
<h2>📜 Ports</h2>
<p>Knowing that we need to have a way to communicate with the outside world. Since we know that the world out there is messy, we use Ports.</p>
<p><strong>Ports are contracts between the Internal and External world.</strong></p>
<p>In .NET terms, Ports will be a set of Interfaces and Classes or Records for DTOs (<a href="https://en.wikipedia.org/wiki/Data_transfer_object">Data Transfer Objects</a>). You will place them together with your Core Application.</p>
<h2>🔌 Adapters</h2>
<p>Ports alone don't do much. We need to plug Adapters there. <strong>Adapters act like Delivery Mechanism translators. They know a Tool or Device and mediate the relationship while fulfilling the contract defined by a Port.</strong> In the real world, you can see a parallel on phone charging adapters that will let you travel through the world and plug your phone even when the power supply is different.</p>
<p>In .NET, Adapters will be a Class implementing a Port interface.</p>
<p>Ports and Adapters define not only how software can reach data storage or send a message (known as Driven/Secondary Adapters), but also how a user will interact (MVC Rest API, Blazor, WPF, Console, etc.) with the Core Application (known as Driving/Primary Adapters).</p>
<p>So, this Port/Adapter concept enables different adapters depending on a Port. Now, you have swappable technologies. That is a powerful idea.</p>
<p><img src="https://guiferreira.me/images/archive/hexagonal-architecture/hexagonal-architecture-sample.png" alt="Hexagonal Architecture Sample"></p>
<h2>⤵️ Dependency Rule</h2>
<p>If you think about it, <strong>Hexagonal Architecture is mostly about the Dependency Rule</strong>. Dependencies should point inwards.
Are you familiar with that? If you know Onion or Clean Architecture you are.</p>
<p>Your Core Application will have Ports and not know about the existence of Adapters. So, Adapters will depend on the Core Application.</p>
<p>You can configure that using Dependency Injection.</p>
<p>It's important to say that you can achieve Hexagonal Architecture using Projects, Components, Folders, or only files. <strong>If you respect the Dependency Rule, Folder / Project structure doesn't matter.</strong></p>
<h2>🌟 Wrap up</h2>
<p>I love Hexagonal Architecture because <strong>it is a simple concept</strong> that can be extended as you wish. <strong>It's more a principle than a prescriptive recipe.</strong> The proof of the value is that <strong>many came after and built on top of it.</strong> Yes, I'm talking about Onion Architecture and Clean Architecture.</p>
<p>In short, Hexagonal Architecture leads you to software like Raviolis 🥟 instead of Lasagna. You can dress them with a different sauce, and the filling will always be protected. I have to confess that I only prefer Raviolis over Lasagna in software. What about you?</p>
<p>https://www.youtube.com/watch?v=5ioLmkgJ_28</p>
<p>Stay tuned. In this post, we talked about the concepts. Soon I will be posting a new post with a Project Structure recommendation for .NET.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
5 things Microsoft needs to do to make Central Package Management widely used2022-09-05T00:00:00-00:00https://guiferreira.me/archive/2022/5-things-microsoft-needs-to-do-to-make-central-package-management-widely-used/<p>There's no perfect governance model. But there's no doubt that a centralized authority model eliminates ambiguity and improves speed.</p>
<p>That's why Central Package Management has so many adopters across the language spectrum.</p>
<p>If you have ever used <a href="https://fsprojects.github.io/Paket/">Paket</a>, nothing here is new to you. What is new is that .NET now has an official <a href="https://devblogs.microsoft.com/nuget/introducing-central-package-management/">Central Package Management</a>. Why is that good? <strong>Because being a Microsoft solution, the chances of having proper tooling around it is enormous.</strong> And we know how the community tends to prefer tools coming from Microsoft. But <strong>this is not a game changer yet.</strong> The experience is not what we got used to in the .NET ecosystem. At least for now.</p>
<p>If Microsoft invests energy in that, this can be a game changer. The way that we manage dependencies may change forever.</p>
<p>Here we will see 5 things that need to happen to make this a success.</p>
<h2>What is Central Package Management</h2>
<p>Before we start, let's see what Central Package Management is.</p>
<p>With Central Package Management, you start defining your packages and their versions in a single centralized place (<code>Directory.Packages.props</code>). By doing that, you can <strong>control package versions used in a single place</strong>.</p>
<p><img src="https://guiferreira.me/images/archive/dotnet/directory-packages-props-file.png" alt="Directory.Packages.props"></p>
<p>Then, <strong>each project will need to opt-in to the packages they need</strong>. They don't need to specify the version. That is already defined in the centralized definition.</p>
<p>If you want to see more about how it works, you can read the announcement <a href="https://devblogs.microsoft.com/nuget/introducing-central-package-management/">here</a> or take a look at <a href="https://youtu.be/C_2BStepVKw?t=3102">Claire Novotny talk at NDC London</a>.</p>
<p>Now that we know what is Central Package Management, let's take a look at why the existing solution, announced in April 2022, will not fulfill its prophecy. At least while some things aren't addressed. Let's take a look at 5 things that need to change so that can happen.</p>
<h2>✅ The 5 things to do</h2>
<h3>1. Tooling</h3>
<p>We know the importance of tooling in the .NET space.
Currently, the experience isn't good when using Visual Studio or the CLI.</p>
<p>Microsoft needs to <strong>provide a delightful experience for Visual Studio and CLI</strong>.
<strong>That will not only increase the adoption but also force other tools like Rider to adopt it as well.</strong></p>
<h3>2. CLI Experience</h3>
<p>We got used to having CLI in our lives since .NET Core, and some of us can't live without it anymore. That means that <strong>Central Package Management can't be only a question of Visual Studio tooling but also part of the default CLI experience</strong>.</p>
<p>I expect that running a command inside a project with Central Package Management, and managing references act accordingly.</p>
<p>I get that it can be hard since the "<code>Directory.Packages.props</code>" file can live anywhere in the folder structure, but at least we should be able to achieve that through arguments or flags.</p>
<h3>3. Migrations</h3>
<p>The biggest benefit of centralized package management will be for the complex solutions. But, <strong>the cost of moving is high if we expect people to do it manually</strong>.</p>
<p>There are already some Open-Source tools like <a href="https://github.com/Webreaper/CentralisedPackageConverter">CentralisedPackageConverter</a>, but <strong>having the migration as part of the CLI is one small step to removing friction</strong>.</p>
<h3>4. Templates</h3>
<p><strong>We know the power of defaults</strong>. Microsoft is slowly convincing most of us that we don't need all that clutter in our "<code>Program.cs</code>" by changing the default templates.</p>
<p>If the same thing happens to package management, we will see adoption ramping up. Once again, it may be through the use of flags and arguments.</p>
<h3>5. Samples</h3>
<p>In the .NET world, it is easy to find good samples built by Microsoft that quickly become a how-to-do things reference.</p>
<p>Once we have proper tooling in place, this would be the next step.</p>
<p>Adopting Central Package Management in projects like <a href="https://github.com/dotnet-architecture/eShopOnWeb">eShopOnWeb</a>. <strong>Seeing it in place will signal to the community that you can confidently adopt it</strong>.</p>
<h2>⏭️ Wrapping up</h2>
<p>If you are excited about managing dependencies centrally, I invite you to play around with <a href="https://fsprojects.github.io/Paket/">Paket</a>. An Open-Source tool in the space for a long time.</p>
<p><strong>Central Package Management can be a game changer, but only if we see a perfect alignment between Tools and Default practices.</strong></p>
<p>If that happens Package Management in .NET will be profoundly changed.
It's up to Microsoft.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
C# 11 Required Members, the imperfectly awesome feature2022-08-28T00:00:00-00:00https://guiferreira.me/archive/2022/csharp-11-required-members-the-imperfectly-awesome-feature/<p>If you skim the <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11">C# 11 feature list</a>, there's one that grabs the attention as a yellow Lamborghini in a parking lot (except <a href="https://en.wikipedia.org/wiki/Monaco">Monaco</a> parking lots 💰). It's <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#required-members">Required Members</a>. The most wanted from the list.</p>
<p><strong>Is it exciting? Yes! Is it perfect? Not sure.</strong> Stay till the end to see why.</p>
<h2>🤨 What are we trying to solve here?</h2>
<p><strong>Constructors are super handy but can be painful. They are positional, so brittle to changes.</strong> Adding a new optional member requires not only a new overload but also making sure that members are added at the end of the list. No one wants to break all consumers. Am I right?</p>
<p>You may say: <em>"let's avoid constructors and take advantage of object Initializers and Nullable Reference Types."</em></p>
<p>And I quickly answer: <em>"Calm down, my friend!"</em></p>
<p>Constructors are still important, and <a href="https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references">nullable reference types</a> have a weak spot at Initialization. Even with the investment to make object Initializers better through the <em>"init"</em> keyword.</p>
<p>What's the weak spot?</p>
<ul>
<li>Have you used <code>= null!</code>? It feels like a hack, right?!</li>
<li>There's no check in place to ensure that the code instantiating the class initializes the member.</li>
</ul>
<h2>👋 Say Hi to Required Members</h2>
<p>Required Members come to solve that. Since C# 1.0 there's no expressive way to declare a member as Required. We are now getting it.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> required <span class="token return-type class-name"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> Email <span class="token operator">=</span> <span class="token string">"gui@guiferreira.me"</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p><strong>Not only do you get an expressive way to annotate your models, but non-nullable warnings go away.</strong></p>
<p>The goal is to annotate fields as well, not just properties. That's why it's named Required Members instead of Required Properties. In case you asked it.</p>
<p>With Required Members, <strong>the compiler will enforce that you initialize that member</strong>. You can use it on Classes, Records or Structs.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name">error</span> CS9035<span class="token punctuation">:</span> Required member 'User<span class="token punctuation">.</span>Email' must <span class="token class-name">be</span> <span class="token keyword">set</span> <span class="token keyword">in</span> the <span class="token keyword">object</span> initializer <span class="token keyword">or</span> attribute constructor<span class="token punctuation">.</span></code></pre>
<p>Please keep in mind that Required will not enforce an explicit initialization to a non-null value. Nullable and required are independent concerns. It's up to you as a developer to enforce it.</p>
<h2>❓ So, what's the problem with it?</h2>
<p>If you remember, I started this article by saying that Required Members isn't perfect.
<strong>The success of a feature is highly related to its adoption.</strong> And here, you can find some things that may impact it.</p>
<ul>
<li><strong>Constructors:</strong> When a Required Member is set on a constructor, you will need to add an attribute <em>"SetsRequiredMembers"</em> to that constructor. This attribute will signal the compiler that the constructor already initializes the required member. This looks sub-optimal. It's this kind of detail that makes features hard to adopt.</li>
</ul>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Diagnostics<span class="token punctuation">.</span>CodeAnalysis</span><span class="token punctuation">;</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span><br><span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">SetsRequiredMembers</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token function">User</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> email<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Email <span class="token operator">=</span> email<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> required <span class="token return-type class-name"><span class="token keyword">string</span></span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span><span class="token punctuation">?</span></span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">init</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">User</span><span class="token punctuation">(</span><span class="token string">"gui@guiferreira.me"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<ul>
<li><strong>Records:</strong> One of the benefits of records in C# is not having to write a bunch of boilerplate code. That is particularly true when you use positional parameters. So, I've been heavily using it on my <a href="https://martinfowler.com/bliki/AnemicDomainModel.html">anemic</a> data structures like <a href="https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff649585(v=pandp.10)?redirectedfrom=MSDN">Data Transfer Objects (DTOs)</a>. In those cases, this feature is kind of useless since positional record properties are inherently required. To use it, you need to ignore positional parameters. That's not my standard way of using Records.
<em>Now that I think about it, it's interesting that Required Members wants to address the problem of constructors and positional records properties that may suffer from the same issue.</em></li>
<li><strong>Guard Clauses:</strong> One of the Required Members' goals is to avoid, in many cases, using Constructors in favour of property initialization. In many cases, migrating will be hard. Because it's common to see constructors applying Guard clauses. That means applying a Guard clause in a setter. So you will need a backing field (at least while we don't have <a href="https://github.com/dotnet/csharplang/issues/140">Semi-Auto-Properties field keyword</a>). That's an extra burden that will create resistance to the adoption.</li>
</ul>
<p>Evolving a language with more than 20 years isn't easy. Each step should be pondered and carefully evaluated. We have seen that in Nullable Reference Types. I believe that it also influenced the design of Required Members.</p>
<h2>⏩ What's now?</h2>
<p>Am I excited about this feature? Yes, I am. 🤩 I will be using it for sure.</p>
<p>Unfortunately, not as much as I first suspected. Nowadays, most of my Data Transfer Objects (DTOs) are records, and in my Domain, you will find more than variables being assigned in the constructor.</p>
<p>I'm curious to see if this is a stepping stone in the language and see what the community will be developing on top of it.</p>
<p>Let me know what you think about it, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
C# 11 Auto Default Structs in depth2022-08-22T00:00:00-00:00https://guiferreira.me/archive/2022/csharp-11-auto-default-structs-in-depth/<p>I always had the feeling that Structs were the ignored son of C#. I don't want to cause problems in the Family. But, hey, it was not me picking favourites. 🤪</p>
<p>Classes were always the first to evolve and improve. Don't get me wrong. It's completely understandable. It's the most used, so the investment is understandable and unquestionable.</p>
<p>Now, I can tell you that it's changing. <strong>On the past few C# versions, we have seen Structs catching up.</strong> Struct Records and Parameterless constructors are steps on that direction. <strong>It's clear the effort to provide a similar experience between Classes and Structs.</strong> And that is good for the language. It brings consistency.</p>
<p>The next on the list is Auto Default Structs.</p>
<h2>🙋♂️ What are we trying to solve?</h2>
<p>Before C# 11, if you declare a structure and you have a Constructor, <strong>you would need to assign each field</strong>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">struct</span> <span class="token class-name">PlayerPosition</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">PlayerPosition</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> X <span class="token operator">=</span> x<span class="token punctuation">;</span><br> Y <span class="token operator">=</span> y<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> X<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> Y<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>If you don't initialize one of the fields, you will have the following compilation error.</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">CS0171</span></span><span class="token punctuation">]</span> Field 'PlayerPosition<span class="token punctuation">.</span>Y' must be fully assigned before control <span class="token keyword">is</span> <span class="token class-name">returned</span> to the caller<span class="token punctuation">.</span></code></pre>
<p>That causes <strong>maintainability problems</strong>. Imagine that you add an extra field to the Struct. Now you need to change all the places where the Constructor is invoked. Besides the fact that this is a behaviour that doesn't mimic what we are used to in Classes.</p>
<h2>🤔 But, why do we need to do that?</h2>
<p>In the way that Structs work, if do not set the value, you could get the following result:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> player <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">PlayerPosition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>player<span class="token punctuation">.</span>X <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span><br>player <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">PlayerPosition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>player<span class="token punctuation">.</span>X<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Assertion will fail. It will be 10 if X isn't initialized in constructor.</span><br><br><span class="token keyword">struct</span> <span class="token class-name">PlayerPosition</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">PlayerPosition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> X<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> Y<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>There's a brilliant thread about it <a href="https://github.com/dotnet/csharplang/issues/5737#issuecomment-1097670457">here</a>.</p>
<h2>🌟 How Auto Default Structs can help?</h2>
<p>Auto Default Structs are the way C# will fix that. Let's start by ignoring the feature name. Is super strange. 🙄</p>
<p>With C# 11, <strong>the compiler will ensure that all fields are initialized to their default value</strong>.</p>
<p>In other words, fields not explicitly initialized on the Constructor will be initialized with the default value. The <a href="https://github.com/dotnet/csharplang/issues/5737">initialization is inserted at the beginning of the Constructor</a>.</p>
<p>Imagine the following code.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">struct</span> <span class="token class-name">PlayerPosition</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">PlayerPosition</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> X <span class="token operator">=</span> x<span class="token punctuation">;</span><br> Y <span class="token operator">=</span> y<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> X<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> Y<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> Z<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>This code is now valid with C# 11. Why? Because the compiler will be doing something like:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">struct</span> <span class="token class-name">PlayerPosition</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">PlayerPosition</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> x<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> y<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> Z <span class="token operator">=</span> <span class="token keyword">default</span><span class="token punctuation">;</span> <span class="token comment">// 👈 Here is the magic</span><br><br> X <span class="token operator">=</span> x<span class="token punctuation">;</span><br> Y <span class="token operator">=</span> y<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> X<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> Y<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> Z<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2>👏 Takeaway</h2>
<p>I like the fact that this is a step on uniformization between Classes and Structs. Structs, will for sure become a bit easier to maintain.</p>
<p>Will I be heavily using this? No. But when I use Structs, this will be useful for sure.</p>
<p>I hope that you liked it. Let me know if you have to give it a try.</p>
<p>In the meanwhile, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch. 😉</p>
Finding .NET Transitive Dependencies and Tidying Up Your Project2022-08-16T00:00:00-00:00https://guiferreira.me/archive/2022/finding-dotnet-transitive-dependencies-and-tidying-up-your-project/<p>Do you remember DLL Hell? 😈 Yes, me too.</p>
<p>If you don't remember, I'm happy for you. No Developer should suffer like that.</p>
<p>Unfortunately, NuGet Packages and References can be (rarely) a new form of Hell. A soft version of Hell, let's be honest. Not the same type of Hell from <code>node_modules</code>. 🤪</p>
<p><strong>When solutions grow in size, it's common to see projects referencing multiple versions of the same package or duplicated references.</strong></p>
<p>Today, I want to tell you about <a href="https://github.com/spectresystems/snitch"><strong>Snitch</strong></a>. Snitch is a simple <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools">.NET tool</a> that:</p>
<blockquote>
<p><em>"help you find transitive package references that can be removed."</em></p>
</blockquote>
<p>That sounds cool. 👍</p>
<h2>🖇️ Transitive Dependencies</h2>
<p>Let's start by defining what a Transitive Package Reference (or Transitive Dependency) is.</p>
<p><strong>A Transitive Dependency is a dependency induced by the dependencies of the direct references of that project.</strong></p>
<p>Let me give you an example.</p>
<p>Imagine that you have projects A, B and C. The dependency flow is <code>A -> B -> C</code>. So, Project A references Project B, which references Project C. In this case, A is transitively dependent on C. Why? Because it was induced by the dependencies of the direct reference Project B.</p>
<p><img src="https://guiferreira.me/images/archive/dotnet/transitive-dependency.png" alt="Transitive Dependency"></p>
<p>Now we know what Transitive Dependencies are.</p>
<h2>🤔 Transitive Dependencies eventual problems</h2>
<p>A question still remains: How does that contribute to Dependency Hell?</p>
<p>Ok. Let's get back to our Projects A, B and C.</p>
<p>This time, Project A will depend on both Project B, and C. Project B and C don't know each other.</p>
<p>Now imagine you have <code>Newtonsoft.Json</code> version <code>12.0.2</code> installed in A, B and C. Next time you need to update it, you update on A and B. You completely forgot C. That can lead to a mess.</p>
<p>You probably noticed in the example above that we not only have a problem with having multiple versions of the same package, but we also have a dependency that can be removed since it's already a transitive dependency.</p>
<p>We are talking about Project A referencing <code>Newtonsoft.Json</code> as well, where its dependencies already reference it.</p>
<p><strong>If you like to keep things clean 🧼 and tidy 🧹, I bet that now you can see the value of it.</strong></p>
<h2>🧹 Using Snitch</h2>
<p>The best part is that <strong>Snitch is simple and frictionless</strong>.</p>
<p>You just install the tool and run it.</p>
<p>Let's see how.</p>
<p>To install, it's a simple dotnet tool. Once you have .NET CLI installed, just run:</p>
<pre><code>dotnet tool install -g snitch
</code></pre>
<p>Then, using the terminal, navigate to the folder of a .NET solution and run:</p>
<pre><code>snitch
</code></pre>
<p>You will likely see a beautiful result like this:</p>
<p><img src="https://guiferreira.me/images/archive/snitch/snitch-result.png" alt="Transitive Dependency"></p>
<p>Out of curiosity, Snitch has this elegant user experience since it's based on <a href="https://github.com/spectreconsole">Spectre.Console</a>. Go check it out (after you finish reading) and give it a start on GitHub. <a href="https://github.com/patriksvensson">Patrik Svensson</a> has a track record of awesomeness ⭐.</p>
<p>Now that you have executed it, you can clean your solution. I bet you have found some things that you were not aware of.</p>
<h2>🤞 Hope and Wrap Up</h2>
<p>Like anything that Patrik Svensson does, this project looks amazing.</p>
<p>There's only one thing that I would love to have here. I would love that Snitch could consider the dependency tree of installed NuGet packages. So, when you install <code>"Newtonsoft.Json"</code> (as an example), Snitch would be able to know that you are depending on version "1.x" of <code>"System.Runtime.Serialization.Primitives"</code> and use that information to help you out.</p>
<p>Even without that, it's a super helpful tool.</p>
<p>Give it a try. <strong>I bet it will be part of your toolbox.</strong></p>
<p>Let me know if you have found it useful, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
C# 11 UTF-8 String Literals - Ignore everything you have seen so far2022-08-08T00:00:00-00:00https://guiferreira.me/archive/2022/csharp-11-utf-8-string-literals-ignore-everything-you-have-seen-so-far/<p>If you want to be sure that spaghetti is cooked 🍝, throw it against the wall and see if it sticks.</p>
<p>What does that have in common with C# 11 UTF-8 String Literals? Microsoft threw it against the wall, but it didn't stick.</p>
<p>Because of that, <strong>anything you have seen about this feature until now is probably outdated</strong>.</p>
<p>But, shall we start from the beginning? Let's do it.</p>
<h2>1️⃣ First iteration</h2>
<p>In April 2022, a <a href="https://devblogs.microsoft.com/dotnet/csharp-11-preview-updates/#utf-8-string-literals">blog post with C# 11 Preview features</a> was published on the .NET Blog. One of the features is UTF-8 String Literals.</p>
<p>The goal of that feature is to <strong>address particularly web scenarios where UTF-8 is king</strong> 👑. It is common to have string constants that need to be converted into UTF-8. In those scenarios, <strong>with previous versions, a developer would need to either pick performance or readability. Not anymore.</strong></p>
<p>The initial design proposed that strings could be converted into byte arrays at compile time in the following way (<a href="https://devblogs.microsoft.com/dotnet/csharp-11-preview-updates/#utf-8-string-literals">snippet extracted from .NET Blog post</a>):</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> array <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span> <span class="token comment">// new byte[] { 0x68, 0x65, 0x6c, 0x6c, 0x6f }</span><br><span class="token class-name">Span<span class="token punctuation"><</span><span class="token keyword">byte</span><span class="token punctuation">></span></span> span <span class="token operator">=</span> <span class="token string">"dog"</span><span class="token punctuation">;</span> <span class="token comment">// new byte[] { 0x64, 0x6f, 0x67 }</span><br><span class="token class-name">ReadOnlySpan<span class="token punctuation"><</span><span class="token keyword">byte</span><span class="token punctuation">></span></span> span <span class="token operator">=</span> <span class="token string">"cat"</span><span class="token punctuation">;</span> <span class="token comment">// new byte[] { 0x63, 0x61, 0x74 }</span></code></pre>
<h2>😰 The problem</h2>
<p>This proposal led to some backlash from the community. As you may know, <strong>.NET works with UTF-16 strings by default</strong>. Many were concerned that this would cause confusion.</p>
<p><strong>Another concern was related to language evolution</strong>. What if one day, <a href="https://devblogs.microsoft.com/dotnet/author/madst/">Mads Torgersen</a> and his team need to get the representation of a UTF-16 into a byte array as well? You can see the problems that this uncovers.</p>
<p>Adding a new language feature is a balance of art, science and future prediction.</p>
<h2>2️⃣ The fix with a suffix</h2>
<p>Based on that concern, the <a href="https://github.com/dotnet/csharplang/blob/main/proposals/utf8-string-literals.md">proposal</a> was reviewed. Now, it stands on a version where the <strong>string must be suffixed with <code>u8</code></strong>, which stands for UTF-8.</p>
<p>That approach was approved at a <a href="https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-04-18.md#issues-with-utf8-string-literals">Language Design meeting</a> on the premise that the .NET ecosystem is standardizing on <code>ReadOnlySpan<byte></code> as the UTF-8 string type.
What's that mean?</p>
<p>That means that, while on the initial proposal, you would be able to simply assign a string to a byte array, now you need not only to suffix it with <code>u8</code> but also to assign it to a <code>ReadOnlySpan<byte></code>.</p>
<p>Let's see it in action:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">// Instead of doing this</span><br><span class="token class-name"><span class="token keyword">var</span></span> u8Bytes <span class="token operator">=</span> System<span class="token punctuation">.</span>Text<span class="token punctuation">.</span>Encoding<span class="token punctuation">.</span>UTF8<span class="token punctuation">.</span><span class="token function">GetBytes</span><span class="token punctuation">(</span><span class="token string">"ABC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>u8Bytes<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeEquivalentTo</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token number">65</span><span class="token punctuation">,</span> <span class="token number">66</span><span class="token punctuation">,</span> <span class="token number">67</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// You can do this</span><br><span class="token class-name">ReadOnlySpan<span class="token punctuation"><</span><span class="token keyword">byte</span><span class="token punctuation">></span></span> u8Span <span class="token operator">=</span> <span class="token string">"ABC"</span>u8<span class="token punctuation">;</span><br>u8Span<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeEquivalentTo</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token number">65</span><span class="token punctuation">,</span> <span class="token number">66</span><span class="token punctuation">,</span> <span class="token number">67</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>In simple terms, code like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name">ReadOnlySpan<span class="token punctuation"><</span><span class="token keyword">byte</span><span class="token punctuation">></span></span> u8Span <span class="token operator">=</span> <span class="token string">"ABC"</span>u8<span class="token punctuation">;</span></code></pre>
<p>Will be lowered to this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name">ReadOnlySpan<span class="token punctuation"><</span><span class="token keyword">byte</span><span class="token punctuation">></span></span> u8Span <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> <span class="token punctuation">{</span> <span class="token number">65</span><span class="token punctuation">,</span> <span class="token number">66</span><span class="token punctuation">,</span> <span class="token number">67</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>You will not need to call that <code>GetBytes</code> anymore 🎉. You don't need to tradeoff maintainability and readability for performance. That makes me happy 😁.</p>
<h2>👏 Takeaway</h2>
<p>This is not only a story about a new feature.</p>
<p>I want to leave with not only an insight into what's coming.
I want you to appreciate that <strong>the Language Team listens to the community and reacts to feedback</strong>.</p>
<p>The journey of this feature demonstrates the importance of playing around with Preview versions and giving your feedback. Only that way, you are part of the evolution of our beloved language.</p>
<p>Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/csharp/11/Utf8StringLiterals">here</a>.</p>
C# 11 Generic Attributes More Than Syntax Sugar2022-06-30T00:00:00-00:00https://guiferreira.me/archive/2022/csharp-11-generic-attributes-more-than-syntax-sugar/<p>Let me be honest. C# 11 is finally bringing <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#generic-attributes">Generic Attributes</a>, but oh, boy! They are hard to sell.</p>
<p>Unless you are a library developer or into code generators, you may not see the benefit of this one. BUT (there's always a but), please bear with me! I believe that Generic Attributes is the stepping stone to many quality-of-life improvements across the framework.</p>
<h2>1️⃣ First thing first: Why should you care?</h2>
<p>Do you know when you use a <code>ServiceFilterAttribute</code> and have to provide the type? Something like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">ServiceFilter</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token type-expression class-name">ResponseLoggerFilter</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span></code></pre>
<p>That syntax isn't pretty. It's verbose.
That makes working with that type painful. The worst part is that <strong>it doesn't seem natural in C#</strong>.</p>
<p>In C#, we are used to Generics to this kind of thing, so you would probably expect something like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">ServiceFilter<ResponseLoggerFilter></span></span><span class="token punctuation">]</span></code></pre>
<p>Isn't it? GOOD NEWS! Is exactly it that will be possible.</p>
<p>It's important to say that the title of this post is not a SCAM or clickbait. Generic Attributes are not only about this change.</p>
<h2>🤔 What am I gaining with it?</h2>
<p>Once C# support it, Attribute developers will gain more than a shorter syntax. You know I LOVE 🥰 simplicity. But we are not here only for that.</p>
<p><strong>The most important win is that now, you can apply constraints.</strong></p>
<p>Let me explain that in different terms: <strong>You will detect issues in compile time, not runtime.</strong></p>
<p>If that is not a good selling point to you, I don't know what to do to amuse you. I'm sold on it!</p>
<h2>🤓 Show me the code</h2>
<p>Let me explain with code. As Abraham Lincoln used to say <em>"A code snippet is worth a thousand words."</em> 🤪</p>
<p><strong>Important:</strong> <em>This is an academic example. The idea is to demonstrate the potential of Generic Attributes in simple terms. I will do it using MVC Filters for the sake of simplicity.</em></p>
<p>Imagine you have an MVC API. You want to support a set of filters to enrich your Response Headers.
The caveat is that you don't know which headers. You need to keep it extensible.</p>
<p>One option to do it with Generic Attributes is by defining an Attribute with a Generic type.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ResponseHeadersEnrichFilterAttribute<span class="token punctuation"><</span>T<span class="token punctuation">></span></span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">Attribute</span><span class="token punctuation">,</span> <span class="token class-name">IFilterFactory</span></span><br> <span class="token keyword">where</span> <span class="token class-name">T</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">BaseHeaderEnrichFilter</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> IsReusable <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name">IFilterMetadata</span> <span class="token function">CreateInstance</span><span class="token punctuation">(</span><span class="token class-name">IServiceProvider</span> serviceProvider<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>serviceProvider <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ArgumentNullException</span><span class="token punctuation">(</span><span class="token keyword">nameof</span><span class="token punctuation">(</span>serviceProvider<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> filter <span class="token operator">=</span> <span class="token punctuation">(</span>IFilterMetadata<span class="token punctuation">)</span>serviceProvider<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">GetRequiredService</span><span class="token generic class-name"><span class="token punctuation"><</span>T<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>filter <span class="token keyword">is</span> <span class="token class-name">IFilterFactory</span> filterFactory<span class="token punctuation">)</span><br> filter <span class="token operator">=</span> filterFactory<span class="token punctuation">.</span><span class="token function">CreateInstance</span><span class="token punctuation">(</span>serviceProvider<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> filter<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br><br><br><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">BaseHeaderEnrichFilter</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IActionFilter</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name"><span class="token keyword">string</span></span> _name<span class="token punctuation">;</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name"><span class="token keyword">string</span></span> _value<span class="token punctuation">;</span><br><br> <span class="token keyword">protected</span> <span class="token function">BaseHeaderEnrichFilter</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> name<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> <span class="token keyword">value</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _name <span class="token operator">=</span> name<span class="token punctuation">;</span><br> _value <span class="token operator">=</span> <span class="token keyword">value</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnActionExecuting</span><span class="token punctuation">(</span><span class="token class-name">ActionExecutingContext</span> context<span class="token punctuation">)</span> <span class="token operator">=></span><br> context<span class="token punctuation">.</span>HttpContext<span class="token punctuation">.</span>Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><br> _name<span class="token punctuation">,</span> _value<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnActionExecuted</span><span class="token punctuation">(</span><span class="token class-name">ActionExecutedContext</span> context<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><br></code></pre>
<p>Notice that we are applying a constraint to the possible Type of <code>T</code>.
By doing it, if I provide a filter that doesn't inherit from <em>BaseHeaderEnrichFilter</em>, I will get a compilation error.</p>
<p>After doing that, defining the Filters is simple. As you can see, we are defining a simple <em>VersionHeaderEnrichFilter</em> that inherits from our Base Header Filter. We are doing it for Version, but we can extend it to other headers.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">VersionHeaderEnrichFilter</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">BaseHeaderEnrichFilter</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token function">VersionHeaderEnrichFilter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span><span class="token string">"Version"</span><span class="token punctuation">,</span> <span class="token string">"2.0"</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>And using it is even simpler. Register the filter in Dependency Injection, and add the Attribute to your controller.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">ResponseHeadersEnrichFilter<VersionHeaderEnrichFilter></span></span><span class="token punctuation">]</span><br><br><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">WeatherForecastController</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ControllerBase</span></span><br><span class="token punctuation">{</span><br><br><span class="token punctuation">}</span></code></pre>
<h2>🧙♂️ Predicting the future</h2>
<p>I'm not as good as a wizard. Never read Harry Potter 🪄.
But let me share with you where I see this going.</p>
<p>In the short term, developers building code generators will have much to gain from it. If you have some advanced use of MVC ServiceFilters, you may also want to take a deeper look into it.</p>
<p>For the rest of us, I can foresee existing attributes in the framework changing in a couple of versions to adopt this more expressive, simple approach. As an example, we may get an improved ServiceFilterAttribute that supports generics.</p>
<p>Even then, I'm excited by seeing a long-waited feature being released.</p>
<p>While we wait, if you have any use case for it, let me know. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/csharp/11/GenericAttributes">here</a>.</p>
A Gentle Introduction to C# 11 List Patterns2022-06-20T00:00:00-00:00https://guiferreira.me/archive/2022/a-gentle-introduction-to-csharp-11-list-patterns/<p>Have you heard about the recent love story in the .NET space?</p>
<p>C# is in love with pattern matching 💘.</p>
<p>And let's face it, they make a cute couple. Definitely better than Anna & Kristoff. Take that, Disney! If you don't get this reference, you can keep reading. I promise you it's not about Olaf or any other Frozen character. It's all about the new <a href="https://devblogs.microsoft.com/dotnet/early-peek-at-csharp-11-features/#c-11-preview-list-patterns"><strong>List Patterns in C# 11</strong></a>.</p>
<p>We all know that F# has been an inspiration for C# lately. We know that Pattern Matching capabilities have been evolving version upon version. Property patterns deserve attention since they came to life on C# 8. <a href="https://guiferreira.me/archive/2021/expressive-c-code-with-property-patterns/">We have seen improvements on C# 9 and C# 10.</a> And now is the time for Lists.</p>
<h2>🤔 What are List Patterns?</h2>
<p>Long story short, <strong>List Patterns let you look into the shape of a list or an array</strong>. If you want to check if the collection starts, ends or contains a given value, List Patterns will be the way to go.</p>
<p>I know, I know. That is strange. And I have to confess that it's even harder to explain it. Perhaps, it's better to do it with a few examples.</p>
<h2>1️⃣ The List Pattern</h2>
<p>List Patterns surround values with square brackets. You will define <em>1</em> to <em>N</em> values that you want to match in the collection.</p>
<p>You can check if a collection has a specific set of values.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> collection <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token keyword">return</span> collection <span class="token keyword">switch</span><br><span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token string">"A"</span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token string">"B"</span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> _<span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token string">"C"</span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span><span class="token range operator">..</span><span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token string">"D"</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br></code></pre>
<p>You can check the shape of the collection by capturing the values.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"Empty"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> <span class="token punctuation">{</span> <span class="token string">"e1"</span><span class="token punctuation">,</span> <span class="token string">"e2"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"Found e1 and e2"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> <span class="token punctuation">{</span> <span class="token string">"e1"</span><span class="token punctuation">,</span> <span class="token string">"e2"</span><span class="token punctuation">,</span> <span class="token string">"e3"</span><span class="token punctuation">,</span> <span class="token string">"e4"</span><span class="token punctuation">,</span> <span class="token string">"e5"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"Many found: from e1 to e5"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenStringCollection_ThenReturnCollectionDescription</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> input<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> output<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> input <span class="token keyword">switch</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token string">"Empty"</span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span><span class="token class-name"><span class="token keyword">var</span></span> a<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">var</span></span> b<span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token interpolation-string"><span class="token string">$"Found </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">a</span><span class="token punctuation">}</span></span><span class="token string"> and </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">b</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span><span class="token class-name"><span class="token keyword">var</span></span> a<span class="token punctuation">,</span> <span class="token range operator">..</span> _<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">var</span></span> z<span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token interpolation-string"><span class="token string">$"Many found: from </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">a</span><span class="token punctuation">}</span></span><span class="token string"> to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">z</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>output<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2>2️⃣ The Slice Pattern</h2>
<p>You have noticed that in the example above when the collection has more than 2 elements, we use a <em>".."</em> and <em>"_"</em>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token class-name"><span class="token keyword">var</span></span> a<span class="token punctuation">,</span> <span class="token range operator">..</span> _<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">var</span></span> z<span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token interpolation-string"><span class="token string">$"Many found: from </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">a</span><span class="token punctuation">}</span></span><span class="token string"> to </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">z</span><span class="token punctuation">}</span></span><span class="token string">"</span></span></code></pre>
<p><em>".."</em> is the slice pattern. It means we match every collection entry from the previous Pattern until the next one.</p>
<p>Slice pattern let you discard those values, as seen above using underscore. Or, we can capture the value into a variable, as you can see below.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> uri <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Uri</span><span class="token punctuation">(</span><span class="token string">"http://www.mysite.com/categories/category-a/sub-categories/sub-category-a.html"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> uri<span class="token punctuation">.</span>Segments <span class="token keyword">switch</span><br><span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token string">"/"</span><span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token string">"Root"</span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span>_<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">var</span></span> single<span class="token punctuation">]</span> <span class="token operator">=></span> single<span class="token punctuation">,</span><br> <span class="token punctuation">[</span>_<span class="token punctuation">,</span> <span class="token range operator">..</span> <span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> entries<span class="token punctuation">,</span> _<span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Join</span><span class="token punctuation">(</span><span class="token string">" > "</span><span class="token punctuation">,</span> entries<span class="token punctuation">)</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2>💪 Is it powerful?</h2>
<p>I have a challenge for you if you are not seeing the potential.</p>
<p>Can you imagine writing a method to calculate Factorial using List Patterns?</p>
<p>You can, and it's neat.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Theory</span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">InlineData</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">3628800</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenNumber_ThenCalculateFactorialUsingListPatterns</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> input<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> output<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> values <span class="token operator">=</span> Enumerable<span class="token punctuation">.</span><span class="token function">Range</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> input<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> factorial <span class="token operator">=</span> <span class="token function">Factorial</span><span class="token punctuation">(</span>values<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> factorial<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>output<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><br> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Factorial</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> values<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br><br> <span class="token keyword">return</span> values <span class="token keyword">switch</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">,</span><br> <span class="token punctuation">[</span><span class="token range operator">..</span> <span class="token class-name"><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> numbers<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">int</span></span> number<span class="token punctuation">]</span> <span class="token operator">=></span> number <span class="token operator">*</span> <span class="token function">Factorial</span><span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>STOP 🛑! You don't need to grab your pitchfork. I'm not saying that Factorial should be implemented like this. I want to show you what this feature can potentially do.</p>
<p>C# 11 is in Preview, and we still need to wait for it, so we need to wait.</p>
<p>While we wait, if you have any use case for it, let me know. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a>, and let's keep in touch.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/csharp/11/ListPatterns">here</a>.</p>
The Complete Guide to C# 11 Raw String Literals2022-06-03T00:00:00-00:00https://guiferreira.me/archive/2022/the-complete-guide-to-csharp-11-raw-string-literals/<p>First things, first.</p>
<p><strong>Why should you care?</strong> Because strings with escaping are hard to read and maintain.</p>
<p><strong>Is it just for JSON objects?</strong> No!</p>
<p><strong>Is it for you?</strong> Hell, yes! 😎</p>
<p>Wanna see it? 👇</p>
<p>Do you know what is unmanageable and ugly C# code? Any kind of text that to be a C# string needs to be heavily escaped. Yap... JSON objects are one of those.</p>
<p>Even if you are a lucky <a href="https://www.jetbrains.com/rider/">JetBrains Rider</a> user, like me 🤘, and your object is magically escaped (<a href="https://twitter.com/gsferreira/status/1532643248409350145">see here</a>), you know how painful it is to read or maintain that string.</p>
<p>Can you imagine how awesome it would be if we could grab a JSON, a SQL, XML, YAML, or a WhateverL (don't bother about googling it, I just made it up), paste it into a string, and it just works? It just works, no magic tricks. No automation.</p>
<p>How awesome would it be if you don't need to escape quotes?</p>
<p>What about pathing? Oh, all that leading white space that we love. 😒</p>
<p>It's hard to imagine that world. For C# developers, this has been this way for a long time. It's one of the things that I couldn't imagine changing in C#. I was sure that this would always be this way. As sure as I was that Game of Thrones would have a great final season.</p>
<p>🛎️ Ding! 🛎️ Ding!</p>
<p>I was wrong. Twice!</p>
<h2>👑 Hail to the new Raw Strings Literals</h2>
<p><em>I’m writing this when C# 11 and <a href="https://devblogs.microsoft.com/dotnet/csharp-11-preview-updates/">Raw String Literals are in Preview</a>.</em></p>
<p>C# will solve this mess for once with <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#raw-string-literals">Raw String Literals</a>.</p>
<p><img src="https://guiferreira.me/images/archive/csharp/raw-string-literals-json.png" alt="Raw String Literals / JSON Object"></p>
<p><strong>So, what are Raw String Literals?</strong></p>
<p>Raw String Literals is a simple way to define a text block and avoid escape nightmares, fighting with pathing or guessing how many double quotes you need. It will make you more productive and improve maintainablity.</p>
<p>You can simply do it by using a set of <strong>at least 3 double quotes</strong> (<code>"""</code>) for opening and closing the Raw String Litteral.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span> <span class="token string">""</span>"Hello World<span class="token operator">!</span><span class="token string">""</span>"<span class="token punctuation">;</span><br><br>text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"Hello World!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// Hello World!</span></code></pre>
<p>I know that you are already thinking about how to break the system 😤.</p>
<p>You are probably asking: <em>What if I want 3 double quotes in my text?</em></p>
<p>I’m glad that you asked. It's here that the thing becomes clever, my friend.</p>
<p>Not sure if you noticed, but a few paragraphs above, I've written: <em>"at least 3 double quotes"</em>. That "at least", is important.</p>
<p>A Raw String Literal will be anything between a pair of 3 or more double quotes.</p>
<p>The rule is simple.</p>
<ul>
<li>If your string needs to have a <strong>sequence of 3 double quotes</strong>, you will need to open and close the Raw String Litteral with <strong>at least 4 double-quotes</strong>.</li>
<li>If your string needs to have a <strong>sequence of 4 double quotes</strong>, you will <strong>need at least 5</strong>.</li>
<li>If your string needs to have a <strong>sequence of 5 double quotes</strong>, you will <strong>need at least 6</strong>.</li>
<li>If your string needs to have a <strong>sequence of 6 double quotes</strong>... you get it.</li>
</ul>
<p>It may look strange, but it's pretty effective since you are not constrained. And it’s future proof.</p>
<h2>😒 Pathing madness</h2>
<p>Do you put a lot of effort into formatting your <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/verbatim">verbatim strings</a>? I do.</p>
<p>But, often you can't keep it perfect in source code and runtime. You need to pick one and assume that the other will not be perfect. As <a href="https://www.kentbeck.com/">Kent Beck</a> says, "it's all about trade-offs".</p>
<p>SQL queries are one of those cases. I always craft them carefully until the moment I see them in runtime. 🤢</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span><br> <span class="token string">""</span>"<br> SELECT Name<br> FROM Customers<br> <span class="token class-name">WHERE</span> id <span class="token operator">=</span> @id<br> <span class="token string">""</span>"<span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// SELECT Name</span><br><span class="token comment">// FROM Customers</span><br><span class="token comment">// WHERE id = @id</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span><br> <span class="token string">@"<br> SELECT Name<br> FROM Customers<br> WHERE id = @id<br> "</span><span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// SELECT Name</span><br><span class="token comment">// FROM Customers</span><br><span class="token comment">// WHERE id = @id</span><br><br></code></pre>
<p>With Raw String Literals, we can finally solve that. How? Let's take a look.</p>
<p>The end sequence of double-quotes is the commander in chief of pathing. If you want to remove the left path, you simply align it with the opening sequence of double quotes. Boom! 💥 Just that and leading white space was through away! Whitespace to the left of the closing quotes will be removed.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span><br> <span class="token string">""</span>"<br> SELECT Name<br> FROM Customers<br> <span class="token class-name">WHERE</span> id <span class="token operator">=</span> @id<br> <span class="token string">""</span>"<span class="token punctuation">;</span><br><br>text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"SELECT Name</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token string">FROM Customers</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token string">WHERE id = @id"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// SELECT Name</span><br><span class="token comment">// FROM Customers</span><br><span class="token comment">// WHERE id = @id</span><br><br>text <span class="token operator">=</span><br> <span class="token string">""</span>"<br> SELECT Name<br> FROM Customers<br> <span class="token class-name">WHERE</span> id <span class="token operator">=</span> @id<br> <span class="token string">""</span>"<span class="token punctuation">;</span><br><br>text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$" SELECT Name</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token string"> FROM Customers</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token string"> WHERE id = @id"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// SELECT Name</span><br><span class="token comment">// FROM Customers</span><br><span class="token comment">// WHERE id = @id</span><br></code></pre>
<h2>💲 Interpolation in Raw String Literals</h2>
<p>More often than not, your long strings are not constants or static. You may be interpolating it with a name, age, amount, or another variable.</p>
<p>You can do it as well in a Raw String Literal.</p>
<p>There's just one thing you need to think about: What if you need to interpolate inside curly braces? In other words, what if the result should be visible inside curly braces?</p>
<p>WAIT! It's not another escaping madness. I promise you.</p>
<p>Raw String Literals have a simple way to solve that as well. And it's future proof! Once again. 😅</p>
<p>So, if you need to accept curly braces, you open the Interpolated Raw String Literal with an extra dollar sign.</p>
<pre class="language-csharp"><code class="language-csharp"><br><span class="token class-name"><span class="token keyword">var</span></span> name <span class="token operator">=</span> <span class="token string">"Guilherme"</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span><br> $<span class="token interpolation-string"><span class="token string">$""</span></span>"<br> Hello <span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token punctuation">{</span> name <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">!</span><br><br> Welcome to the Team<span class="token operator">!</span><br> <span class="token string">""</span>"<span class="token punctuation">;</span><br><br>text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"Hello {{Guilherme}}!</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token string">Welcome to the Team!"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// Hello {Guilherme}!</span><br><span class="token comment">//</span><br><span class="token comment">// Welcome to the Team!</span><br></code></pre>
<p>You define the same number of dollar signs needed to interpolate.</p>
<p>So, if you need to have a sequence of 3 curly braces, you just need to use 4 dollar signs and 4 curly braces to interpolate.</p>
<pre class="language-csharp"><code class="language-csharp"><br><span class="token class-name"><span class="token keyword">var</span></span> name <span class="token operator">=</span> <span class="token string">"Guilherme"</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span><br> $$$<span class="token interpolation-string"><span class="token string">$""</span></span>"<br> Hello <span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token punctuation">{</span> name <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">!</span><br><br> Welcome to the Team<span class="token operator">!</span><br> <span class="token string">""</span>"<span class="token punctuation">;</span><br><br>text<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"Hello {{{{{{Guilherme}}}}}}!</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">System<span class="token punctuation">.</span>Environment<span class="token punctuation">.</span>NewLine</span><span class="token punctuation">}</span></span><span class="token string">Welcome to the Team!"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">// Equal to:</span><br><span class="token comment">// Hello {{{Guilherme}}}!</span><br><span class="token comment">//</span><br><span class="token comment">// Welcome to the Team!</span><br></code></pre>
<h3>⏭️ What's next</h3>
<p><strong>My take on it:</strong> I will use it! I want it!</p>
<p>I will be converting many SQL statements, JSON objects or Test expectations.</p>
<p>I believe you should too! While I'm writing, C# 11 is in Preview, and we still need to wait for it. But, once you start using C# 11, think about it before going wild with double quotes or backslashing.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/csharp/11/RawStringLiterals">here</a>.</p>
<p>See ya! In the meanwhile, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch. 😉</p>
The Blind Spot of C# Records Immutability2022-05-24T00:00:00-00:00https://guiferreira.me/archive/2022/the-blind-spot-of-csharp-records-immutability/<p>Have you been using <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record">Records in C#</a>?</p>
<p>Do you use them for immutability?</p>
<p>Are you sure they are immutable?</p>
<p>Do you use Lists?</p>
<p>So, let me tell you that <strong>you may have some unexpected mutable ones</strong>.</p>
<p><img src="https://guiferreira.me/images/archive/csharp/record-with-mutable-collection.png" alt="Record with mutable collection"></p>
<p>Good news! It’s not your fault.</p>
<h2>The promised immutability in one line</h2>
<p>Before you keep reading, let me address the elephant in the room. You may be thinking: <em>"Guilherme, immutability in .NET is a lie"</em>.</p>
<p>Let me tell you, my friend, that's a different discussion.</p>
<p>If you don’t value the way .NET addresses immutability, you can stop reading here. This post is not for you.</p>
<p>If you are reading this line, thanks for not leaving the boat. I promise you that <strong>there’s value in Immutable data structures in one line</strong>. How can you not love it? 😍</p>
<p>Besides the people that stop reading two paragraphs above, I only know one person who doesn’t make a big deal about it. It’s my daughter. She’s 5.</p>
<h2>A simple rule</h2>
<p>They told us that Records would be simple. But <strong>Records require an extra level of attention</strong>. What wouldn’t be a problem if our attention wasn’t devoted to Twitter or Reddit.</p>
<p>You know that the way you declare them can make them mutable. But, once you master it, it doesn't stop there.</p>
<p><img src="https://guiferreira.me/images/archive/tweets/records-immutability.png" alt="Tweet / Records Immutability"></p>
<p><em><a href="https://twitter.com/gsferreira/status/1467045497441595393?s=20&t=2ELu4AZwZnuIV_qBwjZEcw">(here)</a></em></p>
<p>The question stands. How can you fulfil the prophecy of immutable data structures in one line?</p>
<p>You can do it with a simple rule. 👇</p>
<p><strong><em>Record Properties must be a Primitive, a Record or a Read-only/Immutable collection to preserve immutability.</em></strong></p>
<p>Simple! Isn’t it? Not as simple as knowing where to click to Google search. But simpler than fixing a bug on a Friday afternoon.</p>
<p>Keep an eye on mutable properties, and it will be fine.</p>
<h2>A rule in practice</h2>
<p>Let’s see this thing in action?</p>
<p>The idea is simple. You avoid mutable collections and classes with public modifiers as record properties.</p>
<p>Take a look at the following Record.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">Album</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> Title<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> Artist<span class="token punctuation">,</span> <span class="token class-name">List<span class="token punctuation"><</span>Song<span class="token punctuation">></span></span> Songs<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> songs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">List<span class="token punctuation"><</span>Song<span class="token punctuation">></span></span> <span class="token punctuation">{</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token string">"Hold On"</span><span class="token punctuation">,</span> <span class="token number">265</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> album <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Album</span><span class="token punctuation">(</span><span class="token string">"Down the Way"</span><span class="token punctuation">,</span> <span class="token string">"Angus & Julia Stone"</span><span class="token punctuation">,</span> songs<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>album<span class="token punctuation">.</span>Songs<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Song</span><span class="token punctuation">(</span><span class="token string">"Black Crow"</span><span class="token punctuation">,</span> <span class="token number">230</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>album<span class="token punctuation">.</span>Songs<span class="token punctuation">.</span>Count <span class="token comment">// 2</span></code></pre>
<p>As you can see, you can set the collection 😱</p>
<p>How can we refactor this into an immutable record?</p>
<p>It’s simple, put a Read-Only or Immutable Array in action.</p>
<p><strong>Read-Only</strong></p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">Album</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> Title<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> Artist<span class="token punctuation">,</span> <span class="token class-name">IReadOnlyCollection<span class="token punctuation"><</span>Song<span class="token punctuation">></span></span> Songs<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> songs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ReadOnlyCollection<span class="token punctuation"><</span>Song<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Song</span><span class="token punctuation">(</span><span class="token string">"Hold On"</span><span class="token punctuation">,</span> <span class="token number">265</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> album <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Album</span><span class="token punctuation">(</span><span class="token string">"Down the Way"</span><span class="token punctuation">,</span> <span class="token string">"Angus & Julia Stone"</span><span class="token punctuation">,</span> songs<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>album<span class="token punctuation">.</span>Songs<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Song</span><span class="token punctuation">(</span><span class="token string">"Black Crow"</span><span class="token punctuation">,</span> <span class="token number">230</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ❌</span><br><span class="token comment">// You can't even doing it 👆</span></code></pre>
<p><strong>ImmutableArray</strong></p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">record</span> <span class="token class-name">Album</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> Title<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> Artist<span class="token punctuation">,</span> <span class="token class-name">ImmutableArray<span class="token punctuation"><</span>Song<span class="token punctuation">></span></span> Songs<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> songs <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Song</span><span class="token punctuation">(</span><span class="token string">"Hold On"</span><span class="token punctuation">,</span> <span class="token number">265</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">ToImmutableArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> album <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Album</span><span class="token punctuation">(</span><span class="token string">"Down the Way"</span><span class="token punctuation">,</span> <span class="token string">"Angus & Julia Stone"</span><span class="token punctuation">,</span> songs<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>album<span class="token punctuation">.</span>Songs<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Song</span><span class="token punctuation">(</span><span class="token string">"Black Crow"</span><span class="token punctuation">,</span> <span class="token number">230</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>album<span class="token punctuation">.</span>Songs<span class="token punctuation">.</span>Length <span class="token comment">// 1</span></code></pre>
<h2>Putting it in action</h2>
<p>It may look like common sense, but it's easy to go undercover.</p>
<p>Now that you know the blind spot, it’s time to take action.</p>
<p>Do you have Records in place? Go check them to see if:</p>
<ul>
<li>Are you using Lists or Arrays as properties?</li>
<li>Are you using types with public modifiers as properties?</li>
</ul>
<p>Swap them with an Immutable Array, Read-Only Collection or Record.</p>
<p>After that, you just need to do one more important thing. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch. 😉</p>
Quick Wins for .NET build pipelines2022-02-23T00:00:00-00:00https://guiferreira.me/archive/2022/quick-wins-for-dotnet-build-pipelines/<p>Faster builds are equal to faster feedback cycles 🚀, happier developers 😁, and money saved 🤑.</p>
<p>So, even <strong>if you shave just a few seconds, it's an investment that compounds.</strong></p>
<p>If you have a .NET Core or .NET 6 (or later) application being built as part of your CI/CD process, it will be using the <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/">.NET CLI</a> for sure. Even, if you point and click through <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/">TeamCity</a>, <a href="https://www.jenkins.io/">Jenkins</a>, etc. configuration, behind the scenes .NET CLI will be running. So, the following tips are likely for you.</p>
<p>You can create a .NET build script with just a few simple commands like the following ones:</p>
<ul>
<li><code>dotnet build</code></li>
<li><code>dotnet test</code></li>
<li><code>dotnet publish</code></li>
<li><code>dotnet pack</code></li>
</ul>
<p>But you can do better than that. Each CLI command has a bunch of options that can be provided and they assume default behaviours when you don't specify them.</p>
<h2>Options for optimization</h2>
<p>There are 4 options that I want to pay close attention to and are the ones that will be responsible for our optimizations.</p>
<ul>
<li><code>--configuration <CONFIGURATION></code></li>
<li><code>--no-restore</code></li>
<li><code>--no-build</code></li>
<li><code>--nologo</code></li>
</ul>
<h3><code>--configuration <CONFIGURATION></code></h3>
<p>It will define the build configuration. The problem with Configuration is that by default, it will use <code>Debug</code>.</p>
<p>Since you want to publish your software using <code>Release</code> mode, you may end up in a place where you use different Configurations on different steps. That means that the following build steps may need to rebuild.</p>
<h3><code>--no-restore</code></h3>
<p>Particularly important for the build step.</p>
<p>The CLI uses implicit restore, so you don't need to run <code>dotnet restore</code>. But, if you want to have a step running <code>dotnet restore</code>, you can disable the implicit restore in the build step, so the CLI doesn't need to check if it's needed.</p>
<h3><code>--no-build</code></h3>
<p>By default, steps like <code>"test"</code> or <code>"publish"</code> will try to build the software if needed.</p>
<p>If you set the <code>--no-build</code>, it will not build the project before running that step. By doing so, it implicitly uses the <code>--no-restore</code> flag.</p>
<p>One of the advantages of using the <code>--no-build</code> option, is that it helps you spot problems with previous step configuration. Example: if all the steps use <code>--configuration Release</code>, besides <code>dotnet pack</code>, the <code>dotnet pack</code> step will fail. Without the <code>--no-build</code> option, the problem would go unnoticed, and the project built again.</p>
<h3><code>--nologo</code></h3>
<p>With <code>--nologo</code> Microsoft copyright banner will not be displayed. It is a minor detail, but it's a simple way to remove clutter from your build logs, and IO has a cost even if residual.</p>
<p>Those are details for sure, but they will help you prevent inefficiencies in the build process. Sometimes you may save 1 second, and other times 1 minute, but don't forget that build time savings compound fast.</p>
<pre class="language-powershell"><code class="language-powershell">dotnet build <span class="token operator">--</span>configuration Release <span class="token operator">--</span>nologo<br>dotnet test <span class="token operator">--</span>configuration Release <span class="token operator">--</span>nologo <span class="token operator">--</span>no-build<br>dotnet publish <span class="token operator">--</span>configuration Release <span class="token operator">--</span>nologo <span class="token operator">--</span>no-build<br>dotnet pack <span class="token operator">--</span>configuration Release <span class="token operator">--</span>nologo <span class="token operator">--</span>no-build</code></pre>
<p>I hope that this was useful! If you managed to shave some seconds from your pipeline, please let me know. Follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Providing a better experience for .NET developers with Caller Argument Expressions2022-02-21T00:00:00-00:00https://guiferreira.me/archive/2022/providing-a-better-experience-for-dotnet-developers-with-caller-argument-expressions/<p>I've always been a fan of usability. I love when I see libraries and APIs developed with developer experience in mind.</p>
<p>The <a href="https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">Clean Code</a> movement made a ton for us in that chapter. But sometimes the small details create all the difference.</p>
<p>Since my language of choice is C# .NET, I'm always delighted when the framework gives me new ways to simplify the life of those consuming my code.</p>
<p>So, it's no surprise that I loved .NET 6 <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression">Caller Argument Expressions</a>.</p>
<h2>Why do we need it?</h2>
<p>One common refactoring to improve code readability is implementing <a href="https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html">Guard clauses</a>. It's common to see the first line of a method asserting the provided arguments. And that's fine. If you provide a null value, and you receive an <em>ArgumentNullException</em>, you will be able to understand that something is wrong in the way that you are consuming the API.</p>
<p>What if you could go a step further?
What if instead of letting you know the What, you could tell you the Why?
What if instead of saying <em>"You are not providing a valid argument X"</em>, you could say <em>"You are sending me the variable or expression Y, and that is not valid because of X"</em>.</p>
<p>Do you see the difference?
The difference is that now, I can give you an exception that contains information about your code.
You may not know the names that I use for my arguments, but for sure you know your code. That is awesome! This reduces the cognitive load to diagnose an exception like that.</p>
<p>Maybe it will not be that important if it's a library built by yourself. But will feel awesome if you are using a library that you grab from a random <a href="https://www.nuget.org/">NuGet</a> package.</p>
<h2>How to provide it?</h2>
<p>Using it is simple. Whenever you want to throw an exception with the caller information, you use <code>CallerArgumentExpression</code> like in the example below.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenAnOddNumber_WhenVerify_ThenNoExceptionIsThrown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> action <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">VerifyIsOddNumber</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> action<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">NotThrow</span><span class="token generic class-name"><span class="token punctuation"><</span>Exception<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenAVariableWithAnEvenNumber_WhenVerify_ThenArgumentExceptionIsThrownWithVariableName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">int</span></span> myNumber <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> action <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">VerifyIsOddNumber</span><span class="token punctuation">(</span>myNumber<span class="token punctuation">)</span><span class="token punctuation">;</span><br> action<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Throw</span><span class="token generic class-name"><span class="token punctuation"><</span>ArgumentException<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">"myNumber"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenAnEvenNumber_WhenVerify_ThenArgumentExceptionIsThrownWithValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> action <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">VerifyIsOddNumber</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> action<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Throw</span><span class="token generic class-name"><span class="token punctuation"><</span>ArgumentException<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">"10"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenAnExpressionReturningEvenNumber_WhenVerify_ThenArgumentExceptionIsThrownWithValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> action <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">VerifyIsOddNumber</span><span class="token punctuation">(</span><span class="token number">4</span> <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> action<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Throw</span><span class="token generic class-name"><span class="token punctuation"><</span>ArgumentException<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">"4 * 2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">VerifyIsOddNumber</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> <span class="token keyword">value</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">CallerArgumentExpression</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"value"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">?</span></span> paramName <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">value</span> <span class="token operator">%</span> <span class="token number">2</span> <span class="token keyword">is</span> <span class="token number">0</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ArgumentException</span><span class="token punctuation">(</span>paramName<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<h2>How to consume it?</h2>
<p>As you probably know, with .NET 6 we have a <a href="https://docs.microsoft.com/en-us/dotnet/api/system.argumentnullexception.throwifnull?view=net-6.0">Guard clause for <em>ArgumentNullExceptions</em></a> directly in the exception itself.
You can use it with:</p>
<pre class="language-csharp"><code class="language-csharp">ArgumentNullException<span class="token punctuation">.</span><span class="token function">ThrowIfNull</span><span class="token punctuation">(</span>myObject<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>If you have used it, you were using <code>CallerArgumentExpression</code> in action.</p>
<p>So, if you drill down into the code, you will see how Microsoft is doing it.
Basically, the <code>CallerArgumentExpression</code> attribute is being used to capture the argument.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">/// <summary>Throws an <see cref="ArgumentNullException"/> if <paramref name="argument"/> is null.</summary></span><br><span class="token comment">/// <param name="argument">The reference type argument to validate as non-null.</param></span><br><span class="token comment">/// <param name="paramName">The name of the parameter with which <paramref name="argument"/> corresponds.</param></span><br><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ThrowIfNull</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">NotNull</span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">object</span><span class="token punctuation">?</span></span> argument<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">CallerArgumentExpression</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"argument"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">?</span></span> paramName <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>argument <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token function">Throw</span><span class="token punctuation">(</span>paramName<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<h2>Wrapping up</h2>
<p>As you can see, it's a small detail, that can simplify your consumer's life.
If you are delivering libraries to other Teams or the Public, I suggest you give it a try. Inspire yourself in Microsoft work with <code>ArgumentNullException</code>, and amaze your consumers.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/csharp/10/CallerArgumentExpression">here</a>.</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Embedding dotnet format in your development cycle2022-02-11T00:00:00-00:00https://guiferreira.me/archive/2022/embedding-dotnet-format-in-your-development-cycle/<p>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.</p>
<p>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 <code>.editorconfig</code> and BOOOM! 💥 No more nitpicking on indentation or whitespaces. You can even enforce other rules like having the System using directives first.</p>
<pre class="language-ini"><code class="language-ini"><span class="token comment"># .editorconfig Example</span><br><span class="token comment"># Organize using directives</span><br><span class="token key attr-name">dotnet_sort_system_directives_first</span> <span class="token punctuation">=</span> <span class="token value attr-value">true</span><br><span class="token key attr-name">dotnet_separate_import_directive_groups</span> <span class="token punctuation">=</span> <span class="token value attr-value">false</span></code></pre>
<p>And now we can bring the same experience with <strong>dotnet format</strong>!</p>
<p>.NET CLI has introduced a <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-format">new command to format</a>. <a href="https://github.com/dotnet/format">"dotnet format"</a> 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.</p>
<h2>How can I use it?</h2>
<p>It is a simple command-line tool, so you can integrate it into your CI/CD toolchain.</p>
<p>One interesting "dotnet format" option is to verify if changes should be performed with <code>--verify-no-changes</code>. Besides that, you can include only some files in the verification with <code>--include</code>.</p>
<pre><code>dotnet format --verify-no-changes --include src\Infrastructure\CustomerRepository.cs
</code></pre>
<p>So, those two arguments are perfect for a CI pipeline.
Every time a PR (Pull Request) is open, you can verify any broken format rule during build time.</p>
<h2>Runing dotnet format with GitHub Actions</h2>
<p>You can run it in your prefered build system, being TeamCity, Jenkins, Azure DevOps, etc., but here I will use GitHub Actions.</p>
<p>The process is quite simple. If you go to <a href="https://github.com/marketplace?type=actions">GitHub Actions Marketplace</a>, you will find some extensions to run dotnet format. I will be using <a href="https://github.com/marketplace/actions/dotnet-format">"xt0rted/dotnet-format"</a> by <a href="https://github.com/xt0rted">Brian Surowiec</a>.</p>
<p>So, I added a step to my workflow:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Run dotnet format<br> <span class="token key atrule">uses</span><span class="token punctuation">:</span> xt0rted/dotnet<span class="token punctuation">-</span>format@v1<br> <span class="token key atrule">with</span><span class="token punctuation">:</span><br> <span class="token key atrule">only-changed-files</span><span class="token punctuation">:</span> <span class="token string">"true"</span></code></pre>
<p>The workflow:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">name</span><span class="token punctuation">:</span> .NET<br><br><span class="token key atrule">on</span><span class="token punctuation">:</span><br> <span class="token key atrule">push</span><span class="token punctuation">:</span><br> <span class="token key atrule">branches</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>main<span class="token punctuation">]</span><br> <span class="token key atrule">pull_request</span><span class="token punctuation">:</span><br> <span class="token key atrule">branches</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>main<span class="token punctuation">]</span><br><br><span class="token key atrule">jobs</span><span class="token punctuation">:</span><br> <span class="token key atrule">build</span><span class="token punctuation">:</span><br> <span class="token key atrule">runs-on</span><span class="token punctuation">:</span> ubuntu<span class="token punctuation">-</span>latest<br><br> <span class="token key atrule">steps</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> <span class="token key atrule">uses</span><span class="token punctuation">:</span> actions/checkout@v2<br> <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Setup .NET<br> <span class="token key atrule">uses</span><span class="token punctuation">:</span> actions/setup<span class="token punctuation">-</span>dotnet@v1<br> <span class="token key atrule">with</span><span class="token punctuation">:</span><br> <span class="token key atrule">dotnet-version</span><span class="token punctuation">:</span> 6.0.x<br><br> <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Run dotnet format<br> <span class="token key atrule">uses</span><span class="token punctuation">:</span> xt0rted/dotnet<span class="token punctuation">-</span>format@v1<br> <span class="token key atrule">with</span><span class="token punctuation">:</span><br> <span class="token key atrule">only-changed-files</span><span class="token punctuation">:</span> <span class="token string">"true"</span><br><br> <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Restore dependencies<br> <span class="token key atrule">run</span><span class="token punctuation">:</span> dotnet restore<br> <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Build<br> <span class="token key atrule">run</span><span class="token punctuation">:</span> dotnet build <span class="token punctuation">-</span><span class="token punctuation">-</span>no<span class="token punctuation">-</span>restore<br> <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Test<br> <span class="token key atrule">run</span><span class="token punctuation">:</span> dotnet test <span class="token punctuation">-</span><span class="token punctuation">-</span>no<span class="token punctuation">-</span>build <span class="token punctuation">-</span><span class="token punctuation">-</span>verbosity normal</code></pre>
<p>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.</p>
<p>That is pretty cool, but I would prefer to prevent build attempts because somebody forgot to format a file.</p>
<h2>dotnet format and Git Hooks</h2>
<p>So, how can I prevent commits if I forget to format the code?</p>
<p>The answer to that is <a href="https://githooks.com/">Git Hooks</a>.
Git gives you a way to hook in some git steps. So, you can run your code on pre-commit.</p>
<p>You can do that in many ways (see <a href="https://github.com/dotnet/format/blob/main/docs/integrations.md">here</a>), but I prefer to use <a href="https://pre-commit.com/">"pre-commit"</a>. Pre-commit simplifies your process and offers you an easy way to adopt new hooks. Go take a look. It's pretty cool!</p>
<h3>How to configure pre-commit</h3>
<p>First, you need to install pre-commit (see <a href="https://pre-commit.com/#install">here</a>).</p>
<p>After installed, create a file <code>".pre-commit-config.yaml"</code> in the root folder.</p>
<p>Add the following snippet there.</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">repos</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> <span class="token key atrule">repo</span><span class="token punctuation">:</span> https<span class="token punctuation">:</span>//github.com/dotnet/format<br> <span class="token key atrule">rev</span><span class="token punctuation">:</span> <span class="token string">""</span><br> <span class="token key atrule">hooks</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> <span class="token key atrule">id</span><span class="token punctuation">:</span> dotnet<span class="token punctuation">-</span>format<br> <span class="token key atrule">args</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">-</span><span class="token punctuation">-</span>folder<span class="token punctuation">,</span> <span class="token punctuation">-</span><span class="token punctuation">-</span>include<span class="token punctuation">]</span></code></pre>
<p>Now, install your git hook script:</p>
<p><code>pre-commit install</code></p>
<p>After this, dotnet format will run every time you <code>git commit</code>! 😍</p>
<p><img src="https://guiferreira.me/images/archive/dotnet/dotnet-format-result.png" alt="dotnet format result"></p>
<h2>Wrapping up</h2>
<p>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.</p>
<p>It's quite a simple process, so it's worth trying.</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Looking into C# Property Patterns Performance2022-02-03T00:00:00-00:00https://guiferreira.me/archive/2022/looking-into-csharp-property-patterns-performance/<p>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 <a href="https://guiferreira.me/archive/2021/expressive-c-code-with-property-patterns/">here</a>).</p>
<p>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.</p>
<p><img src="https://guiferreira.me/images/archive/tweets/property-patterns.png" alt="Tweet / Property Patterns"></p>
<p><em><a href="https://twitter.com/gsferreira/status/1486625607895109635">(here)</a></em></p>
<p>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.</p>
<p>One of the comments was the usual when you post .NET related content: <em>"What about performance?"</em></p>
<h2>Performance 🚀</h2>
<p>So, I decided to go on a journey to understand how performant Guard clauses with Property Patterns can be.</p>
<p>To do that, I decided to compare the multiple suggestions received with my loved Property Patterns.</p>
<p>So, the candidates were:</p>
<h3>Option A</h3>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>list <span class="token keyword">is</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token operator">!</span>list<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></code></pre>
<h3>Option B</h3>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>list<span class="token punctuation">?.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token boolean">false</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></code></pre>
<h3>Option C</h3>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>list <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> list<span class="token punctuation">.</span>Length <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></code></pre>
<h3>Option D</h3>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>list <span class="token keyword">is</span> <span class="token keyword">not</span> <span class="token punctuation">{</span> Length<span class="token punctuation">:</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></code></pre>
<h3>Option E</h3>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>list <span class="token keyword">is</span> <span class="token keyword">null</span> <span class="token keyword">or</span> <span class="token punctuation">{</span> Length<span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br><span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></code></pre>
<p>After running a benchmark, I got the following results.</p>
<p><img src="https://guiferreira.me/images/archive/csharp/property-patterns-guard-benchmark-results.png" alt="Property Patterns Benchmark Results"></p>
<p>That was an excellent result.</p>
<h2>How can they do that? 🤔</h2>
<p>As you can see, Property Patterns aren't the most performant, but they are close enough. How?</p>
<p>If you pick option D or E and lower it using <a href="https://sharplab.io/">SharpLab</a>, you will see that the Property Patterns lowered version is quite close to Option C, the most performant option.</p>
<p><img src="https://guiferreira.me/images/archive/csharp/lowered-property-patterns.png" alt="SharpLab / Lowered Property Patterns"></p>
<h2>So what? 🙄</h2>
<p>Now what? Why should I use Property Patterns when there's a most efficient option?</p>
<p>That is true. On the other hand, Property Patterns are expressive (my opinion), but also <strong>they guide you to better decisions</strong>.</p>
<p>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.</p>
<p>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.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/Optimizations/PropertyPatternsBenchmark">here</a>.</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Taking control over xUnit test names2022-01-24T00:00:00-00:00https://guiferreira.me/archive/2021/taking-control-over-xunit-test-names/<p>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.</p>
<p>Often, you even find multiple practices in the same codebase. They go from <em>Given_When_Then</em> to <em>MethodUnderTest_Scenario_ExpectedResult</em> or even variances where one person may use Pascal and another Snake case.</p>
<p>Often, we forget that <strong>the most important thing is expressing clearly the test intent</strong>. So, it's the question of how to make the most of those shapes or forms.</p>
<h2>xUnit Test name customization</h2>
<p>The good news is that you have some ways to control xUnit behaviour in terms of test display names.</p>
<p>The simplest one is defining a custom Display Name through the Fact attribute.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span><span class="token attribute-arguments"><span class="token punctuation">(</span>DisplayName <span class="token operator">=</span> <span class="token string">"Get the max number of an array"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span><br><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">GivenAnArray_WhenApplyMax_ThenGetThenBiggerOne</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">new</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token number">12</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">42</span> <span class="token punctuation">}</span><br> <span class="token punctuation">.</span><span class="token function">Max</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>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.</p>
<h2>So, what can we do?</h2>
<p>One interesting thing from xUnit is the <a href="https://xunit.net/docs/configuration-files">configuration files</a>.</p>
<p>There, you can find many options to change the default behaviours of xUnit. One of them is related to Display Name.</p>
<p>xUnit in .net will display names based on class and method name by default. With the configuration file, you can define the <a href="https://xunit.net/docs/configuration-files#methodDisplay">display name</a> to be the Method name.</p>
<p>To do it, create a <em><code>xunit.runner.json</code></em> file in the xUnit project root, make sure it's included and add the following snippet.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br> <span class="token property">"$schema"</span><span class="token operator">:</span> <span class="token string">"https://xunit.net/schema/current/xunit.runner.schema.json"</span><span class="token punctuation">,</span><br> <span class="token property">"methodDisplay"</span><span class="token operator">:</span> <span class="token string">"method"</span><br><span class="token punctuation">}</span></code></pre>
<p>To include, add to the <em>csproj</em>:</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ItemGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Content</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>xunit.runner.json<span class="token punctuation">"</span></span> <span class="token attr-name">CopyToOutputDirectory</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>PreserveNewest<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ItemGroup</span><span class="token punctuation">></span></span></code></pre>
<p>Besides that, the most interesting thing is the <a href="https://xunit.net/docs/configuration-files#methodDisplayOptions">method display name options</a>, where you can find options to:</p>
<ul>
<li>Replace underscores with spaces;</li>
<li>Replace operators with matching symbols (example: <code>eq becomes =</code>);</li>
<li>Replace periods with a comma and a space.</li>
</ul>
<p>To enable them, go to the <em><code>xunit.runner.json</code></em> file and add a new key.</p>
<pre class="language-json"><code class="language-json"><span class="token property">"methodDisplayOptions"</span><span class="token operator">:</span> <span class="token string">"replaceUnderscoreWithSpace,useOperatorMonikers"</span></code></pre>
<p>So, for the following tests:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DisplayNameTests</span><br><span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Given10_WhenMultiplyBy2_ThenGet20</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> result <span class="token operator">=</span> <span class="token number">10</span> <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">;</span><br><br> result<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Fact</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Is_20_gt_10</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token number">20</span><span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">BeGreaterThan</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Once you run the tests, you will see:</p>
<p><img src="https://guiferreira.me/images/archive/xunit/xunit-configuration-method-name-after.png" alt="xUnit / Result after changing method display name configuration"></p>
<p>Instead of:</p>
<p><img src="https://guiferreira.me/images/archive/xunit/xunit-configuration-method-name-before.png" alt="xUnit / Result before changing method display name configuration"></p>
<h2>Wrapping up</h2>
<p>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 "<em>replaceUnderscoreWithSpace</em>" is a quick improvement.</p>
<p>Now it's time to take a look into your codebase, look into the existing configuration options, and you may find a quick win.</p>
<p>🔗 You can find the source code used <a href="https://github.com/gsferreira/dotnet-playground/tree/main/Tests/xUnit/xUnitDisplayName">here</a>.</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Expressive C# code with Property Patterns2021-12-20T00:00:00-00:00https://guiferreira.me/archive/2021/expressive-c-code-with-property-patterns/<p>C# has been growing with F# inspired features.</p>
<p>One that is most exciting is <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern">Pattern Matching</a>.</p>
<p>The introduction of Pattern matching led to Property Patterns.</p>
<p>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.</p>
<p><strong>Property Patterns are interesting ways to make the code more expressive, and in this post, we will see how.</strong></p>
<h2>What is a Property Pattern</h2>
<p>You use a property pattern to match expression properties to nested patterns.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">IsFirstOfTheMonth</span><span class="token punctuation">(</span><span class="token class-name">DateTime</span> date<span class="token punctuation">)</span> <span class="token operator">=></span> date <span class="token keyword">is</span> <span class="token punctuation">{</span> Day<span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>So, with Property Patterns, you can go from this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token punctuation">(</span><span class="token keyword">bool</span> isValid<span class="token punctuation">,</span> <span class="token keyword">string</span> reason<span class="token punctuation">)</span></span> <span class="token function">Validate</span><span class="token punctuation">(</span><span class="token class-name">Note</span> note<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>note <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ArgumentNullException</span><span class="token punctuation">(</span><span class="token keyword">nameof</span><span class="token punctuation">(</span>note<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <br> <span class="token keyword">if</span> <span class="token punctuation">(</span>note<span class="token punctuation">.</span>Title<span class="token punctuation">.</span>Length <span class="token operator"><</span> <span class="token number">5</span> <span class="token operator">||</span> note<span class="token punctuation">.</span>Title<span class="token punctuation">.</span>Length <span class="token operator">></span> <span class="token number">50</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">"Title should be 5 to 50 char long"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <br> <span class="token keyword">if</span> <span class="token punctuation">(</span>note<span class="token punctuation">.</span>Content <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">"Content is required"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>To this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token punctuation">(</span><span class="token keyword">bool</span> isValid<span class="token punctuation">,</span> <span class="token keyword">string</span> reason<span class="token punctuation">)</span></span> <span class="token function">Validate</span><span class="token punctuation">(</span><span class="token class-name">Note</span> note<span class="token punctuation">)</span><br> <span class="token operator">=></span> note <span class="token keyword">switch</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">{</span> Title<span class="token punctuation">.</span>Length<span class="token punctuation">:</span> <span class="token operator"><</span> <span class="token number">5</span> <span class="token keyword">or</span> <span class="token operator">></span> <span class="token number">50</span> <span class="token punctuation">}</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">"Title should be 5 to 50 char long"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br> <span class="token punctuation">{</span> Content<span class="token punctuation">:</span> <span class="token keyword">null</span> <span class="token punctuation">}</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">"Content is required"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br> <span class="token keyword">null</span> <span class="token operator">=></span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ArgumentNullException</span><span class="token punctuation">(</span><span class="token keyword">nameof</span><span class="token punctuation">(</span>note<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br> _ <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2>Where can you use them</h2>
<p>It's common to see the Property Pattern being used with switch expressions, but don't limit it to there.</p>
<p>Property Patterns can be used in the context of switch case guards, if's, boolean assignments, catch a condition, etc.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">try</span><br><span class="token punctuation">{</span><br> <span class="token comment">//...</span><br><span class="token punctuation">}</span><br><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">NpgsqlException</span> ex<span class="token punctuation">)</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>ex <span class="token keyword">is</span> <span class="token punctuation">{</span>Code<span class="token punctuation">:</span> <span class="token string">"42P01"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token comment">//...</span><br><span class="token punctuation">}</span></code></pre>
<h2>Nested patterns</h2>
<p>Property Patterns can be used to not only test properties but also nested ones.
With <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/extended-property-patterns">C# 10 Extended property patterns</a>, that becomes even simpler.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>person <span class="token keyword">is</span> <span class="token class-name">Student</span> <span class="token punctuation">{</span> Address<span class="token punctuation">.</span>CountryCode<span class="token punctuation">:</span> <span class="token string">"PT"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<h2>Precedence</h2>
<p>With Property Patterns you will not be using "&&", "||" or "!", instead, you can use "and", "or", "not".</p>
<p>You can also use parentheses to specify the precedence.</p>
<pre class="language-csharp"><code class="language-csharp">person <span class="token keyword">is</span> <span class="token class-name">Student</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> Address<span class="token punctuation">.</span>CountryCode<span class="token punctuation">:</span> <span class="token string">"PT"</span> <span class="token punctuation">}</span> <span class="token keyword">or</span> <span class="token punctuation">{</span> Address<span class="token punctuation">.</span>CountryCode<span class="token punctuation">:</span> <span class="token string">"ES"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">and</span> <span class="token punctuation">{</span> Age<span class="token punctuation">:</span> <span class="token operator"><</span> <span class="token number">20</span><span class="token punctuation">}</span></code></pre>
<h2>Wrapping up</h2>
<p>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?</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Where to place C#10 Global Usings2021-12-11T00:00:00-00:00https://guiferreira.me/archive/2021/where-to-place-c10-global-usings/<p>The new C# 10 is packed with quality-of-life features. One that I'm definitively using is <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#global-modifier">Global Usings</a>.</p>
<p>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.</p>
<h2>Why should I care?</h2>
<p>That's a fair question, especially in the days where IDE's do most of the work for us.</p>
<p>Even then, declaring them at the project level will result in tidier source files. Let's be honest, how many times do you import <code>System.Linq</code> or your own Extensions namespace?</p>
<h2>How can I do it?</h2>
<p>Global Usings are simple to use. Simply add the <code>global</code> modifier to the <code>using</code> you want.</p>
<p>Adding the <code>global</code> modifier is the same as adding the same <code>using</code> directive to every source file in your project.</p>
<p>That leads to the question: <em>Where should I declare my global usings?</em></p>
<p>I was facing that same question. 🤔</p>
<p>One thing was obvious to me. I should have a central place for it. Even <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive#global-modifier">Microsoft Docs</a> say so:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>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".</p>
<h3>So, I asked my Twitter friends what would they do.</h3>
<p><img src="https://guiferreira.me/images/archive/tweets/global-usings-where-to-place-question.png" alt="Tweet / Where to add global usings."></p>
<p><em><a href="https://twitter.com/gsferreira/status/1464293275511177217">(here)</a></em></p>
<p>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:</p>
<ul>
<li>Globals.cs</li>
<li>GlobalUsings.cs</li>
<li>Imports.cs</li>
</ul>
<p>That seems a good approach, but there was a comment by <a href="https://twitter.com/martin_costello">Martin Costello</a> that made my mind.</p>
<h2>My preferred way</h2>
<p>Before going into Martin suggestion, it's important to say that you can not only declare <code>global usings</code> in a <code>.cs</code> file but also at the project file.</p>
<p>That can be done by adding a <code><Using></code> item to your project file.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ItemGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Using</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>MyAwesomeApp.Extensions<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ItemGroup</span><span class="token punctuation">></span></span></code></pre>
<p>In principle, I would prefer to declare my usings in C#. I don't love to edit my <code>csproj</code> files, but Martin remembered me that I can do it in a <code>Directory.Build.props</code> file (if you want to know more about this file, take a look at <a href="https://guiferreira.me/archive/2018/06/versioning-net-core-applications-using-cake/">this post</a> that I've written to see the potential).</p>
<p><img src="https://guiferreira.me/images/archive/tweets/global-usings-where-to-place-question-directory-build-props.png" alt="Tweet / Global Usings - Directory Build Props"></p>
<p><em><a href="https://twitter.com/martin_costello/status/1464498288061816838">(here)</a></em></p>
<h3>So, what's the beauty of it?</h3>
<p>The beauty of it is that if you place <code>Directory.Build.props</code> in the root folder that contains your source code, when MSBuild runs will add to every project the properties defined in the <code>Directory.Build.props</code>. So, if you want to do it Solution wise or even only for your Test folder, you can do it.</p>
<h2>Wrapping up</h2>
<p>I will be using <code>Directory.Build.props</code> for sure. At least until we see a new standard way to declare global usings emerging in the community.</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Uploading files with ASP.NET Minimal APIs2021-11-24T00:00:00-00:00https://guiferreira.me/archive/2021/uploading-files-with-aspnet-minimal-apis/<p>With the .net 6 release, I was extremely excited to play with <strong><a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0">Minimal APIs</a></strong>.</p>
<p>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.</p>
<p>I've found the process easy, but <strong>I was surprised when the tests for an Upload endpoint failed</strong>.</p>
<p>My implementation after converting into Minimal API Endpoint was this. 👇</p>
<pre class="language-csharp"><code class="language-csharp">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">"/upload"</span><span class="token punctuation">,</span><br> <span class="token keyword">async</span> <span class="token generic-method"><span class="token function">Task</span><span class="token generic class-name"><span class="token punctuation"><</span>IResult<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token class-name">IFormFile</span> request<span class="token punctuation">)</span> <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>request<span class="token punctuation">.</span>Length <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> stream <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">OpenReadStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> reader <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">StreamReader</span><span class="token punctuation">(</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span> <span class="token keyword">await</span> reader<span class="token punctuation">.</span><span class="token function">ReadToEndAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>And the test this. 👇</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> application <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Application</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> application<span class="token punctuation">.</span><span class="token function">CreateClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> formData <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MultipartFormDataContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> file <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">"text.txt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> streamContent <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">StreamContent</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span><span class="token punctuation">;</span><br>formData<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>streamContent<span class="token punctuation">,</span> <span class="token string">"file"</span><span class="token punctuation">,</span> <span class="token string">"text.txt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token string">"/upload"</span><span class="token punctuation">,</span><br> formData<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>response<span class="token punctuation">.</span>StatusCode<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> data <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span>Content<span class="token punctuation">.</span><span class="token function">ReadAsStringAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>data<span class="token punctuation">.</span><span class="token function">Should</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Be</span><span class="token punctuation">(</span><span class="token string">"\"Hello World!\""</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The expected <em>200 OK</em> status code was now a <em>415 Unsupported Media Type</em> 🤔</p>
<p>That was strange. My first thought was that I was missing to define the content type accepted by that endpoint.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Accepts</span><span class="token generic class-name"><span class="token punctuation"><</span>IFormFile<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"multipart/form-data"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>I realized I was stupid by thinking that since the code above is just about adding OpenAPI Metadata. 😅</p>
<p>Then, finally, I got it. Minimal APIs will try to bind attributes with the assumption that content is JSON.</p>
<h2>So, how do I handle it?</h2>
<p>I had to <strong>receive the HttpRequest request as an argument</strong>.</p>
<p>Then, I was able to read the Form and look for files.</p>
<pre class="language-csharp"><code class="language-csharp">app<span class="token punctuation">.</span><span class="token function">MapPost</span><span class="token punctuation">(</span><span class="token string">"/upload"</span><span class="token punctuation">,</span><br> <span class="token keyword">async</span> <span class="token generic-method"><span class="token function">Task</span><span class="token generic class-name"><span class="token punctuation"><</span>IResult<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token class-name">HttpRequest</span> request<span class="token punctuation">)</span> <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>request<span class="token punctuation">.</span>HasFormContentType<span class="token punctuation">)</span><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> form <span class="token operator">=</span> <span class="token keyword">await</span> request<span class="token punctuation">.</span><span class="token function">ReadFormAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> formFile <span class="token operator">=</span> form<span class="token punctuation">.</span>Files<span class="token punctuation">[</span><span class="token string">"file"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>formFile <span class="token keyword">is</span> <span class="token keyword">null</span> <span class="token operator">||</span> formFile<span class="token punctuation">.</span>Length <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token class-name"><span class="token keyword">var</span></span> stream <span class="token operator">=</span> formFile<span class="token punctuation">.</span><span class="token function">OpenReadStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> reader <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">StreamReader</span><span class="token punctuation">(</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> text <span class="token operator">=</span> <span class="token keyword">await</span> reader<span class="token punctuation">.</span><span class="token function">ReadToEndAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> Results<span class="token punctuation">.</span><span class="token function">Ok</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>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.</p>
<p>I hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Azure Storage Integration Testing with Azurite2021-10-27T00:00:00-00:00https://guiferreira.me/archive/2021/azure-storage-integration-testing-with-azurite/<p>If you depend on Azure Storage, you need a solution to <a href="https://martinfowler.com/articles/practical-test-pyramid.html#IntegrationTests">Integration Test</a> in a local development environment.</p>
<p>We live in a world where we rely more on Cloud offers, using proprietary managed solutions.
One of those examples is Azure Storage (Blobs, Queues, and Tables).</p>
<p>One of the problems with relying on those kinds of offerings is how to have an environment disconnected from Azure to run your code while testing or developing.</p>
<p>Ideally, we want to have a solution to run it in an offline environment. That can give us the following benefits:</p>
<ul>
<li>Money savings.</li>
<li>Extremely fast. No latency involved.</li>
<li>Isolation. No risk of having a colleague testing against the same environment.</li>
<li>You don't need to have access to the internet to be working. When the power supply goes off is extremely useful (ask me how I know 😁).</li>
</ul>
<p>An excellent solution to that in the case of Azure Storage is Azurite.</p>
<h2>What is Azurite?</h2>
<p>Azurite is an open-source Azure Storage emulator that provides a cross-platform experience in a local environment. Azurite simulates most of the commands supported by Azure Storage with minimal dependencies.</p>
<h3>How to use it?</h3>
<p>Azurite is a Node.js application, so you can npm install it and use it from the command line (<a href="https://github.com/Azure/Azurite#npm">see here</a>).</p>
<p>But, I prefer to use docker containers, and it's that what we will see here.</p>
<p>First, create a <code>docker-compose.yml</code> like the following.</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">"3.9"</span><br><span class="token key atrule">services</span><span class="token punctuation">:</span><br> <span class="token key atrule">azurite</span><span class="token punctuation">:</span><br> <span class="token key atrule">image</span><span class="token punctuation">:</span> mcr.microsoft.com/azure<span class="token punctuation">-</span>storage/azurite<br> <span class="token key atrule">hostname</span><span class="token punctuation">:</span> azurite<br> <span class="token key atrule">restart</span><span class="token punctuation">:</span> always<br> <span class="token key atrule">ports</span><span class="token punctuation">:</span><br> <span class="token punctuation">-</span> <span class="token string">"10000:10000"</span><br> <span class="token punctuation">-</span> <span class="token string">"10001:10001"</span><br> <span class="token punctuation">-</span> <span class="token string">"10002:10002"</span></code></pre>
<p>Azurite will listen to <em>10000</em> as Blob service port, <em>10001</em> as Queue service port, and <em>10002</em> as the Table service port. Configure the ones you need.</p>
<p>After that, just run your <code>docker-compose up</code> and you will be able to connect to it.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> connectionString <span class="token operator">=</span> <span class="token string">"DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;"</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> account <span class="token operator">=</span> CloudStorageAccount<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>connectionString<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> account<span class="token punctuation">.</span><span class="token function">CreateCloudTableClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
React components doing too much (and how to simplify them)2020-11-16T00:00:00-00:00https://guiferreira.me/archive/2020/11/react-components-doing-too-much-and-how-to-simplify-them/<p>Do you have the feeling that some of your components are doing too much?</p>
<p>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.</p>
<p>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.</p>
<p>That's why <strong>we need to be careful with component contracts</strong>. That contract is expressed through props by the way.</p>
<p>One way to spot eventual problems is to look for boolean props <a href="https://guiferreira.me/archive/2020/05/that-flag-argument-is-yelling-at-you/">(they will yell at you as you can read here)</a>. A usual case is to have boolean props used as a way to condition the render.</p>
<p><img src="https://guiferreira.me/images/archive/react/bool-props.png" alt="React component boolean props definition"></p>
<p>There are a few problems with that approach:</p>
<ul>
<li>The component contract can become complex and the state of the component difficult to evaluate.</li>
<li>It can be a symptom that the component is doing too much.</li>
</ul>
<p>Let's take a look.</p>
<h2>Complex Contract</h2>
<p>Imagine that you have to create a login Component where the user can log in using username.</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">Login</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Login<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Username:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Password:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Log In<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> Login<span class="token punctuation">;</span></code></pre>
<p>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:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">"prop-types"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">Login</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> usingEmail <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Login<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token punctuation">{</span>usingEmail <span class="token operator">?</span> <span class="token string">"Email:"</span> <span class="token operator">:</span> <span class="token string">"Username:"</span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>usingEmail <span class="token operator">?</span> <span class="token string">"email"</span> <span class="token operator">:</span> <span class="token string">"text"</span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Password:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Log In<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br>Login<span class="token punctuation">.</span>propTypes <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">usingEmail</span><span class="token operator">:</span> PropTypes<span class="token punctuation">.</span>bool<span class="token punctuation">,</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> Login<span class="token punctuation">;</span></code></pre>
<p>Now imagine that one day, users can also log in with phone number. Now you have a problem.</p>
<p>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.</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">"prop-types"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">Login</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> usingEmail<span class="token punctuation">,</span> usingPhoneNumber <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Login<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token punctuation">{</span>usingEmail <span class="token operator">?</span> <span class="token string">"Email:"</span> <span class="token operator">:</span> usingPhoneNumber <span class="token operator">?</span> <span class="token string">"Phone"</span> <span class="token operator">:</span> <span class="token string">"Username:"</span><span class="token punctuation">}</span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>usingEmail <span class="token operator">?</span> <span class="token string">"email"</span> <span class="token operator">:</span> usingPhoneNumber <span class="token operator">?</span> <span class="token string">"tel"</span> <span class="token operator">:</span> <span class="token string">"text"</span><span class="token punctuation">}</span></span><br> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Password:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Log In<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br>Login<span class="token punctuation">.</span>propTypes <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">usingEmail</span><span class="token operator">:</span> PropTypes<span class="token punctuation">.</span>bool<span class="token punctuation">,</span><br> <span class="token literal-property property">usingPhoneNumber</span><span class="token operator">:</span> PropTypes<span class="token punctuation">.</span>bool<span class="token punctuation">,</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> Login<span class="token punctuation">;</span></code></pre>
<p>Contracts with boolean flags are complex and deliver a bad UX to the consumer.</p>
<p>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".</p>
<h3>So, what to do?</h3>
<p>A simple solution would be to <strong>prefer Enums over booleans.</strong> A boolean is extensible and describes a clear intention.</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">"prop-types"</span><span class="token punctuation">;</span><br><br><span class="token keyword">const</span> <span class="token constant">USER_IDENTIFIFICATION_TYPES</span> <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token constant">USERNAME</span><span class="token operator">:</span> <span class="token string">"username"</span><span class="token punctuation">,</span><br> <span class="token constant">EMAIL</span><span class="token operator">:</span> <span class="token string">"email"</span><span class="token punctuation">,</span><br> <span class="token constant">PHONENUMBER</span><span class="token operator">:</span> <span class="token string">"phone"</span><span class="token punctuation">,</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">Login</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> userIdentificationType <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">const</span> shouldUseEmail <span class="token operator">=</span><br> userIdentificationType <span class="token operator">===</span> <span class="token constant">USER_IDENTIFIFICATION_TYPES</span><span class="token punctuation">.</span><span class="token constant">EMAIL</span><span class="token punctuation">;</span><br> <span class="token keyword">const</span> shouldUsePhone <span class="token operator">=</span><br> userIdentificationType <span class="token operator">===</span> <span class="token constant">USER_IDENTIFIFICATION_TYPES</span><span class="token punctuation">.</span><span class="token constant">PHONENUMBER</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Login<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token punctuation">{</span>shouldUseEmail <span class="token operator">?</span> <span class="token string">"Email:"</span> <span class="token operator">:</span> shouldUsePhone <span class="token operator">?</span> <span class="token string">"Phone"</span> <span class="token operator">:</span> <span class="token string">"Username:"</span><span class="token punctuation">}</span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>shouldUseEmail <span class="token operator">?</span> <span class="token string">"email"</span> <span class="token operator">:</span> shouldUsePhone <span class="token operator">?</span> <span class="token string">"tel"</span> <span class="token operator">:</span> <span class="token string">"text"</span><span class="token punctuation">}</span></span><br> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Password:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Log In<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br>Login<span class="token punctuation">.</span>propTypes <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">userIdentificationType</span><span class="token operator">:</span> PropTypes<span class="token punctuation">.</span><span class="token function">oneOf</span><span class="token punctuation">(</span><br> Object<span class="token punctuation">.</span><span class="token function">values</span><span class="token punctuation">(</span><span class="token constant">USER_IDENTIFIFICATION_TYPES</span><span class="token punctuation">)</span><br> <span class="token punctuation">)</span><span class="token punctuation">,</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><br>Login<span class="token punctuation">.</span>defaultProps <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">userIdentificationType</span><span class="token operator">:</span> <span class="token constant">USER_IDENTIFIFICATION_TYPES</span><span class="token punctuation">.</span><span class="token constant">USERNAME</span><span class="token punctuation">,</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> Login<span class="token punctuation">;</span></code></pre>
<p>As you can see, we fix the problem of the contract, but this component is doing too much.</p>
<h2>God Components</h2>
<p>Besides contract complexity, <strong>boolean props are a symptom that the component may be a God Component</strong>, doing too much.</p>
<h3>So, what to do?</h3>
<p>If you notice that you are in the presence of a God Component, you should split the component.</p>
<p>In this login component example, you could create three components, for instance, to encapsulate inner details, something like:</p>
<ul>
<li>UsernameLogin</li>
<li>EmailLogin</li>
<li>PhoneNumberLogin</li>
</ul>
<h4>Base Login Component</h4>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">"prop-types"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">Login</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> children <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Login<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token punctuation">{</span>children<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Password:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Log In<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br>Login<span class="token punctuation">.</span>propTypes <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">children</span><span class="token operator">:</span> PropTypes<span class="token punctuation">.</span>node<span class="token punctuation">,</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> Login<span class="token punctuation">;</span></code></pre>
<h4>Username Login Component</h4>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><br><span class="token keyword">import</span> Login <span class="token keyword">from</span> <span class="token string">"./Login"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">UsernameLogin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Login</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Username:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">Login</span></span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> UsernameLogin<span class="token punctuation">;</span></code></pre>
<h4>Email Login Component</h4>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><br><span class="token keyword">import</span> Login <span class="token keyword">from</span> <span class="token string">"./Login"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">EmailLogin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Login</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">EmailLogin:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">Login</span></span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> EmailLogin<span class="token punctuation">;</span></code></pre>
<h4>Phone Login Component</h4>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><br><span class="token keyword">import</span> Login <span class="token keyword">from</span> <span class="token string">"./Login"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">PhoneNumberLogin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Login</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">Phone:</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tel<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">Login</span></span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> PhoneNumberLogin<span class="token punctuation">;</span></code></pre>
<p>This way, your components will <strong>do one thing and do it well</strong>.</p>
<p>Hope that this was useful! To get more tips like this, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
Avoiding Booleans in React Components with a State Enum2020-10-26T00:00:00-00:00https://guiferreira.me/archive/2020/10/avoiding-booleans-in-react-components-with-a-state-enum/<p>Did you notice that <strong>your React Components tend to have a ton of booleans</strong> (isLoading, hasErrors, ...) <strong>that you use to control the state of your component?</strong></p>
<p>Sure, me too. When we have a simple component this may not be a big problem. But, if there are multiple states, <strong>it may be difficult to control the state of the component according to all the combinations of Boolean flags</strong>.</p>
<p>If we step back to look into the problem, we can see that a component can only be in a given state at a given time. And to do that we already have a solution: Finite State Machines.</p>
<p><strong>Applying a Finite State Machine we can model the states where a given component can be instead of having various boolean flags.</strong> That will result in code easier to read and to maintain. It's easier to understand the status when looking into a variable when compared to looking to boolean combinations.</p>
<h2>Now that you know the solution, what can you do to fix the problem?</h2>
<p>You have two possibilities:</p>
<ol>
<li><strong>A Finite State Machine.</strong> You will have the advantage of using states but also transitions. If you want to follow this approach, I highly recommend you to use a library. You can use <a href="https://github.com/davidkpiano/xstate">XState</a>, an excellent library for defining state machines using code.</li>
<li><strong>Use a simple enumeration.</strong> I will detail this approach in this post. I find that in most of the cases this is more than enough and it's a simpler and lightweight solution.</li>
</ol>
<h2>How can you do it?</h2>
<p>Fist of all, let's imagine that we have a simple component. The goal is to get display the current exchange rate between two currencies.</p>
<p>Our component may be in one of 3 states:</p>
<ol>
<li><strong>Idle:</strong> Waiting for instructions to do the request.</li>
<li><strong>Loading:</strong> Getting data from API.</li>
<li><strong>Error:</strong> Error retrieving data from API.</li>
<li><strong>Complete:</strong> Request to API with success.</li>
</ol>
<p>If follow the approach of having boolean flags, we may come up with a component like the following:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> <span class="token string">"./styles.css"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">CurrencyExchange</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">const</span> <span class="token punctuation">[</span>from<span class="token punctuation">,</span> setFrom<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">const</span> <span class="token punctuation">[</span>to<span class="token punctuation">,</span> setTo<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">const</span> <span class="token punctuation">[</span>result<span class="token punctuation">,</span> setResult<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">isLoading</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br> <span class="token literal-property property">rate</span><span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span><br> <span class="token literal-property property">error</span><span class="token operator">:</span> <span class="token keyword">null</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token function">setResult</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">isLoading</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br> <span class="token literal-property property">rate</span><span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span><br> <span class="token literal-property property">error</span><span class="token operator">:</span> <span class="token keyword">null</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><br> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.exchangeratesapi.io/latest?base=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">from</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&symbols=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>to<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">result</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> response<span class="token punctuation">.</span>ok<br> <span class="token operator">?</span> <span class="token function">setResult</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token operator">...</span>result<span class="token punctuation">,</span><br> <span class="token literal-property property">isLoading</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br> <span class="token literal-property property">rate</span><span class="token operator">:</span> result<span class="token punctuation">.</span>rates<span class="token punctuation">[</span>to<span class="token punctuation">]</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token operator">:</span> <span class="token function">setResult</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token operator">...</span>result<span class="token punctuation">,</span><br> <span class="token literal-property property">isLoading</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br> <span class="token literal-property property">erro</span><span class="token operator">:</span> result<span class="token punctuation">.</span>error<br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">const</span> <span class="token function-variable function">handleSubmit</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> evt<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">.</span>isLoading<span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">Loading...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">onSubmit</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleSubmit<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> Euro:<br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>from<span class="token punctuation">"</span></span><br> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>from<span class="token punctuation">}</span></span><br> <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setFrom</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span></span><br> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> To:<br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>to<span class="token punctuation">"</span></span><br> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>to<span class="token punctuation">}</span></span><br> <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setTo</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span></span><br> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Submit<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token punctuation">{</span>result<span class="token punctuation">.</span>error <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">?</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span><span class="token punctuation">{</span>result<span class="token punctuation">.</span>error<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span><span class="token plain-text">Rate: </span><span class="token punctuation">{</span>result<span class="token punctuation">.</span>rate<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> CurrencyExchange<span class="token punctuation">;</span></code></pre>
<p><em><a href="https://codesandbox.io/s/dreamy-glitter-kgzod?file=/src/CurrencyExchange.jsx">Click here to play with it on codesandbox.</a></em></p>
<p>How can we refactor it toward cleaner code?</p>
<p>First thing is to define an enum with the possible states.</p>
<p><img src="https://guiferreira.me/images/archive/react/state-enum.png" alt="React State enum"></p>
<p>Then, we can refactor the places where a boolean is in use.</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br><span class="token keyword">import</span> <span class="token string">"./styles.css"</span><span class="token punctuation">;</span><br><br><span class="token keyword">function</span> <span class="token function">CurrencyExchangeRefactored</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">const</span> <span class="token constant">STATES</span> <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token constant">IDLE</span><span class="token operator">:</span> <span class="token string">"idle"</span><span class="token punctuation">,</span><br> <span class="token constant">LOADING</span><span class="token operator">:</span> <span class="token string">"loading"</span><span class="token punctuation">,</span><br> <span class="token constant">COMPLETE</span><span class="token operator">:</span> <span class="token string">"complete"</span><span class="token punctuation">,</span><br> <span class="token constant">ERROR</span><span class="token operator">:</span> <span class="token string">"error"</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token keyword">const</span> <span class="token punctuation">[</span>from<span class="token punctuation">,</span> setFrom<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">const</span> <span class="token punctuation">[</span>to<span class="token punctuation">,</span> setTo<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">const</span> <span class="token punctuation">[</span>status<span class="token punctuation">,</span> setStatus<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">state</span><span class="token operator">:</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">IDLE</span><span class="token punctuation">,</span><br> <span class="token literal-property property">data</span><span class="token operator">:</span> <span class="token keyword">null</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token function">setStatus</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">state</span><span class="token operator">:</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">LOADING</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><br> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://api.exchangeratesapi.io/latest?base=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">from</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&symbols=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>to<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">result</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> response<span class="token punctuation">.</span>ok<br> <span class="token operator">?</span> <span class="token function">setStatus</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">state</span><span class="token operator">:</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">LOADING</span><span class="token punctuation">.</span><span class="token constant">COMPLETE</span><span class="token punctuation">,</span><br> <span class="token literal-property property">data</span><span class="token operator">:</span> result<span class="token punctuation">.</span>rates<span class="token punctuation">[</span>to<span class="token punctuation">]</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token operator">:</span> <span class="token function">setStatus</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br> <span class="token literal-property property">state</span><span class="token operator">:</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">LOADING</span><span class="token punctuation">.</span><span class="token constant">COMPLETE</span><span class="token punctuation">,</span><br> <span class="token literal-property property">data</span><span class="token operator">:</span> result<span class="token punctuation">.</span>error<br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">const</span> <span class="token function-variable function">handleSubmit</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> evt<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>status<span class="token punctuation">.</span>state <span class="token operator">===</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">LOADING</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">Loading...</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">onSubmit</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>handleSubmit<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> Euro:<br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>from<span class="token punctuation">"</span></span><br> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>from<span class="token punctuation">}</span></span><br> <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setFrom</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span></span><br> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> To:<br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>to<span class="token punctuation">"</span></span><br> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>to<span class="token punctuation">}</span></span><br> <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setTo</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span></span><br> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Submit<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token plain-text"><br> </span><span class="token punctuation">{</span>status<span class="token punctuation">.</span>state <span class="token operator">===</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">IDLE</span> <span class="token operator">?</span> <span class="token keyword">null</span> <span class="token operator">:</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span><span class="token plain-text"><br> </span><span class="token punctuation">{</span>status<span class="token punctuation">.</span>state <span class="token operator">===</span> <span class="token constant">STATES</span><span class="token punctuation">.</span><span class="token constant">ERROR</span> <span class="token operator">?</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span><span class="token plain-text">Error: </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token punctuation">(</span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span><span class="token plain-text">Rate: </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text"><br> </span><span class="token punctuation">{</span>status<span class="token punctuation">.</span>data<span class="token punctuation">}</span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text"><br> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">export</span> <span class="token keyword">default</span> CurrencyExchangeRefactored<span class="token punctuation">;</span><br></code></pre>
<p><em><a href="https://codesandbox.io/s/dreamy-glitter-kgzod?file=/src/CurrencyExchangeRafactored.jsx">Click here to play with it on codesandbox.</a></em></p>
<p>Following this approach, the component will become more readable and maintainable. Adding a new status to the component will also become easier.</p>
The value of Continuous Refactoring2020-09-24T00:00:00-00:00https://guiferreira.me/archive/2020/09/the-value-of-continuous-refactoring/<p><img src="https://guiferreira.me/images/archive/clean-code/continous-refactoring.png" alt="Continuous Refactoring"></p>
<p>Refactoring is one of those skills that programming classes tend to ignore.</p>
<p>But everyone has to refactor code. Refactor is evening one of the stages of the <a href="https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530">TDD cycle</a>: <a href="https://www.codecademy.com/articles/tdd-red-green-refactor">Red, Green Refactor</a>.
So, if refactoring is that important, why it is a skill that we should learn by ourselves? Why we leave the job to benevolent Senior Developers in our teams? Why we approach it as a skill that will come through experience? As a skill that doesn't require training?</p>
<p>For sure is something that experience will bring. But we are responsible for making it a structured practice since the early days. And that requires learning. Learning code smells, refactoring tactics, best practices, etc.</p>
<p>Otherwise, most of the times someone refactors the code, they are just re-writing it differently, not better.
But, more important than knowing it or following the techniques, is to make it a habit. Refactoring should be part of the job. It shouldn't be an occasional task. Something that you do when everything seems messy.</p>
<p>If we keep the house arranged every single day, the job becomes easy. What takes more time? Keeping the house in order as we go or tidying up once a month?</p>
<p>We should aim for a <strong>continuous refactoring practice</strong>.</p>
<p>Nevertheless, sometimes the codebase can be in bad shape. On those cases, we need to push harder in the beginning. When the task seems impossible, there's nothing better than being bold. Otherwise, we may not be able to create a habit, because every time you want to do something, it will be too painful.</p>
<p>The results of starting big and painful refactor may be what you need to see the value of keeping the house clean.</p>
Avoid GetAwaiter().GetResult() at all cost2020-08-26T00:00:00-00:00https://guiferreira.me/archive/2020/08/avoid-getawaiter-getresult-at-all-cost/<p>When you need to wait for a Task, are you using <em>".GetAwaiter().GetResult()"</em> instead of <em>".Result"</em> and <em>".Wait()"</em> when you are in a synchronous method? You are doing the correct thing! But only if you can't change that method!</p>
<p><img src="https://guiferreira.me/images/archive/dotnet/getawaiter-getresult.png" alt=".GetAwaiter().GetResult()"></p>
<p>In case you don't know, in C#, you should always aim to work with async/await when you have Tasks. You should go all way down with async/await.</p>
<p>If you are using <em>".GetAwaiter().GetResult()"</em>, <em>".Result"</em> or <em>".Wait()"</em> to get the result of a task or to wait for the task completion you may experience deadlocks or <a href="https://docs.microsoft.com/en-gb/archive/blogs/vancem/diagnosing-net-core-threadpool-starvation-with-perfview-why-my-service-is-not-saturating-all-cores-or-seems-to-stall?s=09">thread pool starvation</a>.</p>
<p>But, sometimes <em>".GetAwaiter().GetResult()"</em> is presented as a good way to replace <em>".Result"</em> and <em>".Wait()"</em> when we can't use async/await. That idea can be dangerous. I agree that this is a far better solution then <em>".Result"</em> and <em>".Wait()"</em> because the error handling will be much better. The stack trace of a given expression will be much cleaner. But, under the wood, <a href="https://stackoverflow.com/questions/17284517/is-task-result-the-same-as-getawaiter-getresult/38530225#38530225"><em>".GetAwaiter()"</em> is relying on <em>".Wait()"</em></a>, so you may experience the deadlocks or thread pool starvation.</p>
<p>So, what I have to recommend you is to avoid at all cost using <em>".GetAwaiter().GetResult()"</em>, <em>".Result"</em> or <em>".Wait()"</em>. Refactor your code from top to bottom to use async/await. Use it as a code smell that something can go wrong under stress. You will see that under stress, the system will behave so much better.</p>
<h2>What can I do if I can't use Async/Await?</h2>
<p>That's a fair question. Sometimes we need to go with <a href="https://odetocode.com/blogs/scott/archive/2019/03/04/await-the-async-letdown.aspx">"Sync over async"</a>.</p>
<p>Two simple scenarios are when:</p>
<p>- You have a Task in a constructor;
- Need to respect an interface that you don't control;</p>
<p>In this situation, I recommend you to use <em>".GetAwaiter().GetResult()"</em> only once. Extract a private async method that your public method can relly on.</p>
<h2>What's next?</h2>
<p>Now, It's time to review your codebase and to spread the word!</p>
<p>Also, I recommend you to install the Threading Analyzer (<a href="https://github.com/microsoft/vs-threading"><em>Microsoft.VisualStudio.Threading.Analyzers</em></a>). It will help you to spot potential problems.</p>
<hr>
<p>If this was useful, follow me on <a href="https://twitter.com/gsferreira">Twitter (@gsferreira)</a> and let's keep in touch!</p>
When should a function return? Return Early2020-08-03T00:00:00-00:00https://guiferreira.me/archive/2020/08/when-should-a-function-return-early/<p><em>"A method should return once at the end of the method".</em>
No, I don't think so.</p>
<p>I remember to listen to that sentence when I was learning to program. It was a universal truth to me at the time. I brought this idea to the different languages that I've worked afterwords.
Being honest, I always felt something strange about that. <strong>Keeping the code readable with a single return was a hard task.</strong> I needed to nest conditions, keeping "dummy" variables, having state control variables... <strong>It was a mess.</strong></p>
<p><img src="https://guiferreira.me/images/archive/clean-code/without-early-return.png" alt="Function without early return. Condition nesting."></p>
<p>So I changed. I learn to return early and to return often. I prefer to have multiple returns instead of nesting, for example.</p>
<p>A common and useful scenario is when we need to apply preconditions. If we have conditions to execute a given function, makes no sense to delay the verification. <strong>If you are cooking a recipe, it wouldn't be fun if you didn't have the ingredients list and you only knew what you need while following the instructions.</strong> In code, you can apply the same logic.</p>
<p><img src="https://guiferreira.me/images/archive/clean-code/early-return.png" alt="Function early return applying pre-conditions."></p>
<p>If you apply this principle, you will <strong>reduce the cyclomatic complexity and the cognitive load to understand the code.</strong> In the end, the source <strong>code will be simpler</strong>.</p>
<p>I recommend you to apply this principle together with the <a href="https://guiferreira.me/archive/2019/10/a-simple-tip-to-improve-your-code-maintainability-decompose-if-statements-into-methods/">idea of extracting methods</a>.</p>
<p>Code is like a tree. We need to prune and shape the tree.
Don't let it grow wild.</p>
Eleventy - The Simplest Static Site Generator2020-07-24T00:00:00-00:00https://guiferreira.me/archive/2020/07/eleventy-the-simplest-static-site-generator/<p>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 <a href="https://www.11ty.dev/">Eleventy (11ty)</a> 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.</p>
<p><img src="https://guiferreira.me/images/archive/eleventy/logo.jpg" alt="Eleventy"></p>
<h2>The goal</h2>
<p>I have been thinking about moving my blog to a different framework. I was using <a href="https://guiferreira.me/archive/2014/05/reasons-to-blogging-with-github-pages-and-sandra-snow/">Sandra.Snow</a>, that not have been updated recently.</p>
<p>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.</p>
<h2>The obvious choices</h2>
<p>In the top of my mind, I knew that <a href="https://www.gatsbyjs.org/">Gatsby</a> and <a href="https://nextjs.org/">NextJS</a> 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.</p>
<p>My first attempt was with Gatsby. I installed the <a href="https://www.gatsbyjs.org/starters/gatsbyjs/gatsby-starter-blog/">starter blog</a> 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.</p>
<p>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.</p>
<p>I picked <a href="https://telmo.im/writings/open-sourcing-blog">Telmo blog</a> as a starting point and I tried to move my content. The results show up faster!</p>
<p>But, there was something that I didn't like and I didn't find a way to overcome. Even with the <a href="https://nextjs.org/docs/advanced-features/static-html-export">static HTML export</a> 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.</p>
<h2>Eleventy</h2>
<p>I was tired of fighting with Gatsby and NextJS. Something simpler was needed. I recall seeing a blog post from <a href="https://reverentgeek.com/">David Neal</a> about moving his blog to a different technology. The technology is Eleventy. You can read his blog post <a href="https://reverentgeek.com/moving-from-ghost-to-eleventy/">here</a>.</p>
<p>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.</p>
<p>So, I start working to move my blog into Eleventy. I started with the <a href="https://github.com/marcfilleul/mf-blogstarter">MF Blog Starter Template</a>. 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 <a href="https://www.11ty.dev/docs/">Eleventy documentation</a> was just enough.</p>
<p>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.</p>
<p>You can find <a href="https://github.com/gsferreira/gsferreira.github.com">here the source code for my blog</a>. I hope it can be helpful.</p>
Speaking at a Virtual Conference2020-07-08T00:00:00-00:00https://guiferreira.me/archive/2020/07/speaking-at-a-virtual-conference/<p>I had the honour of having one of my talks selected to <a href="https://ndcoslo.com/">NDC Oslo 2020</a>. I was looking forward to speaking at Oslo Spektrum for the first time. This has been a wish for a long time.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<hr>
<h2>Setup</h2>
<h3>Video</h3>
<p>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.</p>
<h3>Camera</h3>
<p>I bought a <a href="https://secure.logitech.com/en-gb/product/hd-pro-webcam-c920?crid=34">Logitech C920</a>. 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.</p>
<p>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.</p>
<h3>Lighting</h3>
<p>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 <a href="https://www.aliexpress.com/item/33020816527.html">light ring from AliExpress</a>.</p>
<h3>Background</h3>
<p>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.</p>
<p>I didn't want to give them another good reason for distraction by having shiny objects on the background.</p>
<p>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.</p>
<p><img src="https://guiferreira.me/images/speaking-at-a-virtual-conference-background.jpg" alt="Background"></p>
<h3>Microphone</h3>
<p>A decent microphone is a must. Using the laptop microphone is terrible. <a href="https://dylanbeattie.net/2020/05/12/microphones.html">Dylan Beatie crafted an excellent blog post</a> that can help. There you can also see the difference between different microphones.</p>
<p>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 (<a href="http://www.samsontech.com/samson/products/microphones/usb-microphones/q2u/">SAMSON q2u</a>).</p>
<p>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.</p>
<p>I've found really good information about Microphones, Cameras and Lighting <a href="https://mattstauffer.com/blog/setting-up-your-webcam-lights-and-audio-for-remote-work-podcasting-videos-and-streaming">here</a>.</p>
<h3>Glare on Glasses</h3>
<p>If you use glasses like me, Lighting and positioning can be quite difficult.</p>
<p>Facing direct light or bright screens was reflecting everything on my glasses.</p>
<p>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.</p>
<p><a href="https://www.youtube.com/watch?v=9NWAcK-wM80">This video</a> was really helpful.</p>
<h3>Stand-up</h3>
<p>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.</p>
<p><img src="https://guiferreira.me/images/speaking-at-a-virtual-conference-setup-macro.jpg" alt="Setup - Stand-up"></p>
<hr>
<h2>Preparing</h2>
<ol>
<li><strong>Rehearse</strong> in the same environment and with the same setup that you will be using.</li>
<li>Record it and share it with your friends and colleagues. Ask for <a href="https://guiferreira.me/archive/2019/07/leading-improvement-through-honest-feedback/">honest feedback</a>. Use the feedback to improve.</li>
<li><strong>Rehearse</strong></li>
<li>Make sure that you have a Plan B
<ul>
<li>What if your computer fails?</li>
<li>Will you use a pointer? Do you have extra batteries?</li>
</ul>
</li>
<li><strong>Rehearse</strong></li>
<li><strong>Rehearse</strong> with the same software that you will be using in the day. Make yourself comfortable with it.</li>
</ol>
<p>No. Rehearse written so many times isn't a mistake. Honestly, <strong>the most important thing that you can do is rehearse</strong>. Rehearse in the same conditions. Over and over again. By doing that you will feel more comfortable speaking to a camera.</p>
<hr>
<h2>The day</h2>
<p>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.</p>
<h3>Dress-up</h3>
<p>This will signal to your brain that it's time to do important stuff.</p>
<h3>Barefoot</h3>
<p>Barefoot or use socks. You will find yourself more relaxed. You will also make less background noise with your feet.</p>
<h3>Shutdown your doorbell</h3>
<p>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.</p>
<h3>Hydrate</h3>
<p>Have a glass of water nearby. Do not forget.</p>
<h3>Connect to the audience</h3>
<p>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.</p>
<p><img src="https://guiferreira.me/images/speaking-at-a-virtual-conference-micro.jpg" alt="Setup - closeup"></p>
<hr>
<p>Always remember that those attending, are there because they want to learn from you. So enjoy!</p>
That flag argument is yelling at you2020-05-28T00:00:00-00:00https://guiferreira.me/archive/2020/05/that-flag-argument-is-yelling-at-you/<p>Sometimes the code yells at you trying to warn you that something is wrong.</p>
<p>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.</p>
<p>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.</p>
<p>Let's take a look. When a function has a flag argument, we will find something like this (or even worse) in the implementation:</p>
<p><img src="https://guiferreira.me/images/that-flag-argument-is-yelling-at-you-flag-argument.png" alt="Flag Argument"></p>
<p>Wouldn't be better to have something like:</p>
<p><img src="https://guiferreira.me/images/that-flag-argument-is-yelling-at-you-refactor.png" alt="Flag Argument Refactor"></p>
<p>When writing code, remember that the goal is to simplify our client's life.</p>
Don't comment what your code is doing, comment the Why2020-05-22T00:00:00-00:00https://guiferreira.me/archive/2020/05/dont-comment-what-your-code-is-doing-comment-the-why/<p>Code comments are a common topic of love/hate discussions.
It's particularly interesting to see developers shifting opinion while experience grows.</p>
<p>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.</p>
<p>So, what can we do to improve our comments?</p>
<p>I use a simple rule: <strong>Explain the Why, not the What.</strong></p>
<p>I see a lot of Comments that are explaining what the code is doing. That doesn't help.
The effort that we put to write a Comment must be invested refactoring the code (<a href="https://guiferreira.me/archive/2019/10/a-simple-tip-to-improve-your-code-maintainability-decompose-if-statements-into-methods/">this is a good starting point</a>).
<strong>When we need to describe the What is because the code isn't readable at all.</strong></p>
<p>It's also pretty common to have obvious Comments. All we have seen that <em>"// Get a Customer"</em> comment in a <em>"GetCustomer"</em> method.</p>
<div style="width:100%;height:0;padding-bottom:100%;position:relative;"><iframe src="https://giphy.com/embed/gF8vDz0XAUfIWx9jUW" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen=""></iframe></div><p><a href="https://giphy.com/gifs/memecandy-gF8vDz0XAUfIWx9jUW">via GIPHY</a></p>
<p>Those comments don't bring value. They raise the cognitive load required to read and maintain the code.</p>
<p>So, the idea is to <strong>let the code speak for himself</strong>. We only write comments, when we need to explain Why we have done something.</p>
<p>It's useful to understand why a piece of code was written in a certain way.
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.
Those are a few examples, but you get the point.</p>
<p>Our code must be self-describing, but sometimes, we need to explain the Why.</p>
<p>And remember: <strong>don't Comment the code that you don't need anymore. Throw it away.</strong> In case you need it, it will be at the source control.</p>
Manage your code as a successful restaurant2020-05-15T00:00:00-00:00https://guiferreira.me/archive/2020/05/manage-your-code-as-a-successful-restaurant/<p>Have you ever noticed that a successful restaurant has a shorter menu? Especially when compared to those who are struggling.</p>
<p>Why?! <strong>Simplicity!</strong></p>
<p>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.</p>
<p>But, when life doesn't work as we expect, we start throwing new dishes into the menu. Expecting to please everyone.</p>
<p><img src="https://guiferreira.me/images/manage-your-code-as-a-successful-restaurant-complex-menu.jpeg" alt="Complex menu"></p>
<p><strong><em>Spoiler alert: When you build something to everyone, you build it to nobody.</em></strong></p>
<p>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.</p>
<p>What we should all be doing is to <strong>focus on what we have and what customers love.</strong> Those features have a margin to improve. <strong>Don't bring a new feature into the product just because a customer needs it. Bring it because is inevitable.</strong> 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".</p>
<iframe src="https://giphy.com/embed/hvRoo3YcAPUheF3MxY" width="480" height="480" frameBorder="0" class="giphy-embed" allowFullScreen=""></iframe>
<p>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.</p>
<p><strong>Treat your code as a garden, which deserves care and dedication.</strong> Don't write it and ignore it until a bug arises.</p>
<p>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.</p>
<p>Having a continuous improvement mindset is what makes us better than the rest.</p>
A simple way to build your JavaScript tests data2020-05-07T00:00:00-00:00https://guiferreira.me/archive/2020/05/a-simple-way-to-build-your-javascript-tests-data/<p>When writing Unit Tests, you will need to create test data objects for sure. Usually, those objects have tiny differences between different test cases.</p>
<p>There's a pattern that I especially like when I'm doing this is C#. <a href="https://ardalis.com/improve-tests-with-the-builder-pattern-for-test-data">The Builder Pattern</a>.</p>
<p>The builder pattern is an elegant solution to the problem and I really like it. But, is it a simple solution for JavaScript?</p>
<p>Let's see how it would look like using the builder pattern in JS:</p>
<p><img src="https://guiferreira.me/images/a-simple-way-to-build-your-javascript-tests-data-builder.png" alt="Builder pattern"></p>
<p>As you can see, there's a lot of code needed to implement it.</p>
<p><strong>How can we do it more simply?</strong></p>
<p>The basic idea is to <strong>use the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">Spread Operator</a> to customize a default object</strong>.</p>
<p>Let's see how:</p>
<p><img src="https://guiferreira.me/images/a-simple-way-to-build-your-javascript-tests-data-spread.png" alt="Spread Operator"></p>
Don't declare your Variables at the top2020-05-05T00:00:00-00:00https://guiferreira.me/archive/2020/05/dont-declare-your-variables-at-the-top/<p>When I start learning to code, I was taught to declare variables at the top of the code. I followed it for a long time before start questioning that absolute truth.</p>
<p>We are writing code for others to read. So, we shouldn't present our characters too early in the story. <a href="https://www.livescience.com/2493-mind-limit-4.html">Our working memory handle a strict number of things at a given time</a>.</p>
<p><img src="https://guiferreira.me/images/dont-declare-your-variables-at-the-top-memory-overflow.png" alt="Working memory overflow"></p>
<p>Keeping related concepts closer, we are reducing the cognitive load. This will lead us to clean and simple code.</p>
<p>You can find evidence of that, in Design Principles. By using the <a href="https://www.interaction-design.org/literature/article/laws-of-proximity-uniform-connectedness-and-continuation-gestalt-principles-2">Proximity principle</a>, we form groups by keeping things closer.</p>
<p>This is one of the reasons why <strong>I run away from global variables.</strong></p>
<p>Besides the cognitive load reduction, there's a positive side effect from following this. <strong>I use this as a warning sign to extract a function. Whenever you can't keep the variables close to where they are used and to the top, extract it.</strong></p>
<p>So, instead of doing this:</p>
<p><img src="https://guiferreira.me/images/dont-declare-your-variables-at-the-top-example1.png" alt="Example 1"></p>
<p>You can do this:</p>
<p><img src="https://guiferreira.me/images/dont-declare-your-variables-at-the-top-example2.png" alt="Example 2"></p>
<p>And then refactor to this:</p>
<p><img src="https://guiferreira.me/images/dont-declare-your-variables-at-the-top-example3.png" alt="Example 3"></p>
windbg a .net core 3.1 app memory leak2020-04-15T00:00:00-00:00https://guiferreira.me/archive/2020/04/windbg-a-net-core-31-app-memory-leak/<p>I've spent the past few days trying to fix a memory leak. I was having problems to figure out what was leaking, so I used windbg wishing that it would help me.</p>
<p>I confess that I'm not an experienced user of windbg, so I google how to catch memory issues using windbg. There's a ton of information out there. The problem is that I didn't found a guide on how to do it with a .net core application.</p>
<p>So, I'm sharing here how I've done it:</p>
<ol>
<li>Install windbg (<a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools">see here</a>).</li>
<li>Add windbg.exe (x64 version) to your environment path.</li>
<li>Install SOS (<a href="https://github.com/dotnet/diagnostics#installing-sos">see here</a>): <code>dotnet tool install -g dotnet-sos</code>.</li>
<li>Set breakpoint(s) using <code>System.Diagnostics.Debugger.Break()</code> in your source code.</li>
<li>Update your project (*.csproj file) to Load Symbols: <code><DebugSymbols>true</DebugSymbols><DebugType>pdbonly</DebugType></code>.</li>
<li>Build your project using Release configuration: <code>dotnet build -c Release</code>.</li>
<li>Launch with WinDbg attached to your project: <code>windbg dotnet [YOUR DLL PATH].dll</code>.</li>
<li><a href="https://bret.codes/net-core-and-windbg/#loadsos">Load SOS</a> using <code>.load C:\Users\[USERNAME]\.dotnet\sos\sos.dll .</code>.</li>
</ol>
<p><img src="https://guiferreira.me/images/windbg-a-net-core-31-app-memory-leak-load-sos.png" alt="windbg - load sos"></p>
<ol start="9">
<li>Enter <code>g</code> to go to the first breakpoint.</li>
<li>Enter <code>!gchandles</code> to see garbage collector handles.</li>
<li><code>!DumpHeap /d -mt [MT]</code> using the memory type id from the result list of the previous command. Example: <code>!DumpHeap /d -mt 00007ffb4c85ca98</code></li>
<li><code>!gcroot -all [ADDRESS]</code> using the memory address form the result list of the previous command. Example: <code>!gcroot -all 0x0000023cd2e71510</code></li>
</ol>
<p>Following this guide, you should have a clue of what is still in memory and where the object is in use.</p>
<p>Hope this helps.</p>
Optimizing React Render - 3 things that I wish to know before2020-02-26T00:00:00-00:00https://guiferreira.me/archive/2020/02/optimizing-react-render-3-things-that-i-wish-to-know-before/<p><img src="https://guiferreira.me/images/optimizing-react-render-3-things-that-i-wish-to-know-before.png" alt="Optimizing React Render - 3 things that I wish to know before"></p>
<p>My experience with <a href="https://reactjs.org/">React</a> has been awesome so far. My feeling is that I just needed to understand the basic concepts to be productive with React. The problem is that there are a few advanced concepts that I was missing.</p>
<p>Recently, the lack of knowledge manifested itself as performance issues. To fix them I needed to learn in the hard way. So, I'm sharing this here because if I can prevent you from suffering from it, I would be glad.</p>
<p>I observed that the components of my application were rendering too many times, even when I did not need them to re-render. The following 3 recommendations are the main reasons for that to happen.</p>
<hr>
<h2>💡 1. Don't pass props with an object by reference</h2>
<p><strong>If you invoke a component and set a prop with a given object, the object will be passing by reference.</strong> This can cause all kind of problems. I was facing two distinct problems:</p>
<ul>
<li>Despite I was lifting the state up, the child components have access to the same instance of the state.</li>
<li>When passing props by reference, you can receive the same object in the prevProps and nextProps for a componentShouldUpdate event. That will cause you problems. You want to compare those props to know what has been changed, but you are looking at the exact same object.</li>
</ul>
<h3>✅ What to do?</h3>
<p>Use the spread operator. If you have a complex data structure, with multi-level deepness, use a tool like <a href="https://lodash.com/docs/#cloneDeep">Lodash cloneDeep</a>.</p>
<hr>
<h2>💡 2. Only pass properties needed to the component</h2>
<p><strong>Make sure that you don't provide information that isn't needed to the child components. Try to only pass simple props with primitive types or functions.</strong> If you pass a complex object and the child object only needs part of it, React will need to re-render the component. React will re-render every time that the props or the state change.</p>
<h3>✅ What to do?</h3>
<p>Review your components and question all those props where the prop type is Object or Any.</p>
<hr>
<h2>💡 3. React Memo or Pure Components</h2>
<p>Memo and Pure Components are an excellent way of improving performance. But, unless you are using them in the correct scenario you will not see the benefits. <strong>If you are providing a complex object</strong> (like explained in recommendation 2) <strong>Memo and Pure Components will not work as you expect.</strong></p>
<p>To understand that, you need to know that a Pure Component is different from a Component. Pure Components implement the <em>"shouldComponentUpdate"</em> with a shallow prop and state comparison.</p>
<p>React documentation (<a href="https://reactjs.org/docs/react-api.html#reactpurecomponent">see here</a>):</p>
<p><em>"<code>React.PureComponent’s</code> <code>shouldComponentUpdate()</code> only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences."</em></p>
<h3>✅ What to do?</h3>
<p>Try to follow the recommendation 2. If you need to have a complex data structure, use a Component and implement the <em>"shouldComponentUpdate"</em> instead.</p>
<p>You can also take a look into react-fast-compare to help you out comparing complex data.</p>
<hr>
<p>To conclude, try to use primitive data as Props and use Pure Components or Memo when you can.</p>
<p>If you can't, be sure that you clone the data and implement the <em>"shouldComponentUpdate"</em> by yourself.</p>
<p>I hope that this helps you.</p>
One-on-ones - Using behavioural science to maximize the impact2020-02-10T00:00:00-00:00https://guiferreira.me/archive/2020/02/one-on-ones-using-behavioural-science-to-maximize-the-impact/<p><img src="https://guiferreira.me/images/one-on-ones-using-behavioural-science-to-maximize-the-impact.png" alt="One-on-ones - Using behavioural science to maximize the impact."></p>
<p>If you manage or mentor people, you should be doing one-on-one meetings.
They are one of the most important tools that you have, so, it's important to maximize the result.</p>
<p><strong>One-on-one meetings are an excellent moment for goal setting</strong>.
We tend to advise for improvement <strong>and it's a good practice to set a goal</strong>.</p>
<p>The problem is that those goals tend to have the same destiny of new year's eve goals and fail miserably (by the way, if your gym goal has made through January you are doing a good job!).</p>
<p>When we do one-on-one meetings we hope to improve people's lives and the difficult part isn't to identify those goals, those improvement opportunities.
<strong>The difficult part is to help the team to achieve those goals.</strong></p>
<p>Usually, the intentions are good, and everyone is genuinely trying to do their best.
I don't see these failures as people's fault, because we, as humans, are specialists in failing to achieve goals.</p>
<p>If you have been in this situation, probably you have noticed that goals use to stay in the "To do" state for a long time.
So the question is: <strong>What can we do to be more effective?</strong></p>
<p>And the answer is in <strong>Behavioural Science</strong>.</p>
<p>Multiple studies already present how we should approach Goal Setting and what to do to achieve our goals. So, based on Behavioural Science, what do I recommend:</p>
<hr>
<h2>Goals</h2>
<p><strong>🎯 Specific Goals with a specific deadline.</strong></p>
<p>💡 Suggestion: Propose goals that are specific and easy measure. Assign a deadline.
Remember not to impose goals. You are advising, so your role is mentorship.</p>
<hr>
<h2>Plan</h2>
<p><strong>🎯 Create a simple plan with small steps.</strong></p>
<p>💡 Suggestion: Elaborate on the simplest plan possible. A complex plan is more likely to fail
Small steps are easy to measure and to see progress.</p>
<p><strong>🎯 Try to form a new habit.</strong></p>
<p>💡 Suggestion: Goals are an excellent opportunity to form new habits.
Make sure that you plan for routine small steps.
By associating those steps to routine, the habit will be more likely to stick.</p>
<hr>
<h2>Commit</h2>
<p><strong>🎯 Find someone that will act as a referee to enforce a penalty if he fails. If you don't find anyone, do it yourself.</strong></p>
<p>💡 Suggestion: Work with your colleague to find a referee and a good career mentor.</p>
<p><strong>🎯 Advice to make the goals public. This will raise the commitment level and help stick to it.</strong></p>
<p>💡 Suggestion: Lead by example. Inform the team of your own goals. Write it down in a shared space (Slack, Whiteboard, Email, etc.).
This way, everyone will feel safe to do the same.</p>
<hr>
<h2>Reward and Punish</h2>
<p><strong>🎯 Make commitments that put something meaningful at stake and impose a non-negotiable rule. This way we work harder to achieve our goals.</strong></p>
<p>💡 Suggestion: Recommend to assume a goal and commit to a task that no one likes in case of failure.</p>
<hr>
<h2>Feedback</h2>
<p><strong>🎯 Give feedback. Probably you are the reason for that goal, so you should give feedback on the progress or the lack of it.</strong></p>
<p>💡 Suggestion: Keep frequent one-on-ones and always do a follow-up to the "active" goals.
Be honest and try to present data and examples to demonstrate your point of view.</p>
<p>In your next one-on-one try to apply these. If you don't have one-on-ones, make that your first Goal.</p>
Start thinking inside the box2019-12-02T00:00:00-00:00https://guiferreira.me/archive/2019/12/start-thinking-inside-the-box/<p><img src="https://guiferreira.me/images/start-thinking-inside-the-box.png" alt="Don't you freeze when you are asked to be creative and think outside the box?"></p>
<p>Don't you freeze when you are asked to be creative and think outside the box?</p>
<p>If so, you probably have been in the following places. Rumbling through ideas without consequences. Don't know where to start. Being repetitive. Procrastinating. Those are just a few consequences when we are facing a clean slate.</p>
<p>These leads us to frustration, disappointment and lack of confidence in our creative skills.</p>
<p>Probably you even think: <em>"How the hell could Steve Jobs be so creative? That guy was a genius! He could think outside the box for sure."</em> Well... I don't think so. Let's see why.</p>
<p>In 2007, Steve presented to the world the first iPhone. A device that began the revolution of our daily companion: The Smartphone. Today we can't live without it, but in 2001, we weren't so dependent for sure.</p>
<p>iPhone wasn't the first pocket computer that we carried. But, the iPhone was the first one to be really usable. A genius move of Steve Jobs was to understand the limitations of the current devices and drive the innovation to create delightful touch experience. Yes, kids, we used to need a keyboard or even a pen to work with our "smartphones".</p>
<p><a href="https://pt.wikipedia.org/wiki/Stylus"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/HTC_Touch2_used_with_a_stylus.jpg/1280px-HTC_Touch2_used_with_a_stylus.jpg" alt="Phone Stylus"></a></p>
<p>The constraints were there, since the first day. iPhone was built on the shoulders of giants but the difference was to put together in the same device a plot of technologies, a good touch screen and a whole new experience.</p>
<p>As you can see, the <strong>constraints applied to the User Experience guided Steve to question what can be done to bring a better experience to life</strong>. For sure, the fact of Steve being so obsessed with perfection was a constraint that forced the Apple team to find a new path, <strong>testing wild ideas</strong>.</p>
<p><strong>If Apple had to start without constraints, they would need to forget the past, the Phone history.</strong></p>
<p>Everything that has been accomplished in the <strong>past is for sure one of the most important guides in everything that we do.</strong></p>
<p>Embrace the constraints and let them guide your creativity, because sometimes <strong>freedom, can be paralyzing.</strong></p>
<p>Always remember, that when you were a little kid, you could bring to life an house, a car or even a plane with just two simple ingredients: A cardboard box and your imagination.</p>
A simple tip to improve your code maintainability - Decompose IF statements into methods2019-10-24T00:00:00-00:00https://guiferreira.me/archive/2019/10/a-simple-tip-to-improve-your-code-maintainability-decompose-if-statements-into-methods/<p><img src="https://guiferreira.me/images/a-simple-tip-to-improve-your-code-maintainability-decompose-if-statements-into-methods.png" alt="Extract method"></p>
<p>How many times have you been in a situation where you can’t understand a small piece of code?</p>
<p>Readability has a huge impact on code maintenance because reading other’s people code (and sometimes even our code) can be challenging.</p>
<p>As developers, <strong>we tend to ignore the UX (user experience) of our code</strong>. Every single line of code that we do, will eventually be used by others. Is important to be sure that we do the best possible job for our teammates and to future self.</p>
<p><strong>The worst code blocks in terms of UX are the ones that require a huge cognitive load.</strong> It’s our job to ask our selves what we can do to reduce it and improve readability.</p>
<p>Usually when I’m in a situation that requires high cognitive load to understand a piece of code, is because I face a huge and complex IF statement condition and I need to figure out what the hell it’s supposed to do. Do you know the feeling? Having to sketch a decision tree trying to figure out what is happening?</p>
<h2>How to avoid it?</h2>
<p>This is one of the most simple tricks that I do every day and I tend to advise everyone to do.</p>
<p>My rule of thumb is simple: <strong>In case of a multi-part condition, extract it to a method and name it accordingly.</strong></p>
<p>Let’s see it in practice.</p>
<p>Imagine that you have the following expression, that wants to validate if the customer can pay the Order with Credit Card. To do that, the customer should have an active Credit Card.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>PayWithCreditCard <span class="token operator">&&</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>Customer<span class="token punctuation">.</span>CreditCard <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> order<span class="token punctuation">.</span>Customer<span class="token punctuation">.</span>CreditCard<span class="token punctuation">.</span>ExpirationDate <span class="token operator"><</span> DateTime<span class="token punctuation">.</span>Today<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">CreditCardPaymentException</span><span class="token punctuation">(</span><span class="token string">"Customer doesn't have a valid Credit Card"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>To improve it, you can extract the boolean logic related to the credit card validation to a static method, and name it with something easy to understand.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ProcessOrder</span><span class="token punctuation">(</span><span class="token class-name">Order</span> order<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>order<span class="token punctuation">.</span>PayWithCreditCard <span class="token operator">&&</span> <span class="token function">IsCustomerCreditCardInvalid</span><span class="token punctuation">(</span>order<span class="token punctuation">.</span>Customer<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">CreditCardPaymentException</span><span class="token punctuation">(</span><span class="token string">"Customer doesn't have a valid Credit Card"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token punctuation">(</span><span class="token range operator">..</span><span class="token punctuation">.</span><span class="token punctuation">)</span><br><span class="token punctuation">}</span><br><br><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">IsCustomerCreditCardInvalid</span><span class="token punctuation">(</span><span class="token class-name">Customer</span> customer<span class="token punctuation">)</span><br> <span class="token operator">=></span> customer<span class="token punctuation">.</span>CreditCard <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> customer<span class="token punctuation">.</span>CreditCard<span class="token punctuation">.</span>ExpirationDate <span class="token operator"><</span> DateTime<span class="token punctuation">.</span>Today<span class="token punctuation">;</span></code></pre>
<p>By doing this you are abstracting the reader’s mind from details. In case the reader needs to know the details, he can drill down to the details.</p>
You should start working remotely once a week2019-09-05T00:00:00-00:00https://guiferreira.me/archive/2019/09/you-should-start-working-remotely-once-a-week/<p><img src="https://guiferreira.me/images/you-should-start-working-remotely-once-a-week-head.png" alt="Ready to work from home?"></p>
<p>Do you know the benefits of remote working? Do you doubt that it would work for you? Would you like to give it a try? Don’t know how to convince your boss or even how to start?</p>
<p>If so, I have something for you.</p>
<hr>
<p><em>This article is based on my experience of having the complete</em> <a href="https://omnialowcode.com/"><em>company</em></a> <em>working remotely once a week for the past few months.</em></p>
<hr>
<p><strong>Remote working</strong> has been growing in the past few years but for some organizations <strong>can be a change difficult to accept.</strong></p>
<p>If you are in an environment with resistance to Remote Working, the best way is to <strong>propose a small experiment.</strong> The best way to prove a hypothesis is to test it following the scientific method.</p>
<p>I suggest you present the case to the leadership presenting a few reasons (listed below) and proposing a small experience to prove them.</p>
<h2>5 reasons:</h2>
<ol>
<li><a href="https://www.inc.com/scott-mautz/a-2-year-stanford-study-shows-astonishing-productivity-boost-of-working-from-home.html">Studies report</a> that working from home has a <strong>huge impact on productivity</strong>.</li>
<li>It’s a benefit the company gives which can <strong>help to hire people</strong>.</li>
<li>It <strong>reduces costs</strong> both for the company and employee.</li>
<li>Leads to an <strong>improvement of the team communication</strong> skills.</li>
<li><strong>Happiness</strong>
<ol>
<li>Studies report that people who worked remotely were <strong>less likely to leave the company</strong>.</li>
<li>Health improvements.</li>
<li>Less time spent commuting.</li>
</ol>
</li>
</ol>
<h2>How to start</h2>
<p>After presenting a few reasons supporting your case, the best thing to do is to propose an experiment to evaluate the results.</p>
<ul>
<li><strong>Start small.</strong> I suggest starting with one day a week.</li>
<li><strong>Set a period for the experiment.</strong> I suggest to never do it for less than 3 months since in the first weeks everyone is still adapting.</li>
<li>Try to <strong>block a day in the calendar.</strong> For example, schedule a recurring “Remote Wednesday” meeting.</li>
<li>Try to <strong>organize the work to leave remote days free of meetings.</strong> If you have a creative job, this is a <strong>good day to focus</strong>.</li>
<li>Make sure that everyone has a <strong>good pair of headphones</strong>.</li>
<li>Make sure that the team has the <strong>right tools to facilitate the communication</strong> (<a href="https://slack.com/">Slack</a>, <a href="https://teams.microsoft.com/start">Microsoft Teams</a>, <a href="https://www.skype.com/">Skype</a>, <a href="https://zoom.us/">Zoom</a> or other).</li>
</ul>
<p>Don’t forget to <strong>define a few success metrics and define how you will evaluate them.</strong></p>
<p>If you have other technique to start this journey, please share!</p>
The secret to know Yourself2019-08-27T00:00:00-00:00https://guiferreira.me/archive/2019/08/the-secret-to-know-yourself/<p><img src="https://guiferreira.me/images/the-secret-to-know-yourself-head.png" alt="Have you ever heard a recording of your voice"></p>
<p>Have you ever heard a recording of your voice? You don’t sound like that, am I right?!</p>
<p>Everyone has been in that situation, and that is strange, especially because we spend so much time with us. Even so, we sound like a poor imitation.</p>
<p>It’s really common to listen to people that seem pretty sure that they know themself. We even find a lot of books about self-knowledge. The world seems to lead us to believe that we need to find ourselfs by meditation and introspection.</p>
<p>Even if I think that taking the time to reflect is important, I don’t think that is enough.</p>
<p><strong>The vision that we have about us tend to be highly influenced by our ideals and our dreams.</strong> Our brain is a specialist in fooling us and uses our wishes to trick us.</p>
<p>So, what can we do to escape that illusion? We need to see how we act as if we were in an out-of-body experience.</p>
<p>We can use professional sports as an example. We see athletes recording their training as a performance analysis tool. This is a good tool that top performances use to perfect their craft. <strong>Seeing yourself performing in a given context, can be enlightening.</strong></p>
<p>You can follow the example of pro-athletes and record yourself while performing a given task to try to figure out what to improve.</p>
<p>But, the reality is that when we know that we are <strong>being observed, we start acting differently than we normally do and influence the outcome.</strong> Similar to the Observer Paradox from quantum mechanics.</p>
<blockquote>
<p>Observer paradox: the observer's paradox refers to a situation in which the phenomenon being observed is unwittingly influenced by the presence of the observer/investigator.</p>
<p><a href="https://en.wikipedia.org/wiki/Observer%27s_paradox">wikipedia.org</a></p>
<p><a href="http://factmyth.com/factoids/observing-a-phenomenon-affects-its-outcome/">factmyth.com</a></p>
</blockquote>
<p>If you don’t know this paradox, I highly recommend the following video.</p>
<p>https://www.youtube.com/watch?v=Bq69-MI9TA0</p>
<p>So, if recording yourself can be a good way to lie to yourself, what can you do!?</p>
<p><strong>The secret is Feedback! Ask for feedback!</strong> I’ve written an <a href="https://guiferreira.me/archive/2019/07/leading-improvement-through-honest-feedback/">article that you can find here</a> about the importance of feedback for improvement. Go ahead and read it. I will wait…</p>
<p>Reaching out trust worth people that spend a lot of time with you is the easy path. When we are in our day-to-day life, lost in routines, we tend to express our true self and that has an impact on the people that surround us. So, if we do something positive or negative, if we have an annoying or peculiar characteristic, people tend to see it and label you with that specific trait.</p>
<p>It can be uncomfortable, but, <strong>if you want to know who you are, you need to look inside, but you also need to look to the world and discover the impact that you have in others</strong>.</p>
<p>Before we end here, I want to challenge you to a quick challenge that can lead you into this self know journey.</p>
<p>The challenge:</p>
<ol>
<li>Write down 5 words that you think that describe yourself. 5 things that you think that reflects yourself and that other recall those words when thinking about you.</li>
<li>Find 5 people and ask them to send you 3 words that describe you.</li>
<li>Compare the results and see if something that you don’t expect to emerge from their feedback. Sometimes we have bad surprises, but I prefer to know and do something than keep doing the same.</li>
</ol>
<p>Go to your email and send a mail to 5 people that you trust them to give honest feedback. If you're looking to know yourself in a given context try to target people that are part of that given context. If you want to know “who am I as a leader?” reach out to your team and old team members. If you want to know “who am I as a friend?” reach out a group of friends important to you. If you want to know you in multiple contexts, just multiply the challenge.</p>
<p>If you learn something new about yourself, please share!</p>
<p>Next time you are in a one-on-one meeting, in an interview or in another context where you can have valuable feedback, don't forget to ask for feedback.</p>
Leading Improvement through Honest Feedback2019-07-16T00:00:00-00:00https://guiferreira.me/archive/2019/07/leading-improvement-through-honest-feedback/<p><img src="https://guiferreira.me/images/leading-improvement-through-honest-feedback-head.png" alt="if it hurts, do it more often"></p>
<p>When was the last time that a waitress asked about your meal and you were really honest?</p>
<p>Don’t feel ashamed. I’ve definitively been there. Saying that the meal was good when It was dry or too salty for your taste, is more common than we can think.</p>
<p>Unfortunately, being honest when something is wrong isn’t something that we humans tend to feel comfortable about.</p>
<p>Probably you are asking: why the hell should I be honest and risk to advancing into a difficult conversion?!</p>
<p>Because <strong>the worst kind of feedback is fake feedback</strong>.</p>
<h2>Leading improvement</h2>
<p>Have you ever thought that the restaurant could have done something to improve if you have been sincere? Wouldn’t you love to have customers telling you what you should do, to delight them?</p>
<p>The reality is that <strong>without the truth, we can’t improve.</strong></p>
<blockquote>
<p>Empty criticism and snark does no one any good. But genuine, useful, insightful feedback is a priceless gift.</p>
<p>Seth Godin</p>
<p><a href="https://seths.blog/2014/01/the-feedback-youve-been-waiting-for/">https://seths.blog/2014/01/the-feedback-youve-been-waiting-for/</a></p>
</blockquote>
<h2>Promote feedback</h2>
<p><strong>When you give good feedback, you are showing kindness</strong>, even when it’s not positive feedback. They should see you as a Consultant that doesn’t send a bill. Next time that you aren’t sure if you should speak up, remember that in the end, they should thank you for the consideration.</p>
<p>Obviously that in a few cases you will find fences. Some people prefer to ignore and to resist, but in those cases, just move on. They won’t be in the business for too long for sure.</p>
<p>To empower mutual constructive feedback, make sure you <strong>respond to honest feedback with a “Thank you”</strong>.<br>
If you don’t assume a defensive posture and you really look grateful, you will be encouraging the behavior.</p>
<h2>It can be difficult</h2>
<p>The DevOps community has a mantra with which I agree: “if it hurts, do it more often”. I believe that this applies to feedback also.
It may be uncomfortable to start asking for honest feedback or even more to start giving feedback, especially when isn’t that good. But, if you do it over and over again, you will see that it will become natural and you will stop overthinking about it.</p>
<p>It’s really important not to be ashamed for pointing out negative things, because when you always give “OK answers”, your honest positive comments will not have an impact.
If you are known as the guy who speaks honestly, you will be taken into consideration.</p>
<h2>Make it easy</h2>
<p>Since feedback is so valuable, why do we tend to make so difficult for others to give us feedback?</p>
<p>Probably I want to tell you how I feel when I’m using your product, but at the moment when I understand that I need to create a user in a website and fill a 20 field long bug report, you can be sure that I will move on the next time I have an improvement idea.</p>
<p>So, <strong>please bring to your systems a simple way to collect feedback</strong>. Anyone should be able to leave you a note in 40 seconds and feel selfless, instead of 5 minutes of swearing and disappointment.
If you are concerned that 40 seconds won’t be enough to capture all you need to know from the user, I bet that the user will be happier to answer an email with your questions afterward than upfront. At least they know that you have listened. No one wants to speak with a database, specially if nobody cares about it.</p>
<p>Remember that <strong>a good idea can arise anywhere at any time</strong>.</p>
<h2>How to give honest feedback</h2>
<p><strong>Being honest doesn’t mean being rudely honest.</strong> No one wants to feel like being part of a Kitchen Nightmares episode, with Chef Gordon Ramsay yelling how incompetent we must be. That’s not fun.</p>
<p>There are better ways to deliver feedback. I’ve 5 tips that you can start with:</p>
<ol>
<li>Be humble.</li>
<li>Express your feedback as an opinion. For example, saying that the food is “Full of salt” is different than saying “Is too salty for my taste”.</li>
<li>Expose only your top 3 ideas. Don’t be too nitpicking. Having a “shopping list” of stuff won’t help.</li>
<li>Balance positive feedback with negative feedback. When we have something bad to say, we can easily forget to say good things.</li>
<li>If you have an idea on how to improve, say it!</li>
</ol>
<p><a href="https://randomcrab.com/valuable-feedback/"><img src="https://guiferreira.me/images/leading-improvement-through-honest-feedback-valuable-feedback.jpg" alt="Valuable Feedback"></a></p>
<h2>Wrapping up</h2>
<p>We live in a society that seeks approval in social networks, and that thinks that a “Like” is a good kind of feedback. This causes an illusion about the impact we have on society. So, next time you see that a given person, service or product has a positive impact on you, don’t limit yourself to follow them on Facebook or Instagram. Go ahead and send them a message telling how was your experience.</p>
<p>And if you are providing a service or selling a product, make sure you make it easy to receive feedback and encourage your customer to do it.</p>
<p>Are you ready to give it a try? I have a challenge for you. In the next 24 hours, make sure you:</p>
<ol>
<li>Send a message to one of your favorite services, telling them one thing that they can do that would improve your experience. Don’t forget to tell them to keep up with the good work. 😉</li>
<li>Say thanks to someone that positively impacted your life and you know that you never told them.</li>
<li>Leave your honest feedback to this post bellow 😊</li>
</ol>
Logging gRPC requests using Serilog2019-04-10T00:00:00-00:00https://guiferreira.me/archive/2019/04/logging-grpc-requests-using-serilog/<p>Using a Middleware to log Api Requests in ASP.NET Core is a no brainer.</p>
<p>If you have given a try to <a href="https://grpc.io/">gRPC</a>, probably you want to follow the same technique and you will wish that the experience was the same.</p>
<p>I've faced this challenge, in order to log the requests to my RPC services and I've been looking for a solution where:</p>
<ul>
<li>I can use <a href="https://serilog.net/">Serilog</a> to log the requests</li>
<li>I know all the requests made to my services</li>
<li>I know how long each request takes to respond</li>
<li>I know the response status</li>
<li>I can correlate each log entry using a Correlation ID</li>
</ul>
<p>To accomplish that in gRPC, I took advantage of an <strong>Interceptor</strong>.</p>
<p>Using an interceptor, you can intercept the invocation of GRPC methods and intercept Unary calls (Request/Response) or Streaming communication.</p>
<p>In this example, we will be using a <strong>Unary Interceptor</strong>.</p>
<p><em>This example has been done on top of gRPC HelloWorld sample in version 1.19.0</em></p>
<h2>Step 1: Install Serilog</h2>
<p>Start by download the Sample code from gRPC. You can find the instructions <a href="https://grpc.io/docs/quickstart/csharp.html">here</a>.</p>
<p>Install in the GreeterServer the serilog package <code>Install-Package Serilog.Sinks.Console -Version 3.1.1</code>.</p>
<p>I'm using the Console Sink for demonstration proposes. You can easily find tons of sinks like File, Seq, Application Insights, Datadog, etc.</p>
<p>To enable Serilog, create the logger at the beginning of the GreeterServer <em>Main</em>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Main</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> Log<span class="token punctuation">.</span>Logger <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">LoggerConfiguration</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>WriteTo<span class="token punctuation">.</span><span class="token function">Console</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">CreateLogger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">(</span><span class="token range operator">..</span><span class="token punctuation">.</span><span class="token punctuation">)</span><br><span class="token punctuation">}</span></code></pre>
<h2>Step 2: Create the Interceptor</h2>
<p>In the GreeterServer project create the <em>RequestLoggerInterceptor</em>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Grpc<span class="token punctuation">.</span>Core</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Grpc<span class="token punctuation">.</span>Core<span class="token punctuation">.</span>Interceptors</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Serilog</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Diagnostics</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>Tasks</span><span class="token punctuation">;</span><br><br><span class="token keyword">namespace</span> <span class="token namespace">GreeterServer</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">RequestLoggerInterceptor</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">Interceptor</span></span><br> <span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> MessageTemplate <span class="token operator">=</span><br> <span class="token string">"{RequestMethod} responded {StatusCode} in {Elapsed:0.0000} ms"</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>TResponse<span class="token punctuation">></span></span> <span class="token generic-method"><span class="token function">UnaryServerHandler</span><span class="token generic class-name"><span class="token punctuation"><</span>TRequest<span class="token punctuation">,</span> TResponse<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token class-name">TRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">ServerCallContext</span> context<span class="token punctuation">,</span> <span class="token class-name">UnaryServerMethod<span class="token punctuation"><</span>TRequest<span class="token punctuation">,</span> TResponse<span class="token punctuation">></span></span> continuation<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> sw <span class="token operator">=</span> Stopwatch<span class="token punctuation">.</span><span class="token function">StartNew</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">UnaryServerHandler</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> context<span class="token punctuation">,</span> continuation<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> sw<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Log<span class="token punctuation">.</span>Logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span>MessageTemplate<span class="token punctuation">,</span><br> context<span class="token punctuation">.</span>Method<span class="token punctuation">,</span><br> context<span class="token punctuation">.</span>Status<span class="token punctuation">.</span>StatusCode<span class="token punctuation">,</span><br> sw<span class="token punctuation">.</span>Elapsed<span class="token punctuation">.</span>TotalMilliseconds<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> response<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>This interceptor is just logging the Status Code for each request and the time used to complete the execution.</p>
<h2>Step 3: Apply interceptor to the service</h2>
<p>To take effect, you need to bind the interceptor to the Service you want. To do that, go to the <em>Program.cs</em> and configure the Server service binding to use the interceptor for the Greeter service.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Grpc<span class="token punctuation">.</span>Core<span class="token punctuation">.</span>Interceptors</span><span class="token punctuation">;</span><br><span class="token punctuation">(</span><span class="token range operator">..</span><span class="token punctuation">.</span><span class="token punctuation">)</span><br><span class="token class-name">Server</span> server <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Server</span><br><span class="token punctuation">{</span><br> Services <span class="token operator">=</span> <span class="token punctuation">{</span> Greeter<span class="token punctuation">.</span><span class="token function">BindService</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">GreeterImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Intercept</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">RequestLoggerInterceptor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span><br> Ports <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">ServerPort</span><span class="token punctuation">(</span><span class="token string">"localhost"</span><span class="token punctuation">,</span> Port<span class="token punctuation">,</span> ServerCredentials<span class="token punctuation">.</span>Insecure<span class="token punctuation">)</span> <span class="token punctuation">}</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>The Intercept method is an extension method, so don't forget to use <em>Grpc.Core.Interceptors</em> namespace.</p>
<p>If you run the samples now, you will see this as a result.</p>
<p><img src="https://guiferreira.me/images/logging-grpc-requests-using-serilog-simple-log-line.png" alt="Log entry"></p>
<h2>Step 4: Add Correlation ID</h2>
<p>If you have multiple services being part of the execution of a particular request, most probably you would take advantage of having a Correlation ID to track the execution of a given request in every service. If you don't have one, I highly recommend you to do it.</p>
<p>In this example, we will be sending the Correlation ID as an gRPC request header and change the Interceptor to add it to every log line.</p>
<p>Let's start by add the Correlation ID header to the RPC request done by <em>GreeterClient</em>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> reply <span class="token operator">=</span> client<span class="token punctuation">.</span><span class="token function">SayHello</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">HelloRequest</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> user <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Metadata</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Metadata<span class="token punctuation">.</span>Entry</span><span class="token punctuation">(</span><span class="token string">"X-Correlation-Id"</span><span class="token punctuation">,</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><em>In this example, I'm generating a Guid just for demo purposes.</em></p>
<p>In the interceptor, access to the Correlation ID and push it to Serilog as a property. In this way, every single log entry on that context will have the Correlation Id property available.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Grpc<span class="token punctuation">.</span>Core</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Grpc<span class="token punctuation">.</span>Core<span class="token punctuation">.</span>Interceptors</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">Serilog</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">System</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Diagnostics</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Linq</span><span class="token punctuation">;</span><br><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>Tasks</span><span class="token punctuation">;</span><br><br><span class="token keyword">namespace</span> <span class="token namespace">GreeterServer</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">RequestLoggerInterceptor</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">Interceptor</span></span><br> <span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> MessageTemplate <span class="token operator">=</span><br> <span class="token string">"{RequestMethod} responded {StatusCode} in {Elapsed:0.0000} ms"</span><span class="token punctuation">;</span><br><br> <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>TResponse<span class="token punctuation">></span></span> <span class="token generic-method"><span class="token function">UnaryServerHandler</span><span class="token generic class-name"><span class="token punctuation"><</span>TRequest<span class="token punctuation">,</span> TResponse<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token class-name">TRequest</span> request<span class="token punctuation">,</span><br> <span class="token class-name">ServerCallContext</span> context<span class="token punctuation">,</span> <span class="token class-name">UnaryServerMethod<span class="token punctuation"><</span>TRequest<span class="token punctuation">,</span> TResponse<span class="token punctuation">></span></span> continuation<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> sw <span class="token operator">=</span> Stopwatch<span class="token punctuation">.</span><span class="token function">StartNew</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> correlationId <span class="token operator">=</span> context<span class="token punctuation">.</span>RequestHeaders<br> <span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>h <span class="token operator">=></span> h<span class="token punctuation">.</span>Key<span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span><span class="token string">"X-Correlation-Id"</span><span class="token punctuation">,</span> StringComparison<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">?.</span>Value<span class="token punctuation">;</span><br> <span class="token keyword">using</span> <span class="token punctuation">(</span>Serilog<span class="token punctuation">.</span>Context<span class="token punctuation">.</span>LogContext<span class="token punctuation">.</span><span class="token function">PushProperty</span><span class="token punctuation">(</span><span class="token string">"CorrelationID"</span><span class="token punctuation">,</span> correlationId<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">UnaryServerHandler</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> context<span class="token punctuation">,</span> continuation<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> sw<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Log<span class="token punctuation">.</span>Logger<span class="token punctuation">.</span><span class="token function">Information</span><span class="token punctuation">(</span>MessageTemplate<span class="token punctuation">,</span><br> context<span class="token punctuation">.</span>Method<span class="token punctuation">,</span><br> context<span class="token punctuation">.</span>Status<span class="token punctuation">.</span>StatusCode<span class="token punctuation">,</span><br> sw<span class="token punctuation">.</span>Elapsed<span class="token punctuation">.</span>TotalMilliseconds<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">return</span> response<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>To complete the work, we need to configure Serilog to use the Properties pushed to the context.</p>
<p>Go back to the <em>GreeterServer Program</em> and change the logger configuration to have a template where you use the Correlation ID and configure the log enrichment with the context properties.</p>
<pre class="language-csharp"><code class="language-csharp">Log<span class="token punctuation">.</span>Logger <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">LoggerConfiguration</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>Enrich<span class="token punctuation">.</span><span class="token function">FromLogContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span>WriteTo<span class="token punctuation">.</span><span class="token function">Console</span><span class="token punctuation">(</span><span class="token named-parameter punctuation">outputTemplate</span><span class="token punctuation">:</span> <span class="token string">"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{CorrelationID}] {Message}{NewLine}{Exception}"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">CreateLogger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Step 5: Profit!</h2>
<p>In this tutorial, we created a simple gRPC interceptor. Now you have a request log with status codes and timings.</p>
<p><img src="https://guiferreira.me/images/logging-grpc-requests-using-serilog-simple-log-line-with-correlation-id.png" alt="Log entry with Correlation ID"></p>
<p>Go ahead and give it a try.</p>
Versioning .net Core applications using Cake2018-06-27T00:00:00-00:00https://guiferreira.me/archive/2018/06/versioning-net-core-applications-using-cake/<p>If you are moving to .net Core and you want to implement a versioning strategy in your application, now you have an awesome alternative to the good old fellow "AssemblyInfo".</p>
<p>The alternative is the <a href="https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build"><em>Directory.Build.props</em></a> file. If you place these file in the root folder that contains your source code, when MSBuild runs will add to every project the properties defined in the <em>Directory.Build.props</em>.</p>
<p>In this post, we will see how to quickly setup a solution with multiple projects and use <em>Directory.Build.props</em> with <a href="http://cakebuild.net/">Cake</a> to build and increment the version number.</p>
<p><img src="https://guiferreira.me/images/versioning-a-net-core-applications-using-cake-directory-build-props.png" alt="Directory.Build.props"></p>
<h2>Setup your project</h2>
<p>Let's use the <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x">.net Core CLI</a> to quickly accomplish this task.</p>
<p>Start by creating a folder in your computer and then open the command line and go to the directory that you just created. Then execute the following commands.</p>
<ol>
<li>Create a Solution: <code>dotnet new sln --name DotNetCoreVersioning</code></li>
<li>Create a console application and place it in the <em>src</em> folder: <code>dotnet new console --name Application --output src\Application</code></li>
<li>Create a class library and place it in the <em>src</em> folder: <code>dotnet new classlib --name Library --output src\Library</code></li>
<li>Add the console application to the solution: <code>dotnet sln add .\src\Application\Application.csproj</code></li>
<li>Add the class library to the solution: <code>dotnet sln add .\src\Library\Library.csproj</code></li>
<li>Build it: <code>dotnet build</code></li>
</ol>
<p>If you go to the folder you will see a solution file that you can open in Visual Studio.</p>
<h2>Adding the <em>Directory.Build.props</em></h2>
<p>Now it's time to add the file that will do the magic.</p>
<p>You just need to create a file with the name <em>Directory.Build.props</em> inside the <em>src</em> folder.</p>
<p>Add it and then copy the following snippet into it.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Project</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>PropertyGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Company</span><span class="token punctuation">></span></span>Empire<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>Company</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Version</span><span class="token punctuation">></span></span>1.0.1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>Version</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>AssemblyTitle</span><span class="token punctuation">></span></span>Death Star - Superlaser<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>AssemblyTitle</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>PropertyGroup</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>Project</span><span class="token punctuation">></span></span></code></pre>
<p>If you run the <code>dotnet build</code> command and go to the bin folder, of the console application or the class library, you can see in the DLL details that now the version is 1.0.1.</p>
<p><strong>NOTE: The casing is important if you want to use a Linux machine to run your build. Otherwise, the version may be 1.0.0.</strong></p>
<h2>Incrementing the version number.</h2>
<p>In this example, I will use a simple Cake script to increment the version number.</p>
<h3>Setup your build script</h3>
<p>I will explain how to do that manually, but if you are a <a href="https://code.visualstudio.com/">Visual Studio Code</a> user I highly recommend that you install the cake extension and use the tools provided by the extension.</p>
<ol>
<li>Install the Cake bootstrapper. You can find <a href="https://cakebuild.net/docs/tutorials/setting-up-a-new-project">here</a> how to do that.</li>
<li>Create a <em>build.cake</em> file next to the bootstrapper.</li>
<li>Add the following snippet to the build.cake.</li>
</ol>
<p> </p>
<pre class="language-csharp"><code class="language-csharp"><span class="token comment">///////////////////////////////////////////////////////////////////////////////</span><br><span class="token comment">// ARGUMENTS</span><br><span class="token comment">///////////////////////////////////////////////////////////////////////////////</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> target <span class="token operator">=</span> <span class="token function">Argument</span><span class="token punctuation">(</span><span class="token string">"target"</span><span class="token punctuation">,</span> <span class="token string">"Default"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> configuration <span class="token operator">=</span> <span class="token function">Argument</span><span class="token punctuation">(</span><span class="token string">"configuration"</span><span class="token punctuation">,</span> <span class="token string">"Release"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token comment">///////////////////////////////////////////////////////////////////////////////</span><br><span class="token comment">// TASKS</span><br><span class="token comment">///////////////////////////////////////////////////////////////////////////////</span><br><br><span class="token function">Task</span><span class="token punctuation">(</span><span class="token string">"Version"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Does</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">Task</span><span class="token punctuation">(</span><span class="token string">"Build"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">IsDependentOn</span><span class="token punctuation">(</span><span class="token string">"Version"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Does</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br> <span class="token function">DotNetCoreBuild</span><span class="token punctuation">(</span><span class="token string">"./DotNetCoreVersioning.sln"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">Task</span><span class="token punctuation">(</span><span class="token string">"Default"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">IsDependentOn</span><span class="token punctuation">(</span><span class="token string">"Build"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">RunTarget</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Your build has now two steps and is building your solution using <em>DotNetCoreBuild</em>.</p>
<h3>Increment the version number</h3>
<p>To increment the version number we need to update the <em>Directory.Build.props</em> file.</p>
<p>Since the <em>props</em> file is an XML we can use the Cake <a href="https://cakebuild.net/dsl/xml/">XML aliases</a> like XmlPeek and XmlPoke to read and update the version number.</p>
<p><strong>Note:</strong> <em>I recommend you to use the Build Number of your build server to calculate the new version number. In this case, we will read the current version from the file content.</em></p>
<p>Go ahead and copy the following snippet into the <em>Version</em> task in your <em>build.cake</em> file.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> propsFile <span class="token operator">=</span> <span class="token string">"./Directory.Build.props"</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> readedVersion <span class="token operator">=</span> <span class="token function">XmlPeek</span><span class="token punctuation">(</span>propsFile<span class="token punctuation">,</span> <span class="token string">"//Version"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> currentVersion <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Version</span><span class="token punctuation">(</span>readedVersion<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> semVersion <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Version</span><span class="token punctuation">(</span>currentVersion<span class="token punctuation">.</span>Major<span class="token punctuation">,</span> currentVersion<span class="token punctuation">.</span>Minor<span class="token punctuation">,</span> currentVersion<span class="token punctuation">.</span>Build <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> version <span class="token operator">=</span> semVersion<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">XmlPoke</span><span class="token punctuation">(</span>propsFile<span class="token punctuation">,</span> <span class="token string">"//Version"</span><span class="token punctuation">,</span> version<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>As you can see, we are reading the version property, incrementing the build number and then updating the <em>props</em> file again.</p>
<h3>The result</h3>
<p>Now that our build script is completed, go ahead and run your Cake bootstrapper (<em>build.ps1</em> or <em>build.sh</em>) and you will see that the compiled DLLs from all the projects have the version incremented.</p>
<p>You can use the <em>Directory.Build.props</em> to customize other project properties, not only for versioning.</p>
<p>Go ahead and give it a try.</p>
Exploring the Docker Container metaphor2018-03-05T00:00:00-00:00https://guiferreira.me/archive/2018/03/exploring-the-docker-container-metaphor/<p><em>This post is my interpretation of the Container metaphor and how I use it to understand the concepts and explain containers to others.</em></p>
<p>Containers is one of the hot topics in the Software Development world and Docker is the technology that everyone wants to play with.</p>
<p>Thanks to this hype, everyone has at least a brief idea of what a container is. The problem is that we can easily be confused about what containers really are and the advantages of it.</p>
<p>I faced the same problem and, in my case, explore the container metaphor helped me to understand it.</p>
<h2>So, why containers?</h2>
<p>As you know, the Docker logo is a blue whale fully loaded with shipping containers, remembering us of a ship. The ship is a key part in this story.</p>
<p><a href="https://docker.com/"><img src="https://guiferreira.me/images/exploring-the-docker-container-metaphor-docker.png" alt="Docker"></a></p>
<p>Imagine that you have a company in Europe and you want to transport your products to China by sea. So, you can find a ship with the adequate size and load the Ship with your cargo.</p>
<p><em>Metaphor: In the software world, the ship is your Server.</em></p>
<p>In a local trading association you find out that other companies are also sending products to China and you all can use a bigger Ship and send your products together to save some money.</p>
<p>The question is: Should that big Ship carry the smaller boats?</p>
<p><img src="https://guiferreira.me/images/exploring-the-docker-container-metaphor-ship-of-ships.png" alt="Ship of Ships"></p>
<p>Obviously not! No one would do that!</p>
<p><em>Metaphor: Here, the big Ship is your server and the smaller ships are virtual machines. In this case, we have multiple Ships with all the capabilities to travel to China, but they are all constrained to the capacity and limitations of the big ship.</em></p>
<p>If we have a big ship we load the ship with the cargo of every company.</p>
<p>But, you have to face a few challenges:</p>
<ol>
<li>How to be sure that the Cargo of a Port Wine company won't damage or contaminate the Cargo of other company?</li>
<li>How to isolate the cargo?</li>
<li>How to be sure that the cargo is inviolated?</li>
<li>How to make sure that the cargo is being transported in the best conditions (correct temperature for instance)?</li>
</ol>
<p>Well, you can put the cargo into containers.</p>
<p><em>Metaphor: In software, you are now loading the Server with containers. Containers will guarantee you that the software is isolated, protected and that a Container will take care what it needs, not the ship. Other benefit is that Containers are immutable so you can be pretty sure that your container won't be violated.</em></p>
<p>Obviously you are now in a better situation then having a big Ship carry over small ships. But, <strong>don't forget that even an empty Container is pretty heavy</strong>. Heavier then a few boxes.</p>
<p><em>Metaphor: This is a common misconception. The idea that a container is extremely lightweight is dangerous unless you are comparing it to Virtual Machines. In other case you are taking the risk of the other person think that containers are even lighter then running in the bare metal.</em></p>
<p>A cool thing about Shipping Containers is that they are pretty standard and modular. You can assume that when the ship arrives in China, there will be a Truck that can transport it and that the container can return in a different ship. <strong>Shipping containers are ship agnostic.</strong></p>
<p><em>Metaphor: That's another advantage of a container. Containers are pretty standard and without additional effort they can run in any Cloud or Server and be sure that they are self-sufficient.</em></p>
<p><a href="https://unsplash.com/photos/uBe2mknURG4"><img src="https://guiferreira.me/images/exploring-the-docker-container-metaphor-containers.jpg" alt="Containers"></a></p>
<h2>Composing</h2>
<p>How could you be sure that you have two ships loaded in the same way? How to be able to say that they are "equal" in terms of cargo?</p>
<p>Well, since we can't 3D print a ship capable of transport this (at least in 2018), you will need to document the process. You need to explain how the ship is setup with all containers, explaining the position of each container, what is the cargo and how the multiple containers are interconnected.</p>
<p><em>Metaphor: In Docker you use the Docker Compose to accomplish that. Compose is a command that uses a configuration file to know how to build multiple images and how they relate with each other.</em></p>
<h2>The Economic side</h2>
<p>What is more expensive?</p>
<ol>
<li>Sending a big ship carrying small ships or containers?
<em>Metaphor: A Server with Virtual Machines or Docker Containers?</em></li>
<li>Is it better to load the cargo in a repeatable way, right? <em>Metaphor: Docker file and Docker compose are important tools to remove the uncertainty of new deployments.</em></li>
<li>Wouldn't be nice to don't contaminate the cargo of one company because of a problem in other company products? <em>Metaphor: Isolation give you the confidence that your containers are protected. Containers are self-sufficient.</em></li>
</ol>
<p>There's any concept that I'm missing in this interpertation? If so, go ahead and leave a comment!</p>
JSON Patch Builder Online2018-01-08T00:00:00-00:00https://guiferreira.me/archive/2018/01/json-patch-builder-online/<p>Do you know the JSON Patch format? The <a href="https://tools.ietf.org/html/rfc6902">RFC6902</a> defines the structure to express a list of operations to apply over a JSON Document.
This format is designed to be the payload of an HTTP PATCH method.</p>
<p>The format isn't difficult, you can easily understand the rules and build it manually. But, I confess that sometimes I struggle with it, specially when I'm testing a PATCH to a complex object.
So... <strong><a href="https://json-patch-builder-online.github.io/">I built a Tool to help me.</a></strong></p>
<p><img src="https://guiferreira.me/images/json-patch-builder-online.png" alt="JSON Patch Builder Online"></p>
<p><strong><a href="https://json-patch-builder-online.github.io/">JSON Patch Builder Online</a></strong> is a simple and Open Source tool that you can use to calculate the JSON Patch needed to transform a resource/entity in the resource that you want.</p>
<p>To accomplish that, I used <a href="https://github.com/Starcounter-Jack/JSON-Patch">JSON-Patch</a>, a Javascript library, to calculate the Patch and <a href="https://bulma.io/">BULMA CSS</a> to have a good looking tool.
I recommend that you go check them.</p>
<p>If you have something that you want to see in the <strong><a href="https://json-patch-builder-online.github.io/">JSON Patch Builder Online</a></strong>, feel free to open an <a href="https://github.com/json-patch-builder-online/json-patch-builder-online.github.io/issues">Issue</a> or <a href="https://github.com/json-patch-builder-online/json-patch-builder-online.github.io/">Contribute</a>.</p>
<p>Links:</p>
<ul>
<li><a href="https://github.com/json-patch-builder-online/json-patch-builder-online.github.io/">Github</a></li>
<li><a href="https://json-patch-builder-online.github.io/">JSON Patch Builder Online</a></li>
</ul>
<p>I hope that this helps you.</p>
Implementing the HTTP Prefer Header with an ASP.NET Core Filter2017-11-15T00:00:00-00:00https://guiferreira.me/archive/2017/11/implementing-the-http-prefer-header-with-an-aspnet-core-filter/<p>Have you heard about <strong>Prefer Header for HTTP</strong>? The <a href="https://tools.ietf.org/html/rfc7240">RFC-7240</a> defines how this header can be used by a client, in order to request that certain behaviors be employed by a server while processing a request.</p>
<p>Why does it matter? You probably have consumed API's where you use the HTTP POST or PUT method to modify a resource and the server returns a complete representation of the resource. In other cases the API only returns the Identifier of the resource created, for example.</p>
<p><strong>What if you want to defer to the client to specify which optional behavior is preferred?</strong>
That's why you need to know about the HTTP Prefer Header.</p>
<p>The RFC specifies a group of Preference Definitions like a preference to indicate that the client prefers the server to respond asynchronously to a response for example, but this post will be focused on the "return=representation" and "return=minimal" preferences.</p>
<h3>"return=representation"</h3>
<blockquote>
<p>The "return=representation" preference indicates that the client
prefers that the server include an entity representing the current
state of the resource in the response to a successful request.</p>
</blockquote>
<h3>"return=minimal"</h3>
<blockquote>
<p>The "return=minimal" preference, on the other hand, indicates that
the client wishes the server to return only a minimal response to a
successful request.</p>
</blockquote>
<p>This preference is really useful when dealing with replies to a POST, PUT or PATCH request.</p>
<p><strong>The selection of which type of response to return to client have impact on what a client must do after receiving the response.</strong> Example: by returning a representation of the resource in the response the client won't need to do an additional GET request.</p>
<h2>How to implement in ASP.NET Core?</h2>
<p>One of the first questions that I faced when trying to implement the prefer header was <em>"how to implement it in ASP.NET Core?"</em>.</p>
<p>The easy answer would be:</p>
<ul>
<li>Do it in your Controller Action. Easy peasy, right?</li>
</ul>
<p>Not so sure my friend!</p>
<p>Following that approach will be difficult to manage when you face yourself with dozens of Controllers each one with a POST and a PUT. Now you see it... the beauty of the duplicated code :)</p>
<p>So, what if we write an ASP.NET Core filter?</p>
<blockquote>
<p>If you don't know what is a Filter I recommend you to go read <a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/understanding-action-filters-cs">here</a>.</p>
<p>If you find yourself wondering why don't create a Middleware, please see this <a href="https://channel9.msdn.com/Series/aspnetmonsters/ASPNET-Monsters-91-Middleware-vs-Filters">awesome video</a>.</p>
</blockquote>
<h3>Setup</h3>
<p>In my implementation, I defined that DTOs that can be controlled by the "return=minimal" preference should implement an interface <em>"IIdentifiable"</em>. That interface specifies the properties that I need to return in the "minimal" version (an Id for instance).</p>
<p>So, go ahead and create an <em>IIdentifiable</em> interface and add it to your DTO.</p>
<h3>The filter</h3>
<p>I implemented an Action Filter that will only return the full object when the client sends the <em>"return=representation"</em> preference.</p>
<p>So the flow is something like:</p>
<ol>
<li>POST a new Resource</li>
<li>Handle the request</li>
<li>Return an Action Result with a DTO in it</li>
<li>Catch the response in a filter
<ul>
<li>The Request doesn't have the Prefer header?</li>
<li>The Request has the Prefer header without the value "return=representation"?</li>
<li>If the answer to any of the previous questions is "Yes", I update the result to a new object with the minimal information.</li>
</ul>
</li>
</ol>
<p>The filter:</p>
<script src="https://gist.github.com/gsferreira/80aa93d12633c0df271a08f6dc2e52ca.js?file=HttpPreferReturnHeaderFilterAttribute.cs"></script>
<p><em>As you can see I am creating a new IdentifiableDto. That class is just a simple implementation of the IIdentifiable interface. If you prefer, you can just return a dynamic object.</em></p>
<p>Now you can use it in your Controllers like this:</p>
<script src="https://gist.github.com/gsferreira/80aa93d12633c0df271a08f6dc2e52ca.js?file=Controller.cs"></script>
<p><strong>*Note:</strong> If you need to do an extra effort to load the resource from the database, probably the Filter approach isn't the best fit for you.*</p>
Please don't name it "Utils"!2017-09-12T00:00:00-00:00https://guiferreira.me/archive/2017/09/please-don-t-name-it-utils/<p>Imagine that you are working on a code base that you are really proud of. Everything is building up together with great quality and you reach the moment where you need to send a mail. Simple task to you for sure.</p>
<p>You know that eventually you will need to send emails in other points of your application and because you master the DRY principle you decide to write an <em>"Utils"</em> class.</p>
<p>Good idea, isn't it? <strong>NO!!!! Absolutely no!</strong></p>
<p>Why not? What's wrong with an <em>"Utils"</em> folder or an Utility class?</p>
<p>Segregate responsibilities is an important thing, but naming is also important. Readability and discoverability are often underrated.</p>
<p><img src="https://guiferreira.me/images/please-don-t-name-it-utils-code-sample.png" alt="Utils code sample"></p>
<p>When you create an <em>"Utils"</em> class you are creating a collection of random stuff. A place where anything can fit and that someone who doesn't know your project won't know what can be found inside the <em>"Utils"</em>. For them, your <em>"Utils"</em> it's a kind of magical place where treasures and dragons can be hidden.</p>
<p>Please don't feel ashamed by doing that, I have done it in the past.
Phil Karlton once said:</p>
<blockquote>
<p>There are only two hard things in Computer Science: cache invalidation and <strong>naming things</strong>.</p>
</blockquote>
<p>I prefer a name that doesn't sounds catchy than a name that doesn't make sense.</p>
<p>So if you are typing <em>"Utils"</em>, please stop and think what the hell will this code do? Then, name it according to that.</p>
<ul>
<li>Write to a Log file? Name it <em>"Logger"</em>.</li>
<li>Send a mail? Name it <em>"MailSender"</em>.</li>
<li>Generate a random message? Name it <em>"MessageGenerator"</em>.</li>
<li>Provide string extensions? Name it <em>"StringExtensions"</em>.</li>
</ul>
<p>You get it.</p>
Rebuilding SQL Database indexes using Azure Function2017-07-20T00:00:00-00:00https://guiferreira.me/archive/2017/07/rebuilding-sql-database-indexes-using-azure-function/<p>Do you know that index management is under your responsibility and you need to pay attention to how fragmented they are? If you are reading this post, probably you know that (I hope that you didn't find it in the hard way).</p>
<p>Azure SQL Database takes care of a lot of maintenance tasks, but keeping your Indexes healthy isn't one of them.</p>
<p>Indexes get fragmented and fragmented indexes is a performance killer. The good news is that I can help you dealing with that.</p>
<h2>Do I have a problem?</h2>
<p>First let's analyze your database. Read <a href="https://blog.sqlauthority.com/2010/01/12/sql-server-fragmentation-detect-fragmentation-and-eliminate-fragmentation/">this article</a> to undestand the fragmentation indexs and then execute the following query in your database.</p>
<script src="https://gist.github.com/gsferreira/fbb3419a367730f53922f0809991d264.js"></script>
<p>Scared with the results? If so, keep reading.</p>
<h2>Azure Function</h2>
<p>You can find <a href="https://github.com/gsferreira/AzureFunctionSQLDefrag">here</a> the code of an Azure Function to automate the index maintenance of multiple databases.</p>
<p>The function will run and execute a REBUILD and REORGANIZE for Database Indexs, with a given Threshold.</p>
<p>By default, the Function is configured to Rebuild indexs with more than 30% of fragmentation and reorganize indexs with more than 3% but you can adjust those limits.</p>
<p>You can add a Connection String to multiple databases at the Application Settings where the name has the prefix "Defrag.".</p>
<p>You can find information of how to configure it in the project readme file.</p>
<h3>Important Note!!!</h3>
<p><em>The default timeout for functions on a Consumption plan is 5 minutes. The value can be increased to 10 minutes max.</em></p>
<p><em>If you have a big database, the function can stop running during the index maintenance and don't finish the job.</em></p>
<p><em>In that case, you probably want to move to an App Service plan or decompose the function splitting the work by multiple functions. If you want some tips of how to accomplish that, please leave a comment.</em></p>
<p><strong>References:</strong></p>
<ul>
<li><a href="https://blog.sqlauthority.com/2010/01/12/sql-server-fragmentation-detect-fragmentation-and-eliminate-fragmentation/">https://blog.sqlauthority.com/2010/01/12/sql-server-fragmentation-detect-fragmentation-and-eliminate-fragmentation/</a></li>
<li><a href="https://geeks.ms/davidjrh/2015/10/08/rebuilding-sql-database-indexes-using-azure-automation/">https://geeks.ms/davidjrh/2015/10/08/rebuilding-sql-database-indexes-using-azure-automation/</a></li>
<li><a href="https://alexandrebrisebois.wordpress.com/2013/02/06/dont-forget-about-index-maintenance-on-windows-azure-sql-database/">https://alexandrebrisebois.wordpress.com/2013/02/06/dont-forget-about-index-maintenance-on-windows-azure-sql-database/</a></li>
<li><a href="https://www.red-gate.com/simple-talk/cloud/cloud-data/azure-sql-database-maintenance/">https://www.red-gate.com/simple-talk/cloud/cloud-data/azure-sql-database-maintenance/</a></li>
</ul>
5 reasons to convince your boss to adopt Cake (C# Make)2017-06-26T00:00:00-00:00https://guiferreira.me/archive/2017/06/5-reasons-to-convince-your-boss-to-adopt-cake-csharp-make/<p>Have you taken a look into <a href="http://cakebuild.net/">Cake Build</a>?! It's awesome, isn't it?</p>
<p>Probably you are already convinced, but you are having trouble convincing your boss that it's worth to give him a chance.</p>
<p>To help you I give you here five compelling reasons they can't argue with.</p>
<p><img src="https://guiferreira.me/images/cake-build-logo.png" alt="Cake Build"></p>
<h2>1. It's C# ❤</h2>
<p>If you are working in a .NET shop where C# is the common language, you already have the tools to do the Job and probably isn't a good idea to adopt a new language.</p>
<p>The <strong><a href="https://en.wikipedia.org/wiki/Bus_factor">BUS Factor</a></strong> is a good metric to illustrate the risk of adopting a new language for a build system.</p>
<p>Cake scripts are written in C# and you can use all the knowledge that you already have.</p>
<h2>2. Living form of documentation</h2>
<p>What is the best way to describe your system? With coded tests. So <strong>what is the best way to describe your build? With code</strong> for sure!</p>
<p>As we all know, keeping a word document up-to-date is a painful task that one day someone will forget to update it. So, if you know how to read C#, you can read a script that documents it.</p>
<p>You also have the bonus of having a <strong>versioned build script</strong> if you add it to your source control.</p>
<p>Isn't powerful to know that in the future you can go back and see how your software was built in the past week?</p>
<p>Nevertheless, doing this kind of tasks manually shouldn't be a manual process. <strong>“For loops” are for computers</strong> and as programmers we know how to teach them to do it.</p>
<h2>3. Cross platform</h2>
<p>With Cake, you can start <strong>building</strong> your software <strong>in multiple platforms</strong>.</p>
<p>If in your team, there are elements working with different operating systems, with Cake <strong>everyone can be working in the same build script</strong>.</p>
<h2>4. Agnostic from Build Server</h2>
<p>With Cake you can easily <strong>move your scripts from one Build system to another</strong>, without need to completely reconfigure the complete Build.</p>
<p>The best proof of this: Cake is building Cake with Cake in multiple build servers (<a href="https://github.com/cake-build/cake">see it in the Continuous integration section</a>).</p>
<h2>5. Healthy community</h2>
<p>The Cake community is really active.</p>
<p>Cake has a huge list of Addins delivered and maintained by the community.</p>
<p>Also, since 2016 Cake is part of the .NET Foundation.</p>
<hr>
<p><em>I hope that this helps you (and convinced your boss).</em></p>
Tuga IT - Build Automation? It's a piece of Cake2017-05-23T00:00:00-00:00https://guiferreira.me/archive/2017/05/tugait-build-automation-its-a-piece-of-cake/<p>It was a huge privilege to share my experience with <a href="http://cakebuild.net/">Cake Build</a> at <a href="http://tugait.pt/2017/">Tuga IT</a>.</p>
<p>You can find here the slides and demos that have been used, as well as some references related to the theme.</p>
<p>If you have any doubt please leave a comment below.</p>
<ul>
<li>Slides: <a href="https://docs.com/gsferreira/7912/build-automation-its-a-piece-of-cake">docs.com</a></li>
<li>Demos: <a href="https://github.com/gsferreira/cakedemo">GitHub - CakeDemo</a></li>
</ul>
<p>References:</p>
<ul>
<li><a href="http://tugait.pt/2017/sessions/build-automation-its-a-piece-of-cake/">Session description</a></li>
<li><a href="http://cakebuild.net/">Cake Build website</a></li>
<li><a href="https://github.com/cake-build/cake">Cake Build Github Repository</a></li>
<li><a href="https://hanselminutes.com/548/cake-build-a-c-make-cross-platform-build-automation-system-with-patrik-svensson">Hanselminutes Poadcast</a></li>
<li><a href="http://radiotfs.com/Show/126/CakeByDevsForDevs">Radio TFS Poadcast</a></li>
<li><a href="https://www.dotnetrocks.com/?show=1321">.NET Rocks Poadcast - Understanding Cake with Gary Ewan Park</a></li>
<li><a href="https://github.com/cake-build/frosting">Cake Frosting Github Repository</a></li>
</ul>
Adding Custom Arguments to Topshelf2016-12-07T00:00:00-00:00https://guiferreira.me/archive/2016/12/adding-custom-arguments-to-topshelf/<p><a href="http://topshelf-project.com/">Topshelf</a> is an amazing framework that let you easily host and build Windows services.</p>
<p>Topshelf is really extensible, but recently I struggled to find how to configure a custom argument to the service.</p>
<p>This post is simple tip to help you create custom arguments to a <a href="http://topshelf-project.com/">Topshelf</a> service and use it in the command line.</p>
<p>This can be accomplished simply using the Host Configurations.</p>
<p>If you use the method <em>"AddCommandLineDefinition"</em> you will be able to specify the name of your argument (case sensitive) and how you want to use it.</p>
<p>You can find here a simple example.</p>
<script src="https://gist.github.com/gsferreira/615526c3b10fbefcc49caaa4dafed57e.js"></script>
<p>Then you can execute your service sending your argument as you can see in the following example (command line invoke).</p>
<pre><code> .\TopShelfCustomArgs.exe run -path:"c:\temp" -frequency:2
</code></pre>
<p>Hope this helps.</p>
Create a Web Deployment Package with Cake Build2016-11-04T00:00:00-00:00https://guiferreira.me/archive/2016/11/create-a-web-deployment-package-with-cake-build/<p>This is simple tip to help you create Web Deployment Packages with <a href="http://cakebuild.net/">Cake</a>.</p>
<p>If you have a ASP.NET project and you want to create a Web Deployment package using Cake, you just need to use the MSBUILD Command with the right arguments.</p>
<p>Feel free to copy the following command and paste it in a Task from your Cake file.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token function">MSBuild</span><span class="token punctuation">(</span><span class="token string">"PROJECT_NAME.csproj"</span><span class="token punctuation">,</span> settings <span class="token operator">=></span><br> settings<span class="token punctuation">.</span><span class="token function">SetConfiguration</span><span class="token punctuation">(</span>configuration<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">UseToolVersion</span><span class="token punctuation">(</span>MSBuildToolVersion<span class="token punctuation">.</span>VS2015<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithTarget</span><span class="token punctuation">(</span><span class="token string">"Package"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithProperty</span><span class="token punctuation">(</span><span class="token string">"VisualStudioVersion"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">{</span><span class="token string">"14.0"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithProperty</span><span class="token punctuation">(</span><span class="token string">"PackageLocation"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">{</span> packageDir<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithProperty</span><span class="token punctuation">(</span><span class="token string">"PackageTempRootDir"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">{</span><span class="token string">"root"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Here an example of a complete script (<em>build.cake</em>).</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> target <span class="token operator">=</span> <span class="token function">Argument</span><span class="token punctuation">(</span><span class="token string">"target"</span><span class="token punctuation">,</span> <span class="token string">"Default"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> configuration <span class="token operator">=</span> <span class="token function">Argument</span><span class="token punctuation">(</span><span class="token string">"configuration"</span><span class="token punctuation">,</span> <span class="token string">"Release"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> packageDir <span class="token operator">=</span> <span class="token function">MakeAbsolute</span><span class="token punctuation">(</span><span class="token function">Directory</span><span class="token punctuation">(</span><span class="token string">"./package"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">Information</span><span class="token punctuation">(</span><span class="token string">"BUILD DIR:"</span> <span class="token operator">+</span> packageDir<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">Task</span><span class="token punctuation">(</span><span class="token string">"Default"</span><span class="token punctuation">)</span><br><span class="token punctuation">.</span><span class="token function">Does</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span><br><span class="token punctuation">{</span><br> <span class="token function">MSBuild</span><span class="token punctuation">(</span><span class="token string">"PROJECT_NAME.csproj"</span><span class="token punctuation">,</span> settings <span class="token operator">=></span><br> settings<span class="token punctuation">.</span><span class="token function">SetConfiguration</span><span class="token punctuation">(</span>configuration<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">UseToolVersion</span><span class="token punctuation">(</span>MSBuildToolVersion<span class="token punctuation">.</span>VS2015<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithTarget</span><span class="token punctuation">(</span><span class="token string">"Package"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithProperty</span><span class="token punctuation">(</span><span class="token string">"VisualStudioVersion"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">{</span><span class="token string">"14.0"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithProperty</span><span class="token punctuation">(</span><span class="token string">"PackageLocation"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">{</span> packageDir<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">WithProperty</span><span class="token punctuation">(</span><span class="token string">"PackageTempRootDir"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">{</span><span class="token string">"root"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token function">RunTarget</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Hope this helps.</p>
NetPonto - Como construir software altamente eficiente com CQRS2016-09-19T00:00:00-00:00https://guiferreira.me/archive/2016/09/pt-netponto-como-construir-software-altamente-eficiente-com-cqrs/<p>Esta semana tive a oportunidade de falar um pouco sobre a minha experiência com CQRS na Comunidade NetPonto.</p>
<p>Se não tiveste a oportunidade de assistir, coloco aqui os slides, o vídeo da sessão, bem como algumas referências sobre o tema.</p>
<p>Alguma dúvida que tenhas, deixa um comentário.</p>
<p>Video: <a href="https://youtu.be/pM8GycDZji4?t=5614">Youtube</a></p>
<p>Slides: <a href="http://www.slideshare.net/GuilhermeFerreira114/como-construir-software-altamente-eficiente-com-cqrs">SlideShare</a></p>
<p>Referências:</p>
<ul>
<li><a href="https://msdn.microsoft.com/en-us/library/jj554200.aspx">CQRS Journey</a></li>
<li><a href="https://www.youtube.com/watch?v=JHGkaShoyNs">Greg Young - CQRS and Event Sourcing - Code on the Beach 2014</a></li>
<li><a href="http://www.dotnetrocks.com/?show=639">.NET Rocks - Udi Dahan Clarifies CQRS</a></li>
<li><a href="http://www.dotnetrocks.com/?show=1044">.NET Rocks - CQRS Update with Udi Dahan</a></li>
<li><a href="http://www.dotnetrocks.com/?show=820">.NET Rocks - Udi Dahan Talks CQRS, Agile and More</a></li>
<li><a href="https://lostechies.com/jimmybogard/2012/06/26/eventual-consistency-cqrs-and-interaction-design/">Eventual consistency, CQRS and interaction design - LosTechies</a></li>
<li><a href="https://lostechies.com/jimmybogard/2016/06/01/cqrs-and-rest-the-perfect-match">CQRS and REST: the perfect match - LosTechies</a></li>
<li><a href="http://martinfowler.com/bliki/CQRS.html">CQRS - Martin Fowler</a></li>
<li><a href="https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf">CQRS Documents by Greg Young</a></li>
</ul>
<p><img src="https://guiferreira.me/images/pt-netponto-como-construir-software-altamente-eficiente-com-cqrs.jpg" alt="netponto 20160919"></p>
Azure WebJobs dependency injection with Unity2016-08-08T00:00:00-00:00https://guiferreira.me/archive/2016/08/azure-webjobs-dependency-injection-with-unity/<p>In the early days of <strong>Azure WebJobs</strong> use <strong>Dependency Injection</strong> was a little bit tricky because the Triggered methods were only static methods.</p>
<p>Since the WebJobs SDK 1.0.1 you are no longer limited to static methods and that can change how you approach Dependency Injection on WebJobs.</p>
<p>In this blog post I will show how you can use <strong><a href="https://github.com/unitycontainer/unity">Unity</a></strong> to inject dependencies into your WebJobs.</p>
<h2>Setup dependency injection</h2>
<p><em>In this post I'm assuming you already know how to set up a <a href="https://azure.microsoft.com/en-gb/documentation/articles/websites-dotnet-webjobs-sdk-get-started/">WebJob</a>.</em></p>
<p>The first step is to install the Unity Package in your project.</p>
<pre class="language-text"><code class="language-text">Install-Package Unity</code></pre>
<p>Then, we will need to implement the <strong>IJobActivator</strong> Interface, that accepts a Unity container. Here, we will provide the capabilitie of resolve the Instances using the Unity container.</p>
<p>Let's name the class as <strong>"UnityJobActivator"</strong> and fill it with the following code:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UnityJobActivator</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IJobActivator</span></span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">IUnityContainer</span> _container<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token function">UnityJobActivator</span><span class="token punctuation">(</span><span class="token class-name">IUnityContainer</span> container<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _container <span class="token operator">=</span> container<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">T</span> <span class="token generic-method"><span class="token function">CreateInstance</span><span class="token generic class-name"><span class="token punctuation"><</span>T<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> _container<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token generic class-name"><span class="token punctuation"><</span>T<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>As you can see, the <strong>UnityJobActivator</strong> receives in the constructor the Unity Container. Now let's setup the container.</p>
<p><em>I like to use a Unity Configuration Class to organize my Unity configurations.</em></p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UnityConfig</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">Lazy<span class="token punctuation"><</span>IUnityContainer<span class="token punctuation">></span></span> container <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Lazy<span class="token punctuation"><</span>IUnityContainer<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> container <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">UnityContainer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token function">RegisterTypes</span><span class="token punctuation">(</span>container<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> container<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name">IUnityContainer</span> <span class="token function">GetConfiguredContainer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> container<span class="token punctuation">.</span>Value<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">RegisterTypes</span><span class="token punctuation">(</span><span class="token class-name">IUnityContainer</span> container<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> container<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">RegisterType</span><span class="token generic class-name"><span class="token punctuation"><</span>IMailService<span class="token punctuation">,</span> MailService<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">HierarchicalLifetimeManager</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>Now that we have the container defined, we can specify the <strong>JobActivator</strong> that the WebJob should use.</p>
<p>It can be accomplished using the Job Host Configuration (this is done in <em>Program.cs</em> in the main method), as you can see in the following code:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name">JobHostConfiguration</span> config <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">JobHostConfiguration</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> JobActivator <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">UnityJobActivator</span><span class="token punctuation">(</span>UnityConfig<span class="token punctuation">.</span><span class="token function">GetConfiguredContainer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> host <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">JobHost</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span><br>host<span class="token punctuation">.</span><span class="token function">RunAndBlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Finally, open your functions, transform them in non static methods and receive the parameter of the type you want in the constructor.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Functions</span><br><span class="token punctuation">{</span><br> <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">IMailService</span> _mailService<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token function">Functions</span><span class="token punctuation">(</span><span class="token class-name">IMailService</span> mailService<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _mailService <span class="token operator">=</span> mailService<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ProcessQueueMessage</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">QueueTrigger</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"queue"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span> <span class="token class-name"><span class="token keyword">string</span></span> message<span class="token punctuation">,</span> <span class="token class-name">TextWriter</span> log<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> _mailService<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span><br> log<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p>I hope that this helps you.</p>
The shining new C# Scripting API2016-02-03T00:00:00-00:00https://guiferreira.me/archive/2016/02/the-shining-new-csharp-scripting-api/<p><strong>Say hello to the new Scripting Language: C#!</strong></p>
<p>Since the first days the .NET platform lacks scripting capabilities compared to dynamic languages like JavaScript or Ruby, but those days are over.</p>
<p>Why this is awesome?! If you are familiar with the capabilities that VBA brings the Office users and how many "Excel VBA Programming" books were sold to non developers, you will understand why.
And it's <a href="https://github.com/dotnet/roslyn/tree/master/src/Scripting">open source</a>!!!</p>
<p>In the past few years we have been following the growing of the new .NET Compiler, commonly known as Roslyn.</p>
<p>One of the great features of Roslyn is the Scripting API. The scripting API can enable applications to evaluate code at runtime providing the API to implement an excellent scripting experience.</p>
<p>In December Microsoft finally released the Roslyn version 1.1.1 (stable version) in nuget that includes the Scripting API (that has been removed from Roslyn 1.0 release by the team).</p>
<p>Here you can find some examples of how to use the scripting API and what you can do with it.</p>
<h2>How to start</h2>
<p>Install the nuget Scripting package (<a href="http://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp.Scripting/">Microsoft.CodeAnalysis.CSharp.Scripting</a>) in your project.</p>
<p>In the following example I used the version 1.1.1.</p>
<pre class="language-text"><code class="language-text">Install-Package Microsoft.CodeAnalysis.CSharp.Scripting -Version 1.1.1</code></pre>
<h2>Expression evaluation</h2>
<p>Evaluate the result of an C# expression.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">object</span></span> result <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span><br><br>CSharpScript<span class="token punctuation">.</span><span class="token function">EvaluateAsync</span><span class="token punctuation">(</span><span class="token string">"System.DateTime.Today.Year"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> result <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span>DateTime<span class="token punctuation">.</span>Today<span class="token punctuation">.</span>Year<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Expression evaluation with strong type</h2>
<p>Evaluate an expression with an expected result type.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br><br>CSharpScript<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">EvaluateAsync</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">int</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"100 * 2"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> result <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Evaluation with parameters</h2>
<p>Send parameters to the expression and use them in the script logic.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Globals</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> NumberOfStudents<span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> StudentsPerClass<span class="token punctuation">;</span><br><span class="token punctuation">}</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> globals <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Globals</span> <span class="token punctuation">{</span> NumberOfStudents <span class="token operator">=</span> <span class="token number">80</span><span class="token punctuation">,</span> StudentsPerClass <span class="token operator">=</span> <span class="token number">15</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br>CSharpScript<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">EvaluateAsync</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">int</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"NumberOfStudents/StudentsPerClass"</span><span class="token punctuation">,</span> <span class="token named-parameter punctuation">globals</span><span class="token punctuation">:</span> globals<span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> result <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span>globals<span class="token punctuation">.</span>NumberOfStudents <span class="token operator">/</span> globals<span class="token punctuation">.</span>StudentsPerClass<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Build a script and run it multiple times</h2>
<p>The scripting API enables you to create an expression and then use it multiple times, removing the compile time of the remaining evaluations.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> script <span class="token operator">=</span> CSharpScript<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Create</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">decimal</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"NumberOfStudents/StudentsPerClass"</span><span class="token punctuation">,</span> <span class="token named-parameter punctuation">globalsType</span><span class="token punctuation">:</span> <span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token type-expression class-name">Globals</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>script<span class="token punctuation">.</span><span class="token function">Compile</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><br><span class="token punctuation">{</span><br> script<span class="token punctuation">.</span><span class="token function">RunAsync</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">Globals</span> <span class="token punctuation">{</span> NumberOfStudents <span class="token operator">=</span> i<span class="token punctuation">,</span> StudentsPerClass <span class="token operator">=</span> <span class="token number">5</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span><br> Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span>i <span class="token operator">/</span> <span class="token number">5</span><span class="token punctuation">,</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">.</span>ReturnValue<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2>References</h2>
<p>The script can use references to other assemblies with a simple instruction.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">string</span></span> result <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span><br><br>CSharpScript<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">EvaluateAsync</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">string</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"System.Configuration.ConfigurationManager.AppSettings[\"MyValue\"].ToString()"</span><span class="token punctuation">,</span><br>ScriptOptions<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">WithReferences</span><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token type-expression class-name">System<span class="token punctuation">.</span>Configuration<span class="token punctuation">.</span>ConfigurationManager</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Assembly<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> result <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span>ConfigurationManager<span class="token punctuation">.</span>AppSettings<span class="token punctuation">[</span><span class="token string">"MyValue"</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Imports</h2>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br>CSharpScript<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">EvaluateAsync</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">int</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"DateTime.Today.Year"</span><span class="token punctuation">,</span><br>ScriptOptions<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">WithImports</span><span class="token punctuation">(</span><span class="token string">"System"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> result <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span>DateTime<span class="token punctuation">.</span>Today<span class="token punctuation">.</span>Year<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Dynamic Support</h2>
<p>To use dynamic objects in scripts we need to add a reference to the <em>System.Code</em>, <em>Microsoft.CSharp</em> and <em>System.Dynamic</em>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">int</span></span> result <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br><br>CSharpScript<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">EvaluateAsync</span><span class="token generic class-name"><span class="token punctuation"><</span><span class="token keyword">int</span><span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">@"<br> dynamic value = 30;<br> return value;"</span><span class="token punctuation">,</span><br>ScriptOptions<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">WithImports</span><span class="token punctuation">(</span><span class="token string">"System.Dynamic"</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">AddReferences</span><span class="token punctuation">(</span><br> Assembly<span class="token punctuation">.</span><span class="token function">GetAssembly</span><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token type-expression class-name">System<span class="token punctuation">.</span>Dynamic<span class="token punctuation">.</span>DynamicObject</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// System.Code</span><br> Assembly<span class="token punctuation">.</span><span class="token function">GetAssembly</span><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token type-expression class-name">Microsoft<span class="token punctuation">.</span>CSharp<span class="token punctuation">.</span>RuntimeBinder<span class="token punctuation">.</span>CSharpArgumentInfo</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// Microsoft.CSharp</span><br> Assembly<span class="token punctuation">.</span><span class="token function">GetAssembly</span><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token type-expression class-name">System<span class="token punctuation">.</span>Dynamic<span class="token punctuation">.</span>ExpandoObject</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// System.Dynamic</span><br> <span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> result <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span><span class="token number">30</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2>Access to script variables</h2>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> globals <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Globals</span> <span class="token punctuation">{</span> NumberOfStudents <span class="token operator">=</span> <span class="token number">80</span><span class="token punctuation">,</span> StudentsPerClass <span class="token operator">=</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br><span class="token class-name">ScriptState</span> state <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span><br><br>CSharpScript<span class="token punctuation">.</span><span class="token function">RunAsync</span><span class="token punctuation">(</span><span class="token string">@"<br> bool shouldOpenClass = NumberOfStudents >= StudentsPerClass;<br> int numberOfClasses = NumberOfStudents/StudentsPerClass;<br>"</span><span class="token punctuation">,</span> <span class="token named-parameter punctuation">globals</span><span class="token punctuation">:</span> globals<span class="token punctuation">)</span><br><span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>s <span class="token operator">=></span> state <span class="token operator">=</span> s<span class="token punctuation">.</span>Result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> state<span class="token punctuation">.</span><span class="token function">GetVariable</span><span class="token punctuation">(</span><span class="token string">"shouldOpenClass"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Value<span class="token punctuation">)</span><span class="token punctuation">;</span><br>Assert<span class="token punctuation">.</span><span class="token function">AreEqual</span><span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">,</span> state<span class="token punctuation">.</span><span class="token function">GetVariable</span><span class="token punctuation">(</span><span class="token string">"numberOfClasses"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Value<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Those are just a few examples and I recommend you check out the <a href="https://github.com/dotnet/roslyn">Roslyn Github Repository</a>.</p>
Is CQRS too complicated? No!2015-11-09T00:00:00-00:00https://guiferreira.me/archive/2015/11/is-cqrs-too-complicated-no/<p>How do you feel after reading a few articles about CQRS (Command Query Responsibility Segregation)? Confused?!</p>
<p>The good news is that's not your problem.</p>
<p>CQRS is a simple concept, but usually is presented side by side with other patterns creating the perception that CQRS requires a ton of elements to work.</p>
<p>This post pretends to demonstrate that CQRS can be a simple concept that can evolve according to your needs.</p>
<h2>So, what is CQRS?</h2>
<p>The roots of CQRS are based on <a href="https://en.wikipedia.org/wiki/Command%E2%80%93query_separation">Command-query separation (CQS)</a> a principle created by <a href="https://en.wikipedia.org/wiki/Bertrand_Meyer">Bertrand Meyer</a> during the development of Eiffel programming language.</p>
<p>Meyer states that <em>"Asking a question should not change the answer"</em> and that's the foundation of CQRS.</p>
<p>We can conclude from that statement that a command is any method that creates, update or delete data, and a query is any method that returns data.</p>
<p>CQRS is an evolution of CQS, going further with the initial concept and stating that Read and Write models should be distinct.</p>
<p><strong>CQRS is simply that</strong>, is the segregation of two main responsibilities, the responsibility of read data and the responsibility of mutate data.</p>
<p>Don't you recognize this principles? "Denormalization", cache systems, read-optimized databases and others, are proof that the industry is already thinking in the problems CQRS want's to solve.</p>
<p><img src="https://guiferreira.me/images/is-cqrs-too-complicated-no-diagram.png" alt="Diagram CQRS"></p>
<p>It's important to say that there's nothing in CQRS saying that we should use Event Sourcing, Service Bus or another element to implement CQRS.
Those patterns or technologies are usually presented with CQRS, adding a new layer of complexity to CQRS.</p>
<blockquote>
<p>Nothing about CQRS says “you shalt use NServiceBus”. It’s just not there. You’re merely separating infrastructure between handling commands and queries, but the how is quite varied.</p>
<p><em><a href="https://lostechies.com/jimmybogard/2012/08/22/busting-some-cqrs-myths/">Jimmy Bogard</a></em></p>
</blockquote>
<h2>CQRS Benefits</h2>
<p>*All the following benefits are capabilities that CQRS gives you, but <strong>they aren't required to implement CQRS*</strong></p>
<p><strong>Simple Queries</strong></p>
<p>Because the Read model is different from the Write model, it's possible to create simpler queries and with better performance. If the Read and the Write model are shared, you will constrain the Queries to the Write structure.</p>
<p>The system will also benefit of a thinner Read layer.</p>
<blockquote>
<p>Simple code is fast code</p>
<p><em><a href="http://udidahan.com/2009/12/09/clarified-cqrs/">Udi Dahan</a></em></p>
</blockquote>
<p><strong>Separate data store</strong></p>
<p>Since the Read model is separate, you are able to segregate the database, querying a non relational database optimized for queries.</p>
<p>That will lead us to concepts like Eventual Consistency or Event Sourcing, but it's important to say that CQRS doesn't require this, he just enables the capability.</p>
<p><strong>It's perfectly possible to implement CQRS using the same data store.</strong></p>
<blockquote>
<p>Event sourcing is a completely orthogonal concept to CQRS. While they fit well together, doing CQRS does not require event sourcing, and doing event sourcing does not automatically mean we’re doing CQRS.</p>
<p><em><a href="https://lostechies.com/jimmybogard/2012/08/22/busting-some-cqrs-myths/">Jimmy Bogard</a></em></p>
</blockquote>
<p><strong>Queued workload</strong></p>
<p>Commands can be processed using a queue, enabling an asynchronous command processing, what can be useful to deal with complex processing or manage the system load.</p>
<p><strong>Segregate load</strong></p>
<p>Typically the number of queries in a system is much higher than the number of commands. So, why should both be based on the same technologies?</p>
<p>CQRS enables the segregation of the Load, with the possibility of use a different host for each part of system.</p>
<blockquote>
<p>The largest possible benefit though is that it recognizes that their are different architectural properties when dealing with commands and queries … for example it allows us to host the two services differently eg: we can host the read service on 25 servers and the write service on two</p>
<p><em><a href="http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/">Greg Young</a></em></p>
</blockquote>
<h2>Challenges</h2>
<p>CQRS isn't just benefits. CQRS implies complexity and a new mindset when using it.</p>
<p>Usually we are formatted to think in CRUD operations, but with CQRS we're led to a Task-based system. We need to rethink the UI to be based on tasks and to deal with the eventual consistency (if we need it).</p>
<p>I can't say that CQRS fits all the cases or is a tool that you should use always. What I can say is that's an important tool to have in mind when dealing with some complex problems.</p>
<p>It's important to remember that you should start simple and CQRS enables you to adjust and evolve if you need it.</p>
<p>Don't try to do all upfront.</p>
Use T4 as email template in 6 steps2015-10-23T00:00:00-00:00https://guiferreira.me/archive/2015/10/use-t4-as-email-template-in-6-steps/<p>When you want to send emails from .net applications how do you do it?</p>
<p>Do you create an instance of StringBuilder and start adding texts?!</p>
<p>And when you want to format the body as HTML? How do you do it?! A bigger string?!</p>
<p>And if you could write your templates as plain text and still be capable to inject values like names, dates or other values?
The good news is that you can and you have a good old friend to help you: <strong>T4 Templates</strong>.</p>
<p>Let's see how to do it.</p>
<p><strong>1. Open your project and add a template</strong></p>
<p>Right click in your project and go to the option "Add > New Item", select the "Runtime Text Template" and name it <strong>("WelcomeMail.tt" for example)</strong>.</p>
<p><img src="https://guiferreira.me/images/use-t4-as-email-template-in-6-steps-create-t4-template.png" alt="Create T4 Templates"></p>
<p><strong>2. Create your text template</strong></p>
<p>Open the template (<strong>.tt file</strong>) and write your email with all the HTML formatting that you want.
<em>Find an Html Mail template example <a href="https://github.com/leemunroe/responsive-html-email-template">here</a></em></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>#@</span> <span class="token attr-name">template</span> <span class="token attr-name">language</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>C#<span class="token punctuation">"</span></span> <span class="token attr-name">#</span><span class="token punctuation">></span></span> <br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>#@</span> <span class="token attr-name">assembly</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>System.Core<span class="token punctuation">"</span></span> <span class="token attr-name">#</span><span class="token punctuation">></span></span> <br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>#@</span> <span class="token attr-name">import</span> <span class="token attr-name">namespace</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>System.Linq<span class="token punctuation">"</span></span> <span class="token attr-name">#</span><span class="token punctuation">></span></span> <br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>#@</span> <span class="token attr-name">import</span> <span class="token attr-name">namespace</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>System.Text<span class="token punctuation">"</span></span> <span class="token attr-name">#</span><span class="token punctuation">></span></span> <br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>#@</span> <span class="token attr-name">import</span> <span class="token attr-name">namespace</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>System.Collections.Generic<span class="token punctuation">"</span></span> <span class="token attr-name">#</span><span class="token punctuation">></span></span><br><br><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span> <span class="token name">PUBLIC</span> <span class="token string">"-//W3C//DTD XHTML 1.0 Strict//EN"</span> <span class="token string">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/1999/xhtml<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Content-Type<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text/html; charset=utf-8<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><br> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">width</span><span class="token punctuation">:</span>100%<span class="token punctuation">;</span> <span class="token property">margin</span><span class="token punctuation">:</span>0<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span>0<span class="token punctuation">;</span> <span class="token property">-webkit-text-size-adjust</span><span class="token punctuation">:</span>100%<span class="token punctuation">;</span> <span class="token property">-ms-text-size-adjust</span><span class="token punctuation">:</span>100%<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><br> <span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>strong</span><span class="token punctuation">></span></span>Hello!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>strong</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><br> Lorem ipsum dolor sit amet, congue appareat cum ne. Sit postea mediocrem<br> an, erat dissentiet est an. Eu est eius veri assum, et nam sonet molestiae<br> urbanitas. Cu minim cetero nam, utamur accumsan ius in. Est et sint<br> quaestio, cu his primis invenire rationibus.<br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><br> Cibo senserit mnesarchum qui te, sonet ceteros evertitur ad ius, an eam<br> autem mediocrem scribentur. In esse vero sapientem eos, modus consequuntur<br> sit ei, ius et sale fabulas. Te populo commodo gubergren sed, pri autem<br> discere in, accumsan antiopam an usu. Per viris veniam prompta et. In est<br> quas virtute, mea accumsan invidunt id, usu ad cibo justo imperdiet.<br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre>
<p><strong>3. Create variables to use into the template</strong></p>
<p>First you need to create a partial class for the T4 template that you created in the step 2.</p>
<p>In your partial add a property for each value that you want to inject into the template (destination email or signature for example).</p>
<p>Create a constructor to initialize the properties that you have created.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Net<span class="token punctuation">.</span>Mail</span><span class="token punctuation">;</span><br><br><span class="token keyword">namespace</span> <span class="token namespace">MailT4Template</span><br><span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">WelcomeMail</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">MailAddress</span> To <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token keyword">public</span> <span class="token function">WelcomeMail</span><span class="token punctuation">(</span><span class="token class-name">MailAddress</span> to<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">this</span><span class="token punctuation">.</span>To <span class="token operator">=</span> to<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><br><span class="token punctuation">}</span></code></pre>
<p><strong>4. Adapt the template to use the injected values</strong></p>
<p>Just open a C# block code with the tags <strong><#</strong> and <strong>#></strong> and use the equal operator to get the variable value.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>strong</span><span class="token punctuation">></span></span>Hello <#= To.DisplayName #>!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>strong</span><span class="token punctuation">></span></span></code></pre>
<p><strong>5. Transform the text template</strong></p>
<p>Invoke the template with the parameters to get the transformed text.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> to <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MailAddress</span><span class="token punctuation">(</span><span class="token string">"luke@starwars.com"</span><span class="token punctuation">,</span> <span class="token string">"Luke"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name">WelcomeMail</span> mailTemplate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">WelcomeMail</span><span class="token punctuation">(</span>to<span class="token punctuation">)</span><span class="token punctuation">;</span><br>mailTemplate<span class="token punctuation">.</span><span class="token function">TransformText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>6. Compose your email</strong></p>
<p>Use the transformed text and send the email.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="token class-name"><span class="token keyword">var</span></span> from <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MailAddress</span><span class="token punctuation">(</span><span class="token string">"mail@mail.com"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> to <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MailAddress</span><span class="token punctuation">(</span><span class="token string">"luke@starwars.com"</span><span class="token punctuation">,</span> <span class="token string">"Luke"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name">WelcomeMail</span> mailTemplate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">WelcomeMail</span><span class="token punctuation">(</span>to<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><span class="token class-name"><span class="token keyword">var</span></span> mail <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MailMessage</span><span class="token punctuation">(</span>from<span class="token punctuation">,</span> to<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SmtpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>client<span class="token punctuation">.</span>Port <span class="token operator">=</span> <span class="token number">587</span><span class="token punctuation">;</span><br>client<span class="token punctuation">.</span>DeliveryMethod <span class="token operator">=</span> SmtpDeliveryMethod<span class="token punctuation">.</span>Network<span class="token punctuation">;</span><br>client<span class="token punctuation">.</span>UseDefaultCredentials <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br>client<span class="token punctuation">.</span>EnableSsl <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br>client<span class="token punctuation">.</span>Credentials <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">NetworkCredential</span><span class="token punctuation">(</span><span class="token string">"admin@mail.com"</span><span class="token punctuation">,</span><span class="token string">"UseTheForce#"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>client<span class="token punctuation">.</span>Host <span class="token operator">=</span> <span class="token string">"mail.mail.com"</span><span class="token punctuation">;</span><br><br>mail<span class="token punctuation">.</span>Subject <span class="token operator">=</span> <span class="token string">"This is a welcom email."</span><span class="token punctuation">;</span><br>mail<span class="token punctuation">.</span>IsBodyHtml <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br>mail<span class="token punctuation">.</span>Body <span class="token operator">=</span> mailTemplate<span class="token punctuation">.</span><span class="token function">TransformText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>client<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>mail<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>I hope that this helps you.</p>
Using Trello to manage your Wine Cellar2015-10-09T00:00:00-00:00https://guiferreira.me/archive/2015/10/using-trello-to-manage-your-wine-cellar/<p>Do you have a wine cellar at home?!</p>
<p>Nothing too big, but the sufficient number of bottles to lose control?!</p>
<p>Do you really know what you have in your cellar?</p>
<p>This post wants to help you solve those problems, and manage your home cellar with an amazing and free tool.</p>
<p>As a good Portuguese, I have a small wine cellar at home, where I store the excellent wines that we produce at Portugal.</p>
<p><img src="https://guiferreira.me/images/using-trello-to-manage-your-wine-cellar-cellar1.jpg" alt="Wine botle"></p>
<p>I don't have many wine bottles, but I struggled with some questions that I can't answer:</p>
<ol>
<li>When I go to the supermarket, how do I know if I need to buy white or red wine?</li>
<li>How to remember to buy a specific wine?</li>
<li>Which are the oldest bottles?</li>
<li>How to choose a bottle?</li>
</ol>
<p>The conclusion was simple, <strong>I need a system to manage it</strong>.</p>
<p>As you probably know, I'm a huge fan of Trello and I trusted him to do the job.
If you don't know <a href="https://trello.com/">Trello.com</a> you have here a description:</p>
<blockquote>
<p><em>"<a href="https://trello.com/">Trello.com</a> is a collaboration tool that organizes your projects into boards. In one glance, Trello tells you what's being worked on, who's working on what, and where something is in a proces"</em></p>
</blockquote>
<p><strong>How I did it?</strong></p>
<p>I brought some <strong>stickers, where I wrote letters</strong> to name the columns <strong>and numbers</strong> to stick in the rows.</p>
<p>Now I can organize the bottles with the combination, for instance A1, C6, etc.</p>
<p><img src="https://guiferreira.me/images/using-trello-to-manage-your-wine-cellar-cellar2.jpg" alt="Wine cellar"></p>
<p>Then I created a <strong>Trello board</strong> for my wine cellar where I added <strong>4 lists</strong>:</p>
<ul>
<li><strong>To Buy:</strong> Where I add a card for each bottle that I want/need to buy;</li>
<li><strong>White Wine:</strong> The bottles of White Wine;</li>
<li><strong>Red Wine:</strong> The bottles of Red Wine;</li>
<li><strong>Port Wine:</strong> As a good Portuguese and as a Douro and Oporto lover, I have some bottles of Port Wine.</li>
</ul>
<p>You can add more columns according to the Wine or another alcoholic drinks that you have.</p>
<p>Then I created a <strong>card for each bottle</strong>. I named the card <strong>with the bottle name and the slot</strong> where I stored the wine.
For example: "Kopke, Douro 2012 - E9" where "Kopke, Douro 2012" stands for the name and the region of the wine and "E9" stands for the slot where the bottle is.;</p>
<p>In each card you can also place a photo to identify the bottle if you want.</p>
<p><img src="https://guiferreira.me/images/using-trello-to-manage-your-wine-cellar-trello-1.png" alt="Board"></p>
<p>I also like to categorize the wines with labels to add some metadata to help me choose a bottle when I need.
For instance, you can create labels with price groups or a rating that you use to categorize the wine.</p>
<p><img src="https://guiferreira.me/images/using-trello-to-manage-your-wine-cellar-trello-2.png" alt="Final result"></p>
<p><img src="https://guiferreira.me/images/using-trello-to-manage-your-wine-cellar-cellar3.jpg" alt="Final result"></p>
<p>I hope that this helps you.</p>
7th Meeting of NetPonto Community in Oporto2015-09-18T00:00:00-00:00https://guiferreira.me/archive/2015/09/7th-meeting-of-netponto-community-in-oporto/<p>We are bringing to Oporto the 7th Meeting of NetPonto Community.
The meeting will take place at Instituto Superior de Engenharia do Porto (ISEP) at 26 September 2015.</p>
<h2>Program</h2>
<p>09:45 - Check-in</p>
<p>10:00 - SOLR in .NET - Super Solid solution for a Super Fast Search - Pedro Neves Rosa</p>
<p>12:00 - The Future of Web Applications - ECMAScript vNext and others - Ricardo Brandão</p>
<p>13:30 - Closing Panel</p>
<h2>Venue</h2>
<p>Instituto Superior de Engenharia do Porto (ISEP) - Room H202</p>
<p>Rua Dr. António Bernardino de Almeida, 431</p>
<p>4200-072 Porto</p>
<p>Portugal</p>
<p><a href="https://www.google.pt/maps/place/ISEP,+4200-072+Porto/@41.1778457,-8.6081006,17z/data=!4m2!3m1!1s0xd246449b419e1c1:0x16a6fd2fcace4efe">Map</a></p>
<h2>Registration</h2>
<p>Free!</p>
<p>Registration: <a href="https://netponto-porto-setembro-2015.eventbrite.co.uk/">https://netponto-porto-setembro-2015.eventbrite.co.uk/</a></p>
Are you sure that Android is better than Windows Phone?2015-07-23T00:00:00-00:00https://guiferreira.me/archive/2015/07/are-you-sure-that-android-is-better-than-windows-phone/<p><strong>SPOILER ALERT</strong>: This text contains <strong>opinions</strong> from the author about smartphones.</p>
<h2>Confession</h2>
<p>I'm a huge fan of Windows Phone since the early days and I have been using it since 2011.
I followed the growing and I struggled with all the limitations in past years.</p>
<p>Until the last month I'd never used an Android Phone or an iPhone as my personal phones.
I've been playing with them in work or with family phones, and I have to honestly say that I never fall in love for them.
But I need to refer that I'm not a hater of them, I respect both Operating Systems.</p>
<p>I can see their pros and cons and I try to stay away from those fanboy discussions <em>(usually I'm the guy that they will make fun because for my friends I'm the only person in the country with a Windows Phone)</em>.</p>
<p><img src="https://guiferreira.me/images/are-you-sure-that-android-is-better-than-windows-phone-fun.jpg" alt="fun"></p>
<p>In the last month, I noticed that the camera button of my Nokia Lumia was a little loose and I decided that was time to send it to repair.
I needed a substitution phone and I decided to give a try to Android because <strong>I'm a kind of disappointed with the Nokia hardware quality</strong> and I was really <strong>curious to try a different operating system</strong>.
I've faced the experience with an open heart and really expecting to be surprised.</p>
<h2>Context</h2>
<p>I managed to get a Vodafone Prime 6, it's not a flagship product but it's a cool phone and I used it during a month.
Here I will explain <strong>what I loved in Android and what I missed from my Windows Phone</strong>.</p>
<p>_I want to point out that I won't compare hardware features. _</p>
<p><img src="https://guiferreira.me/images/are-you-sure-that-android-is-better-than-windows-phone-oh-you-have-an-android-phone-tell-me-again-how-much-better-than-an-iphone-it-is.jpg" alt="better phone"></p>
<hr>
<h2>What I loved</h2>
<p><strong>1. Meterial Design</strong>
I love minimalist design and all the flat design stuff. I really like the work done by google. All the simplicity, the amazing use of the depth and animations made me like Material Design.
<strong>2. Apps... Tons of Apps...</strong>
If you ask an Android fan how to do something he will reply to you "There's an App to do that!". This is a great resume of the main advantage of the platform comparing to Windows Phone.
I don't say that I like to 500 versions of angry birds or another useless apps in the Play Store, but I appreciate have the official version of some apps that I use every day like Trello, Pocket or Buffer.</p>
<hr>
<h2>What I really don't like</h2>
<p><strong>1. User Experience</strong>
As I said before, I'm a huge fan of Material Design and I think that he can be an important tool to improve the <strong>experience</strong>, but design isn't everything.
The applications have a lack of rules and patterns, even in the most popular apps.
For more than once I had to think <strong>"Where should I touch?"</strong> or <strong>"What should I do?"</strong> and those should be prohibited questions for a phone user.
Example: The following example shows three different cases where the main action button is in different places.</p>
<p><img src="https://guiferreira.me/images/are-you-sure-that-android-is-better-than-windows-phone-ux.png" alt="Compair UX"></p>
<p><strong>2. Opening notifications</strong></p>
<p>Push notifications are amazing and I can't live without them anymore but in Android I got a little confused.</p>
<p>The most annoying thing in Android notification system is open a notification... double touch doesn't seems natural, at least for me.</p>
<p><strong>3. Performance</strong></p>
<p>I installed more a less 8 applications, all them popular (Trello, Sunrise, Pocket, Feedly...) and the phone is constantly blocking.
The system simply doesn't react in a fashion time.
When a user touch to go to the main screen and nothing happens during 1 or 2 seconds the expirience is ruined.
<strong>NOTE</strong>: I know that my Android phone isn't a powerfull machine, so I'm <a href="http://smartphones.specout.com/compare/968-3120/Nokia-Lumia-630-vs-Vodafone-Smart-Prime-6">comparing him with the humble Nokia Lumia 630</a>.
<strong>4. Updates</strong>
I simply can't get it. I'm not able to figure out the updates that are available and how can I run them.
Sometimes I got a notification to update the app "X", another times I need to go to Play Store to do it...
The most annoying thing was one day that I saw that he was installing updates using my 3G data connection without asking for a confirmation. :O</p>
<hr>
<h2>What I missed from my Windows Phone</h2>
<p><strong>1. Tiles</strong>
Isn't amazing to know your next appointment, see the twitter/facebook updates or read part of e-mail without a single gesture?
Windows Phone users know what I mean. Android users will probably say "There's an app to do that". :)
<strong>2. People hub</strong></p>
<p>I really like the people hub and I missed so much the contact list navigation by the first letter.</p>
<p><img src="https://guiferreira.me/images/are-you-sure-that-android-is-better-than-windows-phone-wp-filter-contacts.png" alt="Navigation by letter"></p>
<p><strong>3. Account management</strong>
In android the accounts configuration is distributed and I'm a fan of that Windows Phone <strong>experience</strong> where you buy a phone, go to the Email and Accounts settings, add your accounts and your phone is ready to go.
<strong>4. Vertical scroll at the applications list</strong>
I'm not comfortable with the menu style of Android. Scroll horizontally between pages to get an application is not so productive as the Windows Phone vertical list.</p>
<hr>
<h2>Summary</h2>
<p>As I use to say, Android is a "hackable" (customizable if you prefer the word) version of IOS. With Android we can have a phone that give us <strong>freedom to do what we want</strong> and much cheaper than iPhone.</p>
<p>I <strong>won't say that Android is better or worst than Windows Phone</strong>, because they both have a role to play in this game.</p>
<p>If to you the most important thing are Apps and be able to play the new Candy Crush or Flappy Birds since the first day, I recommend you to go to Android.</p>
<p>If to you, like to me, the most important thing is the <strong>experience</strong>, so you should give a try to Windows Phone.</p>
<p>Users want apps and without apps you can't have users, but without users you will not have so many apps.</p>
<p>In the near future, I will keep my Windows Phone. I know that there are rumors about the platform that aren't cheerful for WP users, but I really believe in the platform and I hope that Microsoft too.</p>
<p>Feel free to leave comments.</p>
Reduce the path length of a Node.js project2015-07-09T00:00:00-00:00https://guiferreira.me/archive/2015/07/reduce-the-path-length-of-a-node-js-project/<p>Are you fighting with the path length of your Node.js projects?</p>
<p>If you are using Microsoft Visual Studio to development, I bet you do. If you don't, you will (this isn't any curse that I'm throwing at you)!</p>
<p>Windows has the "Maximum Path Length Limitation" that is terrible for Node.JS projects.</p>
<blockquote>
<p><em>"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."</em></p>
</blockquote>
<p>As you know, when you install a package in Node.js, the npm will place the dependencies under the package folder. This process is recursive for each package, so you can easily overcome the path length.</p>
<p>Unfortunately, there's no silver bullet to fix it (I'm not a Node.js guru, so please let me know if I'm wrong), but we can follow some tips to deal with it.</p>
<p><img src="https://guiferreira.me/images/reduce-the-path-length-of-your-node-js-project-dependencies-dependencies-everywhere.jpg" alt="dependencies everywhere"></p>
<h3>1. Azure Cloud Services - Change the output directory</h3>
<p>If you are getting an error when you publish your cloud service to azure, it's probably because the deployment will place the output into a subfolder.
I've already had <a href="https://guiferreira.me/archive/2014/11/azure-deploy-and-the-path-length-limitation/">blogged how to deal with it and you can find it here</a>.</p>
<h3>2. Find the packages that are leading you into the limit and install them</h3>
<p>Imagine that you install a package that has a dependency from <em>request</em> and that dependency made you overcome the path limit.
Go to the npm and install the package explicitly. Now, Node.js will not install the request in a subfolder of your first package.</p>
<pre><code> npm install request --save
</code></pre>
<h3>3. Remove dev packages</h3>
<p>Install the packages with the <em>"--production"</em> flag to remove all development only packages.</p>
<pre><code> npm install --production
</code></pre>
<h3>4. Remove duplicated packages</h3>
<p>Npm has a command that will find for you the duplicated dependencies and install them as top dependencies.
With a simple command you can simplify your dependency tree and reduce your project size.</p>
<pre><code> npm dedupe
</code></pre>
<p>Hope this helps. Feel free to leave comments and ask questions.</p>
6th Meeting of NetPonto Community in Oporto2015-06-29T00:00:00-00:00https://guiferreira.me/archive/2015/06/6th-meeting-of-netponto-community-in-oporto/<p>We are bringing to Oporto the 6th Meeting of NetPonto Community.
The meeting will take place at Instituto Superior de Engenharia do Porto (ISEP) at 11 July 2015.</p>
<h2>Program</h2>
<p>09:45 - Check-in</p>
<p>10:00 - ASP.NET VNext, now in Mac! - Bruno Lopes</p>
<p>12:00 - Building applications with Xamarin Forms - Rui Marinho</p>
<p>13:30 - Closing Panel</p>
<h2>Venue</h2>
<p>Instituto Superior de Engenharia do Porto (ISEP) - Room H202</p>
<p>Rua Dr. António Bernardino de Almeida, 431</p>
<p>4200-072 Porto</p>
<p>Portugal</p>
<p><a href="https://www.google.pt/maps/place/ISEP,+4200-072+Porto/@41.1778457,-8.6081006,17z/data=!4m2!3m1!1s0xd246449b419e1c1:0x16a6fd2fcace4efe">Map</a></p>
<h2>Registration</h2>
<p>Free!</p>
<p>Registration: <a href="https://netponto-porto-julho-2015.eventbrite.co.uk/">https://netponto-porto-julho-2015.eventbrite.co.uk/</a></p>
Create an API in Azure App Service - Revista PROGRAMAR Nº 492015-06-18T00:00:00-00:00https://guiferreira.me/archive/2015/06/create-an-api-in-azure-app-service-revista-programar-n49/<p><em>I had the pleasure of write an <a href="http://www.revista-programar.info/artigos/criar-uma-api-no-azure-app-sevice/">article</a> to the <a href="http://www.revista-programar.info/anuncios/revista-programar-no-49-junho-2015/">Revista PROGRAMAR</a>, a Portuguese collaborative magazine about programming. I’m glad with my first article for a magazine and especially because, I'm side by side with people that I admire like <a href="https://twitter.com/PauloMorgado">Paulo Morgado</a> or <a href="https://twitter.com/saramgsilva">Sara Silva</a>, for instance. This was an amazing experience and I want to share with you the result of it.</em></p>
<h2>Introduction</h2>
<p>In March, Microsoft announced an improvement in his services by introducing the new Azure App Service. This service covers the “oldest” Websites, now named as Web Apps, the Azure Mobile Services, now, Mobile Apps, and introduce new capabilities as Logic Apps and the API Apps. This article talks about the last one.
The question is: What’s the reason to create an API App, and not a Web API in a Website? This question can be easily answered, analysing the feature list, for example:</p>
<ul>
<li>Access Control using Azure Active Directory or OAuth services, as Facebook or Twitter;</li>
<li>Fast integration with the Swagger Framework;</li>
<li>Easy integration with Logic Apps;</li>
<li>Private gallery of APIs, enabling us to provide APIs to the other members of the organization;</li>
<li>Automatic generation of an SDK for our API.</li>
</ul>
<p>In this article we will see, how to create an API, publish in our subscription and create an SDK to consume it.</p>
<h2>Description</h2>
<p>There are many services, inside the organizations, that are necessary to multiple applications. A good example of that is the send email notifications.
Let imagine that we pretend to provide an API, so that all applications of our organization, can easily send emails, without need to know the logic of using the email server.
Before we start, we need to be sure that <a href="http://go.microsoft.com/fwlink/?linkid=324322&clcid=0x409">Microsoft Azure SDK for .NET 2.6</a> is installed.</p>
<h3>Create an API App project</h3>
<p>Let’s start to see how to create a project for our API App.</p>
<ol>
<li>Open Visual Studio 2013;</li>
<li>Create a new project using <strong>File > New Project</strong>;</li>
<li>Choose the template <strong>ASP.NET Web Application</strong>;</li>
<li>Give a name to the project, in this case we will use MailApi;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-1.png" alt="New Project"></p>
<ol start="5">
<li>Click <strong>OK</strong>;</li>
<li>Select the template <strong>Azure API App</strong>;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-2.png" alt="Template"></p>
<ol start="7">
<li>Click <strong>OK</strong> and to create the project.</li>
</ol>
<h3>Create the service to send emails</h3>
<p>Let’s see how to expose a method for sending emails in our API. For that, we will create a class that represents the data model to receive the request, and a controller to provide the sending method.</p>
<ol>
<li>In the folder Models, add a new class with the name MailModel. Mouse right click in the folder Models, and select the option <strong>Add > Class</strong>.</li>
<li>In the created file, MailModel.cs, add the following code:</li>
</ol>
<pre class="language-csharp"><code class="language-csharp"> <span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>ComponentModel<span class="token punctuation">.</span>DataAnnotations</span><span class="token punctuation">;</span><br> <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MailModel</span><br> <span class="token punctuation">{</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Required</span></span><span class="token punctuation">]</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">EmailAddress</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> To <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Required</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Subject <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Required</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Body <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span></code></pre>
<ol start="3">
<li>Add a controller to the project (controllers file) with the name MailController, using the template, <strong>Web API 2 Controller – Empty</strong>.</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-3.png" alt="Scaffold"></p>
<ol start="4">
<li>In the created file, <strong>MailController.cs</strong>, add the following method:</li>
</ol>
<pre class="language-csharp"><code class="language-csharp"> <span class="token keyword">using</span> <span class="token namespace">MailApi<span class="token punctuation">.</span>Models</span><span class="token punctuation">;</span><br> <span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">HttpPost</span></span><span class="token punctuation">]</span><br> <span class="token keyword">public</span> <span class="token return-type class-name">HttpResponseMessage</span> <span class="token function">Post</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">FromBody</span></span><span class="token punctuation">]</span><span class="token class-name">MailModel</span> data<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">using</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">System<span class="token punctuation">.</span>Net<span class="token punctuation">.</span>Mail<span class="token punctuation">.</span>SmtpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token comment">// create the message</span><br> <span class="token class-name"><span class="token keyword">var</span></span> mailFrom <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">System<span class="token punctuation">.</span>Net<span class="token punctuation">.</span>Mail<span class="token punctuation">.</span>MailAddress</span><span class="token punctuation">(</span><span class="token string">"noreply@deathstar.com"</span><span class="token punctuation">,</span> <span class="token string">"Death Star"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> mailTo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">System<span class="token punctuation">.</span>Net<span class="token punctuation">.</span>Mail<span class="token punctuation">.</span>MailAddress</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>To<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> mail <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">System<span class="token punctuation">.</span>Net<span class="token punctuation">.</span>Mail<span class="token punctuation">.</span>MailMessage</span><span class="token punctuation">(</span>mailFrom<span class="token punctuation">,</span> mailTo<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> mail<span class="token punctuation">.</span>Subject <span class="token operator">=</span> data<span class="token punctuation">.</span>Subject<span class="token punctuation">;</span><br> mail<span class="token punctuation">.</span>Body <span class="token operator">=</span> data<span class="token punctuation">.</span>Body<span class="token punctuation">;</span><br> mail<span class="token punctuation">.</span>IsBodyHtml <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br><br> <span class="token comment">// send email</span><br> client<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span>mail<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token keyword">return</span> Request<span class="token punctuation">.</span><span class="token function">CreateResponse</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span></code></pre>
<h3>Configure the service</h3>
<p>Since in this example we will send the e-mail via SMTP, we will need to configure the e-mail server data.</p>
<ol>
<li>Access the <strong>Web.config</strong> file of our application;</li>
<li>Add the following configuration (before the line ):</li>
</ol>
<pre class="language-xml"><code class="language-xml"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>system.net</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mailSettings</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>smtp</span> <span class="token attr-name">from</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>noreply@deathstar.com<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>network</span> <span class="token attr-name">host</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>mail.deathstar.com<span class="token punctuation">"</span></span> <span class="token attr-name">port</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>587<span class="token punctuation">"</span></span> <span class="token attr-name">userName</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>noreply@deathstar.com<span class="token punctuation">"</span></span> <span class="token attr-name">password</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#MayTheForceBeWithThisPassword!<span class="token punctuation">"</span></span> <span class="token attr-name">enableSsl</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>smtp</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mailSettings</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>system.net</span><span class="token punctuation">></span></span></code></pre>
<ol start="3">
<li>Fill in with the data from our server.</li>
</ol>
<h3>Publish the application to the Azure App Service</h3>
<p>The publication can be made to an App Service, previously created using the portal, but in the next step we will see how to create the same without leaving Visual Studio.</p>
<p>To do this, it’s required to have an Azure subscription. If you don’t have it, you can create one test subscription of a month, in http://azure.microsoft.com/en-us/pricing/free-trial/.
If you already have it, follow the next steps:</p>
<ol>
<li>In Solution Explorer, right click in project and click <strong>Publish</strong>;</li>
<li>In the publish dialog, access the <strong>Profile</strong> panel and choose the option <strong>Microsoft Azure API Apps</strong>;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-4.png" alt="Publish"></p>
<ol start="3">
<li>Click <strong>New</strong> to create a new API App in the subscription;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-5.png" alt="Azure API Apps"></p>
<ol start="4">
<li>In the Create dialog, add:</li>
</ol>
<ul>
<li>The API App name. Here we will use <strong>MailApiService</strong>;</li>
<li>Select the disired subscription;</li>
<li>Pick a name to the App Service;</li>
<li>Pick a name to the Resource Group;</li>
<li>Choose the access level Available to Anyone;</li>
<li>Pick the region where you what to host the App Service.</li>
</ul>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-6.png" alt="Create API App dialog"></p>
<ol start="5">
<li>Click <strong>OK</strong> and wait a few minutes while the service is being created. The creation request can be followed in the Azure App Service Activity panel;</li>
<li>Once the App Service is created, we go back to the step number 1, access the publish dialog, and we click in the <strong>Publish</strong> option;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-7.png" alt="Publish"></p>
<ol start="7">
<li>The service will be published.</li>
</ol>
<h3>Consume na API from a .NET client.</h3>
<p>Let’s see how to create an SDK to our API and use it.</p>
<ol>
<li>Add a Console Application to our solution;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-8.png" alt="Add console app"></p>
<ol start="2">
<li>In the Solution Explorer, right click in the Console Application and select the option <strong>Add > Azure API App Client</strong>;</li>
<li>In the presented dialog, pick the option <strong>Download from Microsoft Azure API App</strong> and select the MailApiService, create previously;</li>
</ol>
<p><img src="https://guiferreira.me/images/create-an-api-in-azure-app-service-revista-programar-n49-7.png" alt="Add Azure API App Client"></p>
<ol start="4">
<li>Click <strong>OK</strong> and wait until the SDK is created;</li>
<li>When the last step is completed, we are ready to invoke our API, as the following code shows.</li>
</ol>
<pre class="language-csharp"><code class="language-csharp"> <span class="token keyword">class</span> <span class="token class-name">Program</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Main</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token class-name"><span class="token keyword">var</span></span> client <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MailApiService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> data <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Models<span class="token punctuation">.</span>MailModel</span> <span class="token punctuation">{</span> To <span class="token operator">=</span> <span class="token string">"darth.vader@deathstar.com"</span><span class="token punctuation">,</span> Subject <span class="token operator">=</span> <span class="token string">"War Report"</span><span class="token punctuation">,</span> Body <span class="token operator">=</span> <span class="token string">"The Force awakens"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><br> <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> client<span class="token punctuation">.</span>Mail<span class="token punctuation">.</span><span class="token function">Post</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Done!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Console<span class="token punctuation">.</span><span class="token function">ReadKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span></code></pre>
<h2>Summary</h2>
<p>With this new service created by Microsoft, we are able to provide features that in the past had a huge development cost, in an easy and quick way.
The private gallery in conjunction with the easy way to consume APIs, provides the required capabilities to create an API ecosystem.</p>
Lessons learned from Agile Portugal 20152015-05-28T00:00:00-00:00https://guiferreira.me/archive/2015/05/lessons-learned-from-agilept-2015/<p>In the last week I attended to the <a href="http://2015.agilept.org/">Agile Portugal 2015</a>, an amazing event that gathers the agile community.
I had the opportunity to listen excellent speakers as:</p>
<ul>
<li><a href="https://au.linkedin.com/pub/lachlan-heasman/1/920/777">Lachlan Heasman</a></li>
<li><a href="https://twitter.com/haradakiro">Kiro Harada</a></li>
<li><a href="https://twitter.com/_pedro_torres">Pedro Gustavo Torres</a></li>
<li><a href="https://www.uvu.edu/profpages/profiles/show/user_id/1923">Neil Harrison</a></li>
<li><a href="https://twitter.com/theplastictoy">Ricardo Fiel</a></li>
<li><a href="https://twitter.com/carlton858">Carlton Nettleton</a></li>
</ul>
<p>The event was amazing, and I want to share with you the main lessons that I learned.</p>
<hr>
<h2>The importance of Visuals</h2>
<p>Lachlan Heasman has made an amazing talk. He reinforces that the Visual Management is really important to succeed.<br>
That thought made a lot of sense to me. Nowadays, we have a ton of excellent applications to do kanban boards and that's OK, especially if you have remote workers. But I believe that, if you have your team in a single place you should have a physical kanban board.
Why? Because your team will look into it every day... every single day. Even if they don't want, they will! You will see that your team will be positively influenced, building a culture of transparency and trust.</p>
<p><img src="https://guiferreira.me/images/lessons-learned-from-agilept-2015-kanban-style.jpg" alt="Kanban style"></p>
<h2>User stories</h2>
<p>Why we are writing User Stories in the form of "As a... I want to... so that..."? Will the customer realize the language? Or will they think that we are crazy nerds?
As the <a href="http://en.wikipedia.org/wiki/User_story">wikipedia</a> (that eternal font of true) refers, an "user story is a description consisting of one or more sentences in the everyday or business language of the end user or user of a system".
Have you ever listened a business person talking like that?</p>
<p>Carlton Nettleton, presented a simpler and much objective way to write user stories. How? Answering the following questions: Who? What? And Why?
I'm a fan of the <a href="http://en.wikipedia.org/wiki/Five_Ws">Six W's method</a> to describe and understand complex problems, and Carlton made me correlate that with user stories.</p>
<h2>The true essence of agile</h2>
<p>The industry sells us the idea that Agile (or Scrum), is a magic formula that we should apply to have good results. You just need to have some meetings, do sprints of "X" weeks and you will be fine.
That's not true.</p>
<p>Companies are made from people, so they are different. Each one has a different culture and a different identity. This uniqueness will make them agile.</p>
<p>Agile, isn't a process, a system or a mathematical formula. Agile is a culture.
It's different be agile than have a certificate that says that you are agile.
The process is the less important part. You should have the focus on the outcome.
Always think on where you want to go, not on what you need to do to go there.</p>
<hr>
<p>Was an amazing day, with incredible people, in an awesome place.
Hope to be there next year.</p>
Azure App Service API Apps - Microsoft Rest HttpOperationException2015-05-12T00:00:00-00:00https://guiferreira.me/archive/2015/05/azure-app-service-api-apps-microsoft-rest-httpoperationexception/<p>Recently I was playing with API Apps, from the new Azure App Service when I faced the following error:</p>
<pre class="language-csharp"><code class="language-csharp">Microsoft<span class="token punctuation">.</span>Rest<span class="token punctuation">.</span>HttpOperationException`<span class="token number">1</span> was <span class="token class-name">unhandled</span><br> HResult<span class="token operator">=</span><span class="token operator">-</span><span class="token number">2146233088</span><br> Message<span class="token operator">=</span>Exception of type 'Microsoft<span class="token punctuation">.</span>Rest<span class="token punctuation">.</span>HttpOperationException`<span class="token number">1</span><span class="token punctuation">[</span>System<span class="token punctuation">.</span>Object<span class="token punctuation">]</span>' was thrown<span class="token punctuation">.</span><br> Source<span class="token operator">=</span><span class="token class-name">MyMailSenderClient2</span><br> StackTrace<span class="token punctuation">:</span><br> at MyMailSenderClient2<span class="token punctuation">.</span>Mail<span class="token punctuation">.</span><span class="token operator"><</span>PostWithOperationResponseAsync<span class="token operator">></span>d__0<span class="token punctuation">.</span><span class="token function">MoveNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">in</span> c<span class="token punctuation">:</span>\DEV\MyTestApi\MyMailSenderClient2\TestMailApi\Mail<span class="token punctuation">.</span>cs<span class="token punctuation">:</span>line <span class="token number">129</span><br> <span class="token operator">--</span><span class="token operator">-</span> End of stack trace <span class="token keyword">from</span> previous location <span class="token keyword">where</span> <span class="token class-name">exception</span> was thrown <span class="token operator">--</span><span class="token operator">-</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span>CompilerServices<span class="token punctuation">.</span>TaskAwaiter<span class="token punctuation">.</span><span class="token function">ThrowForNonSuccess</span><span class="token punctuation">(</span><span class="token class-name">Task</span> task<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span>CompilerServices<span class="token punctuation">.</span>TaskAwaiter<span class="token punctuation">.</span><span class="token function">HandleNonSuccessAndDebuggerNotification</span><span class="token punctuation">(</span><span class="token class-name">Task</span> task<span class="token punctuation">)</span><br> at System<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span>CompilerServices<span class="token punctuation">.</span>ConfiguredTaskAwaitable`<span class="token number">1</span><span class="token punctuation">.</span>ConfiguredTaskAwaiter<span class="token punctuation">.</span><span class="token function">GetResult</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> at MyMailSenderClient2<span class="token punctuation">.</span>MailExtensions<span class="token punctuation">.</span><span class="token operator"><</span>PostAsync<span class="token operator">></span>d__3<span class="token punctuation">.</span><span class="token function">MoveNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">in</span> c<span class="token punctuation">:</span>\DEV\MyTestApi\MyMailSenderClient2\TestMailApi\MailExtensions<span class="token punctuation">.</span>cs<span class="token punctuation">:</span>line <span class="token number">42</span><br> <span class="token operator">--</span><span class="token operator">-</span> End of stack trace <span class="token keyword">from</span> previous location <span class="token keyword">where</span> <span class="token class-name">exception</span> was thrown <span class="token operator">--</span><span class="token operator">-</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span>CompilerServices<span class="token punctuation">.</span>TaskAwaiter<span class="token punctuation">.</span><span class="token function">ThrowForNonSuccess</span><span class="token punctuation">(</span><span class="token class-name">Task</span> task<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span>CompilerServices<span class="token punctuation">.</span>TaskAwaiter<span class="token punctuation">.</span><span class="token function">HandleNonSuccessAndDebuggerNotification</span><span class="token punctuation">(</span><span class="token class-name">Task</span> task<span class="token punctuation">)</span><br> at System<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span>CompilerServices<span class="token punctuation">.</span>TaskAwaiter`<span class="token number">1</span><span class="token punctuation">.</span><span class="token function">GetResult</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> MyMailSenderClient2<span class="token punctuation">.</span>MailExtensions<span class="token punctuation">.</span><span class="token function">Post</span><span class="token punctuation">(</span><span class="token class-name">IMail</span> operations<span class="token punctuation">,</span> <span class="token class-name">MailModel</span> data<span class="token punctuation">)</span> <span class="token keyword">in</span> c<span class="token punctuation">:</span>\DEV\MyTestApi\MyMailSenderClient2\TestMailApi\MailExtensions<span class="token punctuation">.</span>cs<span class="token punctuation">:</span>line <span class="token number">24</span><br> <span class="token return-type class-name">at</span> MyMailSenderClient2<span class="token punctuation">.</span>Program<span class="token punctuation">.</span><span class="token function">Main</span><span class="token punctuation">(</span><span class="token class-name">String<span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">)</span> <span class="token keyword">in</span> c<span class="token punctuation">:</span>\DEV\MyTestApi\MyMailSenderClient2\Program<span class="token punctuation">.</span>cs<span class="token punctuation">:</span>line <span class="token number">16</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>AppDomain<span class="token punctuation">.</span><span class="token function">_nExecuteAssembly</span><span class="token punctuation">(</span><span class="token class-name">RuntimeAssembly</span> assembly<span class="token punctuation">,</span> <span class="token class-name">String<span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>AppDomain<span class="token punctuation">.</span><span class="token function">ExecuteAssembly</span><span class="token punctuation">(</span><span class="token class-name">String</span> assemblyFile<span class="token punctuation">,</span> <span class="token class-name">Evidence</span> assemblySecurity<span class="token punctuation">,</span> <span class="token class-name">String<span class="token punctuation">[</span><span class="token punctuation">]</span></span> args<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> Microsoft<span class="token punctuation">.</span>VisualStudio<span class="token punctuation">.</span>HostingProcess<span class="token punctuation">.</span>HostProc<span class="token punctuation">.</span><span class="token function">RunUsersAssembly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>ThreadHelper<span class="token punctuation">.</span><span class="token function">ThreadStart_Context</span><span class="token punctuation">(</span><span class="token class-name">Object</span> state<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>ExecutionContext<span class="token punctuation">.</span><span class="token function">RunInternal</span><span class="token punctuation">(</span><span class="token class-name">ExecutionContext</span> executionContext<span class="token punctuation">,</span> <span class="token class-name">ContextCallback</span> callback<span class="token punctuation">,</span> <span class="token class-name">Object</span> state<span class="token punctuation">,</span> <span class="token class-name">Boolean</span> preserveSyncCtx<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>ExecutionContext<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token class-name">ExecutionContext</span> executionContext<span class="token punctuation">,</span> <span class="token class-name">ContextCallback</span> callback<span class="token punctuation">,</span> <span class="token class-name">Object</span> state<span class="token punctuation">,</span> <span class="token class-name">Boolean</span> preserveSyncCtx<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>ExecutionContext<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token class-name">ExecutionContext</span> executionContext<span class="token punctuation">,</span> <span class="token class-name">ContextCallback</span> callback<span class="token punctuation">,</span> <span class="token class-name">Object</span> state<span class="token punctuation">)</span><br> <span class="token return-type class-name">at</span> System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>ThreadHelper<span class="token punctuation">.</span><span class="token function">ThreadStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br> InnerException<span class="token punctuation">:</span></code></pre>
<p>I struggled a bit until I figured why.</p>
<p>Well, let me explain you how I got there and what I have done to solve it.</p>
<p>I access to the new <a href="http://portal.azure.com/">Portal</a> and I created a new API App, then I've followed the Microsoft tutorial of how to <a href="http://azure.microsoft.com/en-us/documentation/articles/app-service-dotnet-create-api-app/">Create an ASP.NET API app in Azure App Service</a>.</p>
<p>Everything was going fine and in a few minutes I published the API. Quick and easy.</p>
<p>Then, I generated my Client SDK and when I tried to invoke it, I got the error.</p>
<p>As you can see, the exception message and the stack trace don't provide much information.</p>
<p>I had to struggle a bit to figure it out.</p>
<p>The reason was really simple, my API service had the Access Level defined as <strong>Internal</strong>.</p>
<p>After changing it to <strong>Public (anonymous)</strong> everything works fine.</p>
<p><img src="https://guiferreira.me/images/azure-app-service-api-apps-microsoft-rest-httpoperationexception-access-level.png" alt="Azure API App - Access Level"></p>
<p>Why this happened? If you follow the tutorial you will create the API App using Visual Studio and you will see that the Visual Studio has the access level <strong>Available to Anyone</strong> as default.</p>
<p>When you create the API App using the portal, you will see that the Access Level is defined as <strong>Internal</strong> by default.</p>
<p>I believe that Microsoft will fix these small problems and make it more clear.
Until then, I hope that this helps you.</p>
AngularJS - After Render Directive2015-03-28T00:00:00-00:00https://guiferreira.me/archive/2015/03/angularjs-after-render-directive/<p>Do you ever wanted to execute code after your Angular template is completely rendered?</p>
<p>This post is the answer of how you can accomplish that.</p>
<p>This a simple tip, but I believe that can be really useful.</p>
<p>Add the following directive to your application.</p>
<pre class="language-js"><code class="language-js">myApp<span class="token punctuation">.</span><span class="token function">directive</span><span class="token punctuation">(</span><span class="token string">"afterRender"</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><br> <span class="token string">"$timeout"</span><span class="token punctuation">,</span><br> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">$timeout</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">var</span> def <span class="token operator">=</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">restrict</span><span class="token operator">:</span> <span class="token string">"A"</span><span class="token punctuation">,</span><br> <span class="token literal-property property">terminal</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br> <span class="token literal-property property">transclude</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br> <span class="token function-variable function">link</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">scope<span class="token punctuation">,</span> element<span class="token punctuation">,</span> attrs</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token function">$timeout</span><span class="token punctuation">(</span>scope<span class="token punctuation">.</span><span class="token function">$eval</span><span class="token punctuation">(</span>attrs<span class="token punctuation">.</span>afterRender<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//Calling a scoped method</span><br> <span class="token punctuation">}</span><span class="token punctuation">,</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> def<span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">,</span><br><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now, add the <em>after-render</em> directive to an element in your template:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">after-render</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>missionCompled<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>At this point, your application will run the <em>missionCompled</em> function (or other that you want) in your controller, after the div is rendered.</p>
<p>You can see the working demo on <a href="https://jsfiddle.net/gsferreira/h53okjtu/">JSFiddle</a>.</p>
<p>I hope that this helps you.</p>
A developer's thoughts on Azure SQL Database performance levels2015-03-14T00:00:00-00:00https://guiferreira.me/archive/2015/03/a-developers-thoughts-on-azure-sql-database-performance-levels/<p>I recently started moving some databases that I have in the old Azure SQL Database Web/Business model. I started it with a good feeling. Let's face it, a guaranteed performance level is excellent. Nobody wants a noisy neighbor boring our database.</p>
<p>The downside, is that this shift brings new challenges and possible big troubles to the ones that already have systems in place. Everything has a price and in this case we call it <strong>Performance</strong>.</p>
<p>In this new model, SQL Azure Databases are paid by performance instead of space. Now we have service tiers with transaction rates per hour (Basic Tier), per minute (Standard Tier) or per second (Premium Tier).</p>
<p>So, what's wrong with this? The prices! In my opinion, there's no equality between the old models and the new ones. Chris Bailiss has some awesome posts that shows that. Take a look:</p>
<ul>
<li><a href="https://cbailiss.wordpress.com/2015/01/31/azure-sql-database-v12-ga-performance-inc-cpu-benchmaring/">Azure SQL Database: v12 GA Performance inc. CPU Benchmaring</a></li>
<li><a href="https://cbailiss.wordpress.com/2014/09/16/performance-in-new-azure-sql-database-performance-tiers/">GA Performance in New Azure SQL Database Performance Tiers</a></li>
</ul>
<p>###Show me the numbers</p>
<p>If you have an Azure SQL Database on the Web model with 1.5GB you will pay 10.42€/month.
By a few more cents (11.18€/month) you can use an SQL Database in the Standard Tier with the S0 Performance Level.</p>
<p>If you have read the Chris Bailiss post, you have seen that the performance between those two can't be compared. S0 is slower than Web.</p>
<p>###So, what can I do?</p>
<p>With this post <strong>I don't want to say that you should run away from SQL Azure Database</strong>. What I mean, is that the game has changed.</p>
<p>In this Cloud era the costs are a variable that Software Developers and Architects need to take in account. Now our code has a visible and measurable impact in the financial health of our products and companies.</p>
<p>So, how to start facing the dragon?
You can find here a list of things that you should have in mind:</p>
<ul>
<li><strong>Question yourself: Do I really need a SQL database?</strong> There's many options in Azure to store your data, probably they can do the task.</li>
<li><strong>Performance is more important than ever!</strong> Don't wait until a query takes a few minutes running to start doing SQL Tuning.</li>
<li><strong>Database design has a significant importance!</strong> Be careful designing your database data model.</li>
<li><strong>Test in Azure since the first day.</strong> Probably your development machine has an SQL Server with more power than the production database.</li>
</ul>
<p><img src="https://guiferreira.me/images/a-developers-thoughts-on-azure-sql-database-performance-levels-works-fine-in-dev.jpg" alt="Works fine in Dev"></p>
<ul>
<li><strong>Reduce the "chatty"</strong> operations in your application.</li>
<li><strong>Be careful using Entity Framework.</strong> Make sure that your code isn't triggering multiple queries that can be done at once. EF can make your life easier, but the database can suffer from that.</li>
<li><strong>Start using cache.</strong> This will reduce the workload at your database and you will consume less DTUs.</li>
</ul>
<p>Hope this helps.</p>
AngularJS - Input number with 2 decimal places2015-02-25T00:00:00-00:00https://guiferreira.me/archive/2015/02/angularjs-input-number-with-two-decimal-places/<p>My <a href="https://guiferreira.me/archive/2014/05/angularjs-smart-float-directive/">AngularJS - Smart Float Directive</a> post has been a post with a lot of traction, so I want to share another tip related to numbers in Angular.</p>
<p>This a kind of simple tip, but I believe that it can be really useful.</p>
<p>My smart-float directive works really fine in a desktop or laptop browser, but in a smartphone I want to take advantage of HTML5 number inputs and show to my users when they enter in the input, the "mini calculator keyboard".</p>
<p>How to accomplish it using angular?</p>
<p>That's easy.</p>
<p><a href="http://www.deque.com/blog/accessible-client-side-form-validation-html5/"><img src="https://guiferreira.me/images/angularjs-input-number-with-two-decimal-places-meme.jpg" alt="meme"></a></p>
<h3>1. Create the number input with the number type.</h3>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Decimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br><span class="token punctuation">/></span></span></code></pre>
<h3>2. Define the step interval.</h3>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Decimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">*step</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.01<span class="token punctuation">"</span></span><br> <span class="token attr-name">*</span><br><span class="token punctuation">/></span></span></code></pre>
<h3>3. Set the regular expression to validate the input using ng-pattern. Here I want to accept only numbers with a maximum of 2 decimal places and with a dot separator.</h3>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Decimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-pattern</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/^[0-9]+(\.[0-9]{1,2})?$/<span class="token punctuation">"</span></span><br> <span class="token attr-name">step</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.01<span class="token punctuation">"</span></span><br><span class="token punctuation">/></span></span></code></pre>
<h3>4. Inform your user if the input has a valid value.</h3>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Decimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-pattern</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/^[0-9]+(\.[0-9]{1,2})?$/<span class="token punctuation">"</span></span><br> <span class="token attr-name">step</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.01<span class="token punctuation">"</span></span><br><span class="token punctuation">/></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>Is a valid decimal? <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span></code></pre>
<p>A full example using bootstrap (<a href="http://jsfiddle.net/gsferreira/Lsv9f0b0/">demo here</a>):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">ng-app</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Todo<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">ng-controller</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myCtrl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myForm<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-horizontal<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><br> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-group<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{<span class="token punctuation">'</span>has-error<span class="token punctuation">'</span>: myForm.myDecimal.$invalid}<span class="token punctuation">"</span></span><br> <span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputText3<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>col-sm-2 control-label<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Decimal<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>col-sm-10<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span><br> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-control<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Decimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-pattern</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/^[0-9]+(\.[0-9]{1,2})?$/<span class="token punctuation">"</span></span><br> <span class="token attr-name">step</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.01<span class="token punctuation">"</span></span><br> <span class="token attr-name">required</span><br> <span class="token punctuation">/></span></span><br><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>help-block<span class="token punctuation">"</span></span> <span class="token attr-name">ng-show</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>!myForm.myDecimal.$valid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> Invalid!<br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-group<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputText3<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>col-sm-2 control-label<span class="token punctuation">"</span></span><br> <span class="token punctuation">></span></span>The value:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><br> <span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>col-sm-10<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-control<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myDecimal<span class="token punctuation">"</span></span><br> <span class="token attr-name">disabled</span><br> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>Hope this helps.</p>
How to Encrypt in Node.js and Decrypt in C#2015-02-16T00:00:00-00:00https://guiferreira.me/archive/2015/02/how-to-encrypt-in-nodejs-and-decrypt-in-c-sharp/<p>Are you trying to send messages to a .NET application from node.js and you want to encrypt them?</p>
<p>You can find here a simple example to accomplish it.</p>
<p>Encrypt in node.js:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">var</span> crypto <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"crypto"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">var</span> key <span class="token operator">=</span> <span class="token string">"00000000000000000000000000000000"</span><span class="token punctuation">;</span> <span class="token comment">//replace with your key</span><br><span class="token keyword">var</span> iv <span class="token operator">=</span> <span class="token string">"0000000000000000"</span><span class="token punctuation">;</span> <span class="token comment">//replace with your IV</span><br><span class="token keyword">var</span> cipher <span class="token operator">=</span> crypto<span class="token punctuation">.</span><span class="token function">createCipheriv</span><span class="token punctuation">(</span><span class="token string">"aes256"</span><span class="token punctuation">,</span> key<span class="token punctuation">,</span> iv<span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token keyword">var</span> crypted <span class="token operator">=</span> cipher<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>authorizationKey<span class="token punctuation">,</span> <span class="token string">"utf8"</span><span class="token punctuation">,</span> <span class="token string">"base64"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>crypted <span class="token operator">+=</span> cipher<span class="token punctuation">.</span><span class="token function">final</span><span class="token punctuation">(</span><span class="token string">"base64"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>crypted<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Decrypt with C#:</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token class-name"><span class="token keyword">string</span></span> keyString <span class="token operator">=</span> <span class="token string">"00000000000000000000000000000000"</span><span class="token punctuation">;</span> <span class="token comment">//replace with your key</span><br> <span class="token class-name"><span class="token keyword">string</span></span> ivString <span class="token operator">=</span> <span class="token string">"0000000000000000"</span><span class="token punctuation">;</span> <span class="token comment">//replace with your iv</span><br><br> <span class="token class-name"><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> key <span class="token operator">=</span> Encoding<span class="token punctuation">.</span>ASCII<span class="token punctuation">.</span><span class="token function">GetBytes</span><span class="token punctuation">(</span>keyString<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> iv <span class="token operator">=</span> Encoding<span class="token punctuation">.</span>ASCII<span class="token punctuation">.</span><span class="token function">GetBytes</span><span class="token punctuation">(</span>ivString<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token keyword">using</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> rijndaelManaged <span class="token operator">=</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">RijndaelManaged</span> <span class="token punctuation">{</span> Key <span class="token operator">=</span> key<span class="token punctuation">,</span> IV <span class="token operator">=</span> iv<span class="token punctuation">,</span> Mode <span class="token operator">=</span> CipherMode<span class="token punctuation">.</span>CBC <span class="token punctuation">}</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> rijndaelManaged<span class="token punctuation">.</span>BlockSize <span class="token operator">=</span> <span class="token number">128</span><span class="token punctuation">;</span><br> rijndaelManaged<span class="token punctuation">.</span>KeySize <span class="token operator">=</span> <span class="token number">256</span><span class="token punctuation">;</span><br> <span class="token keyword">using</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> memoryStream <span class="token operator">=</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MemoryStream</span><span class="token punctuation">(</span>Convert<span class="token punctuation">.</span><span class="token function">FromBase64String</span><span class="token punctuation">(</span>AuthorizationCode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token keyword">using</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">var</span></span> cryptoStream <span class="token operator">=</span><br> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">CryptoStream</span><span class="token punctuation">(</span>memoryStream<span class="token punctuation">,</span><br> rijndaelManaged<span class="token punctuation">.</span><span class="token function">CreateDecryptor</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> iv<span class="token punctuation">)</span><span class="token punctuation">,</span><br> CryptoStreamMode<span class="token punctuation">.</span>Read<span class="token punctuation">)</span><span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">StreamReader</span><span class="token punctuation">(</span>cryptoStream<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ReadToEnd</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span></code></pre>
<p>Hope this helps.</p>
How to access Azure storage emulator using Node.js SDK2015-02-06T00:00:00-00:00https://guiferreira.me/archive/2015/02/how-to-access-azure-storage-emulator-using-nodejs-sdk/<p>Today I have a quick tip that I want to share with you because it took me some time to figure this out.</p>
<p>I'm using Azure SDK for Node.js to interact with Azure Storage and I want to access my development environment with it.</p>
<p>To access the blob storage, for instance, you just need to create a blob service using the resource name and the access key. Too easy!</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token class-name"><span class="token keyword">var</span></span> azure <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span>'azure<span class="token operator">-</span>storage'<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> blobService <span class="token operator">=</span> azure<span class="token punctuation">.</span><span class="token function">createBlobService</span><span class="token punctuation">(</span>'mystorage'<span class="token punctuation">,</span> 'my<span class="token operator">-</span>access<span class="token operator">-</span>key'<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now I want to access the Azure Storage Emulator running in my machine. How to do it? Just replace the previous code with the following piece of code.</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token class-name"><span class="token keyword">var</span></span> azure <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span>'azure<span class="token operator">-</span>storage'<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> devStoreCreds <span class="token operator">=</span> azure<span class="token punctuation">.</span><span class="token function">generateDevelopmentStorageCredendentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">var</span></span> blobService <span class="token operator">=</span> azure<span class="token punctuation">.</span><span class="token function">createBlobService</span><span class="token punctuation">(</span>devStoreCreds<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Hope this helps.</p>
T-SQL: Which schema is consuming more space?2015-01-29T00:00:00-00:00https://guiferreira.me/archive/2015/01/t-sql-which-schema-is-consuming-more-space/<p>Imagine that you have separate schemas in your multi-tenant data architecture and you want to know who is consuming more space. How can you do it?</p>
<p>Just run the following query:</p>
<pre class="language-sql"><code class="language-sql"> <span class="token keyword">SELECT</span> SCHEMA_NAME<span class="token punctuation">(</span>obj<span class="token punctuation">.</span>schema_id<span class="token punctuation">)</span> <span class="token keyword">AS</span> <span class="token string">'Schema'</span><span class="token punctuation">,</span><br> <span class="token function">SUM</span><span class="token punctuation">(</span>stats<span class="token punctuation">.</span>reserved_page_count<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">8.0</span> <span class="token operator">/</span> <span class="token number">1024</span> <span class="token keyword">AS</span> SizeInMB<br> <span class="token keyword">FROM</span> sys<span class="token punctuation">.</span>dm_db_partition_stats stats<br> <span class="token keyword">JOIN</span> sys<span class="token punctuation">.</span>indexes idx <span class="token keyword">ON</span> idx<span class="token punctuation">.</span>object_id <span class="token operator">=</span> stats<span class="token punctuation">.</span>object_id <span class="token operator">AND</span> idx<span class="token punctuation">.</span>index_id <span class="token operator">=</span> stats<span class="token punctuation">.</span>index_id<br> <span class="token keyword">JOIN</span> sys<span class="token punctuation">.</span>objects obj <span class="token keyword">ON</span> idx<span class="token punctuation">.</span>object_id <span class="token operator">=</span> obj<span class="token punctuation">.</span>object_id<br> <span class="token keyword">WHERE</span> obj<span class="token punctuation">.</span><span class="token keyword">Type</span> <span class="token operator">=</span> <span class="token string">'U'</span><br> <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> obj<span class="token punctuation">.</span>schema_id<br> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> SizeInMB <span class="token keyword">DESC</span></code></pre>
<p>Hope this helps.</p>
5 awesome tools to craft the perfect Domain Name2015-01-14T00:00:00-00:00https://guiferreira.me/archive/2015/01/5-awesome-tools-to-craft-the-perfect-domain-name/<p>One of the common tips to pick the perfect domain name is to choose one dot-com domain, but a good domain name is a needle in a haystack.</p>
<p>Here, you will find five awesome tools to help you craft an incredible (and available) domain name.</p>
<h3>1. <a href="http://wordoid.com/">WORDOID</a></h3>
<p><a href="http://wordoid.com/"><img src="https://guiferreira.me/images/5-awesome-tools-to-craft-the-perfect-domain-name-wordoid.jpg" alt="WORDOID"></a></p>
<p>WORDOID generates words and show the availability in .com and .net domains. You can search using parameters like length or language.</p>
<h3>2. <a href="http://www.namemesh.com/">Name Mesh</a></h3>
<p><a href="http://www.namemesh.com/"><img src="https://guiferreira.me/images/5-awesome-tools-to-craft-the-perfect-domain-name-namemesh.jpg" alt="Name Mesh"></a></p>
<p>Name Mesh searches for synonyms and similar words. Use wisely the search box and you will receive useful results.</p>
<h3>3. <a href="http://www.panabee.com/">Panabee</a></h3>
<p><a href="http://www.panabee.com/"><img src="https://guiferreira.me/images/5-awesome-tools-to-craft-the-perfect-domain-name-panabee.jpg" alt="Panabee"></a></p>
<p>Panabee gives you suggestions inspired by your original idea, using prefixes, suffixes, abbreviations and popular trends. He also suggests words related to the idea.</p>
<h3>4. <a href="http://impossibility.org/">Impossibility</a></h3>
<p><a href="http://impossibility.org/"><img src="https://guiferreira.me/images/5-awesome-tools-to-craft-the-perfect-domain-name-impossibility.jpg" alt="Impossibility"></a></p>
<p>Impossibility combines your idea with a list of nouns, verbs, and adjectives.</p>
<h3>5. <a href="http://www.domainsbot.com/">DomainsBot</a></h3>
<p><a href="http://www.domainsbot.com/"><img src="https://guiferreira.me/images/5-awesome-tools-to-craft-the-perfect-domain-name-domainsbot.jpg" alt="DomainsBot"></a></p>
<p>DomainsBot offers you the possibility of search by synonyms, prefixes and suffixes, mixing them with your idea.</p>
<p>Hope this helps.</p>
Overcome the DEPTH_ZERO_SELF_SIGNED_CERT on Node.js2014-12-15T00:00:00-00:00https://guiferreira.me/archive/2014/12/overcome-the-depth_zero_self_signed_cert-on-nodejs/<p>If you are making requests to a server that uses self-signed certificates in Node.js probably you already have seen the error DEPTH_ZERO_SELF_SIGNED_CERT.
That's an usual error, for instance, if you are working in a test environment.</p>
<p>I faced this error in my test environment and after google it, I got a lot of answers telling me to set the option "rejectUnhauthorized" as false on my request to the server.</p>
<p>But, that doesn't make me happy. Why?</p>
<p>Because I'm using other node modules that do requests to the same server and I will need to "hack" those modules to inject the rejectUnhauthorized attribute. Seems boring isn't it?!</p>
<p>So, what I've done?</p>
<p><img src="https://guiferreira.me/images/overcome-the-depth_zero_self_signed_cert-on-nodejs-one-row-to-rule-them-all.jpg" alt="One row to rule them all!"></p>
<p>I opened my node start file and I put there the following line of code:</p>
<pre class="language-js"><code class="language-js">process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_TLS_REJECT_UNAUTHORIZED</span> <span class="token operator">=</span> <span class="token string">"0"</span><span class="token punctuation">;</span></code></pre>
<p>If you, like me, want to apply this rule only to a test/development environment, you can do this:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">"development"</span> <span class="token operator">==</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"env"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_TLS_REJECT_UNAUTHORIZED</span> <span class="token operator">=</span> <span class="token string">"0"</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>Now you are conditioning it to the environment that you want.</p>
<p>Hope this helps.</p>
<hr>
<p><strong><em>UPDATE</em></strong></p>
<p>If you are thinking about applying this to Production environments, please read the comments below.</p>
Disable your html cache2014-12-05T00:00:00-00:00https://guiferreira.me/archive/2014/12/disable-your-html-cache/<p>Do you know that usually when you use the back button of your browser, your page won't be requested to the server again? By default this is the behaviour that you can expect.</p>
<p>But, you can control it!</p>
<p>Go to your web.config and place the following code into the <system.web> element.</p>
<pre class="language-xml"><code class="language-xml"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>caching</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>outputCache</span> <span class="token attr-name">enableOutputCache</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>outputCache</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>caching</span><span class="token punctuation">></span></span></code></pre>
<p>In your web.config place the following code into the <system.webserver> element to enable the caching for resource files, as images or stylesheets.</p>
<pre class="language-xml"><code class="language-xml"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>caching</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>profiles</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.gif<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:30:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.png<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:01:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.js<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:01:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.css<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:01:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:01:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.jpeg<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:01:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>add</span> <span class="token attr-name">extension</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>.txt<span class="token punctuation">"</span></span> <span class="token attr-name">policy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">kernelCachePolicy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CacheUntilChange<span class="token punctuation">"</span></span> <span class="token attr-name">duration</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0.00:01:00<span class="token punctuation">"</span></span> <span class="token attr-name">location</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Any<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>profiles</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>caching</span><span class="token punctuation">></span></span></code></pre>
<p>Last but not least, create a Base Controller and copy the code below to your base controller.</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnActionExecuting</span><span class="token punctuation">(</span><span class="token class-name">ActionExecutingContext</span> filterContext<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token comment">// Code disables caching by browser.</span><br> Response<span class="token punctuation">.</span>Cache<span class="token punctuation">.</span><span class="token function">SetCacheability</span><span class="token punctuation">(</span>HttpCacheability<span class="token punctuation">.</span>NoCache<span class="token punctuation">)</span><span class="token punctuation">;</span><br> Response<span class="token punctuation">.</span>Cache<span class="token punctuation">.</span><span class="token function">SetExpires</span><span class="token punctuation">(</span>DateTime<span class="token punctuation">.</span>UtcNow<span class="token punctuation">.</span><span class="token function">AddHours</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Response<span class="token punctuation">.</span>Cache<span class="token punctuation">.</span><span class="token function">SetNoStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span></code></pre>
<p>Hope this helps.</p>
Azure deploy and the path length limitation2014-11-27T00:00:00-00:00https://guiferreira.me/archive/2014/11/azure-deploy-and-the-path-length-limitation/<p>Windows has that boring thing, the "Maximum Path Length Limitation". That can be a terrible headache when you are dealing with Azure Cloud Service deploy.</p>
<p>If you create your projects in the Visual Studio default folder (<em>C:\Users\USER\Documents\Visual Studio 2013\Projects</em>) or in a longer path, probably you already have faced the error:</p>
<blockquote>
<p><em>"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."</em></p>
</blockquote>
<p>To fix this:</p>
<ol>
<li>Go to the Cloud Service project folder.</li>
<li>Edit the user cloud service options file (<em>*.ccproj</em> file) in notepad.</li>
<li>Add the ServiceOutputDirectory element with the value <em>"c:\azure"</em> for example.</li>
<li>Open the solution in Visual Studio again and the error has gone.</li>
</ol>
<p>Example:</p>
<pre class="language-xml"><code class="language-xml"> <span class="token prolog"><?xml version="1.0" encoding="utf-8"?></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Project</span> <span class="token attr-name">ToolsVersion</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>4.0<span class="token punctuation">"</span></span> <span class="token attr-name">DefaultTargets</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Build<span class="token punctuation">"</span></span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://schemas.microsoft.com/developer/msbuild/2003<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>PropertyGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Name</span><span class="token punctuation">></span></span>WorkerRole<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>Name</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ServiceOutputDirectory</span><span class="token punctuation">></span></span>c:\azure\<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ServiceOutputDirectory</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>PropertyGroup</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>Project</span><span class="token punctuation">></span></span></code></pre>
<p>Hope this helps.</p>
Azure SQL Database: Automatic Backups2014-10-02T00:00:00-00:00https://guiferreira.me/archive/2014/10/azure-sql-database-automatic-backups/<p>This week, I've found a new feature in Azure Management Portal that I wished at so many times.</p>
<p>In July, <a href="http://weblogs.asp.net/scottgu/windows-azure-july-updates-sql-database-traffic-manager-autoscale-virtual-machines">Scott Guthrie announced the support for Automated SQL Database Exports.</a></p>
<p>This is awesome because now we can forget the complex powershell scripts to achieve it. Now we can easily configure fully automated exports to a Storage account and, the best part of it, this is a built-in feature of Windows Azure Management Portal.</p>
<p>If you want to automate the backup of your database, just go your database and jump to the Configuration Section. In this section, you will see the settings available.</p>
<p><img src="https://guiferreira.me/images/azure-sql-database-automatic-backups-configure-screen.jpg" alt="Azure SQL Database: Automatic Backups - Configure screen"></p>
<p>Here you can configure:</p>
<ul>
<li>The storage account where you want to keep the backup files;</li>
<li>The backup frequency;</li>
<li>The retention period;</li>
</ul>
<p>Lastly, you'll need to enter the SQL Database login name and password.</p>
<p>So far as I know, you just pay the storage space.</p>
<p>Hope this helps.</p>
How to implement Getting Things Done with Trello2014-09-08T00:00:00-00:00https://guiferreira.me/archive/2014/09/how-to-implement-getting-things-done-with-trello/<p>Today I want to tell you about one of my favorites productivity methodologies and about one of my favorite tools. Why both? Because they can work perfectly side by side.</p>
<p>The methodology? <a href="http://gettingthingsdone.com/">Getting Things Done (GTD) by David Allen</a>. GTD is about clearing your mind and put everything you need to do in one place first. Collect, process, doing and keep track of it, are the key of GTD.</p>
<p>The tool? <a href="https://trello.com/">Trello.com</a>. Do you love Trello? If you don't, probably you didn't give him a try. What is Trello?</p>
<blockquote>
<p><em>"Trello is a collaboration tool that organizes your projects into boards. In one glance, Trello tells you what's being worked on, who's working on what, and where something is in a proces"</em></p>
</blockquote>
<p>I bet that you can find on the web a ton of good articles that explain the beauty of Trello and how GTD can boost your productivity, but that isn't the purpose of this post.
The objective here is to explain you how Trello and GTD can work beautifully side by side.</p>
<p><img src="https://guiferreira.me/images/how-to-implement-getting-things-done-with-trello-funny-productivity.jpg" alt="Productivity funny"></p>
<h3>Why Trello?</h3>
<p>I've been a Trello user since 2012 so I think that I'm a kind of Trello Ninja. Besides that, I follow the David Allen methodology and I've struggled to put the system rolling until I use Trello to support it.</p>
<p>Trello is based on the <a href="http://en.wikipedia.org/wiki/Kanban">Kanban</a> method. Kanban it's a way to visualize workflow. Usually a <a href="http://en.wikipedia.org/wiki/Kanban_board">kanban board</a> consists in several columns for different phases for a task. Trello also offers you multiple forms of organization like: boards, lists, cards and checklists.</p>
<h3>System setup</h3>
<p>So, how do I take advantage of it to manage my workflow? I've created a Board only for GTD management.</p>
<p>Lists:</p>
<ul>
<li>Inbox</li>
<li>Later</li>
<li>Waiting On</li>
<li>This Week</li>
<li>Today</li>
<li>Done</li>
</ul>
<p><img src="https://guiferreira.me/images/how-to-implement-getting-things-done-with-trello-board.png" alt="Trello board"></p>
<p>I also have used labels to setup contexts like:</p>
<ul>
<li>home</li>
<li>blog</li>
<li>work</li>
<li>High Priority (Use the red label for it)</li>
</ul>
<p>Appling labels to cards, related to contexts, help me to see only the cards from my current context. You can also use labels only for priority management.</p>
<h3>Weekly review</h3>
<p>On Mondays morning I look at my Trello "Later" list and move all the tasks into the "This week" or "Today" list.</p>
<h3>Daily review</h3>
<p>Use the "Inbox" list as capture repository. Process the items in the "Inbox" list daily and move them to the list that you want.
When a task is complete, archive the card.</p>
<p>Move the cards where I'm expecting someone else to do a task, to the "Waiting On" list so I can keep on top of everything.</p>
<p>If I have a complex project, I create a specific board for that project. Then, I can create some lists to control the status of each task, like: To Do, Doing, Testing, Done.</p>
<p>Before implementing your own system, read also these great examples:</p>
<ul>
<li><a href="http://joshuaearl.com/rocking-gtd-with-trello/">Rocking GTD with Trello</a></li>
<li><a href="http://schurpf.com/getting-things-done-trello-google-calendar-evernote-zapier-project-task-management/">Getting Things Done with Trello, Google Calendar, Evernote and Zapier – Project and Task Management</a></li>
</ul>
<p>I hope this helps you.</p>
Automate NuGet package creation using Grunt2014-08-29T00:00:00-00:00https://guiferreira.me/archive/2014/08/automate-nuget-package-creation-using-grunt/<p>Probably you are already using Grunt, to automate the tasks to build your application or library. In <a href="https://github.com/TalksLab/metro-bootstrap">metro-bootstrap</a> we are using Grunt to automate the build process, but until now there's a last step that we are doing manually: <strong>create the NuGet package</strong> for new releases, until today.</p>
<p>How we automate the package build?</p>
<p>It's simpler than it seems.</p>
<h3>1. Install nuget</h3>
<p>First make sure that you have nuget.exe in your machine.</p>
<p><strong>Is NuGet.exe in your PATH?</strong></p>
<ol>
<li>Open a command prompt.</li>
<li>Type <em>nuget</em> and hit enter.</li>
</ol>
<ul>
<li>If the nuget help documentation is displayed, then nuget.exe is already in your PATH.</li>
<li>If you received the message, "'nuget' is not recognized as an internal or external command, operable program or batch file." then nuget.exe is not in your PATH.</li>
</ul>
<p><strong>How to add NuGet.exe to your PATH?</strong></p>
<ol>
<li>Open a command prompt.</li>
<li>Enter the following command: <em>set PATH=%PATH%;C:\nuget</em> where "c:\nuget" is the path to the nuget.exe (<a href="http://docs.nuget.org/docs/start-here/installing-nuget#Installing_a_CI_build">available here</a>).</li>
</ol>
<h3>2. Create the NuGet definition file</h3>
<p>Create the following XML file with the definition for the package with the <em>".nuspec"</em> extension.</p>
<pre class="language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0"?></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>package</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>metadata</span><span class="token punctuation">></span></span><br> <span class="token comment"><!--<br> ID used to identify the nuget package<br> --></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span><span class="token punctuation">></span></span>metro-bootstrap<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span><br> <span class="token comment"><!--<br> Package version - leave this blank<br> --></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>0.0.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><br> <span class="token comment"><!-- Author, Owner and Licensing details --></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>authors</span><span class="token punctuation">></span></span>TalksLab<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>authors</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>owners</span><span class="token punctuation">></span></span>TalksLab<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>owners</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>requireLicenseAcceptance</span><span class="token punctuation">></span></span>false<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>requireLicenseAcceptance</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>copyright</span><span class="token punctuation">></span></span>Copyright 2014<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>copyright</span><span class="token punctuation">></span></span><br> <span class="token comment"><!-- General Information --></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>description</span><span class="token punctuation">></span></span>metro-bootstrap: Twitter Bootstrap with Metro style<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>description</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>releaseNotes</span><span class="token punctuation">></span></span>-<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>releaseNotes</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>tags</span><span class="token punctuation">></span></span>twitter bootstrap css metro responsive html5 talkslab<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>tags</span><span class="token punctuation">></span></span><br> <span class="token comment"><!--<br> Packages (incl. minimum version) on which this package<br> depends<br> --></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Twitter.Bootstrap.Less<span class="token punctuation">"</span></span> <span class="token attr-name">version</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>3.2.0.1<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>metadata</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>files</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>file</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>app\less\*<span class="token punctuation">"</span></span> <span class="token attr-name">target</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>content\Content\metro-bootstrap<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>file</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dist\css\metro-bootstrap.css<span class="token punctuation">"</span></span> <span class="token attr-name">target</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>content\Content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>file</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dist\css\metro-bootstrap.min.css<span class="token punctuation">"</span></span> <span class="token attr-name">target</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>content\Content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>files</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>package</span><span class="token punctuation">></span></span></code></pre>
<p>Define in the files element the files to copy to the package.
If you want to test the nuspec file, just type the following command in the command line (where mypackage.nuspec is the name of the nuspec file).</p>
<pre class="language-text"><code class="language-text">nuget pack mypackage.nuspec</code></pre>
<h3>3. Create grunt task to build the NuGet package</h3>
<p>In order to create the file, go to the grunt script and add the following task (just rename the definition file name):</p>
<pre class="language-js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">"nuget"</span><span class="token punctuation">,</span> <span class="token string">"Create a nuget package"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">var</span> done <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">async</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token comment">//invoke nuget.exe</span><br> grunt<span class="token punctuation">.</span>util<span class="token punctuation">.</span><span class="token function">spawn</span><span class="token punctuation">(</span><br> <span class="token punctuation">{</span><br> <span class="token literal-property property">cmd</span><span class="token operator">:</span> <span class="token string">"nuget.exe"</span><span class="token punctuation">,</span><br> <span class="token literal-property property">args</span><span class="token operator">:</span> <span class="token punctuation">[</span><br> <span class="token comment">//definition file</span><br> <span class="token string">"pack"</span><span class="token punctuation">,</span><br> <span class="token string">"metro-bootstrap.nuspec"</span><span class="token punctuation">,</span><br><br> <span class="token comment">//path where the package should be created</span><br> <span class="token string">"-OutputDirectory"</span><span class="token punctuation">,</span><br> <span class="token string">"nuget"</span><span class="token punctuation">,</span><br><br> <span class="token comment">//override the version using the version in package.json</span><br> <span class="token string">"-Version"</span><span class="token punctuation">,</span><br> grunt<span class="token punctuation">.</span>config<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"pkg"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>version<span class="token punctuation">,</span><br> <span class="token punctuation">]</span><span class="token punctuation">,</span><br> <span class="token punctuation">}</span><span class="token punctuation">,</span><br> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">error<span class="token punctuation">,</span> result</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span><br> grunt<span class="token punctuation">.</span>log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br> grunt<span class="token punctuation">.</span>log<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token function">done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now, just open the command line and run the <em>"grunt nuget"</em> command, and a nuget package will be created.</p>
<p>The configuration used in this post is running on <a href="https://github.com/TalksLab/metro-bootstrap">metro-bootstrap</a> library. Fill free to fork it and try.</p>
<p>I hope this helps you.</p>
metro-bootstrap 3.2.0.1 released2014-08-07T00:00:00-00:00https://guiferreira.me/archive/2014/08/metro-bootstrap-3-2-0-1-released/<p>Yesterday we released metro-bootstrap 3.2.0.1. The new version brings the update to bootstrap 3.2.0 and some new configurations related to tiles.</p>
<h2>What's new</h2>
<h3>Dependencies</h3>
<ul>
<li>bootstrap 3.2.0</li>
</ul>
<h3>Bower configuration - Add "main"</h3>
<p>Has been added the "main" option to the bower.json file. Thanks to <a href="https://github.com/fumitoito">@fumito_ito</a>.</p>
<h3>New variables</h3>
<ul>
<li><em>@tile-light-text-color</em>: Set the default color for <em>tile-clouds</em>.</li>
<li><em>@tile-font-size-h1</em>: Set the default font size in h1 tags inside tiles.</li>
<li><em>@tile-font-size-h2</em>: Set the default font size in h2 tags inside tiles.</li>
<li><em>@tile-font-size-h3</em>: Set the default font size in h3 tags inside tiles.</li>
<li><em>@tile-font-size-h4</em>: Set the default font size in h4 tags inside tiles.</li>
</ul>
Have fun with Cortana2014-07-31T00:00:00-00:00https://guiferreira.me/archive/2014/07/have-fun-with-cortana/<p>Have you heard about Cortana? If you are a proud owner of a Windows Phone, I bet you did.</p>
<p>To the others, Cortana is like Siri, but for Windows Phone. One of the few things where iPhone was the first, since Windows Phone release (if you are an Apple fan, I bet that you want to leave your opinion, scroll down and leave a comment, but remember that this is just my humble opinion ☺ ).</p>
<p>If you have a Windows Phone with 8.1 installed you can start using Cortana. I have been testing and I found some funny questions and another more useful.</p>
<p>I leave a cool list below.</p>
<h2>Funny commands</h2>
<ul>
<li>Tell me a joke.</li>
<li>Sing me a song.</li>
<li>Tell me a story.</li>
<li>What does the fox say?</li>
<li>Knock knock.</li>
<li>Why did the chicken cross the road?</li>
<li>Say something funny.</li>
<li>Where do babies come from?</li>
<li>What is the meaning of life?</li>
<li>Guess what?</li>
<li>Do you like Siri?</li>
<li>What are you wearing?</li>
<li>May the force be with you.</li>
<li>Cortana, I'm your father.</li>
<li>Which is better: Linux or Windows?</li>
<li>Are you drunk?</li>
<li>Can you cook?</li>
<li>Fu*k you.</li>
<li>Cortana.</li>
<li>Talk dirty.</li>
</ul>
<h2>Useful commands</h2>
<ul>
<li>Call Peter.</li>
<li>Text Peter.</li>
<li>Add appointment to calendar tomorrow.</li>
<li>What do I have next?</li>
<li>Remind me to call Peter tomorrow.</li>
<li>Note: Get eggs.</li>
<li>Wake me up at 8 AM.</li>
<li>What song is playing.</li>
<li>Pause playing.</li>
<li>Forecast for tomorrow.</li>
<li>Forecast for tomorrow in celsius degrees.</li>
<li>Change in Celsius.</li>
</ul>
<p>Enjoy and have fun!</p>
Your product needs an identity2014-07-23T00:00:00-00:00https://guiferreira.me/archive/2014/07/your-product-needs-an-identity/<p>Have you ever asked yourself why people fall in love with products? Recently I listen <a href="http://sethgodin.typepad.com/">Seth Godin</a> saying that <em>"if you are making a product for everyone, you are making a product for no one"</em>. I believe that this incredible sentence reveals the answer to the question.</p>
<p>This post will tell you why it's so important to create a strong identity for your product.</p>
<p><img src="https://guiferreira.me/images/your-product-needs-an-identity-homer-simpson-donut-dream.gif" alt="product-love"></p>
<p>The philosophy behind Seth's words isn't something new. You probably heard about this on product development methodologies or about the <em>horizontal marketing</em> vs <em>vertical marketing</em>.</p>
<p>I'm a defensor that we should read Seth's advise as "a product should have a mission, a vision, an identity, as if we were describing a person, a friend", because when we are creating something for everyone, a "horizontal product", we usually add complexity and a lack of "identity" to our product.</p>
<p>So, <strong>what makes up an identity?</strong> It’s what you stand for, it's your passions, values and beliefs.</p>
<p>The world around us has a lot of good examples of this, for example:</p>
<ul>
<li><strong>Apple</strong>: Has an identity of innovation and design.</li>
<li><strong>McDonald's</strong>: Provide the best quick service restaurant experience. Let's be honest, isn't McDonald's one of the first options that came to your mind when you need a quick meal?</li>
<li><strong>Basecamp</strong>: Has started with a mission to create an awesome project management tool for design companies.</li>
<li><strong>Personas</strong>: UX and Design teams, usually start by creating a persona that represents a hypothetical customer.</li>
<li><strong>Google</strong>: Simplicity and information side by side.</li>
<li><strong>Gourmet restaurants</strong>: They create a clear identity based on quality, trying to reach a concrete market.</li>
</ul>
<p><strong>Why an identity is so important?</strong></p>
<p>People feel attracted to strong identities and tend to create a relation with a brand or a product that has some characteristics that they like. As <a href="https://stackingthebricks.com/how-do-you-market-a-product-thats-for-everyone/">Amy Hoy</a> said <em>"Nobody wants to be everybody"</em>.
Your friends are amazing because of their unique personality or because they are likable people?! I bet that you like them because they are awesome.</p>
<iframe src="https://giphy.com/embed/ly12YiQjsvupi" width="500" height="233" frameBorder="0" webkitAllowFullScreen="" mozallowfullscreen="" allowFullScreen=""></iframe>
<p>So, if you are creating a product, you should try to find your identity and remember that, your target market should see in your identity a personality that they love. Then, just keep in mind "who you are" and you will see people falling in love with your product.</p>
<!--[![shut-up-and-take-my-money](/images/00-global-shut-up-and-take-my-money.gif)](http://knowyourmeme.com/photos/264241-shut-up-and-take-my-money)-->
<p>An identity isn't just something to be written on a wall. It’s something that you believe and that you live it everyday.</p>
<p>Just remember, "it’s for everybody!" probably isn't the best answer.</p>
Analyse Azure Log Tables using SQL Queries2014-07-15T00:00:00-00:00https://guiferreira.me/archive/2014/07/analyse-azure-log-tables-using-sql-queries/<p>If you are using <a href="http://azure.microsoft.com/en-us/documentation/articles/cloud-services-dotnet-diagnostics/">Diagnostics</a> in Microsoft Azure, probably you walked through the horrible experience of analyse that data, specially if you are looking for a specific TimeStamp in the middle of tons of records.</p>
<p>This is so slow because the TimeStamp column, in Azure Table Storage, isn't indexed, but if you take a closer view, you will see that the partition key of WADLogTable is the date-time in ticks, and querying by the partition key is incredible fast.</p>
<p>If you want to query your table manually you will need to convert your date into ticks like this:</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token class-name">DateTime</span> dt <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2014</span><span class="token punctuation">,</span> <span class="token number">07</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token class-name"><span class="token keyword">long</span></span> tks <span class="token operator">=</span> dt<span class="token punctuation">.</span>Ticks<span class="token punctuation">;</span><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span>tks<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This can be useful, but in some cases you will need to query over the "Message" column and that can be hard.</p>
<p>To overtake this difficulty, recently I was looking for a way to run SQL queries over the WADLogsTable since the Azure Storage Explorer isn't a good help. So, I have found this great tool <a href="https://github.com/SageLukeDean/AzureLogSpelunker">AzureLogSpelunker</a> by <a href="https://github.com/SageLukeDean">Luke Dean</a>.</p>
<p><img src="https://guiferreira.me/images/analyse-azure-log-tables-using-sql-queries-azurelogspelunker.png" alt="AzureLogSpelunker"></p>
<p>AzureLogSpelunker can be used to request the logs for a specific period, then the tool will cache them locally in a SQLite database where you may run SQL queries. This tool is a must have if you are using the Microsoft Azure Platform.</p>
<p>I hope this helps you.</p>
metro-bootstrap with improved tiles2014-07-04T00:00:00-00:00https://guiferreira.me/archive/2014/07/metro-bootstrap-with-improved-tiles/<p>Yesterday we released metro-bootstrap 3.1.1.2. The highlights of this release are based on improvements to tiles. We have been working to give you the flexibility to implement tiles where you want and as you want.</p>
<p>In the previous version metro-bootstrap tiles were based on the Thumbnail component of bootstrap that will let you place them side by side easily. Now you will be able to place a tile in a "div" tag, for example, and set the positioning as you want.</p>
<h2>What's new</h2>
<p>Here's a look at tiles news.</p>
<h3>New positioning - Remove Thumbnail dependency</h3>
<p>In the last version was mandatory to use thumbnails, now don't. If you want, you can use them, but you aren't obligated anymore. For example, if you want to create a Tile board taking part of the Bootstrap grid system you can (<a href="http://talkslab.github.io/metro-bootstrap/dashboardtemplate.html">you can find here an example of how you can accomplish this</a>).</p>
<h3>New template</h3>
<p>You can find <a href="http://talkslab.github.io/metro-bootstrap/dashboardtemplate.html">here</a> a template of a responsive dashboard based on tiles.</p>
<p><img src="https://guiferreira.me/images/metro-bootstrap-with-improved-tiles-dashboard-template.png" alt="metro-bootstrap dashboard template"></p>
<h3>New colors</h3>
<p>Using the info, danger, warning and success colors already defined in bootstrap, you can add the following classes to your tiles:</p>
<ul>
<li><em>tile-info</em></li>
<li><em>tile-danger</em></li>
<li><em>tile-warning</em></li>
<li><em>tile-success</em></li>
</ul>
<h3>New default variables</h3>
<p>In the <em>variables.less</em> file you can find the following variables:</p>
<ul>
<li><em>@tile-bg</em> to define the default color for tiles</li>
<li><em>@tile-border</em> to define the border size</li>
<li><em>@tile-border-bg</em> to define the border color</li>
</ul>
<h3>New sizes</h3>
<p>Following the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh465403.aspx">Microsoft Guidelines</a> were implemented new classes and now it's possible define the following sizes:</p>
<ul>
<li>Small (70x70). Add the css class <em>tile-small</em>.</li>
<li>Medium (150x150). Add the css class <em>tile-medium</em>.</li>
<li>Wide (310x150). Add the css class <em>tile-wide</em>.</li>
<li>Large (310x310). Add the css class <em>tile-large</em>.</li>
</ul>
<h3>Tile title</h3>
<p>Place a tile title on the lower left corner.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tile-label<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Tile 5<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span></code></pre>
<h3>What's next</h3>
<p>Well, since Bootstrap v3.2.0 has been released we'll be updating metro-bootstrap to be compatible with it soon.</p>
Add documentation to your Web API in 5 steps2014-06-27T00:00:00-00:00https://guiferreira.me/archive/2014/06/add-documentation-to-your-web-api-in-5-steps/<p>APIs are created to expose the system to other developers, so we need to provide documentation that explain how to use our API.</p>
<p>So far, so good, but maintain documents manually is a kind of boring. What about auto-generate it?</p>
<p>Well, if you are using ASP.NET Web API this is a piece of cake.</p>
<p>How to add documentation to your ASP.NET Web API?</p>
<ol>
<li>Install "<em>Microsoft.AspNet.WebApi.HelpPage</em>" package from nuget. (If you are using VB.NET install "<em>Microsoft.AspNet.WebApi.HelpPage.VB</em>"). This package will create an Area called "Help" in the API project.</li>
<li>Make sure that you have the following code in the "<em>Application_Start</em>" method at your Global.asax file: <em>AreaRegistration.RegisterAllAreas();</em></li>
<li>Documentation will be available in the <em>/Help</em> URI. So, just add a link to it in your application.</li>
<li>To enable the XML Documentation comments, open the file <em>Areas/HelpPage/App_Start/HelpPageConfig.cs</em> and uncomment the line "<em>config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));</em>"</li>
<li>In Solution Explorer, right-click the project, select Properties, then go to the <em>Build</em> page. In the <em>Output</em> section check the <em>XML documentation file</em> property and set the text box with the value "App_Data/XmlDocument.xml".</li>
</ol>
<p>Now you are able to start adding comments to your Web API methods, as you can see in the following example:</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token comment">/// <summary></span><br> <span class="token comment">/// Get text by ID</span><br> <span class="token comment">/// </summary></span><br> <span class="token comment">/// <param name="id">ID used to get the result text.</param></span><br> <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> id<span class="token punctuation">)</span><br> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token string">"value"</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span></code></pre>
<p>Build your application and you are done! Now, if you want to do some advanced stuff, I recommend that you take a look into the following posts:</p>
<ul>
<li><a href="http://www.asp.net/web-api/overview/creating-web-apis/creating-api-help-pages">Creating Help Pages for ASP.NET Web API</a></li>
<li><a href="http://blogs.msdn.com/b/yaohuang1/archive/2012/12/10/asp-net-web-api-help-page-part-3-advanced-help-page-customizations.aspx">Advanced Help Page customizations</a></li>
<li><a href="http://blogs.msdn.com/b/yaohuang1/archive/2012/08/15/introducing-the-asp-net-web-api-help-page-preview.aspx">Introducing the ASP.NET Web API Help Page</a></li>
</ul>
<p>I hope this helps you.</p>
Update GitHub Pages using a project subfolder2014-06-21T00:00:00-00:00https://guiferreira.me/archive/2014/06/update-github-pages-using-a-project-subfolder/<p>Do you have a project in GitHub and you are tired of manage the <em>gh-pages</em> branch manually?! If so, stay tuned because that can be pretty simple.</p>
<p>I used to make a full copy of the master repository into the <em>gh-pages</em> using the <em>rebase</em> command, but this brings a lack of organization because it's difficult don't mix the source code and the web pages files.</p>
<p>This is the process that I used to update the full branch:</p>
<pre class="language-text"><code class="language-text">git checkout gh-pages // go to the gh-pages branch<br>git rebase master // bring gh-pages up to date with master<br>git push origin gh-pages // commit the changes<br>git checkout master // return to the master branch</code></pre>
<p>Recently I re-organize my repository to have a <em>docs</em> subdirectory, on the master branch, where I put the files required for web pages and with the following command I did some magic:</p>
<pre class="language-text"><code class="language-text">git subtree push --prefix docs origin gh-pages // Replace 'docs' by your folder name</code></pre>
<p>Now, the <em>docs</em> folder is the root directory of gh-pages branch.</p>
<p>This seems pretty simple, but in the process I found some troubled waters. So, I leave the details here, in case you get the same problem.</p>
<p>In my first tries I got the following error:</p>
<pre class="language-text"><code class="language-text">! [rejected] 1835ac01fe63c030216c22d3d834366d5e2a854r -> gh-pages (non-fast-forward)<br>error: failed to push some refs to 'https://github.com/gsferreira/myrepository.git'<br>hint: Updates were rejected because a pushed branch tip is behind its remote<br>hint: counterpart. Check out this branch and integrate the remote changes<br>hint: (e.g. 'git pull ...') before pushing again.<br>hint: See the 'Note about fast-forwards' in 'git push --help' for details.</code></pre>
<p>If you want to get rid of this error, I suggest that you delete your gh-pages branch and then recreate it before execute the <em>git subtree</em> command.</p>
<p>How to delete a branch?</p>
<pre class="language-text"><code class="language-text">git push origin :gh-pages</code></pre>
<p>I hope this helps you.</p>
Bringing Grunt and Bower to metro-bootstrap2014-06-05T00:00:00-00:00https://guiferreira.me/archive/2014/06/bringing-grunt-and-bower-to-metro-bootstrap/<p>Since we publish <a href="https://github.com/TalksLab/metro-bootstrap">metro-bootstrap</a> we saw an incredible acceptance to the project and we are really happy to have decided to delivery it as an open source project.</p>
<p>This project has grown up with a lack of structure in my opinion, so, this week I've been working to add Grunt and Bower to metro-bootstrap. To accomplish this task, I have the valuable help of <a href="http://yeoman.io/">Yeoman</a>. If you're like me, and <a href="http://gruntjs.com/">Grunt</a> or <a href="http://bower.io/">Bower</a> are crazy talk, you will find in Yeoman a great way to start.</p>
<p><a href="http://yeoman.io/"><img src="https://guiferreira.me/images/bringing-grunt-and-bower-to-metro-bootstrap-yeoman.jpg" alt="Yeoman"></a></p>
<p>We have adopted bower for dependency management, so we can manage the dependencies in a declarative way. Now you can know the current dependencies looking at the bower.json file.</p>
<p>Since the metro-bootstrap release, we always work on .less files, but we also release the css file and a minified version of it. To do this, we used some tools like <a href="http://wearekiss.com/simpless">SimpLESS</a> or <a href="http://winless.org/">WinLess</a>. This is over, now we leave this responsibility to Grunt. Grunt is the tool to compile the less files, minify the css files and release our page for GitHub Pages.</p>
<p>What have changed? Take a look.</p>
<h2>Repository structure</h2>
<p>In the repository you will find the following directories:</p>
<p>app/
├── fonts/
│ └── (FontAwesome files)
└── less/
└── (metro-bootstrap less files)
dist/
├── fonts/
│ └── font-awesome/
│ │ └── (FontAwesome files)
└── css/
├── metro-bootstrap.css
└── metro-bootstrap.min.css
docs/
└── (metro-bootstrap GitHub Pages)</p>
<p>We provide compiled CSS (<code>metro-bootstrap.css</code>) in the dist folder, as well as compiled and minified CSS (<code>metro-bootstrap.min.css</code>).</p>
<h2>Instaling Dependencies</h2>
<p>We manage dependencies using Bower.
Run <code>bower install</code> to download the required dependencies.</p>
<p>If don't have Grunt installed, execute the following steps from the command line:</p>
<ol>
<li>Make sure you have node.js installed.</li>
<li>Install bower with <code>npm install -g bower</code>.</li>
</ol>
<h2>Compiling CSS</h2>
<p>We compile metro-bootstrap using <a href="http://gruntjs.com/">Grunt</a>.
Run <code>grunt build</code> to compile the CSS into <code>/dist</code>.</p>
<p>If don't have Grunt installed, execute the following steps from the command line:</p>
<ol>
<li>Make sure you have node.js installed.</li>
<li>Install <code>grunt-cli</code> globally with <code>npm install -g grunt-cli</code>.</li>
<li>Go to the <code>metro-bootstrap</code> directory, then run <code>npm install</code>. npm will look at package.json and automatically install the necessary dependencies.</li>
</ol>
<p>Now, go fork it!</p>
Reasons to blogging with GitHub Pages and Sandra.Snow2014-05-31T00:00:00-00:00https://guiferreira.me/archive/2014/05/reasons-to-blogging-with-github-pages-and-sandra-snow/<p>This is my second try to create a personal blog and the third blog where I'm writing. The first two experiences were in WordPress.</p>
<p>In the past, my attempts failed by my fault, lack of commitment... But during the process, I learned how hard is to maintain a self hosted blog.</p>
<p>Create content to a blog is really time-consuming, so I don't need more work to maintain it. Maybe this is my Developer side telling me to stay away from maintenance tasks, like update packages and be sure that I'm not hacked.</p>
<p>let's be realistic, when we're a blogger <strong>the focus should be the content</strong>, the other tasks are just a black hole for the precious free time.</p>
<p><img src="https://guiferreira.me/images/reasons-to-blogging-using-github-pages-and-sandra-snow-my-precious-time.jpg" alt="Gollum - My Precious Time"></p>
<p>So, what I was looking for when I started this page?!</p>
<ol>
<li>Write using markdown</li>
<li>Comments using Disqus</li>
<li>Easy customization</li>
<li>Reduce the infrastructure costs</li>
<li>A lightweight blog</li>
<li>No database</li>
<li>Version control/Hitory</li>
</ol>
<p>Based on these requirements, I found <a href="https://jekyllrb.com/">Jekyll</a> hosted over <a href="https://pages.github.com/">GitHub Pages</a>. It fits perfectly and the number of users active can attest it. The downside?! I need ruby to use it. Since I'm a Windows guy and in my professional life I'm mostly connected to .NET Developement I don't want to install ruby on my machines.</p>
<p>A friend of mine (<a href="https://twitter.com/NelsonReis">@NelsonReis</a>) suggested I look at <a href="https://github.com/Sandra/Sandra.Snow">Sandra.Snow</a>, a system inspired by Jekyll, which is <strong>written in .NET and <a href="https://nancyfx.org/">Nancy</a></strong>, by <a href="https://twitter.com/philliphaydon">Phillip Haydon</a> and <a href="https://twitter.com/jchannon">Jonathan Channon</a>. So, I picked it! Now my website is generated using Sandra.Snow and hosted on GitHub pages.</p>
<p>During the process, I created <a href="https://github.com/gsferreira/letsnow"><em>letsnow</em></a>, a simple theme based on snowbyte theme. You can use it, fork it and contribute. I would love to hear your opinion.</p>
<p>Well, I could describe here how I did it, but since there's already a lot of good articles of it, I leave you here some to guide you. You will see that it's a piece of cake.</p>
<ul>
<li><a href="https://www.philliphaydon.com/2013/10/introducing-sandra-snow/">"Introducing Sandra.Snow"</a> by Phillip Haydon</li>
<li><a href="https://www.macsdickinson.com/SandraSnow/hello-sandra-snow/#.U4j33_ldXN1">"Hello Sandra Snow"</a> by Macs Dickinson</li>
<li><a href="https://blog.jonathanchannon.com/2013/10/01/blogging-with-markdown-and-git/">"Blogging with Markdown & Deploying via Git - Introducing Sandra.Snow"</a> by Jonathan Channon</li>
</ul>
<p><img src="https://guiferreira.me/images/reasons-to-blogging-using-github-pages-and-sandra-snow-feel-like-superhero.png" alt="Feel like a superhero"></p>
<p><strong>What I hope to see in Sandra.Snow in a near future?!</strong></p>
<ul>
<li>Generate RSS feeds for any category</li>
<li>More configuration options, like Google Analytics ID or Disqus ID</li>
<li>A "marketplace" for Sandra.Snow blog templates</li>
</ul>
<p>It's too early to say that Sandra.Snow is perfect for me, but I hope that it was a wise decision!</p>
AngularJS - Smart Float Directive2014-05-24T00:00:00-00:00https://guiferreira.me/archive/2014/05/angularjs-smart-float-directive/<p>Recently I started looking for an AngluarJS directive to validate numbers and I found the "smart-float" directive <a href="https://docs.angularjs.org/guide/forms">here</a>, in the AngularJS documentation. This amazing example solves the problem of convert my numbers that use a comma as decimal mark to a Javascript number.</p>
<p>My problem is that this directive doesn't solve my two problems:</p>
<ol>
<li>Display numbers with 2 fractional digits by default.</li>
<li>Validate numbers with thousands separator.</li>
</ol>
<p>So, this is an improved directive based on Angular's <em>smart-float</em> directive.
First, add the following directive to your application:</p>
<pre class="language-js"><code class="language-js">myApp<span class="token punctuation">.</span><span class="token function">directive</span><span class="token punctuation">(</span><span class="token string">"smartFloat"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">$filter</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">var</span> <span class="token constant">FLOAT_REGEXP_1</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\$?\d+.(\d{3})*(\,\d*)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span> <span class="token comment">//Numbers like: 1.123,56</span><br> <span class="token keyword">var</span> <span class="token constant">FLOAT_REGEXP_2</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\$?\d+,(\d{3})*(\.\d*)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span> <span class="token comment">//Numbers like: 1,123.56</span><br> <span class="token keyword">var</span> <span class="token constant">FLOAT_REGEXP_3</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\$?\d+(\.\d*)?$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span> <span class="token comment">//Numbers like: 1123.56</span><br> <span class="token keyword">var</span> <span class="token constant">FLOAT_REGEXP_4</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\$?\d+(\,\d*)?$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span> <span class="token comment">//Numbers like: 1123,56</span><br><br> <span class="token keyword">return</span> <span class="token punctuation">{</span><br> <span class="token literal-property property">require</span><span class="token operator">:</span> <span class="token string">"ngModel"</span><span class="token punctuation">,</span><br> <span class="token function-variable function">link</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">scope<span class="token punctuation">,</span> elm<span class="token punctuation">,</span> attrs<span class="token punctuation">,</span> ctrl</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> ctrl<span class="token punctuation">.</span>$parsers<span class="token punctuation">.</span><span class="token function">unshift</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">viewValue</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">FLOAT_REGEXP_1</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> ctrl<span class="token punctuation">.</span><span class="token function">$setValidity</span><span class="token punctuation">(</span><span class="token string">"float"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token function">parseFloat</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">"."</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">","</span><span class="token punctuation">,</span> <span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">FLOAT_REGEXP_2</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> ctrl<span class="token punctuation">.</span><span class="token function">$setValidity</span><span class="token punctuation">(</span><span class="token string">"float"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token function">parseFloat</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">","</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">FLOAT_REGEXP_3</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> ctrl<span class="token punctuation">.</span><span class="token function">$setValidity</span><span class="token punctuation">(</span><span class="token string">"float"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token function">parseFloat</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">FLOAT_REGEXP_4</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> ctrl<span class="token punctuation">.</span><span class="token function">$setValidity</span><span class="token punctuation">(</span><span class="token string">"float"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token function">parseFloat</span><span class="token punctuation">(</span>viewValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">","</span><span class="token punctuation">,</span> <span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br> ctrl<span class="token punctuation">.</span><span class="token function">$setValidity</span><span class="token punctuation">(</span><span class="token string">"float"</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token keyword">return</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> ctrl<span class="token punctuation">.</span>$formatters<span class="token punctuation">.</span><span class="token function">unshift</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">modelValue</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br> <span class="token keyword">return</span> <span class="token function">$filter</span><span class="token punctuation">(</span><span class="token string">"number"</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token function">parseFloat</span><span class="token punctuation">(</span>modelValue<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> <span class="token punctuation">}</span><span class="token punctuation">,</span><br> <span class="token punctuation">}</span><span class="token punctuation">;</span><br><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now, add the <em>smart-float</em> directive to your input:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputAmount<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputAmount<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Amount<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>amount<span class="token punctuation">"</span></span><br> <span class="token attr-name">smart-float</span><br><span class="token punctuation">/></span></span></code></pre>
<p>This gives you what you need. Now, you can improve it showing to your users that the value in the input is invalid. In the following example I used <a href="https://getbootstrap.com/">Bootstrap</a> to demonstrate it:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myForm<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-horizontal<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form<span class="token punctuation">"</span></span> <span class="token attr-name">novalidate</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-group<span class="token punctuation">"</span></span> <span class="token attr-name">ng-class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{<span class="token punctuation">'</span>has-error<span class="token punctuation">'</span>: myForm.inputAmount.$invalid}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputText3<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>col-sm-2 control-label<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Amount<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>col-sm-10<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span><br> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><br> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-control<span class="token punctuation">"</span></span><br> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputAmount<span class="token punctuation">"</span></span><br> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inputAmount<span class="token punctuation">"</span></span><br> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Amount<span class="token punctuation">"</span></span><br> <span class="token attr-name">ng-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>amount<span class="token punctuation">"</span></span><br> <span class="token attr-name">smart-float</span><br> <span class="token punctuation">/></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>help-block<span class="token punctuation">"</span></span> <span class="token attr-name">ng-show</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myForm.inputAmount.$error.float<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br> Invalid Amount!<br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span></code></pre>
<p>You can see the working demo on <a href="https://jsfiddle.net/gsferreira/SCr6X/">JSFiddle</a>.</p>
<p>I hope that this helps you.</p>
<h2>UPDATE 2015-03-11</h2>
<p>Post has been updated with a fix to a bug that <a href="https://disqus.com/by/coopersellers/">Cooper Sellers</a> found (you can see the details at the comment feed below).</p>
Pomodoro Technique, the productivity sauce2014-05-19T00:00:00-00:00https://guiferreira.me/archive/2014/05/pomodoro-technique-the-productivity-sauce/<p>You've probably heard about the <a href="https://pomodorotechnique.com/">Pomodoro Technique</a>. This is one of the most popular time management tools nowadays. This technique has been developed by <em><a href="https://francescocirillo.com/">Francesco Cirillo</a></em> in the late 1980s.</p>
<p>In the modern days we keep fighting against the clock, trying to accomplish all the assignments. But in the other hand we have a lot of distractions, as the Facebook messages, new tweets or our phones. The Pomodoro Technique wants to teach you to use the time as your friend, being productive, eliminating the procrastination, the pressure and get free time for yourself. Pomodoro Technique also can be a great complement for other methodology's. I used it in my <a href="https://gettingthingsdone.com/">GTD (Getting Things Done)</a> workflow for example.</p>
<p><img src="https://guiferreira.me/images/pomodoro-technique-the-productivity-sauce-modern-family-decisions-under-pressure.jpg" alt="Modern Family - Decisions under pressure"></p>
<p>Pomodoro is the Italian word for tomato, and Francesco named it as pomodoro because he used a kitchen timer with a tomato shape as his personal timer.
The technique consists in for each 25 minute work period (this period is called a "Pomodoro") take a five minutes break. In this break <strong>you shouldn't go to your social networks</strong>... beware of shiny objects. Instead, you should rest your eyes, grab a cup of coffee or go take a walk. Every four pomodoros you should take a longer break of 20 minutes. Frequent breaks keep your mind fresh and focused. Your brain will retrieve you the favor.</p>
<p><a href="https://www.flickr.com/photos/33593406@N03/7738254354/"><img src="https://guiferreira.me/images/pomodoro-technique-the-productivity-sauce-pomodoro-timer.jpg" alt="Pomodoro timer"></a></p>
<!---*"Photo by [Kate Bunker](http://www.flickr.com/photos/33593406@N03/7738254354/) licensed under [Creative Commons Attribution-NonCommercial License](http://creativecommons.org/licenses/by-nc/2.0/)."*
-->
<p>You should be asking <strong>why the 25 minutes</strong>? I really don't know, and that is a question that I have made to myself. After some research, I believe that the 25 minutes is the "ideal" period to keep the focus on a single task, if you have longer periods your brain will get tired, but this is a personal conclusion.</p>
<p>This isn't applicable for anyone, but if you usually seat down at a desk and you need to get things done, I believe that you can use it. I use it while I'm programming because it helps me stay focused and "force" me to break large tasks into short steps. I also like to use it in teamwork, for example, in pair programming or in a <a href="https://en.wikipedia.org/wiki/Stand-up_meeting">Scrum stand-up meeting</a>. The ticking clock will teach your team that time is running out and the task should completed. If you are questioning yourself if this is a good tool for you, go check this <a href="https://pomodorotechnique.com/get-started/">page</a>, probably you will find your case.</p>
<p>You could find some problems to apply it, for example:</p>
<ul>
<li>How to concentrate without interruptions, specially if you are inside a team.</li>
<li>The open-plan offices can be an enemy, so pick the perfect music and put your headphones.</li>
<li>It's possible don't answer your phone during a pomodoro in your position?</li>
<li>Keep the flow while dealing with interaction with the co-workers.</li>
<li>Meetings... a necessary evil.</li>
</ul>
<p>Pomodoro Technique is free, you can spend some money to get a kitchen timer if you want… or you can use any timer program on your computer or phone (I'm using the <a href="https://chrome.google.com/webstore/detail/simple-pomodoro%C2%AE/blidjjfbdbkcmegfnidmgndgdamhhelp"><em>Simple Pomodoro</em> extension for Chrome</a>). The process isn't ideal for every person, but if you want to boost your productivity you can try it and let me know the results in the comments below.</p>
<p>By the way, this post has been written in 4 pomodoros.</p>
The dark side of dynamic typing2014-05-08T00:00:00-00:00https://guiferreira.me/archive/2014/05/the-dark-side-of-dynamic-typing/<p><a href="https://msdn.microsoft.com/en-us/library/dd264736.aspx">Dynamic typing</a> isn't anything new in the .NET Framework world, he is available since .NET 4.0 and I'm sure that you have used it. If you didn't, you should take a spare of time for it. Dynamic typing is great because it let you get your work done faster and it may avoid some complicated reflection code, for example. I've used it a lot, but recently I've discovered his dark side... <strong>the performance side</strong>.</p>
<p>Why do I say it? If you measure the performance cost of a simple "Set" or "Get" operation you will see a great improvement simply changing it to typed code. You can use the following code to test it.</p>
<pre class="language-csharp"><code class="language-csharp"> <span class="token comment">//Typed Object performance - SET PERFORMANCE</span><br> <span class="token class-name">MyClass</span> myObject <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MyClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> myObject<span class="token punctuation">.</span>Str <span class="token operator">=</span> <span class="token string">"Hello World!"</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Typed Object - SET - Elapsed={0}"</span><span class="token punctuation">,</span> sw<span class="token punctuation">.</span>Elapsed<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><br> <span class="token comment">//Typed Object performance - GET PERFORMANCE</span><br> sw<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> result <span class="token operator">=</span> myObject<span class="token punctuation">.</span>Str<span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Typed Object - GET - Elapsed={0}"</span><span class="token punctuation">,</span> sw<span class="token punctuation">.</span>Elapsed<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br><br> <span class="token comment">//Dynamic Object performance - SET PERFORMANCE</span><br> <span class="token class-name"><span class="token keyword">dynamic</span></span> myDynamicObject <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MyClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> myDynamicObject<span class="token punctuation">.</span>Str <span class="token operator">=</span> <span class="token string">"Hello World!"</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Dynamic Object - SET - Elapsed={0}"</span><span class="token punctuation">,</span> sw<span class="token punctuation">.</span>Elapsed<span class="token punctuation">)</span><span class="token punctuation">;</span><br><br> <span class="token comment">//Dynamic Object performance - GET PERFORMANCE</span><br> sw<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> result <span class="token operator">=</span> myDynamicObject<span class="token punctuation">.</span>Str<span class="token punctuation">;</span><br> sw<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br> Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Dynamic Object - GET - Elapsed={0}"</span><span class="token punctuation">,</span> sw<span class="token punctuation">.</span>Elapsed<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>With this piece of code inside a loop I got the following results. You can see the time differences.</p>
<ul>
<li>Typed Object - GET - Elapsed=00:00:00.0000022</li>
<li>Typed Object - SET - Elapsed=00:00:00.0000008</li>
<li>Dynamic Object - GET - Elapsed=00:00:00.0330937</li>
<li>Dynamic Object - SET - Elapsed=00:00:00.0027800</li>
<li>Typed Object - GET - Elapsed=00:00:00</li>
<li>Typed Object - SET - Elapsed=00:00:00.0000004</li>
<li>Dynamic Object - GET - Elapsed=00:00:00.0000031</li>
<li>Dynamic Object - SET - Elapsed=00:00:00.0000026</li>
<li>Typed Object - GET - Elapsed=00:00:00.0000004</li>
<li>Typed Object - SET - Elapsed=00:00:00.0000004</li>
<li>Dynamic Object - GET - Elapsed=00:00:00.0000022</li>
<li>Dynamic Object - SET - Elapsed=00:00:00.0000026</li>
<li>Typed Object - GET - Elapsed=00:00:00.0000004</li>
<li>Typed Object - SET - Elapsed=00:00:00.0000004</li>
<li>Dynamic Object - GET - Elapsed=00:00:00.0000022</li>
<li>Dynamic Object - SET - Elapsed=00:00:00.0000022</li>
</ul>
<p>I'm not trying to tell you to keep a safety distance from dynamic typing, I'm just saying that if you're building an application where the performance is a key factor, where you don't need dynamic typing and you really need to pay attention to any fraction of second... so you should keep an eye on it.</p>
Move your database to new SQL Azure Service Tiers2014-05-03T00:00:00-00:00https://guiferreira.me/archive/2014/05/move-database-new-sql-azure-service-tiers/<p>In the last Build conference Scott Guthrie announced the new Basic and Standard tier option to the SQL Databases on Azure. Those tiers bring amazing features and you can find more about them in the <a href="https://weblogs.asp.net/scottgu/archive/2014/04/29/azure-99-95-sql-database-sla-500-gb-db-size-improved-performance-self-service-restore-and-business-continuity.aspx">Scott's post</a>. If you want to try it, as I did, go ahead and take advantage of the 50% discount during the preview period.</p>
<p>You can find here how to move your SQL Database currently in the Web or Business edition using the following tips.</p>
<p>Before you start, make sure that you have a Windows Azure Storage Account and a container in it.</p>
<p>First of all you should take your web site or any client of your database offline, just to ensure that no one updates the database during this operation.</p>
<p>Open a connection to your SQL Server using SQL Management Studio. Right click on your database. Choose <em>"Tasks > Export Data-tier Application"</em>. Make sure that you store the bacpac file in your Windows Azure Storage. You can find a good example <a href="https://blogs.msdn.com/b/brunoterkaly/archive/2013/09/26/how-to-export-an-on-premises-sql-server-database-to-windows-azure-storage.aspx?Redirected=true">here</a>.</p>
<p><strong>Now you need to create a SQL Server before create the database</strong>, by some reason (probably a "preview version bug") if you try to import the database before create the server you will get an <a href="https://social.technet.microsoft.com/Forums/en-US/54a073aa-b554-403b-87ca-53196a897c9c/cant-create-a-new-sql-azure-standard-tier-db?forum=ssdsgetstarted">error</a>. So, go to <a href="https://manage.windowsazure.com/">Azure Manage web site</a> and create a new SQL Server. Make sure that you set the "Supported Database Editions" to "Basic, Standard, Premium".</p>
<p><img src="https://guiferreira.me/images/move-database-new-sql-azure-service-tiers-create-server.png" alt="alt text" title="Create a new server"></p>
<p>After that, add a new SQL Database (imported from the previous backup) to the server created in the last step.</p>
<p><img src="https://guiferreira.me/images/move-database-new-sql-azure-service-tiers-import-database.png" alt="alt text" title="Create a new database menu"></p>
<p>Select the Backup that you made, choose one of the Preview Editions and the server created before.</p>
<p>When the create database operation is completed, just update your connection string and you are ready to go.</p>
<p>Just remember to delete the backup from storage and the old server if you want.</p>
<p>Enjoy it!</p>
Let's blog2014-04-28T00:00:00-00:00https://guiferreira.me/archive/2014/04/lets-blog/<p>Hi! My name is Guilherme Ferreira. I'm a <a href="https://www.pinterest.com/igori/portugal/">Portuguese</a> software developer, mostly connected to the web development and to the .net Framework, living in the beautiful city of <a href="https://www.pinterest.com/turismportugal/porto-portugal/">Porto</a>. Go check the pictures, I will be right here waiting for you.</p>
<p>I'm starting this blog with the intent to share the lessons that I learn,
write news about my work and to improve my English writing skills.</p>
<p>Following this page you can expect to read cool stuff about software development, entrepreneurship, productivity tips and other living stuff.</p>
<p><img src="https://www.gravatar.com/avatar/93c1c26212f9eb3673538e6ad6ca7eb4.png?s=200" alt="alt text" title="This is me"></p>
<p>Go subscribe the <a href="https://guiferreira.me/rss.xml">RSS feed</a>, visit the <a href="https://guiferreira.me/about/">about page</a> to find my contacts and feel free to contact me.</p>
<p>I'll see you soon... and now let's blog!</p>