<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Ben Hyrman's Blog</title>
  <subtitle>Think About Things</subtitle>
  <link href="https://hyr.mn/feed.xml" rel="self"/>
  <link href="https://hyr.mn"/>
  <updated>2023-07-15T00:00:00Z</updated>
  <id>https://hyr.mn</id>
  <author>
    <name>Ben Hyrman</name>
    <email>ben@hyr.mn</email>
  </author>
  <entry>
    <title>A Hitchhiker&#39;s Guide to Strategic Design</title>
    <link href="https://hyr.mn/strategic-design/"/>
    <updated>2023-07-15T00:00:00Z</updated>
    <id>https://hyr.mn/strategic-design/</id>
    <content type="html">&lt;p&gt;In this post, I&#39;d like to talk about strategic software design and aligning architecture and delivery with business needs. I&#39;ll provide a high-level introduction to some of the strategic aspects of Domain Driven Design (DDD), Event Sourcing, and Event-Driven Architecture (EDA) as a way to achieve long-term objectives. Not the only way... but a way.&lt;/p&gt;
&lt;p&gt;My hope is that, by the end of this article, you&#39;ll have some ideas on how to approach challenges that arise in the balance of shipping software that lasts. Each section only barely scratches the surface of the topic but it will give you a starting point to dig deeper as you map out your own domain.&lt;/p&gt;
&lt;p&gt;Not every software product is a good fit for domain driven design. Event Sourcing doesn&#39;t fit every problem space. Event-Driven Architecture isn&#39;t a magic bullet for scale problems. And, not every business will survive long enough to have scale problems.&lt;/p&gt;
&lt;p&gt;Once a business has validated their market fit, started to clarify their core value stream, and is grappling with cross-team coordination, then the topics below will be worth considering.&lt;/p&gt;
&lt;figure class=&quot;my-8 pl-6&quot;&gt;&lt;blockquote class=&quot;text-xl font-medium text-stone-800 dark:text-stone-200 not-italic leading-relaxed&quot;&gt;Cash Rules Everything Around Me&lt;/blockquote&gt;&lt;figcaption class=&quot;mt-3 text-sm font-medium text-stone-400 dark:text-stone-500&quot;&gt;— Wu-Tang Clan&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;our-simple-scenario&quot; tabindex=&quot;-1&quot;&gt;Our &amp;quot;Simple&amp;quot; Scenario &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#our-simple-scenario&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s pretend that we work at a small, luxury hotel chain. This chain specializes in destination properties. Business comes from a mix of individual bookings, group bookings for weddings, and corporate retreats. Our CEO wants to modernize the business and has asked us to build a new system to manage bookings and reservations.&lt;/p&gt;
&lt;h2 id=&quot;and-off-we-go&quot; tabindex=&quot;-1&quot;&gt;And Off We Go &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#and-off-we-go&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But, wait. A word of warning before we start.&lt;/p&gt;
&lt;p&gt;Domain Driven Design is slower than other approaches. It is more deliberate. It involves aligning business, product, and technology. You should use it when you want to build software that lasts. You should use it to focus on your core domain; your core differentiator and value proposition. It might be the follow-on implementation step once you&#39;ve drawn out Wardley Maps and know where to best spend your engineering hours.&lt;/p&gt;
&lt;p&gt;Do not use these techniques to build an MVP to validate market fit.&lt;/p&gt;
&lt;p&gt;With that, let&#39;s get started with the first tools in our kit for building software that lasts.&lt;/p&gt;
&lt;p&gt;As you start to work with the business and product owners on a hotel reservation system, you&#39;ll start to form a high-level picture of various aspects of running a hotel.&lt;/p&gt;
&lt;p&gt;We can use some techniques from Domain Driven Design to help bring order and focus to these aspects.&lt;/p&gt;
&lt;h2 id=&quot;bounded-contexts&quot; tabindex=&quot;-1&quot;&gt;Bounded Contexts &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#bounded-contexts&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the challenges with delivering a solution is understanding the current process. As you talk to key stakeholders, you&#39;ll discover that the front desk personnel have separate functions from the group sales team. And, likewise, the housekeeping staff have different tasks than the maintenance team. They&#39;ll all have distinct workflows and language.&lt;/p&gt;
&lt;figure class=&quot;my-8 pl-6&quot;&gt;&lt;blockquote class=&quot;text-xl font-medium text-stone-800 dark:text-stone-200 not-italic leading-relaxed&quot;&gt;Put Like With Like&lt;/blockquote&gt;&lt;figcaption class=&quot;mt-3 text-sm font-medium text-stone-400 dark:text-stone-500&quot;&gt;— literally every organization book ever&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;A Bounded Context is a way to group the common things together within a team or function. It&#39;s very hard to get it right the first time and you likely will iterate in several sessions with your stakeholders before boundaries crystalize. One tip from Vaughn Vernon is that a Bounded Context is a linguistic boundary. That is, the terms and language within a Bounded Context are consistent.&lt;/p&gt;
&lt;p&gt;For example, the front desk staff will talk about reservations, check-ins, check-outs, and folios. The housekeeping staff will talk about floor assignments, dirty rooms, and late checkouts. While the group sales team will talk about room blocks, room rates, and room types.&lt;/p&gt;
&lt;p&gt;Drawing these bounded contexts will help you to design the components of the system. If you are delivering a modular monolith then you&#39;ll want to keep these boundaries in mind as you design the modules. If you are delivering a microservice architecture then you&#39;ll want to keep these boundaries in mind as you design the services.&lt;/p&gt;
&lt;p&gt;One more tip... odds are very good that the bounded contexts you identify will align with the organizational structure of the business. That&#39;s ok.&lt;/p&gt;
&lt;figure class=&quot;my-8 pl-6&quot;&gt;&lt;blockquote class=&quot;text-xl font-medium text-stone-800 dark:text-stone-200 not-italic leading-relaxed&quot;&gt;Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization&#39;s communication structure.&lt;/blockquote&gt;&lt;figcaption class=&quot;mt-3 text-sm font-medium text-stone-400 dark:text-stone-500&quot;&gt;— Melvin E. Conway&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;ubiquitious-language&quot; tabindex=&quot;-1&quot;&gt;Ubiquitious Language &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#ubiquitious-language&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Concurrently with discovering the bounded contexts, you&#39;ll want to start to build a shared language with the business. This is called a Ubiquitous Language. Referring back to Mr. Vernon&#39;s tip about linguistic barriers, we should ensure that the organization refers to the same thing with the same label within a given context.&lt;/p&gt;
&lt;p&gt;Imagine working in IT at a yoga chain, for example, where one part of the business calls an instructor-led session a &amp;quot;class&amp;quot; while another team calls it an &amp;quot;event&amp;quot; and yet another team might call it an &amp;quot;activity&amp;quot;. This is a recipe for confusion and frustration.&lt;/p&gt;
&lt;p&gt;We should avoid confusion and frustration.&lt;/p&gt;
&lt;p&gt;For all of the teams working within a bounded context, we should develop and mature a ubiquitous language. We want developers, designers, product managers, and business stakeholders to have a common language; a common way to describe the problem. We want this to permeate so deeply that the language used in meetings is the language used in support tickets is the language used in the software code.&lt;/p&gt;
&lt;p&gt;Some language will be common across the entire organization. For example, a &amp;quot;guest&amp;quot; means the same thing to the front desk, housekeeping, and maintenance.&lt;/p&gt;
&lt;p&gt;Some language will be specific to a bounded context. For example, a &amp;quot;Do Not Rent&amp;quot; list is specific to the front desk.&lt;/p&gt;
&lt;p&gt;(aside, you never want to be a &amp;quot;guest&amp;quot; on a &amp;quot;do not rent&amp;quot; list in any context)&lt;/p&gt;
&lt;h2 id=&quot;context-maps&quot; tabindex=&quot;-1&quot;&gt;Context Maps &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#context-maps&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After we&#39;ve discovered the bounded contexts and started to develop a ubiquitous language, we&#39;ll want to start to map the relationships between the bounded contexts. This is called a Context Map.&lt;/p&gt;
&lt;p&gt;A Context Map will show the synapses firing in the organizational brain; the impulses that cause other parts of the business to light up.&lt;/p&gt;
&lt;p&gt;Within our reservation system, a &amp;quot;check-in&amp;quot; in the front desk context will cause a &amp;quot;room assignment&amp;quot; in the housekeeping context. It might also trigger a &amp;quot;forecast for breakfast&amp;quot; in the kitchen context.&lt;/p&gt;
&lt;h2 id=&quot;event-storming-event-modeling&quot; tabindex=&quot;-1&quot;&gt;Event Storming / Event Modeling &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#event-storming-event-modeling&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Domain Driven Design is, in many ways, focused on the flow of information through the business and capturing how that information is acted on to make decisions. It captures process and workflow. Software becomes an outcome that supports and automates these workflows.&lt;/p&gt;
&lt;p&gt;Discovering and validating the workflow (aka, finding the &amp;quot;things everybody knows&amp;quot; and making sure everybody actually knows them) is difficult.&lt;/p&gt;
&lt;p&gt;One way to do this, and surface your boundaries and assumptions at the same time, is through Event Storming sessions. In these sessions, you&#39;ll take one, or several, long-lived business processes and model the events that occur end-to-end. These sessions must involve the stakeholders, product owners, and tech.&lt;/p&gt;
&lt;p&gt;Stay high-level in these sessions. You can go deeper into Event Storming within a team or single business function later. However, your initial session is to capture the strategic, organizational-wide view. Look for the handoffs between teams to complete critical business functions in the core value stream of the business.&lt;/p&gt;
&lt;p&gt;At the end of the sessions, you should have clarified and validated your bounded contexts and context maps. Pay attention to the language people use when describing their process inputs and outputs. If you think you have solidly defined borders for your bounded contexts but the language within one of those borders isn&#39;t consistent then you may have found a new context... or at least you&#39;ve identified that you need some workshops.&lt;/p&gt;
&lt;h2 id=&quot;event-driven-architecture&quot; tabindex=&quot;-1&quot;&gt;Event-Driven Architecture &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#event-driven-architecture&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;ve talked about events quite a bit so far. This is no coincidence. In this context, events tend to be asynchronously communicated information. In many ways, this models the natural flow of information in an organization.... unless you have a boss that hovers over your desk until you complete your task.&lt;/p&gt;
&lt;p&gt;Let&#39;s imagine that you&#39;re going to your favorite restaurant this weekend. You called to make a reservation. That&#39;s an event. You give the waiter your order. Another event. That waiter then gives the order to the kitchen. That is, you guessed it, another event.&lt;/p&gt;
&lt;p&gt;All along the way, there&#39;s valuable information being passed and translated for each bounded context. But, no one is blocked and waiting for a response.&lt;/p&gt;
&lt;p&gt;Going back to our event storming and context maps, we can see that exchanging information between bounded contexts is a useful paradigm. When it comes to the actual implementation of our software, we can translate this into an Event-Driven Architecture.&lt;/p&gt;
&lt;p&gt;An Event-Driven Architecture is valuable on its own. While Domain Driven Design makes the most sense when focusing on our core domain, an Event- Driven Architecture is useful for communication between supporting systems as well. It allows us to independently scale and decouple capabilities. And, it allows us to build future capabilities that tap into existing information flow without impact.&lt;/p&gt;
&lt;p&gt;But, there is also a real cost to adopting this architecture. If multiple services must coordinate to fulfill a user&#39;s request then you must plan and design for scenarios when one or more of those services has a stale view of the world because they are delayed in processing events or a myriad of other communication and processing issues.&lt;/p&gt;
&lt;h2 id=&quot;event-sourcing&quot; tabindex=&quot;-1&quot;&gt;Event Sourcing &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#event-sourcing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it is more tactical than the other topics we&#39;ve covered, I wanted to cover Event Sourcing as well. I&#39;ve been in too many conversations where Event Sourcing and Event-Driven Architecture are conflated and used interchangeably.&lt;/p&gt;
&lt;p&gt;Event Sourcing is a technique where we model the current state of the system by capturing every decision that led to that state. As an overused, but classic, example, the current state (balance) of your bank account is the sum of all events (deposits and withdrawals) that have happened.&lt;/p&gt;
&lt;p&gt;Event Sourcing is very powerful but should not be used indiscriminately. In the hotel reservation system within the front desk bounded context, event sourcing would probably be very useful for the guest folio. You&#39;ll want to know every charge and every payment that has been made. However, that same front desk bounded context does not care about the history of the guest... that they moved or changed their name. However, that information is useful to the group sales bounded context and it might make sense to event source that there. Meanwhile, the housekeeping system might not benefit from event sourcing at all.&lt;/p&gt;
&lt;p&gt;Choose carefully. Event Sourcing is a great way to capture the &amp;quot;why&amp;quot; behind state changes in a system. It is focused on all of the small changes within a system. Meanwhile, events in an Event-Driven Architecture tend to be &amp;quot;chunkier&amp;quot;.&lt;/p&gt;
&lt;p&gt;Back to our reservation system, internally we might capture when a room is reserved, when the reservation is moved to a new room because of some request, when the guest checked in, and when the guest checked out. But, it might only publish the check-in and check-out events and those events may be enriched with more information than internal events (or, conversely, less information if you&#39;re publishing skinny events).&lt;/p&gt;
&lt;p&gt;As an aside, if you adopt Event Sourcing, then you will likely also adopt Command Query Responsibility Segregation (CQRS). You can, of course, adopt CQRS on its own as well and I happen to think it&#39;s one of the easiest ways to simplify a system&#39;s architecture. As it&#39;s orthogonal to this blog post&#39;s topic, I&#39;ll leave it to another post.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/strategic-design/#conclusion&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My goal in this blog post was to provide a very high-level introduction to strategic DDD and some of the supporting tactical architectures that often go hand-in-hand with DDD.&lt;/p&gt;
&lt;p&gt;Delivery speed, real or perceived, is slower with DDD; at least at first. In my opinion, the real value of DDD is in aligning people and teams. This alignment is critical in the core value streams of the organization. Unless you&#39;re an HR services company, your payroll system is not a differentiator. On the other hand, if you work at a hotel chain then the reservation system may be a core competitive advantage. Spend time on your advantage.&lt;/p&gt;
&lt;p&gt;Even if you adopt nothing else from strategic DDD, there&#39;s immense value in capturing your organization&#39;s ubiquitious language. If you&#39;re not ready for bounded contexts and event storming then at least start with this.&lt;/p&gt;
&lt;p&gt;Adopting an Event-Driven Architecture brings its own set of trade-offs. Asynchronous communication between disparate services can be more scalable but will also bring challenges and trade-offs around data exchange, eventual consistency, and data staleness.&lt;/p&gt;
&lt;p&gt;Event Sourcing is a powerful approach to baking the reason for each state change into your system. And, while you get an audit log &amp;quot;for free&amp;quot; out of the implementation, you now need to think through how events will change and be versioned over time. Even within a single system within a bounded context, it is likely that not everything in that system would benefit from being event sourced.&lt;/p&gt;
&lt;p&gt;But, in spite of the challenges, strategic DDD is a very valuable tool in aligning everyone around delivering the core value of your organization. And, it will ensure that you can best focus on what matters vs what is important but not part of your core domain.&lt;/p&gt;
&lt;p&gt;Adopting an Event-Driven Architecture can happen independent of DDD but it shines as the bridge between bounded contexts identified by DDD. It allows teams to be loosely-coupled and able to evolve their systems and architectures independently by adhering to messaging contracts for information exchange. And, defining these messaging contracts can be a concrete implementation of the ubiquitous language in the organization.&lt;/p&gt;
&lt;p&gt;And, implementing Event Sourcing in your core applications and services will also reflect the business processes and ubiquitous language within the bounded context they support. You&#39;ll capture the intent with each change which can unlock other capabilities. And, since you will always have the events that led to the current state of the system, you aren&#39;t limited on when those capabilities can manifest.&lt;/p&gt;
&lt;p&gt;I hope that you found this overview helpful.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Let&#39;s Make Some Art - Part 2</title>
    <link href="https://hyr.mn/lets-make-art-pt2/"/>
    <updated>2021-09-25T00:00:00Z</updated>
    <id>https://hyr.mn/lets-make-art-pt2/</id>
    <content type="html">&lt;p&gt;In &lt;a href=&quot;https://hyr.mn/lets-make-art-pt1&quot;&gt;part 1&lt;/a&gt;, we had our computer draw some boxes. I want to go in a different direction here to lead up to part 3. This time I want to explore reading pixels from an existing image.&lt;/p&gt;
&lt;h2 id=&quot;what-are-we-making-this-time&quot; tabindex=&quot;-1&quot;&gt;What are we making this time? &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt2/#what-are-we-making-this-time&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I bet you, like me, have looked at an image and wondered what it would look like if all of the lines were sorted by their RGB color values. Well, let&#39;s write some code and find out!&lt;/p&gt;
&lt;h2 id=&quot;lets-create&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s Create! &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt2/#lets-create&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, we&#39;ll need a program to run our code.  I&#39;m going to create a new .NET 6.0 project and then add ImageSharp.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt;dotnet new console&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt;dotnet add package SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Drawing &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;version 1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0-beta13&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, at the time of this post, &lt;a href=&quot;https://www.nuget.org/packages/SixLabors.ImageSharp.Drawing&quot;&gt;ImageSharp.Drawing&lt;/a&gt; is still in beta so you&#39;ll need to explicitly add the version. Be sure to check before you start in case there&#39;s a newer version available. Technically, for this post, we&#39;re not even using anything from the Drawing package, but it has a dependency on ImageSharp and we&#39;ll be back to using the Drawing package in part 3 so... to keep the flow consistent... Onward!&lt;/p&gt;
&lt;p&gt;My goal is to read in an existing file, sort the pixels by some arbitrary scale, and then write them out to a destination file. We&#39;ll use the source image&#39;s dimensions to create the destination image.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Formats&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jpeg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PixelFormats&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcFilename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ArgumentNullException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Must supply a source&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcFile &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;FileInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcFilename&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;srcFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Exists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bad src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; destFilename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetFileNameWithoutExtension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_sorted.jpg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcImg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Rgb24&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FullName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcWidth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; srcImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcHeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; srcImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Height&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; destImg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Image&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Rgb24&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcWidth&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; srcHeight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; srcHeight&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; row&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; pixels &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; srcImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetPixelRowSpan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; orderedPixels &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pixels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OrderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;R &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;G &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;B&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; col &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; col &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; orderedPixels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; col&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        destImg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;col&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; orderedPixels&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;col&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

destImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SaveAsJpeg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFilename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;JpegEncoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Quality &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;95&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Done&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code reads in the source file, creates a destination image the same size, then goes row by row down the source image. It reads the row of pixels, reorders it by the sum of their RGB values, and then writes to the destination a pixel at a time. No, it&#39;s not the most efficient... but we don&#39;t need it to be for generating art.&lt;/p&gt;
&lt;p&gt;Given an input like &lt;a href=&quot;https://www.flickr.com/photos/benhyr/4464434633&quot;&gt;this image I took of a controlled burn near our house&lt;/a&gt;, the above code will generate an &lt;a href=&quot;https://www.flickr.com/photos/benhyr/51007091787&quot;&gt;image where each row is sorted by the sum of the colors in each pixel&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;messing-around&quot; tabindex=&quot;-1&quot;&gt;Messing around &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt2/#messing-around&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it&#39;s not a lot, the above work will be critical input in part 3. But, since this post doesn&#39;t have a lot of code... let&#39;s mess around and see what kind of mayhem we can create.&lt;/p&gt;
&lt;p&gt;Of course, there are lots of other possibilities. We could figure out how to sort things by column instead of row. We could randomly sort each row. But... I noticed a neat method available on &lt;code&gt;Image&lt;/code&gt;. &lt;code&gt;TryGetSinglePixelSpan&lt;/code&gt;. It looks like, if possible, this method will give you back a &lt;a href=&quot;https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay&quot;&gt;&lt;code&gt;Span&lt;/code&gt;&lt;/a&gt; over the entire image. There are some practical limits to this. But, who cares about practical. In my case, since my input image is 2400x1600 pixels, my &lt;code&gt;Span&lt;/code&gt; will cover an array of 3,840,000 (because math) pixels... all in a 1-dimensional array.&lt;/p&gt;
&lt;p&gt;Knowing absolutely nothing about the underlying implementation and not really bothering to &lt;a href=&quot;https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Image-1.html#SixLabors_ImageSharp_Image_1_TryGetSinglePixelSpan_&quot;&gt;read the excellent docs&lt;/a&gt;, let&#39;s see what happens if we do something like... oh, I don&#39;t know...&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Formats&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jpeg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PixelFormats&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcFilename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ArgumentNullException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Must supply a source&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcFile &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;FileInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcFilename&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; destFilename &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetFileNameWithoutExtension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_sorted&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; srcFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Extension&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcImg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Rgb24&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FullName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcWidth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; srcImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; srcHeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; srcImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Height&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; destImg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Image&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Rgb24&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srcWidth&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; srcHeight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

srcImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;TryGetSinglePixelSpan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; pixels&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; srcHeight&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; row&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; col &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; col &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; srcWidth&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; col&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        destImg&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;col&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pixels&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;col &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

destImg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SaveAsJpeg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destFilename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;JpegEncoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Quality &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;95&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Done&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that, because col keeps resetting to zero, the first row starts with pixel 0 in the array and continues to pixel 2399. The second row in the destination will start at pixel 1 and continue to pixel 2400. This leads to some very interesting streaked output as you can see in &lt;a href=&quot;https://www.flickr.com/photos/benhyr/51529903051&quot;&gt;the generated image&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And, if you&#39;re like me, your first question is &amp;quot;hey, what happens if we change that little &lt;code&gt;pixels[col + row]&lt;/code&gt; code to do some multiplication instead &lt;code&gt;pixels[col * row]&lt;/code&gt;?&amp;quot;&lt;/p&gt;
&lt;p&gt;The answer, interestingly, is &lt;a href=&quot;https://www.flickr.com/photos/benhyr/51529097152&quot;&gt;a beautiful star field&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up-for-now&quot; tabindex=&quot;-1&quot;&gt;Wrapping up... for now &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt2/#wrapping-up-for-now&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As with &lt;a href=&quot;https://hyr.mn/lets-make-art-pt1&quot;&gt;part 1&lt;/a&gt;, this is just meant to get you thinking of other things you might want to explore. The key take-away from this post that you&#39;ll need for part 3 (not yet written) is that it&#39;s possible to read pixels from a source image and use them when writing to a destination image.&lt;/p&gt;
&lt;p&gt;Some ideas of where you could take this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Randomize the sort order for each row&lt;/li&gt;
&lt;li&gt;Sort by row and column&lt;/li&gt;
&lt;li&gt;Randomize the span and then write it out to the destination image&lt;/li&gt;
&lt;li&gt;Combine two source input images into one destination&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Swapping two numbers in C#</title>
    <link href="https://hyr.mn/swapping-numbers/"/>
    <updated>2021-09-13T00:00:00Z</updated>
    <id>https://hyr.mn/swapping-numbers/</id>
    <content type="html">&lt;p&gt;Occasionally in programming, we come across the need to swap two numbers. That is, if we have &lt;code&gt;var x = 10&lt;/code&gt; and &lt;code&gt;var y = 20&lt;/code&gt;, we need to end up with &lt;code&gt;x = 20&lt;/code&gt; and &lt;code&gt;y = 10&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s a possible way to do it in C#&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithTemp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Back when I was first learning to program, there were a finite number of variables in the world and we all needed to call the central variable office to see if we could use one. As you can imagine, this was a very lengthy process so interviewers started asking candidates a brain teaser question. &lt;code&gt;How can you swap two variables without using a third temp variable?&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I&#39;ll show the code (in C#) and then discuss why it works&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithXor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;^&lt;/code&gt; in this context is the XOR, or Exclusive OR, operator. It&#39;s much easier to visualize how things work if we can see the numbers like a computer does. Since computers see everything in binary, we need to as well.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The computer sees&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1010&lt;/span&gt;
y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0001&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0100&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The rules for &lt;a href=&quot;https://en.wikipedia.org/wiki/XOR_gate&quot;&gt;XOR&lt;/a&gt; are that it&#39;s true when one of the values is true and false if both values are the same.&lt;/p&gt;
&lt;p&gt;This means that:
1 XOR 0 is 1;
1 XOR 1 is 0;
and 0 XOR 0 is 0.&lt;/p&gt;
&lt;p&gt;Let&#39;s step through the code and see what happens under the covers&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//x = 0000 1010&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//y = 0001 0100&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//We will go through x and y and compare row to row. &lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//Any time there&#39;s a 1 in one row and a 0 in another, make it a 1 in the output&lt;/span&gt;
x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  0000 1010&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  0001 0100&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//x=0001 1110&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//If we work left to right then we know at the end x will be 0001 1110 &lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//Now we do the same thing with y&lt;/span&gt;
y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//Work left to right and compare the new value of x (0001 1110) to y&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//so compare these two with an XOR&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  0001 1110&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  0001 0100&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//y=0000 1010&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//At the end of this, y is 0000 1010 (10 in decimal. Oh, nice, the original value of x)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//Now do the same thing with x again to get the original value of y&lt;/span&gt;
x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  0001 1110&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  0000 1010&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//x=0001 0100&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We saved using a temp variable, which honestly hasn&#39;t mattered since hard drives shrunk down from the size of small cars. But, is it better? We&#39;ll get into that in a minute.&lt;/p&gt;
&lt;p&gt;I want to share one more way to swap numbers in C#. We can use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tuple&quot;&gt;tuple&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithTuple&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will either see this and say that it&#39;s the most straightforward and idiomatic way to do a number swap in C# or you&#39;ll hate it and swear off this approach forever. We&#39;re telling the compiler to make a tuple of the values x and y and then assign it the tuple of values y and x. We&#39;ll go under the covers later and it will look more obvious then if it doesn&#39;t now.&lt;/p&gt;
&lt;p&gt;So, three viable ways to swap two numbers. Which one makes the most sense? Writing software, in any language, can be a balancing act of writing code that is fast and code that is maintainable. If the XOR approach happened to be the fastest code, and the code was called often enough that optimizing a few nanoseconds was worth it, then it&#39;d be worth using an approach that isn&#39;t as immediately obvious to everyone. (possibly including you six months later).&lt;/p&gt;
&lt;p&gt;As we did in &lt;a href=&quot;https://hyr.mn/fun-with-benchmarkdotnet/&quot;&gt;Measure Two Hundred Times, Tweak Twice&lt;/a&gt;, let&#39;s set up &lt;a href=&quot;https://benchmarkdotnet.org/&quot;&gt;BenchmarkDotNet&lt;/a&gt; and profile some code.&lt;/p&gt;
&lt;p&gt;Here&#39;s the code in .NET 6.0 / C# 10. I&#39;ve included two other possible ways to swap numbers from the many (stupid) &lt;a href=&quot;https://gist.github.com/hyrmn/387e9e8d4e2858daf5e89097396b88fb&quot;&gt;ways we came up with to swap numbers&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;BenchmarkDotNet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Attributes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;BenchmarkDotNet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Running&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; summary &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; BenchmarkRunner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Swappy&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Swappy&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithTemp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithXor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithTuple&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; scratch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; scratch&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; scratch&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithLinq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Last&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;First&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SwapWithInterlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Interlocked&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Exchange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ref&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compile the above code in release mode and then run the exe from the command prompt and you&#39;ll get some output like the following:&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;            Method &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  x &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  y &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;       Mean &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;     Error &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;    StdDev &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;:&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;:&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;:&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;      SwapWithTemp &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 10 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 20 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;1575 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0113 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0106 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;       SwapWithXor &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 10 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 20 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;6337 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0106 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0094 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;     SwapWithTuple &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 10 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 20 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;1589 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0023 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0021 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;     SwapWithArray &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 10 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 20 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;4849 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0427 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0357 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;      SwapWithLinq &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 10 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 20 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 33&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;4991 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;4638 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;4339 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; SwapWithInterlock &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 10 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 20 &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;  3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0909 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0334 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0261 ns &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can trust BenchmarkDotNet to give us useful measurements because it&#39;s handled all of the execution warmup, works to remove noise, and repeats runs to get useful data.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/swapping-numbers/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So, at least in C#, the temp variable and tuple approach are the fastest. And, in my mind, the two most readable as well.&lt;/p&gt;
&lt;p&gt;If you show up at an interview and they ask you to swap two numbers without using a third, you can push back and dazzle them with science.&lt;/p&gt;
&lt;p&gt;If you like the tuple syntax, then you should go with that. If you prefer the temp, then that&#39;s fine too. While I&#39;m not in love with the tuple version, I would say that will be the canonical version you&#39;ll encounter in the wild and I can live with that.&lt;/p&gt;
&lt;p&gt;Before I go, I wanted to dive into the temp version and tuple version further. This time with a look at the generated &lt;a href=&quot;https://en.wikipedia.org/wiki/Common_Intermediate_Language&quot;&gt;IL&lt;/a&gt;. My go-to tool for this on Windows is &lt;a href=&quot;https://www.microsoft.com/en-us/p/ilspy/9mxfbkfvsq13?SilentAuth=1&amp;amp;wa=wsignin1.0&amp;amp;activetab=pivot:overviewtab&quot;&gt;ILSpy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using that to explore the compiled DLL from our test above, let&#39;s look at the generated IL for the &lt;code&gt;SwapWithTemp&lt;/code&gt; version:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maxstack &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;locals&lt;/span&gt; init &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;int32&lt;/span&gt; tmp
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// int num = x;&lt;/span&gt;
IL_0000&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
IL_0001&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ldind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4&lt;/span&gt;
IL_0002&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stloc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// x = y;&lt;/span&gt;
IL_0003&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
IL_0004&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
IL_0005&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ldind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4&lt;/span&gt;
IL_0006&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4
&lt;span class=&quot;token comment&quot;&gt;// y = num;&lt;/span&gt;
IL_0007&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
IL_0008&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldloc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
IL_0009&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4
&lt;span class=&quot;token comment&quot;&gt;// }&lt;/span&gt;
IL_000a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ret&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It creates a local variable, &lt;code&gt;num&lt;/code&gt;, and then does the assignment swapping.&lt;/p&gt;
&lt;p&gt;Now let&#39;s look at the decompiled version of &lt;code&gt;SwapWithTuple&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maxstack &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;locals&lt;/span&gt; init &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; int32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; int32
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// int num = y;&lt;/span&gt;
IL_0000&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
IL_0001&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ldind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4&lt;/span&gt;
IL_0002&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stloc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// int num2 = x;&lt;/span&gt;
IL_0003&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
IL_0004&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ldind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4&lt;/span&gt;
IL_0005&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stloc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// x = num;&lt;/span&gt;
IL_0006&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
IL_0007&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldloc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
IL_0008&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4
&lt;span class=&quot;token comment&quot;&gt;// y = num2;&lt;/span&gt;
IL_0009&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldarg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
IL_000a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ldloc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
IL_000b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;i4
&lt;span class=&quot;token comment&quot;&gt;// }&lt;/span&gt;
IL_000c&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ret&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s incredibly similar to the version that uses a temp variable to swap. Except, in this case, it&#39;s using two temp variables for us; &lt;code&gt;num&lt;/code&gt; and &lt;code&gt;num2&lt;/code&gt;. That explains why they&#39;re so close for timings on our benchmark tests. And, while it actually wastes just a little tiny bit more than &lt;code&gt;SwapWithTemp&lt;/code&gt;, we&#39;re in a new bountiful age of variables where everyone can have as many as they want without some central variable assignment authority getting upset.&lt;/p&gt;
&lt;p&gt;Anyway, that covers more than any reasonable person ever cared to know about swapping two numbers in C#. If you can think of any other creative ways that you want to contribute, please stop by &lt;a href=&quot;https://gist.github.com/hyrmn/387e9e8d4e2858daf5e89097396b88fb&quot;&gt;https://gist.github.com/hyrmn/387e9e8d4e2858daf5e89097396b88fb&lt;/a&gt; and leave a comment with some code.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Host your static 11ty site on Google Cloud</title>
    <link href="https://hyr.mn/eleventy-on-google-cloud/"/>
    <updated>2021-03-17T00:00:00Z</updated>
    <id>https://hyr.mn/eleventy-on-google-cloud/</id>
    <content type="html">&lt;p&gt;I am working on a &lt;a href=&quot;https://github.com/TwoPeas/SharpStatusApp&quot;&gt;fake product&lt;/a&gt; for a &lt;a href=&quot;https://github.com/TwoPeas&quot;&gt;fake business&lt;/a&gt;. Of course, I need a &lt;a href=&quot;https://sharpstatus.com/&quot;&gt;marketing site&lt;/a&gt; for my fake app! It&#39;s a static web site so I&#39;m using my favorite site generator, &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt;. Of course, you could use the same approaches below with any static site generator or hand-rolled HTML. Many of the same steps apply.&lt;/p&gt;
&lt;p&gt;My requirements were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Static site hosted on Google Cloud&lt;/li&gt;
&lt;li&gt;All content is served over HTTPS and if you go to the HTTP site then you get redirected&lt;/li&gt;
&lt;li&gt;Content hosted on GitHub&lt;/li&gt;
&lt;li&gt;Site automatically built and deployed when I push new content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rather than walk you step-by-step through yet another tutorial, I&#39;m going to link to the resources that helped me and then provide the stitching that I had to figure out to get a complete solution. I have a feeling that this will be simplified and turned into a product offering soon.&lt;/p&gt;
&lt;h2 id=&quot;step-1-the-basics-of-a-static-site&quot; tabindex=&quot;-1&quot;&gt;Step 1 - The basics of a static site &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/eleventy-on-google-cloud/#step-1-the-basics-of-a-static-site&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Follow this excellent &lt;a href=&quot;https://cloud.google.com/storage/docs/hosting-static-website&quot;&gt;Google Cloud guide on hosting a static website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I want to call out a couple items.&lt;/p&gt;
&lt;p&gt;First, you&#39;ll need to ensure that you&#39;ve already validated your domain with Google. That involves adding a TXT record to your DNS entry with whoever your registrar is (Godaddy, NameCheap, etc). If you&#39;ve already done this, or if Google is your DNS provider, then you can skip this.&lt;/p&gt;
&lt;p&gt;Next, you can only make your storage bucket for your website files multi-region when you create it.&lt;/p&gt;
&lt;p&gt;Also, to start, don&#39;t enable CDN caching when you create your HTTPS load balancer. Enable this later, but you will hate yourself while you&#39;re doing the initial development if you have this on.&lt;/p&gt;
&lt;p&gt;On the subject regarding the load balancer, unless you know what you&#39;re doing and have a good reason to do it, just let Google manager your SSL cert.&lt;/p&gt;
&lt;p&gt;Last, you&#39;re going to end up with just an HTTPS site at the end of this step. Don&#39;t worry, though, we&#39;ll take care of that next to add an HTTP to HTTPS redirect.&lt;/p&gt;
&lt;h2 id=&quot;step-2-add-an-http-to-https-redirect&quot; tabindex=&quot;-1&quot;&gt;Step 2 - Add an HTTP to HTTPS redirect &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/eleventy-on-google-cloud/#step-2-add-an-http-to-https-redirect&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Skip almost to the end of this &lt;a href=&quot;https://cloud.google.com/load-balancing/docs/https/setting-up-http-https-redirect#partial-http-lb&quot;&gt;Google Cloud guide on setting up an HTTP to HTTPS load balancer&lt;/a&gt;. This whole article provides a nice overview of the network topology and how and why. But, if you&#39;re in a hurry, just skip to the section on redirecting traffic to your HTTPS load balancer. You have an HTTPS load balancer from step 1 already, so now you need to set up one that will listen to HTTP.&lt;/p&gt;
&lt;p&gt;At this point, you should be set.&lt;/p&gt;
&lt;h2 id=&quot;step-3-automate-building-and-deploying-your-site&quot; tabindex=&quot;-1&quot;&gt;Step 3 - Automate building and deploying your site &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/eleventy-on-google-cloud/#step-3-automate-building-and-deploying-your-site&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;re going to leverage Cloud Build for this. And, we&#39;re going to leverage the existing &lt;a href=&quot;https://github.com/GoogleCloudPlatform/cloud-builders&quot;&gt;Cloud Builders&lt;/a&gt; that Google provides.&lt;/p&gt;
&lt;p&gt;You&#39;ll need to create a &lt;code&gt;cloudbuild.yaml&lt;/code&gt; (or json) file in your repository that we&#39;ll then point Cloud Run at. Here&#39;s &lt;a href=&quot;https://github.com/TwoPeas/SharpStatusSite/blob/main/cloudbuild.yaml&quot;&gt;my cloudbuild.yaml&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;gcr.io/cloud-builders/npm&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;ci&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;gcr.io/cloud-builders/npm&#39;&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;run&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;build&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;NODE_ENV=production&#39;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; gcr.io/cloud&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;builders/gsutil
   &lt;span class=&quot;token key atrule&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;-m&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;rsync&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;-r&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;-c&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;-d&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./dist&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;gs://www.sharpstatus.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;ll cover how this is triggered next, but... when you push a change to GitHub, Cloud Run will clone your repository and then run the steps in the &lt;code&gt;cloudbuild.yaml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;m leveraging the &lt;code&gt;npm&lt;/code&gt; cloud builder because that&#39;s how I build my site. First, I run &lt;code&gt;npm ci&lt;/code&gt; to restore my node packages. Then I run &lt;code&gt;npm run build&lt;/code&gt; which runs the npm script labeled &lt;code&gt;build&lt;/code&gt; in &lt;a href=&quot;https://github.com/TwoPeas/SharpStatusSite/blob/main/package.json&quot;&gt;my package.json&lt;/a&gt; file. I&#39;m using TailwindCSS and I have it configured to purge unused CSS. But, by default, it only does that for production builds. You signal that by setting your Node environment to production, which you can see I&#39;m doing above for the second step.&lt;/p&gt;
&lt;p&gt;As part of my 11ty configuration, I&#39;m copying all generated assets to &lt;code&gt;/dist&lt;/code&gt;. So the last step is to use the &lt;code&gt;gsutil&lt;/code&gt; builder top copy (rsync) everything from my output to my storage bucket. If you&#39;ll recall, the guide in step 1 showed using &lt;code&gt;gsutil rsync&lt;/code&gt; locally to copy files.&lt;/p&gt;
&lt;p&gt;That&#39;s the basics of automating the build. The last step is to tie it all together and actually trigger it.&lt;/p&gt;
&lt;p&gt;Again, I&#39;m going to start by pointing you to the &lt;a href=&quot;https://cloud.google.com/build/docs/automating-builds/create-github-app-triggers&quot;&gt;Google Cloud guide on triggering builds from GitHub&lt;/a&gt;. At a high level, you&#39;re going to connect Cloud Run to your repository. This involves granting permissions to the Google Cloud Build app. You&#39;ll also want to tell the trigger to run the cloudbuild.yaml file we just defined.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping Up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/eleventy-on-google-cloud/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;🤞🏻 That should be everything you need to deploy your static site. Once you&#39;re happy with your site, be sure to go back to your HTTPS load balancer that you created in step 1 and enable CDN.&lt;/p&gt;
&lt;p&gt;It&#39;s a bit involved; I&#39;m not going to lie. I feel like &lt;a href=&quot;https://netlify.com/&quot;&gt;Netlify&lt;/a&gt; is significantly easier to get started with. In fact, this site that you&#39;re reading right now is hosted there. But, I wanted to host all of my infrastructure together and also experiment a little. I&#39;d call the experiment a success.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Let&#39;s Make Some Art - Part 1</title>
    <link href="https://hyr.mn/lets-make-art-pt1/"/>
    <updated>2021-03-15T00:00:00Z</updated>
    <id>https://hyr.mn/lets-make-art-pt1/</id>
    <content type="html">&lt;p&gt;I saw a tweet from &lt;a href=&quot;https://twitter.com/James_M_South&quot;&gt;@James_M_South&lt;/a&gt;, creator of the amazing ImageSharp library where he mentioned there wasn&#39;t a lot of public chatter about said library. Now, I know nothing about image processing or graphics. But, I&#39;ve been wanting to learn more about creating &lt;a href=&quot;https://en.wikipedia.org/wiki/Algorithmic_art&quot;&gt;Algorithmic Art&lt;/a&gt;, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Generative_art&quot;&gt;Generative Art&lt;/a&gt;, for a while. And, &lt;a href=&quot;https://twitter.com/James_M_South/status/1367430358472536064&quot;&gt;James&#39; tweet&lt;/a&gt; inspired me to dive in.&lt;/p&gt;
&lt;h2 id=&quot;generative-art&quot; tabindex=&quot;-1&quot;&gt;Generative Art? &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt1/#generative-art&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Wikipedia links above provide some really great in-depth links into generative art. For my purposes, I want to use an algorithm to get a computer to make a picture within the constraints I&#39;ve provided. I also want to introduce some randomness so that no two runs will produce the same result. I&#39;m going to do this as a bit of a series and you&#39;re going to explore with me. Each post will be self-contained to a specific idea and should offer up some space to explore your own ideas after.&lt;/p&gt;
&lt;h2 id=&quot;lets-create&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s Create! &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt1/#lets-create&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, we&#39;ll need a program to run our code. And then I&#39;m going to pull in the ImageSharp Drawing library to abstract away the drawing magic for me. I&#39;m going to create a new project and then add ImageSharp&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt;dotnet new console&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt;dotnet add package SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Drawing &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;version 1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;0-beta11&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, at the time of this post, &lt;a href=&quot;https://www.nuget.org/packages/SixLabors.ImageSharp.Drawing&quot;&gt;ImageSharp.Drawing&lt;/a&gt; is still in beta so you&#39;ll need to explicitly add the version. Be sure to check before you start in case there&#39;s a newer version.&lt;/p&gt;
&lt;p&gt;Now, let&#39;s get the basics in place. I&#39;ll create an image, fill it with a color, and then save it. Just to ensure it works.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Drawing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Drawing&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Processing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PixelFormats&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;SixLabors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ImageSharp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Processing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; destWidth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1920&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; destHeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; image &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Image&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Rgba32&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;destWidth&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; destHeight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Mutate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ic &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Color&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Black&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; outputStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; File&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenWrite&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;generated.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;SaveAsPng&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;outputStream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Done!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code creates a new 32-bit &lt;a href=&quot;https://en.wikipedia.org/wiki/RGBA_color_model&quot;&gt;RGBA&lt;/a&gt; image. Drawing on the image happens in an image context, which we set-up above and then use that context to fill the image a solid black.&lt;/p&gt;
&lt;p&gt;There you have it, our first algorithmic art. It&#39;s sized for a background right now at 1920x1080 (the resolution of my little monitor). But, you could make it huge, call it a Study in Black, and wait for the offers to roll in!&lt;/p&gt;
&lt;h2 id=&quot;lets-make-it-art&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s Make It Art! &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt1/#lets-make-it-art&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is fun and all, but variety is the spice of life. Let&#39;s add some randomness and let that drive our colors.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; rand &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; g &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; todaysLuckyColor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Rgba32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Mutate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ic &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todaysLuckyColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default, our random number generator will be seeded with the current timestamp. We then use that to create random values for our red, green, and blue. We then fill the image with that color. I ended up with a horrible mustard yellow and then a wonderful violet the second time I ran it. Let&#39;s push this just a little bit further before we wrap up today&#39;s post.&lt;/p&gt;
&lt;h2 id=&quot;shapes-boxes-oh-my&quot; tabindex=&quot;-1&quot;&gt;Shapes! Boxes... oh my. &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt1/#shapes-boxes-oh-my&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Drawing a single color image is cool and all, but what about a single tiny box instead?&lt;/p&gt;
&lt;p&gt;Changing up the mutate function yet again, let&#39;s draw a square.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Mutate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ic &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Color&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;White&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; rotation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; GeometryUtilities&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DegreeToRadian&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; square &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;RegularPolygon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rotation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    ic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todaysLuckyColor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; square&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ImageSharp.Drawing has some great utilities for making shapes. And, that&#39;s what we&#39;re after. Shapes. Or, specifically, squares. I&#39;m asking ImageSharp to make me a 4-sided polygon that is 50 pixels wide with a centerpoint that is 40 pixels from the top and 40 pixels from the left (the top left corner is our reference point of 0,0). Technically... ImageSharp is giving us a polygon where each corner touches the edge of a circle that is 50 pixels around. Which brings up an interesting thing... if we draw this without rotating it, we get a diamond. I haven&#39;t looked at the internals, but I assume ImageSharp starts at 0 on a circle and then draws. So, we need to rotate our shape. ImageSharp uses radians. I&#39;m not smart enough to understand radians but I know I need to rotate my diamond 45 degrees so I&#39;ll use their handy utility.&lt;/p&gt;
&lt;p&gt;Run this program and you now have a pretty square on an expanse.&lt;/p&gt;
&lt;p&gt;Let&#39;s go a little further and generate a lot of squares. A lot of multi-colored squares.&lt;/p&gt;
&lt;p&gt;If we think about each square as going in a row and column, then we can look for a number that&#39;s easily divisible into 1920 and 1080. Completely by coincidence, if we divide by 40, we get 48 columns and 27 rows.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;image&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Mutate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ic &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Color&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;White&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; rotation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; GeometryUtilities&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DegreeToRadian&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; row&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; col &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; col &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; col&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; g &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;rand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; squareColor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Rgba32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; polygon &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;RegularPolygon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; col&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rotation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            ic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;squareColor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; polygon&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m using two &lt;code&gt;for&lt;/code&gt; loops here. The first to walk down the imaginary rows in my image and the second to walk across the columns. I&#39;m offsetting each square by 40 pixes and drawing a 20 pixel square in the middle. Because each square should be a random color, we need to move the randomized color creation into the loop as well. Try it out and show off your creation.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up-for-now&quot; tabindex=&quot;-1&quot;&gt;Wrapping up... for now &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/lets-make-art-pt1/#wrapping-up-for-now&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We scratched the surface of what we can do with &lt;a href=&quot;https://sixlabors.com/&quot;&gt;Six Labors&#39;&lt;/a&gt; ImageSharp library and used it with a very simple algorithm to make a unique piece of art... which is pretty damn cool.&lt;/p&gt;
&lt;p&gt;Some ideas of where you could take this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Randomize the rotation&lt;/li&gt;
&lt;li&gt;Rotate and shrink the size as you get closer to the image edge&lt;/li&gt;
&lt;li&gt;Randomize the location&lt;/li&gt;
&lt;li&gt;Different shapes&lt;/li&gt;
&lt;li&gt;Vary the shapes&lt;/li&gt;
&lt;li&gt;Constrain the colors to a specific range&lt;/li&gt;
&lt;li&gt;Make the colors grayscale&lt;/li&gt;
&lt;li&gt;Overlap the shapes and play with the alpha blending&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Multi-stage Docker builds for ASP.NET Core 5</title>
    <link href="https://hyr.mn/docker-dotnet5/"/>
    <updated>2021-02-28T00:00:00Z</updated>
    <id>https://hyr.mn/docker-dotnet5/</id>
    <content type="html">&lt;p&gt;I am building an app with .NET 5 and &lt;a href=&quot;http://asp.net/&quot;&gt;ASP.NET&lt;/a&gt; Core 5. And, I want to run it on a cloud provider. Since .NET 5 isn&#39;t widely adopted yet (and probably won&#39;t be since it&#39;s not an LTS version), that means the easiest path to deployment is a Docker image.&lt;/p&gt;
&lt;p&gt;That part isn&#39;t hard. When you create a new .NET project, you get a multi-stage Dockerfile for free (well, as long as you select that option). But, I want to use vanilla Node.js build options for processing and bundling my CSS and JS files. The common solutions I&#39;ve seen for Docker + Node + .NET involve starting with the base .NET image and then using &lt;code&gt;apt-get&lt;/code&gt; to install Node. I didn&#39;t want to go down that path if I could help it. I don&#39;t know why, but the idea of modifying the Docker image outside of just building stuff offended my aesthetic.&lt;/p&gt;
&lt;p&gt;What I&#39;ve learned so far is that you can start with a .NET base image, then layer Node on that, build your app, and then copy out the final assets.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;FROM mcr.microsoft.com/dotnet/aspnet&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.0&lt;/span&gt;-buster-slim AS base
WORKDIR /app

FROM node&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;lts-buster-slim AS node_base
FROM mcr.microsoft.com/dotnet/sdk&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.0&lt;/span&gt;-buster-slim AS build
COPY --from=node_base . .

WORKDIR /src
COPY &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp/MyDotNetApp.csproj&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
RUN dotnet restore &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp/MyDotNetApp.csproj&quot;&lt;/span&gt;
WORKDIR &lt;span class=&quot;token string&quot;&gt;&quot;/src/MyDotNetApp/&quot;&lt;/span&gt;
COPY &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp/.&quot;&lt;/span&gt; .

ENV NODE_ENV=production
RUN npm ci
RUN npm run build
RUN dotnet build &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp.csproj&quot;&lt;/span&gt; -c Release -o /app/build

FROM build AS publish
RUN dotnet publish &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp.csproj&quot;&lt;/span&gt; -c Release -o /app/publish

FROM base AS final
EXPOSE &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dotnet&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp.dll&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see how everything fits together &lt;a href=&quot;https://github.com/TwoPeas/SharpStatusApp/blob/main/SharpStatusApp/package.json&quot;&gt;here&lt;/a&gt; where I am building &lt;a href=&quot;https://github.com/TwoPeas/SharpStatusApp&quot;&gt;SharpStatusApp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The core bits:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;FROM node&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;lts-buster-slim AS node_base
FROM mcr.microsoft.com/dotnet/sdk&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.0&lt;/span&gt;-buster-slim AS build
COPY --from=node_base . .&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re going to pull down Node&#39;s LTS image built on Buster-Slim and Microsoft&#39;s .NET 5 SDK image built on Buster-Slim. Then we&#39;ll copy the contents of the Node image into the .NET image. For me, this means I get the Node bits I need from an official image rather than using &lt;code&gt;apt-get&lt;/code&gt; to figure out and install my own dependencies.&lt;/p&gt;
&lt;p&gt;On to the build part:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;ENV NODE_ENV=production
RUN npm ci
RUN npm run build
RUN dotnet build &lt;span class=&quot;token string&quot;&gt;&quot;MyDotNetApp.csproj&quot;&lt;/span&gt; -c Release -o /app/build&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PurgeCSS will automatically tree-shake the final CSS for you if it&#39;s in production mode. So, I default the &lt;code&gt;NODE_ENV&lt;/code&gt; to production. This will also help with any other tooling I bring in later that might make different choices based on build environment.&lt;/p&gt;
&lt;p&gt;You should use &lt;code&gt;npm ci&lt;/code&gt; on your build server rather than &lt;code&gt;npm install&lt;/code&gt; as &lt;code&gt;ci&lt;/code&gt; will use your &lt;code&gt;package-lock.json&lt;/code&gt; file to grab versions... which gives you a bit of confidence that you won&#39;t accidentally rev a version that you haven&#39;t tried locally yet.&lt;/p&gt;
&lt;p&gt;Then it&#39;s a matter of running my &lt;a href=&quot;https://github.com/TwoPeas/SharpStatusApp/blob/main/SharpStatusApp/package.json#L10&quot;&gt;npm script&lt;/a&gt; with &lt;code&gt;npm run build&lt;/code&gt; and compiling my .NET app with &lt;code&gt;dotnet build&lt;/code&gt; then we bundle things up and
get a svelte(?) final image with just our assets and runtime and none of the build tools or artifacts.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping Up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/docker-dotnet5/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Including a Node.js Docker image as a base part of your build might be old hat, but I hadn&#39;t seen any examples of it. I wanted to document what I learned in case it helped anyone else down the road. I, personally, think it&#39;s a pretty clean way to assemble an app for deployment.&lt;/p&gt;
&lt;p&gt;If you have any questions, comments or complaints, you can always DM or skeet me &lt;a href=&quot;https://bsky.app/profile/hyr.mn&quot;&gt;@hyrmn&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Living with your creations</title>
    <link href="https://hyr.mn/application-oddities/"/>
    <updated>2021-02-01T00:00:00Z</updated>
    <id>https://hyr.mn/application-oddities/</id>
    <content type="html">&lt;p&gt;Last week, I &lt;a href=&quot;https://twitter.com/hyrmn/status/1355249530086838279&quot;&gt;tweeted out&lt;/a&gt; the three oddities of application development:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How you thought you built the system&lt;/li&gt;
&lt;li&gt;How you built the system&lt;/li&gt;
&lt;li&gt;How your system is used&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m not treading any new ground here. There&#39;s been a lot of thinking by smart people on emerging properties of complex systems. But, I wanted to take a bit of time and talk about my experience and maybe share some ideas and techniques for life in a small company with a focus on a B2B SaaS product.&lt;/p&gt;
&lt;p&gt;I&#39;ve been living with, and supporting, a software product for 8 years now. So, these opinions are formed by that.&lt;/p&gt;
&lt;p&gt;When you first set out to build a system, you&#39;ll anchor some large architectural and design decisions. You probably won&#39;t do a big design up front, but you&#39;ll make decisions and live with them. Some decisions you won&#39;t even know you&#39;ve made... but not choosing is still a choice. Because communication is lossy, your mental model of the system will never match your coworkers&#39; mental model of the system. You&#39;ll try, and you&#39;ll get pretty close but you&#39;ll all have implicit assumptions that seep in.&lt;/p&gt;
&lt;p&gt;Over time, what you thought you built is not what you built.&lt;/p&gt;
&lt;p&gt;You&#39;ll face market pressure; real and imagined. Enhancements and features, like water, will seek the path of least resistance in their journey to production. You&#39;ll shore up pathways and dam off bad directions, but riverbanks will still shift on you.&lt;/p&gt;
&lt;p&gt;Heck, you will not be the same person with the same skills in two years that you are now. Your tools, libraries, frameworks and, most importantly, your thinking will change. You&#39;ll purposely take new code and new designs in a different direction. But you can&#39;t lift and shift all of the old code.&lt;/p&gt;
&lt;p&gt;Again, over time, what you thought you built is not what you built. Multiply that by the size (and churn) of your team. Multiply it by the years your app has existed. Realize that, in some nook, some forgotten logic path, your code is lying to you. Unit tests help. Integration tests help. You still missed what happens with that I/O interaction at the edge.&lt;/p&gt;
&lt;h2 id=&quot;how-to-handle-code-untruths&quot; tabindex=&quot;-1&quot;&gt;How to handle code untruths &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/application-oddities/#how-to-handle-code-untruths&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For me, this is multi-pronged.&lt;/p&gt;
&lt;p&gt;You must revisit the concepts and models in your code and question if it still makes sense. Be zealous on this. Every design decision is an inflection point and a chance to think about past choices.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example that I&#39;m playing with right now. We have some resources that can be deactivated. Deactivated resources shouldn&#39;t show up through any of the normal UI paths. But, you can choose to view them and reactivate them. We have other resources that can be deleted. Sometimes delete means a hard delete. &lt;em&gt;Poof&lt;/em&gt; Gone. But, sometimes they have to be soft-deleted. A soft-deleted resource still exists but shouldn&#39;t show up through any of the normal UI paths.&lt;/p&gt;
&lt;p&gt;That introduces cognitive load that might not be worth it. Do we really need three paths for making a resource disappear? Is the choice to live with it the easy choice or the right choice? Would addressing it help the system or just feed a need to be technically correct?&lt;/p&gt;
&lt;p&gt;During development, leave your code better than you found it. You can&#39;t be solely focused on pulling work, completing work, pushing work and moving on. You need to revisit those old code paths. Clean behind the fridge once in a while. Can your unit tests be better? Should you add an integration test for that path you noticed but didn&#39;t touch while you were working on your feature?&lt;/p&gt;
&lt;p&gt;In production, I&#39;ve found that you absolutely will live and die by your application instrumentation and logging. Maybe you can invest in observability. Maybe you can&#39;t. But, at the very least, you need to be able to see the runtime execution path. For us, we&#39;ve gotten a lot of mileage off of correlation ids from the front-end all the way back and using &lt;a href=&quot;https://datalust.co/seq&quot;&gt;Seq&lt;/a&gt; to monitor and slice when things go wrong. Things will go wrong.&lt;/p&gt;
&lt;h2 id=&quot;but-then-the-users&quot; tabindex=&quot;-1&quot;&gt;But then, the users &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/application-oddities/#but-then-the-users&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The thing is.. all of the above is trivial once you get to the real issue with your application. And that&#39;s that people will use it. People will use it in ways you didn&#39;t realize or understand.&lt;/p&gt;
&lt;p&gt;We had an idea in mind that people would edit a certain document maybe a dozen times. Heck, even that seemed like a stretch. When a user saved their edits, we&#39;d throw the current and previous state on a queue to be picked up by a backend store for reporting. Well, our mental model of our users was shattered when one user made 300 edits which caused the document to be so large that the system couldn&#39;t enqueue it.&lt;/p&gt;
&lt;p&gt;Or, they won&#39;t use a feature you built.&lt;/p&gt;
&lt;p&gt;There are two broad efforts you should think about with your users. First, learn how they use your software, and then either adapt to them or help them adapt. Second, write tools to analyze the data to answer meta questions.&lt;/p&gt;
&lt;p&gt;Broadly, think about how you can test your hypotheses quickly and cheaply. Then put the tooling in place to do that.&lt;/p&gt;
&lt;p&gt;If you&#39;re offering a web-based service, instrument the important paths through your system so that you can see how your application is being used. &lt;strong&gt;Talk to the people that use your system&lt;/strong&gt;. You will have a core group of power users. You will have people that absolutely love your product and want you to succeed. Identify these people and talk to them; make their life easier.&lt;/p&gt;
&lt;p&gt;Think about how you&#39;ll store your data and write tools to give you answers.&lt;/p&gt;
&lt;p&gt;We store some information in a way that we can answer questions about trends about, or affecting, all of our customers. We have utilities in place to run a little bit of code across all of our tenants. Being about to go from question to answer in &amp;lt; 30 minutes is powerful. Why have a meeting to talk about if you should work on a feature when you can quickly show how people are using it. And who the heaviest users are.&lt;/p&gt;
&lt;p&gt;These tools can be rough. They&#39;re for your team and you can add the polish in over time. But, you must have internal support tooling from the start.&lt;/p&gt;
&lt;h2 id=&quot;parting&quot; tabindex=&quot;-1&quot;&gt;Parting &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/application-oddities/#parting&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;re a small team with a profitable product. We&#39;ve out-competed much bigger companies in our space. We have great net promoter scores with our customers. Some of that is driven by the fact that we can quickly learn about, and adapt to, our customers. Accept that your system is going to evolve and be used in ways you never imagined and think about how to support your team and your customers on that journey.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How (not) to convert a string to lowercase in C#</title>
    <link href="https://hyr.mn/converting-to-lowercase/"/>
    <updated>2020-07-06T00:00:00Z</updated>
    <id>https://hyr.mn/converting-to-lowercase/</id>
    <content type="html">&lt;p&gt;You&#39;re looking for a job, you had a good initial chat with the recruiter and the team would love to have you on-site for an interview day; starting with a technical interview. You&#39;ve heard that the team you&#39;re interviewing with is a bit, well, eccentric. That&#39;s ok.&lt;/p&gt;
&lt;p&gt;The good news, though. They encourage you to bring your own laptop configured how you&#39;d prefer if it&#39;d make you more comfortable. And you&#39;ll be free to use any language you want.&lt;/p&gt;
&lt;p&gt;You show up. You think you&#39;re prepared for anything. You walk in only to be greeted by Alice and Bob. You think you&#39;re getting set up for a &lt;a href=&quot;https://en.wikipedia.org/wiki/Alice_and_Bob&quot;&gt;cryptology joke&lt;/a&gt; but, no, it&#39;s interview time.&lt;/p&gt;
&lt;p&gt;Alice tells you that you&#39;ve got one task. Come up with as many ways as possible, using your preferred language, to convert a string to lowercase. Given the string &amp;quot;This IS COOL&amp;quot;, you should end up with &amp;quot;this is cool&amp;quot;.&lt;/p&gt;
&lt;p&gt;Luckily, since you read my blog, you are well-prepared with stupid ways to do stupid things with code.&lt;/p&gt;
&lt;h3 id=&quot;using-tolower&quot; tabindex=&quot;-1&quot;&gt;Using ToLower() &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/converting-to-lowercase/#using-tolower&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s do the simplest method first, just to make sure we&#39;re jibing with Alice and Bob.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;TEST STRING😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToLower&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
Debug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;test string😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;String has a &lt;code&gt;.ToLower()&lt;/code&gt; method on it to do exactly what we need. Bob frowns slightly that you took the easy route but you assure them that you&#39;re just getting started. Meanwhile, Alice is happy that you thought to include some Unicode in your test case.&lt;/p&gt;
&lt;p&gt;You consult MSDN and see that the &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.string&quot;&gt;String class&lt;/a&gt; implements an &lt;code&gt;IEnumerable&lt;/code&gt; over a collection of &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.char&quot;&gt;Char&lt;/a&gt;. Not only is &lt;code&gt;hello&lt;/code&gt; a string, it&#39;s a collection of five characters &lt;code&gt;new [] {&#39;h&#39;, &#39;e&#39;, &#39;l&#39;, &#39;l&#39;, &#39;o&#39;};&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can work with this.&lt;/p&gt;
&lt;h3 id=&quot;using-tolower-one-character-at-a-time&quot; tabindex=&quot;-1&quot;&gt;Using ToLower() one character at a time &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/converting-to-lowercase/#using-tolower-one-character-at-a-time&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s write a for loop and lowercase a character at a time.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;TEST STRING😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Empty&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    lower &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToLower&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

Debug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;test string😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we&#39;re getting somewhere (not good, but it&#39;s still somewhere). We can iterate over the string one character at a time.&lt;/p&gt;
&lt;p&gt;Let&#39;s see what else we can do.&lt;/p&gt;
&lt;h2 id=&quot;linq-to-the-rescue&quot; tabindex=&quot;-1&quot;&gt;LINQ to the rescue &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/converting-to-lowercase/#linq-to-the-rescue&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can use LINQ. Like other languages, we have &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, and &lt;code&gt;filter&lt;/code&gt; in C# (thanks to LINQ). Unfortunately, we have different names for these methods. &lt;code&gt;reduce&lt;/code&gt; is &lt;code&gt;Aggregate&lt;/code&gt; in LINQ. It&#39;s common to reach for &lt;code&gt;reduce&lt;/code&gt; when you need to do something &amp;quot;mathy&amp;quot;, like maybe sum a bunch of numbers. But, C# lets us work on &lt;em&gt;any&lt;/em&gt; collection type.&lt;/p&gt;
&lt;p&gt;This is going to get a bit confusing, so let&#39;s start with the method signature.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;TAccumulate&lt;/span&gt; &lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Aggregate&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TSource&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TAccumulate&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IEnumerable&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TSource&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TAccumulate&lt;/span&gt; seed&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Func&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TAccumulate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TSource&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TAccumulate&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; func&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are going to start with a &lt;code&gt;seed&lt;/code&gt; in a known starting state. This will be where we&#39;ll &lt;code&gt;accumulate&lt;/code&gt; the result of our function call as well. We&#39;re then going to walk over (enumerate) each entry in our collection (characters in our string in this case). As we do that, we will pass our current state and the entry into a &lt;code&gt;Func&lt;/code&gt;. This can be either an inline lambda or any function that matches the signature &lt;code&gt;(string, char) =&amp;gt; string&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Confusing! Let&#39;s see it in action and hopefully understand it a bit clearer.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;TEST STRING😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Aggregate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Empty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;current&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; current &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToLower&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Debug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;test string😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re starting with an empty string as our &lt;code&gt;seed&lt;/code&gt; (the initial value). We then start iterating through the characters in the string. On the first character, we pass in an empty string and &lt;code&gt;T&lt;/code&gt; to our lambda function. We then concatenate the lowercased &lt;code&gt;t&lt;/code&gt; to our empty string. We then proceed to the next character &lt;code&gt;E&lt;/code&gt;, and pass in our current string &lt;code&gt;t&lt;/code&gt; and the now-current character &lt;code&gt;E&lt;/code&gt;. We do this until the end of the string and then LINQ returns our final &lt;code&gt;accumulate&lt;/code&gt; value to us.&lt;/p&gt;
&lt;p&gt;Bob and Alice are, frankly, very impressed with the mess you&#39;ve made.&lt;/p&gt;
&lt;p&gt;But, we&#39;re not done.&lt;/p&gt;
&lt;h2 id=&quot;reflecting-on-our-progress&quot; tabindex=&quot;-1&quot;&gt;Reflecting on our progress &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/converting-to-lowercase/#reflecting-on-our-progress&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By now, I&#39;m sure you&#39;ve realized that there&#39;s a glaring problem with our code. That&#39;s right. It&#39;s not dynamic enough. &lt;code&gt;String&lt;/code&gt; has two methods we can call. There&#39;s &lt;code&gt;.ToLower()&lt;/code&gt;, which honors the rules of the current culture, and there&#39;s &lt;code&gt;.ToLowerInvariant()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&#39;s revisit how we started our journey but, this time, we&#39;ll make it sizzle with some choose-your-own-adventure options for callers of our function.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WaysToLower&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ToLower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    ToLowerInvariant
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;TEST STRING😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; lowerMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token type-expression class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetMethods&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;First&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; WaysToLower&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ToLowerInvariant&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; lower &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lowerMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Debug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lower &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;test string😁&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can dynamically choose which function we want to invoke. We&#39;ll use reflection to find the corresponding method on &lt;code&gt;String&lt;/code&gt; and then invoke it. The beauty of this approach is that it&#39;s slower, breaks our IDE experience, and will cause a runtime exception if we try and invoke a function that doesn&#39;t exist.&lt;/p&gt;
&lt;p&gt;Bob and Alice are overjoyed at all of the bad code you know how to write. Because, after all, knowing how to write lots of bad code is the mark of a good programmer.&lt;/p&gt;
&lt;h2 id=&quot;lets-get-serious-for-a-moment&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s get serious for a moment &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/converting-to-lowercase/#lets-get-serious-for-a-moment&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ok, all of the above code was, well, bad code. You shouldn&#39;t let it anywhere near your production systems. I wanted to highlight some ways to have fun with a trivial task in C#. But, in reality, string manipulation is not a trivial task. I&#39;m not going to delve any more into it in this blog post, but I want to leave you with a parting example.&lt;/p&gt;
&lt;p&gt;Strings are comprised of &lt;code&gt;Char&lt;/code&gt; objects. But, that might not be a direct mapping with what you picture as a character. I&#39;ve actually snuck this into the examples above. In linguistics, a &lt;a href=&quot;https://en.wikipedia.org/wiki/Grapheme&quot;&gt;grapheme&lt;/a&gt; is the smallest fundamental unit in a writing system. In English, when you learn your ABCs, you&#39;re learning your graphemes. Or, to belabor the point, &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;C&lt;/code&gt; are graphemes.&lt;/p&gt;
&lt;p&gt;With that in mind, how many graphemes are in &lt;code&gt;test string😁&lt;/code&gt;? How many &lt;code&gt;Char&lt;/code&gt; objects are in &lt;code&gt;test string😁&lt;/code&gt;? As any Millenial or Zoomer can tell you, an emoji is the smallest fundamental unit of any text message. (and, if you want even more fascinating insight into how emoji are impacting language and our ability to signal non-verbal communication in writing, check out &amp;quot;&lt;a href=&quot;https://gretchenmcculloch.com/book/&quot;&gt;Because Internet&lt;/a&gt;&amp;quot; by Gretchen McCulloch)&lt;/p&gt;
&lt;p&gt;If you showed a college student our test string, they would quickly tell you that there are twelve graphemes.&lt;/p&gt;
&lt;p&gt;But, if you ask .NET the same question, you&#39;re going to get conflicting answers. We need two characters to represent that innocuous 😁. Calling &lt;code&gt;.Length&lt;/code&gt; will tell us there are 13 &lt;code&gt;Char&lt;/code&gt; objects. But, there&#39;s been a recent addition to the .NET Framework so we can be as smart as a fifth grader. If we call &lt;code&gt;.EnumerateRunes()&lt;/code&gt;, we&#39;ll learn that there are only 12 graphemes. (both .NET and Go call them runes)&lt;/p&gt;
&lt;p&gt;Why does this matter? In your everyday coding life, it may not. After all, the .NET runtime was smart enough to not ruin our smiley no matter what we did. You&#39;ll know when it does matter, though. And, before you get to that point, you might want to dive deeper on &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/base-types/character-encoding-introduction&quot;&gt;Character encoding in .NET&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, that&#39;s all for now.&lt;/p&gt;
&lt;p&gt;👋🏻&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Various ways to map data between classes</title>
    <link href="https://hyr.mn/mapping-objects-in-csharp/"/>
    <updated>2020-07-01T00:00:00Z</updated>
    <id>https://hyr.mn/mapping-objects-in-csharp/</id>
    <content type="html">&lt;p&gt;A while ago, I wrote about &lt;a href=&quot;https://hyr.mn/intro-to-automapper&quot;&gt;using AutoMapper to copy data between objects&lt;/a&gt;. Today I want to revisit that and provide some alternatives for mapping. Some serious... some not so serious.&lt;/p&gt;
&lt;p&gt;It can be useful to reshape our data by copying it to a more specific structure that&#39;s tailored to the current use case. For example, we want to return a limited amount of data in response to an API request rather than our full domain object. Or, maybe we want to let the user send us changes and we want to protect against &lt;a href=&quot;https://www.hanselman.com/blog/ASPNETOverpostingMassAssignmentModelBindingSecurity.aspx&quot;&gt;overposting&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&#39;s explore some options in C# and learn something about two potentially useful C# &lt;code&gt;operator&lt;/code&gt; type converters along the way.&lt;/p&gt;
&lt;p&gt;To set the scene, I have a &lt;code&gt;User&lt;/code&gt; that holds the state for some login and profile information on my to-be-announced e-commerce platform (it&#39;s a tool to find cheeses you&#39;ll love based on your favorite color... very scientific).&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Id &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; Name &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; EmailAddress &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; HashedPassword &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; FavoriteColor &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;DateTimeOffset&lt;/span&gt; AddedOn &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; favoriteColor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DateTimeOffset&lt;/span&gt; addedOn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    FavoriteColor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; favoriteColor&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    AddedOn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; addedOn&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also have an admin screen that lists all of my users. I don&#39;t need, or want, nearly as much information for that view. So, I&#39;m going to return a summary object. You might hear these referred to as view models. There&#39;s nothing special about them; they&#39;re data models that exist to make rendering the data via an API response or HTML page or CSV download easier. For a web app, they can look pretty darn boring.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserSummary&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Id &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; Name &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, how do we get the data from our domain and put it in our view model? Seems trivially easy, right? You probably came up with a few ideas already. This would be a rather dull blog post if I stopped writing here and left the rest as an exercise to the reader. Let&#39;s take a look at some options.&lt;/p&gt;
&lt;h2 id=&quot;inline-mapping&quot; tabindex=&quot;-1&quot;&gt;Inline Mapping &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#inline-mapping&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One option is that we can force the caller to do the mapping.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MapUserManually&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob Almighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice Wunder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; view &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;UserSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach &lt;em&gt;can&lt;/em&gt; be sensible. Especially if there is only one location, or function, where the mapping occurs. However, this quickly falls down if you have, say, three controllers that rely on the same view model. If we decide that the summary must always include the email address, then we have to update &lt;em&gt;every&lt;/em&gt; place that we map &lt;code&gt;User&lt;/code&gt; -&amp;gt; &lt;code&gt;UserSummary&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is also a bit unpleasant for users of your code, either other developers on your team or you in six months, because it forces you to be intimately familiar with how to construct a valid &lt;code&gt;UserSummary&lt;/code&gt; from a &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There&#39;s got to be a better way&lt;/p&gt;
&lt;h2 id=&quot;mapping-with-automapper&quot; tabindex=&quot;-1&quot;&gt;Mapping with AutoMapper &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#mapping-with-automapper&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s start with a look at AutoMapper again.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MapUsingAutoMapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;MapperConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cfg &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; cfg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;CreateMap&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserSummary&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; mapper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CreateMapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob Almighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice Wunder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; view &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mapper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;IEnumerable&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;UserSummary&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;users&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since this is not an in-depth AutoMapper article, I&#39;ve chosen to keep the configuration together with the mapping call. In a production application, you would create the mapping configuration as part of your application&#39;s startup.&lt;/p&gt;
&lt;p&gt;With AutoMapper, &lt;code&gt;cfg.CreateMap&amp;lt;User, UserSummary&amp;gt;()&lt;/code&gt; creates a mapping &lt;em&gt;from&lt;/em&gt; &lt;code&gt;User&lt;/code&gt; &lt;em&gt;to&lt;/em&gt; &lt;code&gt;UserSummary&lt;/code&gt;. This automatically works with scenarios like above where I am mapping a &lt;strong&gt;collection&lt;/strong&gt; of &lt;code&gt;User&lt;/code&gt;s to a &lt;strong&gt;collection&lt;/strong&gt; of &lt;code&gt;UserSummary&lt;/code&gt;s. Note, however, that the mapping is one-way only. If you want to map from &lt;code&gt;UserSummary&lt;/code&gt; back to &lt;code&gt;User&lt;/code&gt; then you would need to add the inverse as well by adding &lt;code&gt;cfg.CreateMap&amp;lt;UserSummary, User&amp;gt;()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;AutoMapper is pretty powerful and we use it extensively at my employer. However, there&#39;s no perfect solution and that includes mapping tools in .NET. If we change &lt;code&gt;Name&lt;/code&gt; to &lt;code&gt;FullName&lt;/code&gt; on our &lt;code&gt;User&lt;/code&gt; domain object, but then &lt;strong&gt;forget&lt;/strong&gt; to rename the same property on our model, we won&#39;t get a compilation error. Rather, AutoMapper will happily give us an object with a mapped &lt;code&gt;Id&lt;/code&gt; and a null &lt;code&gt;Name&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note, AutoMapper has a method that you can call after you set up the configuration to ensure that all properites on the target mapping are accounted for. You can perform this check by calling &lt;code&gt;config.AssertConfigurationIsValid();&lt;/code&gt;. But, it&#39;s still a runtime check. So, unfortunately, we lose the benefits of our compiler.&lt;/p&gt;
&lt;h2 id=&quot;static-map-method&quot; tabindex=&quot;-1&quot;&gt;Static Map Method &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#static-map-method&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This next approach is my personal favorite. There&#39;s a few reasons for that. First, it puts the responsibility for mapping in &lt;strong&gt;one&lt;/strong&gt; spot. This could be a dedicated mapper object somewhere, but I like to have the mapping live right with the target. This feels natural in a &amp;quot;typical&amp;quot; namespace hierarchy as well where the view models will live closer to the end user and the domain will live further away.&lt;/p&gt;
&lt;p&gt;Let&#39;s revisit the &lt;code&gt;UserSummary&lt;/code&gt; and add a responsiblity for creating itself from a &lt;code&gt;User&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserSummary&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Id &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; Name &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;UserSummary&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MapFrom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;UserSummary&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      Id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;ve added a static method that takes in a &lt;code&gt;User&lt;/code&gt; and gives us back a &lt;code&gt;UserSummary&lt;/code&gt;. I like this because there is a clear home for the mapping logic; if I rename a property on my domain object then my IDE will update the mapping for me; and if I search for references on my UserSummary, I&#39;m guided here.&lt;/p&gt;
&lt;p&gt;In action, the call to map looks like this&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MapUserWithStaticMapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob Almighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice Wunder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; view &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; UserSummary&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MapFrom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s very similar to the first example but now the mapping has a home.&lt;/p&gt;
&lt;p&gt;One downside of this is that now we have to write &lt;em&gt;a lot&lt;/em&gt; of mapping code. However, there is a very nice Visual Studio add-in that will do this work for you. Check out &lt;a href=&quot;https://mappinggenerator.net/&quot;&gt;MappingGenerator&lt;/a&gt;; a Visual Studio add-in by &lt;a href=&quot;https://twitter.com/cezary_piatek&quot;&gt;Cezary Piątek&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Depending on how frequently your mappings change and the existing structure of your app, you may find AutoMapper a better fit for you or you may prefer a static mapper.&lt;/p&gt;
&lt;h2 id=&quot;on-to-misusing-c-to-do-what-we-want&quot; tabindex=&quot;-1&quot;&gt;On to misusing C# to do what we want! &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#on-to-misusing-c-to-do-what-we-want&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I promised some &amp;quot;creative&amp;quot; alternatives for mapping as well.&lt;/p&gt;
&lt;h3 id=&quot;explicit-type-conversion&quot; tabindex=&quot;-1&quot;&gt;Explicit type conversion &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#explicit-type-conversion&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider the following code, &lt;code&gt;var view = (UserSummary) user&lt;/code&gt;. We&#39;re telling C# that we want to take our &lt;code&gt;User&lt;/code&gt; object and strong-arm it into being a &lt;code&gt;UserSummary&lt;/code&gt; object. As our code stands above, this won&#39;t work. It won&#39;t work because, as far as C# is concerned, there&#39;s no commonality... without making &lt;code&gt;User&lt;/code&gt; a subclass of &lt;code&gt;UserSummary&lt;/code&gt;, C# is just going to give us a compiler error, throw it&#39;s digital hands up, and call us names.&lt;/p&gt;
&lt;p&gt;But, this would be a pretty lackluster spot to leave this blog post if we couldn&#39;t come up with some options.&lt;/p&gt;
&lt;p&gt;And, we do have options. A way to dazzle your friends and win that coveted trivia night contest finally.&lt;/p&gt;
&lt;p&gt;The explicit type conversion operator.&lt;/p&gt;
&lt;p&gt;Let&#39;s change our &lt;code&gt;UserSummary&lt;/code&gt; class again and give C# a roadmap on how to get from A to B.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserSummary&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Id &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; Name &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;explicit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserSummary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;UserSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the risk of repeating ourselves, let&#39;s see the explicit cast in action&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MapUserWithExplicitCast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob Almighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice Wunder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; view &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UserSummary&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&#39;re familiar with LINQ, you&#39;re probably wondering why you can&#39;t call &lt;code&gt;users.Cast&amp;lt;UserSummary&amp;gt;()&lt;/code&gt;. The reason is because the explicit cast that we introduced is bound at the &lt;a href=&quot;https://en.wikipedia.org/wiki/Call_site&quot;&gt;call sites&lt;/a&gt; at compile-time (that is, the code to do the conversion is written at the time you build your app) but the LINQ &lt;code&gt;.Cast&amp;lt;&amp;gt;()&lt;/code&gt; method is a generic cast performed at runtime and, as such, misses out on that compilation switch-out.&lt;/p&gt;
&lt;p&gt;Would I do this in production code? Not for this kind of use case... no. It forces your caller to know that they can (and should) use an explicit cast to transform the data. Compare this to the &lt;code&gt;UserSummary.MapFrom()&lt;/code&gt; method where we get intellisense in our IDE and a clear expectation of what to pass.&lt;/p&gt;
&lt;p&gt;That said, we&#39;ve gotta have some fun in the blog. Plus, there are some valid use cases for it, such as creating a strongly typed ID value object that can pretend to be a GUID when needed. This is worth exploring if you&#39;re pursuing a Domain Driven Design.&lt;/p&gt;
&lt;h3 id=&quot;implicit-type-conversion&quot; tabindex=&quot;-1&quot;&gt;Implicit type conversion &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#implicit-type-conversion&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s wrap up the code examples with a look at a similar approach to explicit type conversion. In a way, it feels like the inverse. Whereas our explicit type conversion is set up with, well, an explicit cast &lt;code&gt;var view = (UserSummary) user&lt;/code&gt;, an implicit type conversion relies on the left hand side of the assignment &lt;code&gt;UserSummary view = user&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After modifying our code, we have the following&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserSummary&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Id &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; Name &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserSummary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;UserSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I should mention that you &lt;strong&gt;cannot&lt;/strong&gt; have both an explicit and implicit operator that take the &lt;em&gt;same source type&lt;/em&gt; and return the &lt;em&gt;same converted type&lt;/em&gt;. If you try and create a class with both the explicit and implicit operators as I have them in this article, you&#39;ll get a compiler error.&lt;/p&gt;
&lt;p&gt;Now, on to the calling code&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MapUserWithImplicitCast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob Almighty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice Wunder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DateTimeOffset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; view &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserSummary&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;ve had to change up our LINQ &lt;code&gt;.Select()&lt;/code&gt; statement quite a bit. LINQ uses this type internally when iterating over the source collection. As it does, it will call our implicit type converter.&lt;/p&gt;
&lt;p&gt;Again, I would not actually use this in production code although, honestly, to me the Select statement reads fairly nice.&lt;/p&gt;
&lt;p&gt;The reason that I don&#39;t like the implicit cast here is that it hides the complexity in a way that I&#39;d rather keep centered. And, as with our explicit cast, it forces the caller to understand too much of your internal implementation. But, it&#39;s useful to understand explicit and implicit type conversions so you can know when, and when not, to use them.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/mapping-objects-in-csharp/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;ve covered a bit of ground on how to take data from over here and put it over there. I think AutoMapper or static mappers make the most sense for production applications of any notable size. I prefer static mapping methods as the maintenance &lt;em&gt;can&lt;/em&gt; be easier and having one less dependency to manage and update might be worth the trade-off. On the other hand, AutoMapper is great when you have a consistent convention and tests in place to catch any missed mappings.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>My Setup</title>
    <link href="https://hyr.mn/my-setup/"/>
    <updated>2020-05-20T00:00:00Z</updated>
    <id>https://hyr.mn/my-setup/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://hyr.mn/img/office.jpg&quot; alt=&quot;My Office&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My wife and I both work remote. I mean, lots of developers do right now in the time of COVID, but we&#39;ve been doing it for a while.&lt;/p&gt;
&lt;p&gt;I bought a new computer in February 2019. My goal at the time was something portable with decent battery life. We spent about half of 2019 on the road.  I haven&#39;t been ready to fully embrace that desktop life, but I did make some purchases in December. (and my wife bought me the poster)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chair&lt;/strong&gt;: Herman Miller Celle. I found it to be more comfortable than the Aeron and significantly cheaper. I like a metal folding chair, though, so take it with a grain of salt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Desk&lt;/strong&gt;: Ikea something or other. It&#39;s their manual crank adjustable desk. (I distrust technology). Even if you don&#39;t stand during the day, it&#39;s nice to be able to adjust throughout the day. I&#39;ve owned and really like a Multitable in the past but this was a cheaper option.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Computer&lt;/strong&gt;: Lenovo Thinkpad T-480s. If I were doing it over, I&#39;d get the full T-480 with 32GB of RAM (mine has 24) and a large battery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monitor&lt;/strong&gt;: LG 34&amp;quot; ultrawide with USB-C. The single-cable connection to the laptop is very nice. I love how it cleans the desk up. I plug my keyboard and mouse into the laptop too (and it has enough juice to power their lights).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keyboard&lt;/strong&gt;: &lt;a href=&quot;https://drop.com/buy/drop-ctrl-mechanical-keyboard&quot;&gt;Drop CTRL&lt;/a&gt; with Halo Clears. It&#39;s a joy to type on and the build quality is amazing. I also own a WASD Keyboard tenkeyless that I enjoy and a &lt;a href=&quot;https://shop.keyboard.io/products/model-01-keyboard&quot;&gt;Keyboardio Model 01&lt;/a&gt; that I keep meaning to use more and keep not using more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mouse&lt;/strong&gt;: Roccat Kone XTD. It&#39;s got adjustable weighting and an optical sensor. This model is quite old and it&#39;s held up well with some tarnishing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Headset&lt;/strong&gt;: Some cheap-ish HyperX. They&#39;re &lt;em&gt;ok&lt;/em&gt; but not &lt;em&gt;great&lt;/em&gt;. I&#39;ve had some AKG K240 MK II headphones in the past that I loved.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sundry&lt;/strong&gt;: &lt;a href=&quot;https://www.startupvitamins.com/products/startup-poster-fuck-it-ship-it&quot;&gt;Fuck It Ship It poster&lt;/a&gt;. &lt;a href=&quot;https://www.pcgamingrace.com/products/glorious-xxl-gaming-mouse-pad&quot;&gt;Glorious PC Gaming Race desk pad&lt;/a&gt;. &lt;a href=&quot;https://www.etsy.com/listing/529764167/macbook-laptop-stand-holder-rest-tidy?ref=yr_purchases&quot;&gt;Walnut laptop holder&lt;/a&gt;. &lt;a href=&quot;https://www.etsy.com/listing/264733887/wooden-walnut-keyboard-wrist-rest?ref=yr_purchases&quot;&gt;Walnut wrist wrest&lt;/a&gt;. &lt;a href=&quot;https://www.etsy.com/listing/605415466/headphone-stand-wood-steel-and-wood?ref=yr_purchases&quot;&gt;Walnut headphone holder&lt;/a&gt;. &lt;a href=&quot;https://www.etsy.com/listing/718141557/customizable-wooden-desk-lamp-table-lamp?ref=yr_purchases&quot;&gt;USB-powered desk light&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hyr.mn/img/desk_closeup.jpg&quot; alt=&quot;My Desk&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My wife made the paper flowers and she&#39;s made it very clear that they&#39;re only on loan 😁&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Counting lines with C#</title>
    <link href="https://hyr.mn/catching-flowers-with-a-net/"/>
    <updated>2020-05-15T00:00:00Z</updated>
    <id>https://hyr.mn/catching-flowers-with-a-net/</id>
    <content type="html">&lt;p&gt;This is, I guess, part 2 in a series.&lt;/p&gt;
&lt;p&gt;I previously wrote about &lt;a href=&quot;https://hyr.mn/counting-flowers-on-the-wall/&quot;&gt;writing a utility in Go&lt;/a&gt; to count carriage returns (or newline characters) in a file. I decided that I wanted to do the same in C# on &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/core/about&quot;&gt;.NET Core&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, let&#39;s take a look at some of the neat new goodies in .NET and see what a command line utility to parse a file might look like. If you want to just see the code, it&#39;s &lt;a href=&quot;https://github.com/hyrmn/nlc&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;implementation-recap&quot; tabindex=&quot;-1&quot;&gt;Implementation Recap &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/catching-flowers-with-a-net/#implementation-recap&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I want this to function just like the Go version. One difference, though. Since I named the Go version &lt;code&gt;lc&lt;/code&gt;, I&#39;m going to go ahead and dub this one &lt;code&gt;nlc&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This means that our little application might be called like this&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; nlc &lt;span class=&quot;token string&quot;&gt;&quot;path/to/your/file.txt&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or like this&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; &lt;span class=&quot;token function&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Count the lines in this&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; nlc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(you can substitute &lt;code&gt;cat&lt;/code&gt;, or &lt;code&gt;grep&lt;/code&gt;, or anything else, for &lt;code&gt;echo&lt;/code&gt; above)&lt;/p&gt;
&lt;p&gt;In either case, the count of carriage returns (&lt;code&gt;&#92;n&lt;/code&gt;) in the file will be printed out.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; nlc &lt;span class=&quot;token string&quot;&gt;&quot;path/to/your/file.txt&quot;&lt;/span&gt;
109&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;handling-a-file-argument&quot; tabindex=&quot;-1&quot;&gt;Handling a file argument &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/catching-flowers-with-a-net/#handling-a-file-argument&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s first figure out how to read a file if the user calls our application with a file path &lt;code&gt;nlc c:&#92;somedir&#92;somefile.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We create an entry point into our console application by declaring a &lt;code&gt;static void Main&lt;/code&gt; function. This can take in a string array of command-line arguments. We don&#39;t need to support named arguments or even more than one argument, so we&#39;ll just assume that the first argument is the path to the file.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;nlc&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Program&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;LineCounter&lt;/span&gt; counter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;LineCounter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;//...//&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;FileStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
		                                FileMode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Open&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
										FileAccess&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Read&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
										FileShare&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;None&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
										&lt;span class=&quot;token named-parameter punctuation&quot;&gt;bufferSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; LineCounter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BufferSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
										FileOptions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SequentialScan&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; counter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CountLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FileNotFoundException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;$&quot;Could not find &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token expression language-csharp&quot;&gt;args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;. Check the file path.&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;//...//&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;.NET gives us different kinds of &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.io.stream?view=netcore-3.1&quot;&gt;Streams&lt;/a&gt; for reading and writing a sequence of bytes. Or, broadly, we get different classes with a shared abstraction to do things like... read and write to files, read and write to memory, the network, etc.&lt;/p&gt;
&lt;p&gt;So, here we&#39;re opening a &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.io.filestream?view=netcore-3.1&quot;&gt;FileStream&lt;/a&gt; in read-only mode. We&#39;re specifying a buffer size, or the number of bytes we expect to read at a time, and we&#39;re providing a hint that we&#39;ll be processing the file sequentially. This gives the runtime a chance to work with the operating system to optimize for read performance.&lt;/p&gt;
&lt;h2 id=&quot;handling-piped-input&quot; tabindex=&quot;-1&quot;&gt;Handling piped input &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/catching-flowers-with-a-net/#handling-piped-input&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Next, we should handle piped input. In my &lt;a href=&quot;https://hyr.mn/counting-flowers-on-the-wall/&quot;&gt;Go line counting article&lt;/a&gt;, I covered file descriptors and how &lt;code&gt;stdin&lt;/code&gt; can be treated as just another file descriptor. Well, in .NET, the abstraction gets kicked up a notch and, you may have guessed already, we can treat it as a stream!&lt;/p&gt;
&lt;p&gt;We can use the System.Console object to determine if the user is piping input to us on &lt;code&gt;stdin&lt;/code&gt; and then read that as a stream if they are&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IsInputRedirected&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; counter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CountLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenStandardInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;count-them-lines&quot; tabindex=&quot;-1&quot;&gt;Count Them Lines &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/catching-flowers-with-a-net/#count-them-lines&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On to the core of the program. The LineCounter&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;nlc&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LineCounter&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; BufferSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;/span&gt; rune &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CountLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Stream&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; read&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; idxOf&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;Span&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;byte&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BufferSize&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;read &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; slice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; read&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;idxOf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slice&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IndexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rune&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          slice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slice&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;idxOf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          count&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As in the Go version, I&#39;m creating a 32 &lt;a href=&quot;https://en.wikipedia.org/wiki/Kibibyte&quot;&gt;kibibyte&lt;/a&gt; buffer. From there, we&#39;re quickly going to diverge from the Go implementation and get weird with things.&lt;/p&gt;
&lt;p&gt;One of the shiny and amazing new offerings that came with C# 7.2 is &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=netcore-3.1&quot;&gt;Span&amp;lt;T&amp;gt;&lt;/a&gt;. Rather than loading the entire file into memory at once (which would be impossible with a large enough file!), we&#39;ll load a chunk at a time and then look for all occurances of our &lt;code&gt;&#92;n&lt;/code&gt; character.&lt;/p&gt;
&lt;p&gt;Some of this looks similar to the Go version. In both, we&#39;re reading a 32kb section of file at a time. The steps we need to take in the .NET version are remarkably similar to the &lt;strong&gt;alternate&lt;/strong&gt; version of the Go program.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For reference, here&#39;s that Go code again.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; target &lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//...//&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; position &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		idxOf &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IndexByte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;position&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; idxOf &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		count&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;
		position &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; idxOf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In both, we look at how many bytes we&#39;ve read, and then we slice over that section of the file; looking for our newline character as we go. Once we find once, we advance past it in the slice and continue our search.&lt;/p&gt;
&lt;p&gt;You can spot some philosophical differences between the .NET and Go versions. I think the one that strikes me the most is that, in .NET, I can&#39;t read past the end of the stream. The documentation has this to say&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Return Value&lt;/strong&gt;
&lt;strong&gt;The total number of bytes read into the buffer&lt;/strong&gt;. This can be less than the number of bytes allocated in the buffer if that many bytes are not currently available, &lt;strong&gt;or zero (0) if the end of the stream has been reached&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Contrast that with the Go version.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;read&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//...//&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EOF &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//...//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Go, we expect to get back &lt;em&gt;either&lt;/em&gt; the number of bytes read &lt;em&gt;or&lt;/em&gt; an error. The error is our signal that the end of file has been reached.&lt;/p&gt;
&lt;p&gt;I think this type of thinking is probably one of the harder switches for someone accustomed to writing C# or Java code when they first start with Go. In those languages, we&#39;re told that raising exceptions is expensive and should truly only be used for exceptional cases (reaching the end of a file is a normal control flow and certainly not exceptional). However, in Go, raising or returning an error is idiomatic and not costly.&lt;/p&gt;
&lt;h2 id=&quot;is-net-as-fast-as-go&quot; tabindex=&quot;-1&quot;&gt;Is .NET as Fast as Go? &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/catching-flowers-with-a-net/#is-net-as-fast-as-go&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The real reason you&#39;re reading. Maybe.&lt;/p&gt;
&lt;p&gt;As a reminder from the last post, I&#39;m warming up reads of a 1.6GB text file. Using our &lt;strong&gt;Go version&lt;/strong&gt; &lt;code&gt;lc&lt;/code&gt;, I get the following averages after an initial warmup call:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;real    0m0.625s
user    0m0.015s
sys     0m0.015s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using our &lt;strong&gt;.NET version&lt;/strong&gt; &lt;code&gt;nlc&lt;/code&gt;, I get the following averages after an initial warmup call:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;real    0m0.619s
user    0m0.000s
sys     0m0.015s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks like a tie to me (and they&#39;re both faster than &lt;code&gt;wc&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Of course, there are other considerations. The compiled Go version on Windows is 2.8mb. Respectable. And, easy enough to compile to multiple targets and distribute. Meanwhile, the .NET version... if you have the framework installed already... is a svelte 170kb (yes, kilobytes). You &lt;em&gt;can&lt;/em&gt; choose to compile the .NET version standalone. I&#39;ll leave that as an exercise for the reader. (spoiler, it results in quite a bit more to bring along for a deployment).&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping Up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/catching-flowers-with-a-net/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I haven&#39;t demonstrated any tests for this program. I&#39;ll leave you to &lt;a href=&quot;https://github.com/hyrmn/nlc/blob/master/nlc.tests/LineCounterTests.cs&quot;&gt;review them&lt;/a&gt; at your leisure.&lt;/p&gt;
&lt;p&gt;Contrasting .NET and Go with a small utility like this has been fun and interesting. The new developments with .NET Core and C# have been exciting to watch and playing with the new Span class has been great. I would be hard-pressed to reach for .NET over Go for a utility like this though. But, I think I could easily say the inverse for other problem spaces.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Counting lines with Go</title>
    <link href="https://hyr.mn/counting-flowers-on-the-wall/"/>
    <updated>2020-05-13T00:00:00Z</updated>
    <id>https://hyr.mn/counting-flowers-on-the-wall/</id>
    <content type="html">&lt;p&gt;I was thinking the other day about &lt;a href=&quot;https://en.wikipedia.org/wiki/Unix_philosophy&quot;&gt;The Unix Philosophy&lt;/a&gt;. Broadly, you can get a lot of power from small command line utilities that do one thing well and can be chained, or composed, into more powerful use cases. For example, there&#39;s a command called &lt;code&gt;wc&lt;/code&gt; (word count). It, well, unsurprisingly, counts words. But, you can also have it count lines if you pass in a flag &lt;code&gt;wc -l&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I wanted to take the idea of &amp;quot;do one thing well&amp;quot; to the extreme. And, since I&#39;m learning Go, I thought a line count utility would be a fitting exercise. In building this, we&#39;ll be able to learn how to read input from another program to support composability; we&#39;ll learn a bit about command line arguments; and we&#39;ll learn about reading files.&lt;/p&gt;
&lt;p&gt;I mentioned composability a bit. Let&#39;s see what that entails. It means that this utility will output only the line count (so that it can be piped on to another command). And, it will need to accept, as input, either the output of another program (we might call this piped input). Or, it will need to be given a file location.&lt;/p&gt;
&lt;p&gt;This means that our little application might be called like this&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; lc &lt;span class=&quot;token string&quot;&gt;&quot;path/to/your/file.txt&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or like this&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; &lt;span class=&quot;token function&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Count the lines in this&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; lc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(you can substitute &lt;code&gt;cat&lt;/code&gt;, or &lt;code&gt;grep&lt;/code&gt;, or anything else, for &lt;code&gt;echo&lt;/code&gt; above)&lt;/p&gt;
&lt;p&gt;In either case, the count of carriage returns (&lt;code&gt;&#92;n&lt;/code&gt;) in the file will be printed out.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; lc &lt;span class=&quot;token string&quot;&gt;&quot;path/to/your/file.txt&quot;&lt;/span&gt;
109&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to just see the code, it&#39;s &lt;a href=&quot;https://github.com/hyrmn/lc&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;implementation-considerations&quot; tabindex=&quot;-1&quot;&gt;Implementation Considerations &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#implementation-considerations&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are some counting assumptions that I made. I had originally chosen to have this match my editor&#39;s line count. That is, if Visual Studio Code shows &lt;code&gt;x&lt;/code&gt; lines then my logic would also show &lt;code&gt;x&lt;/code&gt; lines. However, I&#39;ve chosen to follow the behavior of &lt;code&gt;wc -l&lt;/code&gt;. I count carriage returns (&lt;code&gt;&#92;n&lt;/code&gt;). If a file does not end with a carriage return then the last line will not be counted.&lt;/p&gt;
&lt;p&gt;While I&#39;m not sure how I feel about this behavior, it is consistent with other tooling. A trailing carriage return is required to get an accurate count. Changing this is an exercise left to the reader.&lt;/p&gt;
&lt;p&gt;Also, I think I might want to reuse the line-counting logic in other applications. So, I&#39;m going to separate the command-line interface from the code that understands how to read through a stream and count returns.&lt;/p&gt;
&lt;h2 id=&quot;handling-a-file-argument&quot; tabindex=&quot;-1&quot;&gt;Handling a file argument &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#handling-a-file-argument&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Go has a nice flag library to read from the command line. We&#39;re going to abuse it a bit to read in the first argument a user passes. Remember, the first scenario is, &lt;code&gt;lc &amp;quot;path/to/your/file.txt&amp;quot;&lt;/code&gt;. In this usage, there are no named flags being passed in. I simply need &lt;code&gt;arg0&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
filePath &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; filePath &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Usage:&#92;n&#92;tlc &#92;&quot;path&#92;&#92;to&#92;&#92;file.txt&#92;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;OpenFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filePath&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;O_RDONLY&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0444&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;countLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m opening a file for read-only access, and requiring that the file have read permissions set for the user, group, and other. We&#39;ll get a file descriptor back from the call to &lt;code&gt;os.OpenFile&lt;/code&gt;. You can think of a file descriptor as a small reference that we&#39;ll keep around so know know where to read data from later. And, to clean up after ourselves, we&#39;ll close the file when we&#39;re done reading. We can do with with the call to &lt;code&gt;defer file.Close()&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;handling-piped-input&quot; tabindex=&quot;-1&quot;&gt;Handling piped input &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#handling-piped-input&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The other use case we have to handle is when the data is passed, or piped, directly into our utility.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; &lt;span class=&quot;token function&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Count the lines in this&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; lc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is passed in on &lt;code&gt;stdin&lt;/code&gt;, or &lt;code&gt;standard input&lt;/code&gt;. Unix introduced &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_streams&quot;&gt;three standard streams&lt;/a&gt;. These are ubiquitious enough that many programming languages have some way to access them and will, as needed, abstract the implementation details for the operating system away for you. These streams are &lt;code&gt;stdin&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt; (&lt;code&gt;standard output&lt;/code&gt;), and &lt;code&gt;stderr&lt;/code&gt; (&lt;code&gt;standard error&lt;/code&gt;). You might read something from the user on &lt;code&gt;stdin&lt;/code&gt;, give them some results on &lt;code&gt;stdout&lt;/code&gt;, and log any problems to &lt;code&gt;stderr&lt;/code&gt;. But, as you can see in my use case above, &lt;code&gt;stdin&lt;/code&gt; might be input from anything, including another program.&lt;/p&gt;
&lt;p&gt;And, Unix loves file descriptors. Like, it really loves them. &lt;code&gt;stdin&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt;, and &lt;code&gt;stderr&lt;/code&gt; are all file descriptors. Yep, just like the result of the &lt;code&gt;os.OpenFile&lt;/code&gt; call earlier. This will come in handy. Trust me.&lt;/p&gt;
&lt;p&gt;We need to probe the &lt;code&gt;stdin&lt;/code&gt; file descriptor to see if we received any data.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;stat&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stdin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Stat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; stat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModeCharDevice &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	reader &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; bufio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewReader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stdin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;countLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Calling &lt;code&gt;Stat()&lt;/code&gt; will give us information on the associated file descriptor. In this case, that&#39;s Go&#39;s reference to &lt;code&gt;stdin&lt;/code&gt;, which Go nicely stores for us in a variable called &lt;code&gt;os.Stdin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I know &lt;code&gt;stat.Mode() &amp;amp; os.ModeCharDevice == 0&lt;/code&gt; looks a little hairy. We&#39;re asking Go for the current file mode on the file information. This is a bitmask of the current modes that are set on the file. When the &#39;this is character input&#39; flag is set, then we know that &lt;code&gt;stdin&lt;/code&gt; is open and being written to.&lt;/p&gt;
&lt;p&gt;We could read directly from the &lt;code&gt;stdin&lt;/code&gt; file. But, I want to buffer the input to more efficiently traverse it. Go provides a &lt;a href=&quot;https://www.quora.com/In-C-what-does-buffering-I-O-or-buffered-I-O-mean/answer/Robert-Love-1&quot;&gt;buffered I/O&lt;/a&gt; library for just such a use case. We give &lt;code&gt;bufio.NewReader&lt;/code&gt; an &lt;code&gt;io.Reader&lt;/code&gt; and get back an &lt;code&gt;io.Reader&lt;/code&gt;. What a deal. But, it does &lt;em&gt;a ton&lt;/em&gt; for us under the hood.&lt;/p&gt;
&lt;p&gt;Now that we have an &lt;code&gt;io.Reader&lt;/code&gt;, we can call into the package (that we haven&#39;t written yet), and count them carriage returns.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;countLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Reader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	count&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; lc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CountLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;count-them-lines&quot; tabindex=&quot;-1&quot;&gt;Count Them Lines &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#count-them-lines&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Long article. I know. But, we&#39;re here. All of that setup and we can deliver the actual value in 22 lines of code&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CountLines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Reader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; count &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; read &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; err &lt;span class=&quot;token builtin&quot;&gt;error&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; target &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&#92;n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	buffer &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		read&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		count &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EOF &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just to recap, we want to know how many times a &lt;code&gt;&#92;n&lt;/code&gt; character appears in a given file. In a text file, at least, this would tell us how many lines long it is (emoji can&#39;t have carriage returns in the middle; I checked).&lt;/p&gt;
&lt;p&gt;We don&#39;t care about any of the content. So, the question is. How can we efficiently read through the file, get what we want, and get out. I&#39;m going to rule out using &lt;code&gt;io.ReadBytes(&#39;&#92;n&#39;)&lt;/code&gt; or higher-level abstractions like &lt;code&gt;scanner&lt;/code&gt; as I want to hold as little in memory as possible. With those options, I might end up trying to read an entire file into memory before I find the first newline character.&lt;/p&gt;
&lt;p&gt;But, we can create a byte buffer, read into that buffer, and then search just that buffer. When we&#39;re done, we&#39;ll move on to the next chunk.&lt;/p&gt;
&lt;p&gt;So, let&#39;s create a 32 &lt;a href=&quot;https://en.wikipedia.org/wiki/Kibibyte&quot;&gt;kibibyte&lt;/a&gt; buffer&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;buffer &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then read from our file into that&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;read&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This might give us a buffer with the following content&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;Hello World&#92;nThis is a&#92;nThree line file&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The variable &lt;code&gt;read&lt;/code&gt; will tell us how many bytes were read in. This is &lt;em&gt;very&lt;/em&gt; important information because we&#39;re reusing our buffer and not re-initializing it between reads. Suppose we read &lt;strong&gt;32kb&lt;/strong&gt; of data on the first call to &lt;code&gt;r.Read(buffer)&lt;/code&gt; but only &lt;strong&gt;5kb&lt;/strong&gt; of data on the second call. &lt;strong&gt;Our buffer will still contain 32kb of data&lt;/strong&gt;. 5kb from the last read followed by 27kb of old data...&lt;/p&gt;
&lt;p&gt;Next, we can use the &lt;code&gt;bytes.Count&lt;/code&gt; method in the Go standard library to find the number of newline characters. We&#39;ll store the result in our counter variable.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;count &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will loop &amp;quot;forever&amp;quot;. In reality, we will read incrementially to the end of the file. Then, we&#39;ll try and read &lt;em&gt;one more time&lt;/em&gt; and Go will return an end of file error. We&#39;ll check to see when this is encountered and return our results then. In our use case, an end of file error is &lt;em&gt;expected&lt;/em&gt; so... well, we shouldn&#39;t return it to the caller.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EOF &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;an-alternative-way-to-read&quot; tabindex=&quot;-1&quot;&gt;An Alternative Way to Read &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#an-alternative-way-to-read&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Calling &lt;code&gt;bytes.Count(buffer[:read], target)&lt;/code&gt; is a very specific choice that I can make for this application. However, it might not always work for us. Suppose we were looking for a slightly more complicated pattern. Go has a way for us to do that. &lt;code&gt;bytes.IndexByte&lt;/code&gt; will return the index position of the first occurance of a byte in a byte array. If no occurance is found, then a &lt;code&gt;-1&lt;/code&gt; is returned.&lt;/p&gt;
&lt;p&gt;So, while it&#39;s more complicated, we can look for our &lt;code&gt;&#92;n&lt;/code&gt; character, and then look at the next slice of the array after that character, and then look at the next slice... continuing on until we&#39;re out of things to look at. Then we&#39;d move on to the next chunk of file.&lt;/p&gt;
&lt;p&gt;In that implementation, we would replace &lt;code&gt;count += bytes.Count(buffer[:read], target)&lt;/code&gt; with the following&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; target &lt;span class=&quot;token builtin&quot;&gt;byte&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; position &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		idxOf &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; bytes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IndexByte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;position&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; idxOf &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		count&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;
		position &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; idxOf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;is-it-fast&quot; tabindex=&quot;-1&quot;&gt;Is it Fast? &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#is-it-fast&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am only concerned with if this is &lt;em&gt;comparatively&lt;/em&gt; fast when measured against &lt;code&gt;wc&lt;/code&gt;. Getting true benchmarking numbers are outside of the scope of my efforts here. I&#39;ve run both programs several times which ensures the operating system and my storage have both done any caching they plan to do.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;time&lt;/code&gt; (Unix timing utility) &lt;code&gt;wc&lt;/code&gt; on my machine (a midrange dev laptop with an NVMe SSD drive) to parse a 1.6GB text file of lorem ipsum text, I get the following averages after an initial warmup call:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;real    0m0.822s
user    0m0.156s
sys     0m0.655s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;lc&lt;/code&gt; to parse the same file, I get the following averages after an initial warmup call:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;real    0m0.625s
user    0m0.015s
sys     0m0.015s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, I&#39;m happy with how this experiment went.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping Up? &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/counting-flowers-on-the-wall/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I haven&#39;t demonstrated any tests for this program. I&#39;ll leave you to &lt;a href=&quot;https://github.com/hyrmn/lc/blob/master/pkg/lc/lc_test.go&quot;&gt;review them&lt;/a&gt; at your leisure. Or, wait for the next exciting installment.&lt;/p&gt;
&lt;p&gt;I&#39;ve &lt;a href=&quot;https://hyr.mn/go-structure-windows/&quot;&gt;previously covered&lt;/a&gt; how I set Go up locally and added &lt;code&gt;%GOPATH%&#92;bin&lt;/code&gt; to my path. So, from within the &lt;code&gt;lc&lt;/code&gt; project directory, I can run &lt;code&gt;go install&lt;/code&gt; and have a shiny new command line utility to use.&lt;/p&gt;
&lt;p&gt;Honestly, thinking up bespoke little utilities has been a lot of fun. And, once you unlock the power of chaining them together, you&#39;ll think of many new use cases. Just keep the Unix philosophy in mind.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Formatting Go code with goimports</title>
    <link href="https://hyr.mn/gofmt/"/>
    <updated>2020-01-20T00:00:00Z</updated>
    <id>https://hyr.mn/gofmt/</id>
    <content type="html">&lt;p&gt;I&#39;ve found a couple things that help when writing Go in Visual Studio Code. If you&#39;re using VS Code then you&#39;ve probably been prompted to install some Go-related extensions already. But, there are a couple of settings that you might not have enabled. These settings will make things a little more enjoyable. At least they did for me&lt;/p&gt;
&lt;h2 id=&quot;format-on-save&quot; tabindex=&quot;-1&quot;&gt;Format on Save &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/gofmt/#format-on-save&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Go to your VS Code settings. You can either press &lt;code&gt;ctrl + ,&lt;/code&gt; or go to File -&amp;gt; Preferences -&amp;gt; Settings. Ensure that &lt;code&gt;Format on Save&lt;/code&gt; is enabled:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hyr.mn/img/vscodeformatonsave.png&quot; alt=&quot;VS Code Format on Save&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Every time you save the file in VS Code, it will run it through your format tool. Yay!&lt;/p&gt;
&lt;h2 id=&quot;switch-from-gofmt-to-goimports&quot; tabindex=&quot;-1&quot;&gt;Switch from gofmt to goimports &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/gofmt/#switch-from-gofmt-to-goimports&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;gofmt&lt;/code&gt; tool does one thing. It formats your code to ensure it follows the Go standards. Useful, but not helpful. For example, Go will throw a compilation error if your source contains an unused import. &lt;code&gt;gofmt&lt;/code&gt; doesn&#39;t care; it&#39;s happy to just make sure things look decent.&lt;/p&gt;
&lt;p&gt;The following won&#39;t compile&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;log&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; go run &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&#92;main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;go:5:2: imported and not used: &lt;span class=&quot;token string&quot;&gt;&quot;log&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s another option. &lt;a href=&quot;https://godoc.org/golang.org/x/tools/cmd/goimports&quot;&gt;goimports&lt;/a&gt;. In addition to the formatting work of &lt;code&gt;gofmt&lt;/code&gt;, &lt;code&gt;goimports&lt;/code&gt; will remove unused imports, lay out imports so that the standard library ones are grouped first, and list everything alphabetically. It will also try and resolve and import any missing imports.&lt;/p&gt;
&lt;p&gt;The link above has steps to get running with some editors but VS Code is missing. Fortunately, it&#39;s uncomplicated.&lt;/p&gt;
&lt;p&gt;First, we need to install &lt;code&gt;goimports&lt;/code&gt;. Open a command prompt and do that&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt; go get golang&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;org/x/tools/cmd/goimports&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, go to to your VS Code settings.&lt;/p&gt;
&lt;p&gt;Search for &lt;code&gt;go: format tool&lt;/code&gt; and pick &lt;code&gt;goimports&lt;/code&gt; from the list.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hyr.mn/img/vscodegoformattool.png&quot; alt=&quot;VS Code editor setting for Go: Format Tool&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That&#39;s it. Now you&#39;ll get a little more help when writing code.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot; tabindex=&quot;-1&quot;&gt;Next Steps &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/gofmt/#next-steps&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Of course, &lt;code&gt;gofmt&lt;/code&gt; and &lt;code&gt;goimports&lt;/code&gt; aren&#39;t the only two tools in town for code tidying. Search around, find others, and see if you find one that meshes nicely with your workflow. For example, check out &lt;a href=&quot;https://github.com/sqs/goreturns&quot;&gt;goreturns&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy formatting.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Go 1.13 on Windows - File Structure</title>
    <link href="https://hyr.mn/go-structure-windows/"/>
    <updated>2020-01-15T00:00:00Z</updated>
    <id>https://hyr.mn/go-structure-windows/</id>
    <content type="html">&lt;p&gt;I&#39;ve been playing with Go and I thought it might be helpful to others to document a bit of what I&#39;ve learned about Go on Windows. The &lt;a href=&quot;https://golang.org/doc/code.html&quot;&gt;Go Docs&lt;/a&gt; are very thorough but I&#39;m putting things down so I can remember and maybe it will help someone else as well. &lt;strong&gt;Just keep in mind, these are the notes of a Go novice&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-go-path&quot; tabindex=&quot;-1&quot;&gt;The Go Path &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/go-structure-windows/#the-go-path&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you install Go, it should add its bin directory to your path automatically. For me, everything related to the Go tooling went in &lt;code&gt;C:&#92;Go&#92;bin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In addition to this, Go likes all of the Go code to live under one common root. It defaults to &lt;code&gt;%USERPROFILE%&#92;go&lt;/code&gt;. This most likely maps to &lt;code&gt;c:&#92;Users&#92;{Your user name}&lt;/code&gt;. You can override this easily enough. I want everything to live under &lt;code&gt;c:&#92;code&#92;go&lt;/code&gt;. To make this change, you need to set the &lt;code&gt;GOPATH&lt;/code&gt; environment variable.&lt;/p&gt;
&lt;p&gt;You can do this from a command prompt by running&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;setx GOPATH c:&#92;code&#92;go&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, if you prefer, navigate to the environment variables UI and add a User Variable with the above value.&lt;/p&gt;
&lt;p&gt;Your Go directory structure is going to closely mirror where the code comes from. If you run &lt;code&gt;go get github.com/hyrmn/GoTcpEchoServer&lt;/code&gt; then that code will end up in &lt;code&gt;c:&#92;code&#92;go&#92;src&#92;github.com&#92;hyrmn&#92;GoTcpEchoServer&lt;/code&gt;. So, while you can develop 100% locally, if you&#39;re going to eventually push the code to a remote repository then you should probably think about making the structures match now.&lt;/p&gt;
&lt;p&gt;The full structure is probably going to look different than how you normally organize your code.&lt;/p&gt;
&lt;p&gt;We&#39;ll also want a Go module definition file, &lt;code&gt;go.mod&lt;/code&gt;. This file will live at the root of our repository. You can have more than one in your repository but it seems most common to only have one... The module is important as it defines the import path for your packaged code. This is another good reason to have your code structure match where it will ultimately live.&lt;/p&gt;
&lt;h2 id=&quot;hello-file-structure&quot; tabindex=&quot;-1&quot;&gt;Hello File Structure &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/go-structure-windows/#hello-file-structure&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s make Go say &amp;quot;hi&amp;quot; to us.&lt;/p&gt;
&lt;p&gt;On a new command prompt (so you can pick up the &lt;code&gt;GOPATH&lt;/code&gt; settings), navigate to your new root.&lt;/p&gt;
&lt;p&gt;Since we haven&#39;t done anything yet, it&#39;s going to be empty. However, Go will eventually put some top-level directories in here. Go expects all of the source code to live under &lt;code&gt;src&lt;/code&gt; so make that directory now.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;c:&#92;code&#92;go&gt;md src&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your structure will now look like&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;c:&#92;code&#92;go&#92;
└── src&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For &amp;quot;simplicity&#39;s sake&amp;quot; (well, simplicity for future you when you&#39;re pushing code, pulling other people&#39;s code, etc), make a structure under here to map to your remote repository home. For me, that&#39;s GitHub.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;c:&#92;code&#92;go&#92;src&#92;github.com&#92;{replace with your username}&#92;hello&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So, for me, I would run&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;c:&#92;code&#92;go&gt;md src&#92;github&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&#92;hyrmn&#92;hello&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will eventually get pushed up to GitHub to a new repository under my account.&lt;/p&gt;
&lt;p&gt;Navigate to that new directory&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;C:&#92;code&#92;go&gt;cd src&#92;github&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&#92;hyrmn&#92;hello&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;hello-world&quot; tabindex=&quot;-1&quot;&gt;Hello World &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/go-structure-windows/#hello-world&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At last, code time.&lt;/p&gt;
&lt;p&gt;First, let&#39;s tell Go that we want this to be a module.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;c:&#92;code&#92;go&#92;src&#92;github&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&#92;hyrmn&#92;hello&gt;go mod init github&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com/hyrmn/hello&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open up that go.mod file in your favorite editor.&lt;/p&gt;
&lt;pre class=&quot;language-md&quot;&gt;&lt;code class=&quot;language-md&quot;&gt;module github.com/hyrmn/hello

go 1.13&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is useful, I promise.&lt;/p&gt;
&lt;p&gt;Now, while you have your favorite editor open, create a new file &lt;code&gt;main.go&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello, world.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;run it.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt;go run &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

Hello&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; world&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also package the code into an executable with &lt;code&gt;go build&lt;/code&gt;. That will put an executable in the project directory named &lt;code&gt;hello.exe&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;But, there&#39;s more we can do&lt;/p&gt;
&lt;h2 id=&quot;install-the-world&quot; tabindex=&quot;-1&quot;&gt;Install the world &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/go-structure-windows/#install-the-world&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can &lt;code&gt;go install&lt;/code&gt; our program.&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&gt;go install&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will take a second to run. Finish with no output. And... nothing new in your current directory. What gives?&lt;/p&gt;
&lt;p&gt;When you run that command, Go builds your code and, if it succeeds, puts the executable under &lt;code&gt;%GOPATH%&#92;bin&lt;/code&gt;. Or, in our case, &lt;code&gt;c:&#92;code&#92;go&#92;bin&lt;/code&gt;. Go has also taken the opportunity to create a &lt;code&gt;pkg&lt;/code&gt; directory. You don&#39;t need anything in here. Go uses it as a module cache when you start &lt;s&gt;downloading the internet&lt;/s&gt; pulling in modules from other developers.&lt;/p&gt;
&lt;p&gt;Our full directory structure now looks like&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
├── bin
│   └── hello&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exe
├── pkg
└── src
    └── github&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com
        └── hyrmn
            └── hello&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;one-last-setting&quot; tabindex=&quot;-1&quot;&gt;One Last Setting &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/go-structure-windows/#one-last-setting&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you have that fancy executable sitting in that bin directory, you should add your GOPATH bin to your path. One thing Go seems well suited for are fun little command line utilities (I mean, lots of serious stuff too, but I know where I&#39;m starting). With them readily accessible in my bin directory, I just get them for free and at the ready the minute I &lt;code&gt;go install&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping Up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/go-structure-windows/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are starting out in Go, and if 1.13, or the changes it introduced, are still current when you read this, then I hope you find it helpful.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Exploring the Polly.Contrib.WaitAndRetry helpers</title>
    <link href="https://hyr.mn/polly-wait-and-retry/"/>
    <updated>2019-09-18T00:00:00Z</updated>
    <id>https://hyr.mn/polly-wait-and-retry/</id>
    <content type="html">&lt;p&gt;If you&#39;re just here for the code, you can grab it in &lt;a href=&quot;https://gist.github.com/hyrmn/a5227ed08923f3d14bab7736a9683c24&quot;&gt;this Gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In a previous post, I covered a little bit of what you can do with Polly to &lt;a href=&quot;https://hyr.mn/Dapper-and-Polly/&quot;&gt;wait and retry SQL Server exceptions&lt;/a&gt;. Today I want talk about one of the contrib libraries and how it can help standardize some better practices into your retry policies.&lt;/p&gt;
&lt;p&gt;In my code, I use Polly in several places to retry remote calls. Our software is deployed to a cloud provider and, while people should generally build for it anyway, hosting in a cloud environment really drives home that you need to bake resiliency in to any of your code that involves a network connection. That&#39;s not to say cloud hosting is unreliable; far from it. But, you can&#39;t control those small hiccups and blips that happen when underlying infrastructure is upgraded or rerouted.&lt;/p&gt;
&lt;p&gt;So, I might have a Polly retry policy for handling saves to our RavenDB document database&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; retryTimes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;List&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; retryPolicy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Policy
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;WebException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; TransientErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Contains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;OrInner&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;WebException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; TransientErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Contains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Or&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TimeoutException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;OrInner&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TimeoutException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;retryTimes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeSpan&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; retryCount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            LogTo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Warning&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                exception&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;WARNING: Unable to save to Raven, will retry after {RetryTimeSpan}, Retry attempt {RetryCount}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                timeSpan&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                retryCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What I&#39;ve defined in my code above is a linear back-off. If my first try fails, I try again immediately. On each subsequent failure, I&#39;ll wait an additional 50ms and try again. After the last wait and retry, Polly will kick the underlying error up the call chain.&lt;/p&gt;
&lt;p&gt;There are a few things to think about when deciding on a retry policy.&lt;/p&gt;
&lt;p&gt;First, how long should we wait after the initial failure? In my use case (hosting in the cloud), it makes sense to retry failures immediately. A connection might fail because traffic is being killed and routed through a different network path within the data center. In this case, trying again right away will (probably) succeed.&lt;/p&gt;
&lt;p&gt;Next, how long should we wait between retries? That depends on a balance of understanding the resource being called and the execution path of the caller. The code I posted above is in the execution path for a user&#39;s action on our web-based application. The last thing I want to do is force my users to wait. And, I&#39;m calling a well-provisioned multi-node database cluster so I expect it to respond quickly outside of minor traffic blips.&lt;/p&gt;
&lt;p&gt;Choosing how long to wait in a wait-and-retry loop is a balance of resources. You don&#39;t want to overwhelm a remote resource by retrying too quickly. You don&#39;t want to wait too long between retries, though; especially when a user is on the line and waiting. (user patience is the most valuable resource of all.)&lt;/p&gt;
&lt;p&gt;While my code works well for my use case, let&#39;s take a look at &lt;a href=&quot;https://github.com/Polly-Contrib/Polly.Contrib.WaitAndRetry/&quot;&gt;Polly.Contrib.WaitAndRetry&lt;/a&gt; and see if it can help with making things cleaner or at least clearer.&lt;/p&gt;
&lt;p&gt;As the name alludes to, these are helper methods for wait-and-retry that are maintained outside of the official Polly library. There&#39;s so much you can do with Polly and they can&#39;t possibly bake everything into the core library.&lt;/p&gt;
&lt;p&gt;So, let&#39;s redo that Raven retry policy with the contrib library.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; linearBackoff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Backoff&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LinearBackoff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;retryCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;fastFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; retryPolicy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Policy
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;WebException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; TransientErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Contains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;OrInner&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;WebException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; TransientErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Contains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ex&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Or&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TimeoutException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;OrInner&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TimeoutException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitAndRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;linearBackoff&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeSpan&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; retryCount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            LogTo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Warning&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                exception&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;WARNING: Unable to save to Raven, will retry after {RetryTimeSpan}, Retry attempt {RetryCount}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                timeSpan&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                retryCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, I&#39;m using the contrib library to define a linear back-off. The execution is exactly like mine but I like that the intent is clearer. It&#39;s clear that I want to retry four times, that I want a linear growth of 50 milliseconds per retry, and that I want to retry the first time immediately (ok, granted, &lt;code&gt;fastFirst&lt;/code&gt; might not be the clearest name).&lt;/p&gt;
&lt;p&gt;The contrib library also provides a helper for a constant back-off. (I&#39;m also going to switch to a shorter policy definition so this post isn&#39;t a scary length)&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; constant &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Backoff&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ConstantBackoff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;retryCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;fastFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; constantPolicy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Policy
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;FooException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;constant&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, it will retry the first one immediately and then wait 100 milliseconds between each additional retry (and, if we remove that &lt;code&gt;fastFirst&lt;/code&gt; flag then it will wait 100 milliseconds before the first retry as well). A constant back-off is a good choice when your issue is predictable. For example, a batched upload to a rate-limited resource. Or, it can be a good choice when you&#39;re just not sure what a good back-off wait time should be.&lt;/p&gt;
&lt;p&gt;Next, there&#39;s a helper for an exponentially increasing back-off&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; exponential &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Backoff&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExponentialBackoff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;retryCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token named-parameter punctuation&quot;&gt;fastFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; exponentialPolicy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Policy
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;FooException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exponential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The default growth factor is 2.0 but you can provide your own value. With the default growth factor and a fast first retry, our delays will be 0ms, 20ms, 40ms, 80ms, 160ms. Since the growth is exponential, you should start with a low initial value; especially if your retry policy is in the path of a user request. An exponential back-off can be an excellent choice when you&#39;re trying to ensure that your requests don&#39;t all hit the remote resource at the same time every retry. If you&#39;re calling an overburdened service that&#39;s causing your code to retry, then some will retry immediately, some will be on their second retry which will take exponentially more time, etc.&lt;/p&gt;
&lt;p&gt;This brings me to a potential problem with all of these retry strategies, and something that the Polly.Contrib.WaitAndRetry library solves brilliantly.&lt;/p&gt;
&lt;p&gt;Suppose in my scenario, where I&#39;m retrying saves to Raven in response to a user on my web app, Raven becomes overloaded and starts refusing connections. In this case, where I have overloaded my service with a larger number of calls, then there is a strong chance that my failures and my retries will be highly correlated. Service gets overwhelmed so hundreds of requests wait and retry. Then the service comes up, those requests slam the server and bring it down again. We need a way to decorrelate the retries. That is, we want some requests to take, say, 30ms to retry and others to take 70ms, or 49ms, etc.&lt;/p&gt;
&lt;p&gt;What we want to do is add jitter into our retry strategy.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; jittered &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Backoff&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DecorrelatedJitterBackoffV2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token named-parameter punctuation&quot;&gt;medianFirstDelay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; TimeSpan&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;FromMilliseconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    retryCount&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;token named-parameter punctuation&quot;&gt;fastFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; jitteredPolicy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Policy
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;FooException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jittered&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create a retry policy where the initial wait will be close to the first delay and then subsequent delays will, largely, follow an exponential back-off. The key here is to shift things just a little per request in an attempt to have lots of little waves crashing against your resource rather than big waves of retries. There&#39;s a much fuller write-up (along with science and graphs!) on the &lt;a href=&quot;https://github.com/Polly-Contrib/Polly.Contrib.WaitAndRetry/blob/master/README.md&quot;&gt;Polly.Contrib.WaitAndRetry readme&lt;/a&gt; and I would highly encourage heading there.&lt;/p&gt;
&lt;p&gt;This is where the magic of the WaitAndRetry helpers really shines. While it&#39;s awesome for communicating intent with the simpler use cases like in my example of &lt;code&gt;Backoff.LinearBackoff&lt;/code&gt;, it&#39;s downright amazing with the addition of the decorrelated jitter policy. &lt;a href=&quot;https://twitter.com/georgepolevoy&quot;&gt;George Polevoy&lt;/a&gt;, the author of the decorrelation approach, put a lot of hard thinking into this and it really shows. Frankly, I don&#39;t have the knowledge to have come up with it myself, but I do have the knowledge to easily take advantage of it thanks to the packaging provided by &lt;a href=&quot;https://twitter.com/softwarereisen&quot;&gt;Dylan Reisenberger&lt;/a&gt; and &lt;a href=&quot;https://github.com/grant-d&quot;&gt;Grant Dickinson&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Again, the full code for the above blog snippits can be found on &lt;a href=&quot;https://gist.github.com/hyrmn/a5227ed08923f3d14bab7736a9683c24&quot;&gt;this Gist&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>SQL Server Retries with Dapper and Polly</title>
    <link href="https://hyr.mn/dapper-and-polly/"/>
    <updated>2019-09-03T00:00:00Z</updated>
    <id>https://hyr.mn/dapper-and-polly/</id>
    <content type="html">&lt;p&gt;If you&#39;re just here for the code, you can grab it in &lt;a href=&quot;https://gist.github.com/hyrmn/ce124e9b1f50dbf9d241390ebc8f6df3&quot;&gt;this Gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/kendaleiv&quot;&gt;Ken Dale&lt;/a&gt; wrote a post on the RIM Dev blog on how to &lt;a href=&quot;https://rimdev.io/retry-transient-failures-using-sqlclient-adonet-with-polly/&quot;&gt;Retry Transient Failures Using SqlClient / ADO.NET With Polly&lt;/a&gt;. Their use case is similar to mine but different enough that I thought it&#39;d be worth sharing our implementation.&lt;/p&gt;
&lt;p&gt;Like RIM, our tech stack is on Azure and we heavily rely on SQL Azure. We write to a service bus topic; a service then uses those messages to update a reporting database. If the message cannot be written then it&#39;s automatically returned to the queue and retried later. After 5 retries, the service dead-letters the message.&lt;/p&gt;
&lt;p&gt;To accomplish this, our database structure and message handling code is idempotent. Getting, or applying, the same message twice won&#39;t cause duplicated data.&lt;/p&gt;
&lt;p&gt;Our first thought that attempting to process the message x times and then deadlettering would be enough. However, at least in the early days (6+ years ago) after launch, we found out that we were mistaken. Sometimes SQL Azure just didn&#39;t want to cooperate. it&#39;s gotten much better since.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/App-vNext/Polly/&quot;&gt;Polly&lt;/a&gt;. Polly allows for all sorts of amazing retry logic. The things you need to care about in any distributed environment. From basic retry logic like I&#39;ll show here to circuit breakers (great if you&#39;re calling a flaky remote service and you don&#39;t want their service degradation to bring your app down).&lt;/p&gt;
&lt;p&gt;The original code, along with &lt;a href=&quot;https://github.com/StackExchange/Dapper&quot;&gt;Dapper&lt;/a&gt;, has been in production for quite a while. I&#39;ve since updated to use the &lt;code&gt;async&lt;/code&gt; methods in Dapper and thought I should share what we use.&lt;/p&gt;
&lt;p&gt;Following is a simplified version of the full code that&#39;s available on &lt;a href=&quot;https://gist.github.com/hyrmn/ce124e9b1f50dbf9d241390ebc8f6df3&quot;&gt;this Gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the time of this post, I&#39;m using Polly v7.0 and Dapper v2.0&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; retryPolicy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Policy
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;SqlException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SqlServerTransientExceptionDetector&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ShouldRetryOn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Or&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TimeoutException&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;OrInner&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Win32Exception&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;SqlServerTransientExceptionDetector&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ShouldRetryOn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RetryTimes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SqlServerTransientExceptionDetector&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ShouldRetryOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SqlException&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// See Gist&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ShouldRetryOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Win32Exception&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// See Gist&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re defining an &lt;code&gt;AsyncRetryPolicy&lt;/code&gt; Polly policy. When an exception is raised in the called code, Polly will look to see if it&#39;s an exception we want handled. In this case, we&#39;re looking for SqlExceptions, Timeouts, and a wrapped Win32 exception. For SqlExceptions and Win32 exceptions, we&#39;re going to further look to see if we can retry it with a call to &lt;code&gt;SqlServerTransientExceptionDetector&lt;/code&gt;. For timeout exceptions, we&#39;ll just retry automatically.&lt;/p&gt;
&lt;p&gt;I&#39;ve given Polly a set number of times to retry with a static back-off. If it exhausts the number of retry times then the exception will then be bubbled up to the calling code. Our service then throws the message back on the service bus to try again or deadletters the message to be handled out of band.&lt;/p&gt;
&lt;p&gt;I&#39;ve created two Dapper extension methods to wrap up calling Polly.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Task&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ExecuteAsyncWithRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IDbConnection&lt;/span&gt; cnn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt;&lt;/span&gt; param &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; RetryPolicy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExecuteAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cnn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExecuteAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Task&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;IEnumerable&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;QueryAsyncWithRetry&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IDbConnection&lt;/span&gt; cnn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt;&lt;/span&gt; param &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; RetryPolicy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExecuteAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cnn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;QueryAsync&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The caller might then look like this&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UpsertPerson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; _conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ExecuteAsyncWithRetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_upsertSql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        lastName
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, the full code for the above classes can be found on &lt;a href=&quot;https://gist.github.com/hyrmn/ce124e9b1f50dbf9d241390ebc8f6df3&quot;&gt;this Gist&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Measure Two Hundred Times, Tweak Twice</title>
    <link href="https://hyr.mn/fun-with-benchmarkdotnet/"/>
    <updated>2019-07-25T00:00:00Z</updated>
    <id>https://hyr.mn/fun-with-benchmarkdotnet/</id>
    <content type="html">&lt;p&gt;My buddy &lt;a href=&quot;https://twitter.com/purekrome&quot;&gt;Pure.Krome&lt;/a&gt; stopped by the JabbR nerd chat with a question.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With this code, would a string be created &lt;em&gt;each time&lt;/em&gt; the response was generated?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;httpResponse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cache-Control&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;$&quot;public,max-age=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token expression language-csharp&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;,must-revalidate&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/davidwengier&quot;&gt;David Wengier&lt;/a&gt; helpfully provided an answer (yes), and why (a bling-string is just a &lt;code&gt;string.Format()&lt;/code&gt; call when it&#39;s converted to IL). But, in TRUE NERD FASHION, we took things to the extreme with some helpful and not-helpful alternatives.&lt;/p&gt;
&lt;p&gt;Mr. Wengier also has a &lt;a href=&quot;https://www.youtube.com/watch?v=24qazsRnc40&quot;&gt;talk on pragmatic performance&lt;/a&gt; that is worth the watch and inspired me to sit down and play with &lt;a href=&quot;https://benchmarkdotnet.org/&quot;&gt;BenchmarkDotNet&lt;/a&gt; for the first time.&lt;/p&gt;
&lt;p&gt;BenchmarkDotNet is a wonderful tool for micro-benchmarking. When you have a small bit of code and you want to know if one option is better or worse than another, you need a miro-benchmarking tool. It will warm your environment to establish a baseline. Then it will run though a bunch of iterations for you and present a cleaner picture than if you put a timer on each end yourself.&lt;/p&gt;
&lt;p&gt;Below, I set up a .NET Core console app, create a class to hold the benchmarks I want to compare, and then tell the BenchmarkRunner to go to town. By default, the output will be sent to the console window.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;CoreJob&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Strings&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Baseline &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgumentsSource&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nameof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PassingInts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BlingString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;$&quot;public,max-age=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token expression language-csharp&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;,must-revalidate&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IEnumerable&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PassingInts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Program&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; summary &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; BenchmarkRunner&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Strings&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, spoiler alert, the &lt;code&gt;BlingString(seconds)&lt;/code&gt; method is not speedy. But, it&#39;s not horrible. I&#39;m going to throw my pragmatic hat in the bushes and come up with some alternatives. Then I&#39;ll order a shiny, new pragmatic hat and discuss trade-offs.&lt;/p&gt;
&lt;p&gt;First, the easy alternative. If we want execution speed, then let&#39;s just hard-code something in. Everything gets cached for an hour.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public,max-age=3600,must-revalidate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;BlingString&lt;/code&gt; is our skateboard, then &lt;code&gt;Literal()&lt;/code&gt; is the super-charged sport bike. There is no computation. BenchmarkDotNet is confused why it&#39;s here.&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;Strings.Literal: Core -&gt; The method duration is indistinguishable from the empty method duration&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s interesting but... well, only until one of your teammates uses your cache header function when they want to cache a critical lookup for just a second. Then your high-frequency trading app makes decisions on stale data. The investors lose millions. And you swear you&#39;ll never use C# again.&lt;/p&gt;
&lt;p&gt;So, now we know that literals are fast. And, we know that &lt;code&gt;string.Format()&lt;/code&gt; (our bling string) is slow. If we could just cache strings we&#39;ve returned before...&lt;/p&gt;
&lt;p&gt;It turns out, in fact, that we can do just that.&lt;/p&gt;
&lt;p&gt;One of the collection objects in .NET is the &lt;code&gt;ConcurrentDictionary&lt;/code&gt;. It&#39;s thread-safe (well, enough for our usage) and, as importantly, it has a &lt;code&gt;GetOrAdd&lt;/code&gt; method we can use&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token return-type class-name&quot;&gt;TValue&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetOrAdd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TKey&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Func&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TValue&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; valueFactory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If a given key exists, then the value is returned.&lt;/p&gt;
&lt;p&gt;If the key does not exist, then the Func is called to generate the value. The value is then added to the dictionary and returned. Broadly, this means we can store our cached strings and generate new ones only when needed.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ConcurrentDictionary&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; LittleShopOfHorrors &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ConcurrentDictionary&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgumentsSource&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nameof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PassingInts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LookupDictionary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    LittleShopOfHorrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetOrAdd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;seconds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;$&quot;public,max-age=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token expression language-csharp&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;,must-revalidate&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But, this has a glaring problem that &lt;a href=&quot;https://twitter.com/adandy_&quot;&gt;Aaron Dandy&lt;/a&gt; pointed out &amp;quot;dictionaries fill up&amp;quot;. That is, there&#39;s no limit to how big our dictionary can grow. Other developers, intentionally (adversarial) or not, might leave you with a 2GB dictionary full of unused values.&lt;/p&gt;
&lt;p&gt;But, this part of the journey is to keep some brainstorming ideas going. We don&#39;t have our pragmatic hat on so we don&#39;t care about memory!&lt;/p&gt;
&lt;p&gt;On to a couple of more elegant ideas proposed by David...&lt;/p&gt;
&lt;p&gt;First, if we&#39;re fairly sure that we will often see many requests for the same value at once, we can implement a poor cache. Just track what we&#39;ve seen last and use that if it matches.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; _lastSeconds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3600&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; _lastHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public,max-age=3600,must-revalidate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgumentsSource&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nameof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PassingInts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LastCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_lastSeconds &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        _lastSeconds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; seconds&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        _lastHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;$&quot;public,max-age=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token expression language-csharp&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;,must-revalidate&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _lastHeader&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This retains the flexibility of working for any number of seconds passed in while betting on most calls using the same value.&lt;/p&gt;
&lt;p&gt;The next option is to just take all but a couple options off of the table. We can use an enum to control what is returned.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CacheLengths&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Short &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Medium &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Long &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgumentsSource&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nameof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PassingEnums&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LiteralByChoice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CacheLengths&lt;/span&gt; cacheLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CacheLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Short&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public,max-age=60,must-revalidate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CacheLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Medium&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public,max-age=3600,must-revalidate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CacheLengths&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Long&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public,max-age=86400,must-revalidate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public,max-age=0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, obviously, this is very inflexible. But, on the other hand, it allows the original author to provide a clearer indication of what the impact of a given value is.&lt;/p&gt;
&lt;p&gt;Last, I came up with what I feel is a more esoteric option. I learned a lot about some parts of the framework that I didn&#39;t know before. I can keep this knowledge filed away in case I need it in the future. And, of course, we&#39;re not going to limit ourselves until we see what the runtime characteristics are.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Entries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; StepSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; _acceptableSeconds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    Enumerable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Entries&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;seconds &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; seconds &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; StepSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; _fuckYouImATrain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    _acceptableSeconds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;seconds &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;$&quot;public,max-age=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token expression language-csharp&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;,must-revalidate&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ToArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ArgumentsSource&lt;/span&gt;&lt;span class=&quot;token attribute-arguments&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nameof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PassingInts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FindNearest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; seconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; idx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;BinarySearch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_acceptableSeconds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RoundToNearest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;seconds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StepSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;idx &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _fuckYouImATrain&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;idx &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Entries &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt; _fuckYouImATrain&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _fuckYouImATrain&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Entries &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We create some acceptable values for &lt;code&gt;seconds&lt;/code&gt;. And then we create a string array of cache headers generated from those acceptable values.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;FindNearest(seconds)&lt;/code&gt; is called, we want to find the closest matching header. We know that we store strings generated in 60 second increments. So, if &lt;code&gt;FindNearest(50)&lt;/code&gt;, &lt;code&gt;FindNearest(60)&lt;/code&gt;, or &lt;code&gt;FindNearest(59)&lt;/code&gt; is called, then we want to find the nearest match to &lt;code&gt;60&lt;/code&gt; (in this case).&lt;/p&gt;
&lt;p&gt;This code is, honestly, a mess from top to bottom:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It relies on keys and values being the same length and in the same order.&lt;/li&gt;
&lt;li&gt;The returned value does not follow the principal of least surprise because there&#39;s no obviously correlation between what you pass in and what you receive back (better naming would help a little).&lt;/li&gt;
&lt;li&gt;From a maintenance standpoint, you&#39;ll need to remember what operator &lt;code&gt;~&lt;/code&gt; is each time you read the code;&lt;/li&gt;
&lt;li&gt;you&#39;ll have to know why you&#39;re using either the index or the XORed compliment of the index&lt;/li&gt;
&lt;li&gt;and you&#39;ll have to think about bounds checking.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But, if the speed is there then maybe... maybe... it&#39;s worth it.&lt;/p&gt;
&lt;p&gt;Let&#39;s put it all together (&lt;a href=&quot;https://gist.github.com/hyrmn/160fe639d4e5627be16fbeb4ae3b2cdf&quot;&gt;gist here&lt;/a&gt;) and see what those numbers look like.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hyr.mn/img/run_results.png&quot; alt=&quot;BenchmarkDotNet results&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A look at the results will tell us that, by far, the bling string approach is the worst with a mean time of about 250 nanoseconds per call.&lt;/p&gt;
&lt;p&gt;Our enum option is the best contender if we can live with the constraints while the the simple cache approach is perfect if we&#39;ll often use the same value in subsequent calls (it trends towards the bling string performance the less often that&#39;s true).&lt;/p&gt;
&lt;p&gt;The lookup dictionary is next fastest while our binary search is slow enough that it hardly seems worth the trouble. This is because search time for the dictionary is an &lt;code&gt;O(1)&lt;/code&gt; operation while the binary search is, on average, &lt;code&gt;O(log n)&lt;/code&gt;. (Thanks &lt;a href=&quot;https://en.wikipedia.org/wiki/Binary_search_algorithm&quot;&gt;Wikipedia&lt;/a&gt;!)&lt;/p&gt;
&lt;p&gt;So, pragmatic hat back on. What&#39;s the best option? That depends! Look at that, after reading all the way to here, I pull out a trite catchphrase. This is where we need to understand our system. We don&#39;t care about optimizing the 97% that doesn&#39;t matter; we need to apply ourselves to the 3% that does.&lt;/p&gt;
&lt;p&gt;If this method is called on every single HTTP request, but it&#39;s an internal app that gets called 1000 a day, then who cares! Leave the bling string in place.&lt;/p&gt;
&lt;p&gt;Or, if this is only called when an image is requested from blob storage and the cache time is an hour, then maybe just hard-code it and be done.&lt;/p&gt;
&lt;p&gt;On the other hand, if this is part of some critical infrastructure where saving milliseconds will net you a comfortable end-of-year bonus, then it&#39;s time to dig in and make some harder choices that depend on understanding your system.&lt;/p&gt;
&lt;p&gt;When we optimize code, we have to keep mutiple audiences in mind. There&#39;s the callers of our code. Which design choice keeps the API straightforward and unsurprising? There&#39;s future maintenance devs (including yourself after you&#39;ve forgotten the reasoning behind your original implementation). Which change makes the code straightforward? What can we do to minimize breaking logic changes? And, of course, the runtime. Which change has a positive impact on execution time? Which change is least likely to have unintended runtime consequences if misused?&lt;/p&gt;
&lt;p&gt;Lots of questions but no answers. But, with a solid handle on writing small benchmarks to evaluate options, you&#39;ll be better equiped to make choices within the scope of the applications that you write and maintain.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Simple echo server in Go</title>
    <link href="https://hyr.mn/golang-tcp-echo/"/>
    <updated>2018-02-05T00:00:00Z</updated>
    <id>https://hyr.mn/golang-tcp-echo/</id>
    <content type="html">&lt;p&gt;When I first started learning to program, I had a blast writing little utilities and servers. I didn&#39;t realize it, but I&#39;ve missed out on that feeling for too many years. I found it again. Thanks to my good friend &lt;a href=&quot;https://twitter.com/pgermishuys&quot;&gt;Pieter&lt;/a&gt;, I&#39;ve started making some progress on my backburner interest in &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;ve written a TCP echo server. There&#39;s a not-very-prescriptive RFC for an echo protocol in &lt;a href=&quot;https://tools.ietf.org/html/rfc862&quot;&gt;RFC 0862&lt;/a&gt;. And, luckily for you, dear reader, the implementation is just as short.&lt;/p&gt;
&lt;p&gt;I&#39;ll only cover the highlights of my server here. Which, given to the small program size, is pretty much all of it. But, you can get a copy of everything over on &lt;a href=&quot;https://github.com/hyrmn/GoTcpEchoServer&quot;&gt;my GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;my-first-go-at-go&quot; tabindex=&quot;-1&quot;&gt;My first go at Go &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/golang-tcp-echo/#my-first-go-at-go&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;m still learning Go so if I fumble on any important point, please let me know! I&#39;m also going to gloss over a few things. So if, like me, you&#39;re new to Go, just know for now that it&#39;s important there&#39;s a &lt;code&gt;func main()&lt;/code&gt; in a &lt;code&gt;package main&lt;/code&gt;. Take that as gospel, we&#39;ll get into the rest.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; function will be run first, and it seems like a good place to put the configuration stuff.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StringVar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;PORT&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Default listen port&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	flag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;7&quot;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I want to be able to configure the port I&#39;ll bind. Yes, the only solid part of the RFC says port 7, but what if I&#39;m on some *nix distro with an echo server daemon already running.&lt;/p&gt;
&lt;p&gt;I&#39;m  using the built-in flags library to allow the user to specify a port with &lt;code&gt;-p&lt;/code&gt;. If they don&#39;t supply one, I&#39;ll look to see if an environment variable named &lt;code&gt;PORT&lt;/code&gt; has been set already. I assume the program will be running in an isolated space which is why I have such a generic environment variable. Finally, if no port is specified, I default to port 7 (at long last, we&#39;ll obey the RFC).&lt;/p&gt;
&lt;p&gt;Next, let&#39;s actually do something and set up our server to listen for a client to connect.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;listening on port %v&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	ln&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tcp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatalf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;listen error, err=%s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; ln&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		conn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; ln&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatalf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;accept error, err=%s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleConn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;conn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;connection accepted %v&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;RemoteAddr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s a lot going on here, but half of it is Go&#39;s approach to error handling. We&#39;ll skip that.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;ln&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tcp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;opt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; ln&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This binds my program to the specified TCP port and waits for a client to connect. And, I&#39;ve indicated with the &lt;code&gt;defer ln.close()&lt;/code&gt; that I want to tidy up and stop listening when my &lt;code&gt;main()&lt;/code&gt; function exits. I don&#39;t think this is necessary in this code, but it&#39;s a good practice to always clean up any resources your application has open.&lt;/p&gt;
&lt;p&gt;The next section is, for me, mind-blowing.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    conn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; ln&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleConn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;conn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Usually, when you put your program in an infinite loop (in this case, a for loop with no signal on when to stop), bad things happen to your CPU. Here, we accept any new client connections from our listener and then pass them off to a &lt;a href=&quot;https://gobyexample.com/goroutines&quot;&gt;goroutine&lt;/a&gt;. A goroutine is a lightweight thread that will run without tying up our main application. So, if 100 clients connect, my program will send off 100 independent goroutines and handle each client. This is infinitely easier than a lot of multithreaded code I&#39;ve written in the past. It&#39;s not without its trade-offs, but that&#39;s immaterial for now.&lt;/p&gt;
&lt;p&gt;Now, finally, on to the actual meat of the application. Echoing the what the client sends back to the client.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleConn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;conn net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Conn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;conn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EOF &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;received EOF. client disconnected&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatalf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;copy error, err=%s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait, that&#39;s it?&lt;/p&gt;
&lt;p&gt;Note the use of the defer again. Here, we&#39;re saying we want to tidy up the server&#39;s connection to the client when we exit. I also want to point out the &lt;code&gt;if err == io.EOF&lt;/code&gt; as a special case to the other error handling in the program so far. If the client disconnects, it may send an EOF (end of file) marker to the server. We don&#39;t care about those kinds of errors; it just means the client disconnected. So, we&#39;ll note it but not treat it as an error we care about.&lt;/p&gt;
&lt;p&gt;On to actually echoing back to the client... (yes, yes, I promised that earlier)&lt;/p&gt;
&lt;p&gt;Here&#39;s where we can get a lot of help from Go&#39;s standard libraries.&lt;/p&gt;
&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;conn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We don&#39;t need to set up an temporary buffer to read from the client or anything. &lt;a href=&quot;https://golang.org/pkg/io/#Copy&quot;&gt;io.copy&lt;/a&gt; expects to be able to read bytes from something and write bytes to something else. In our case, the connection object satisfies both of these requirements. So, we read some bytes from the connection... and then write some bytes straight back to the connection.&lt;/p&gt;
&lt;p&gt;This is really nice.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot; tabindex=&quot;-1&quot;&gt;Wrapping up &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/golang-tcp-echo/#wrapping-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Well, there it is, in a nutshell. A very basic Go TCP server. It might be useful if you wanted to, say, test connectivity between two computers. I also learned a bit about Docker and how to set up a Docker image to build the application, but I&#39;m going to save that for a future post.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>2017 Review</title>
    <link href="https://hyr.mn/2017-year-in-review/"/>
    <updated>2018-01-28T00:00:00Z</updated>
    <id>https://hyr.mn/2017-year-in-review/</id>
    <content type="html">&lt;p&gt;I thought it would be useful, for myself, to reflect back on 2017. I haven&#39;t written anything since July 2016 so this will bleed into 2016 as well... or, at least the end of 2016.&lt;/p&gt;
&lt;h2 id=&quot;2016&quot; tabindex=&quot;-1&quot;&gt;2016 &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/2017-year-in-review/#2016&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;2016 kicked off what turned into an interesting 2017 for us. 2016 started with a lot of grief as we lost our dog, Bandit. I&#39;ve written about &lt;a href=&quot;https://hyr.mn/2017-year-in-review/on-pets&quot;&gt;life with an aging dog&lt;/a&gt; before. Shortly after that, we decided we had to get out of the house and travel for a bit (we both worked remote at the time). That led us west to Denver where we stopped in to visit coworkers and then off to see family in Arizona. We settled in Denver for a few months before finally realizing our goal of living abroad. We moved to the Netherlands in October!&lt;/p&gt;
&lt;p&gt;If you&#39;re an American and want to experience life as an expat, I highly recommend the Netherlands. I tell people that it&#39;s expat life with training wheels. The government&#39;s process is streamlined (they have an expatcenter in The Hague so that you have a one-stop shop for all paperwork and registration as well as a helpdesk staffed by volunteer expats). Plus, the people are friendly and willing to help and, in the cities at least, everyone has a strong command of English. While you should learn Dutch and absorb Dutch culture, you won&#39;t feel like you&#39;ll drown in the meantime.&lt;/p&gt;
&lt;p&gt;However, even with the training wheels, we found our first few months living abroad to be rough. Finding a new routine, adjusting to the lack of sunlight in the winter, and figuring out food labels are all small things but they can wear on you. We were fortunate to spend Christmas with friends in Hamburg, Germany.&lt;/p&gt;
&lt;h2 id=&quot;2017&quot; tabindex=&quot;-1&quot;&gt;2017 &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/2017-year-in-review/#2017&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Life became infinitely better heading into spring of 2017. Sunshine, knowing enough to buy laundry detergent instead of accidentally buying fabric softener, and building new friendships all helped immensely. I feel like we&#39;ve gained a bit of resiliency.&lt;/p&gt;
&lt;p&gt;That helped when I unexpectedly lost my dad in September. My boss and company were nothing short of amazing in helping me deal with the tragedy. My wife and I hopped on a plane with no notice and went back to the US for two weeks to grieve and reminisce with my family. I still don&#39;t know that I&#39;ve fully processed everything, so there may be some future writing...&lt;/p&gt;
&lt;p&gt;Enough with the personal stuff...&lt;/p&gt;
&lt;p&gt;Professionally, I&#39;ve stepped into a team lead role. Moving from IC to line manager responsibility has been a growth opportunity for me. My manager has been great at mentoring and I&#39;ve found myself turning to more blogs and books on management and leadership than tech lately. However, I&#39;ve recently rekindled a joy for programming that, frankly, I haven&#39;t felt in a while.&lt;/p&gt;
&lt;p&gt;After you&#39;re 20 years in the industry, even when you&#39;re learning and keeping up with your field, and even if you&#39;re playing around with other languages and platforms, things can start to feel... tired. When I first started programming, I was playing with things like C (later Java) and writing stupid little toys. A Finger client, a TCP echo server, a multi-threaded SMTP sender (which led to a fun discussion with the mainframe email admin at university when I needed help deleting the 100k email messages I had sent myself). I&#39;ve found that joy again in &lt;a href=&quot;https://golang.org/&quot;&gt;golang&lt;/a&gt;. I don&#39;t know if I&#39;ll ever take it into business apps, but I do know I&#39;ve been having a blast playing with it. My first project, of course, was a &lt;a href=&quot;https://github.com/hyrmn/GoTcpEchoServer&quot;&gt;TCP echo server&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;ve been fortunate to have a friend and coworker help me with my Go journey. I&#39;m hoping we&#39;ll jam together on some substantial open source in the future.&lt;/p&gt;
&lt;p&gt;One interesting side-effect, for me, of being interested in programming again is that it&#39;s gotten me interested in writing again as well. I have no Google analytics and no server logs. So, frankly, I don&#39;t know if anyone is reading. But, it&#39;s useful for me to have a space to think out loud.&lt;/p&gt;
&lt;h2 id=&quot;2018&quot; tabindex=&quot;-1&quot;&gt;2018 &lt;a class=&quot;visually-hidden&quot; href=&quot;https://hyr.mn/2017-year-in-review/#2018&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dig into Golang more&lt;/li&gt;
&lt;li&gt;Burn my fingers on Elixir&lt;/li&gt;
&lt;li&gt;Finally, finally write one of my, frankly, &lt;a href=&quot;https://github.com/hyrmn/ThousandDollarIdeas&quot;&gt;brilliant ideas&lt;/a&gt;. Because I think it has merit, I&#39;ll probably write it with C# on .NET Core using some event sourcing (ES) and command query responsibility segregation (CQRS) because there&#39;s a lack examples in the .NET space that encompass a whole application.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
</feed>