<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>csMACnz&#39;s Blog</title>
    <link>https://blog.csmac.nz/</link>
    <description>Recent content on csMACnz&#39;s Blog</description>
    <image>
      <url>https://blog.csmac.nz/favicon.png</url>
      <title>csMACnz&#39;s Blog</title>
      <link>https://blog.csmac.nz</link>
    </image>
    <ttl>1440</ttl>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-nz</language>
    <lastBuildDate>Tue, 07 Apr 2026 01:11:00 +0000</lastBuildDate><atom:link href="https://blog.csmac.nz/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Vibe Coding up a Vibe Blogging Machine</title>
      <link>https://blog.csmac.nz/post/vibe-coding-up-a-vibe-blogging-machine/</link>
      <pubDate>Tue, 07 Apr 2026 01:11:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/vibe-coding-up-a-vibe-blogging-machine/</guid>
      <description>&lt;p&gt;Introducing VibeBlog, my playground for exploring GitHub&amp;rsquo;s agentic workflows (that&amp;rsquo;s the whole AI-powered automation thing everyone&amp;rsquo;s talking about). It&amp;rsquo;s also a daily experiment in AI-generated writing—one post per day, initially curated from my own knowledge but eventually evolving into a learning tool based on whatever topics catch my interest. The goal? Produce publicly useful content while I play copyeditor to Copilot&amp;rsquo;s drafts, turning AI output into genuinely informative articles.&lt;/p&gt;
&lt;p&gt;Seriously, as a learning exercise in various Github Copilot features, it has been great fun to build out a daily generated blog site with minimal human-in-the-loop vibes.&lt;/p&gt;
&lt;p&gt;What follows is a bit of a diary of the development and how I got here.&lt;/p&gt;
&lt;h2 id=&#34;the-setup&#34;&gt;The Setup&lt;/h2&gt;
&lt;p&gt;I didn’t start by “writing posts.” I started by building a machine that could publish them reliably.&lt;/p&gt;
&lt;p&gt;When creating a repository in GitHub, you can start with an initial prompt, So I did.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A static site generated blog. Articles will be written and stored as markdown and rendered as a static site. Uses GitHub Actions to build and publish. Agwntic instruction files will support copilot agent tasks to write the posts.&lt;/p&gt;
&lt;p&gt;C# is the preferred language for any code used in this repository&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah, I went with what I know, C#. I could have left it up to the AI but I did want to at least feel confident that what it produced was valid, safe and maintainable code.&lt;/p&gt;
&lt;p&gt;While I did review what it created, I left this as the first prototype and commited without change. As I went on, reviews often fell into more of a YOLO camp, but I did try to stick to a couple of guardrails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read everything before it gets merged&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t produce any commits directly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(I only had a couple of late-stage exceptions to that second rule, due to trying to save a few premium session tokens on one-lineer changes.)&lt;/p&gt;
&lt;p&gt;This PR was complete enough that will a few extra clicks to enable GitHub Pages, I had a live blog with a working generator and deploy pipeline within minutes of creating the repo. From there, I just iterated on the codebase and the agentic workflow, with the goal of making it more robust and more automated over time.&lt;/p&gt;
&lt;p&gt;From this point on, every PR started as an agentic session prompt, and proceeded as a Pull Request collaboration workflow.&lt;/p&gt;
&lt;p&gt;I went straight into a CICD mindset and added automated tests, especially leveraging playwright, and some GitHub Actions for doing more robust build and deploy. The first prompt out of the gate did manage to provide a build and deploy which was great.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It looks like we gave no tests. We should add some xunit and playwright .net tests for both the generator app and the generated site. These tests should be part of the github actions, and verified against pull requests too.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fortunately for me, I was able to give a very vague prompt for CI and it ran with it, producing more and better that I probably would have even thought to ask for.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Review the github actions for build and test and offer improvements&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I went through a short manual testing and feedback phase at this point, where I identified some bugs. Since I was already using a custom domain for GitHub Pages, it did require a little bit of change to make the expected relative paths work, but that was a quick fix. From this, I layered on some extra integrity checking of the site as well.&lt;/p&gt;
&lt;p&gt;I managed to even get it to scrape my styles from the existing blog for consistency. This was a lesson on the Github copilot Firewall configuration. It wasn&amp;rsquo;t perfect, but it got the job done with a bit of iteration.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/agents/pull/14&#34;&gt;Updating site design to align with parent blog&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The style of the site needs updated. Id like to follow the style of the existing parent site blog.csmac.nz Ensure the pull request has a screenshot of the design attached as a comment. Please make sure you also download background images referenced in the css for reuse in this site as well&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As I went, I tried to add additional improvement to both avoid regression, and add automation to catch the same or similar issues from resurfacing. Each time it did something wrong, I would correct it, but ask it to &amp;ldquo;remember&amp;rdquo; essentially.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please fix this articles title length.&lt;/p&gt;
&lt;p&gt;Please also update the agent prompts to always enforce this, even if the title provided is too long, enforce a shorter alternative title to the suggested one. This restriction is higher priority than keeping the suggested title.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;becoming-a-publishing-platform&#34;&gt;Becoming a publishing platform&lt;/h2&gt;
&lt;p&gt;The foundations were set, now the writing could begin.&lt;/p&gt;
&lt;p&gt;This went through a couple of refining phases:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/5&#34;&gt;Updating Copilot agent instructions toward the actual writing style&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Take a look at my site &lt;a href=&#34;https://github.com/csMACnzBlog/csMACnzBlog.github.io&#34;&gt;https://github.com/csMACnzBlog/csMACnzBlog.github.io&lt;/a&gt; and improve the writing style guidance to match my writing style in github copilot markdown instructions&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/18&#34;&gt;Enhance blog-post-writer style guide with patterns from csMACnzBlog&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I would like a review of the writing style from the articles on blog.csmac.nz compared with the writing style used in this VibeBlog so far. I would like to enhance the style guides in this repository with any missing refinements or details for producing future posts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This improved the voice of the articles. These two prompts together did a great job of refining the style and tone of the writing, and I was pretty happy with the results. It was able to pick up on some of the nuances of my writing style that I hadn&amp;rsquo;t explicitly called out in the instructions, which was great. The &lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/blob/main/.copilot/agents/blog-post-writer.md&#34;&gt;final blog-post-writer.md agent&lt;/a&gt; is now pretty detailed and specific, and I think it will do a good job of maintaining a consistent voice across future posts.&lt;/p&gt;
&lt;h2 id=&#34;robustness-phase&#34;&gt;Robustness phase&lt;/h2&gt;
&lt;p&gt;I followed up by adding some more robustness to the publishing process, with a focus on making sure that the quality gates were in place and that the agent instructions were well-defined and versioned. This included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Featured image support: &lt;strong&gt;PR #20&lt;/strong&gt; (merged &lt;strong&gt;2026-02-27&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/20&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/20&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adding baseline validation steps to that setup flow: &lt;strong&gt;PR #102&lt;/strong&gt; (merged &lt;strong&gt;2026-03-28&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/102&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/102&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pagination (15 posts/page): &lt;strong&gt;PR #62&lt;/strong&gt; (merged &lt;strong&gt;2026-03-18&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/62&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/62&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search page via lazy-loaded modal iframe: &lt;strong&gt;PR #64&lt;/strong&gt; (merged &lt;strong&gt;2026-03-19&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/64&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/64&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search UX fixes + tag focus/order: &lt;strong&gt;PR #66&lt;/strong&gt; (merged &lt;strong&gt;2026-03-19&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/66&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/66&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clicking a tag opens search pre-filtered: &lt;strong&gt;PR #103&lt;/strong&gt; (merged &lt;strong&gt;2026-03-29&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/103&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/103&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;image-generation&#34;&gt;Image Generation&lt;/h2&gt;
&lt;p&gt;This took a few iterations to get working but I was able to leverage some python and the Hugging Face API to get some blog images being generated for me as part of the build process. This was a fun one to iterate on, and I had to learn a bit about how to use the Hugging Face API and how to handle credentials in GitHub Actions. I tried out the familiarity of Powershell to start with but in the end went with what the models know best - Python. I also had to iterate on the prompt a bit to get it to generate images that were actually relevant and looked good. I ended up with a pretty good prompt that I can reuse for future image generation tasks as well. Maybe as a reduction exercise I&amp;rsquo;ll see if I can migrate what I have back to Powershell, but for now I&amp;rsquo;m happy with the Python solution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Image generation pipeline moved from PowerShell → Python + HuggingFace client: &lt;strong&gt;PR #21&lt;/strong&gt; (merged &lt;strong&gt;2026-02-27&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/21&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/21&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It did take a bunch of trial-and-error to get the credentials and API calls working correctly, but I got there in the end. The images are now being generated and uploaded to the site as part of the PR generation lifecycle process, which is pretty cool. Most of my drama came from fighting different environment sandboxes and differences between Copilot, and Workflow.&lt;/p&gt;
&lt;p&gt;I even did a bit of experimenting with the new &lt;a href=&#34;https://github.github.com/gh-aw/&#34;&gt;https://github.github.com/gh-aw/&lt;/a&gt;. It is pretty cool, but wasn&amp;rsquo;t the right tool for this particular job, since the repository sits public in the open. But I have some ideas for how I might be able to leverage it in the future for some of my more private repositories, so it was worth playing around with it a bit.&lt;/p&gt;
&lt;h2 id=&#34;finishing-the-automation&#34;&gt;Finishing the automation&lt;/h2&gt;
&lt;p&gt;I had a pretty good workflow going at this point, but I wanted to get to the point where I could just merge a PR and have it go live without any manual steps. This involved making sure that all the quality gates were in place and that the agent instructions were well-defined.&lt;/p&gt;
&lt;p&gt;I was still triggering and reviewing the daily post generation manually, but I wanted to get to the point where it was fully automated. So I tried a few different strategies and landed on the following approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In another repository, I trigger the creation of a new Issue into the repository, and assign it to Copilot to work on&lt;/li&gt;
&lt;li&gt;Copilot then creates a new branch, and starts working on the post in that branch, using the agent instructions and style guide to produce the content&lt;/li&gt;
&lt;li&gt;Once the post is ready, it creates a PR from that branch into main, and assigns it to me for review&lt;/li&gt;
&lt;li&gt;Another automation checks over the PR for quality gates (links, accessibility, etc) and if it passes, it merges the PR automatically, which triggers the build and deploy process to publish the new post&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I read every post daily. So far I haven&amp;rsquo;t really had to make any changes to the articles, and find them both accurate and interesting to read.&lt;/p&gt;
&lt;p&gt;I even followed up with an automation that can investigate a topic suggestion and raise a more detailed Issue. If one of these is present, it uses that to assign to copilot instead of the generic &amp;ldquo;write a post about X&amp;rdquo; issue. This allows me to have a bit more control over the topic and the direction of the post, while still leveraging the automation to do the heavy lifting of writing and publishing.&lt;/p&gt;
&lt;h2 id=&#34;a-working-system&#34;&gt;A working system&lt;/h2&gt;
&lt;p&gt;By early April 2026, the engineering arc looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A C# generator that deploys cleanly to Pages (&lt;strong&gt;PR #1&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;CI + testing from day one (&lt;strong&gt;PR #2&lt;/strong&gt;, &lt;strong&gt;PR #4&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Deployment correctness handled early (subpath link fix) (&lt;strong&gt;PR #9&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Publishing quality gates baked in (&lt;strong&gt;PR #10&lt;/strong&gt;, &lt;strong&gt;PR #105&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Agent instructions + setup treated as versioned system components (&lt;strong&gt;PR #5&lt;/strong&gt;, &lt;strong&gt;PR #6&lt;/strong&gt;, &lt;strong&gt;PR #24&lt;/strong&gt;, &lt;strong&gt;PR #102&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Media pipeline with real-world credential iteration (&lt;strong&gt;PR #20&lt;/strong&gt;, &lt;strong&gt;PR #21&lt;/strong&gt;, &lt;strong&gt;PR #88&lt;/strong&gt;, &lt;strong&gt;PR #92&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Scale features (pagination + search) (&lt;strong&gt;PR #62&lt;/strong&gt;, &lt;strong&gt;PR #64&lt;/strong&gt;, &lt;strong&gt;PR #66&lt;/strong&gt;, &lt;strong&gt;PR #103&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;A daily agentic publishing workflow that’s been battle-tested through break/fix cycles (&lt;strong&gt;PR #68&lt;/strong&gt;, &lt;strong&gt;PR #79–#86&lt;/strong&gt;, &lt;strong&gt;PR #77/#87&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Towards this later couple of weeks I&amp;rsquo;ve been focusing more on the main site and blog, trying to tie this new part into the larger site more seamlessly. This has identified many opportunities to apply similar learnings back to the way I opperate in the rest of the site&amp;rsquo;s development.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;Well I&amp;rsquo;m pretty well set up for the moment. At some point topic choice might get interesting, and I don&amp;rsquo;t know what the LLM is going to do. I do have my mechanism to generate topics and topic notes, so perhaps that feeds it for a while. It is one I am very interested to watch.&lt;/p&gt;
&lt;p&gt;Otherwise, I just need to keep an eye on the daily workflow and make sure it doesn&amp;rsquo;t break. I have a good sense of what the failure modes are, so hopefully I can catch and fix them quickly if they come up. And since it runs on GitHub workflows, I get notifications when it fails, so that should help me stay on top of it.&lt;/p&gt;
&lt;p&gt;Security is always a concern, but since this is a public repo with no sensitive data, the main risk is someone trying to break the workflow or inject bad content. I&amp;rsquo;ll need to monitor for that and be ready to revert if necessary. Hopefully I&amp;rsquo;ve locked down enough of the accesses that it is resilient to obvious attack vectors.&lt;/p&gt;
&lt;h2 id=&#34;appendix&#34;&gt;Appendix&lt;/h2&gt;
&lt;p&gt;Some of the PRs are referenced directly for your interest and further reading.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/1&#34;&gt;PR #1: Generator + Pages deploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/2&#34;&gt;PR #2: xUnit + Playwright + CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/4&#34;&gt;PR #4: CI/CD optimizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/9&#34;&gt;PR #9: fix broken links&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/10&#34;&gt;PR #10: quality gates (link/html/a11y)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/20&#34;&gt;PR #20: featured images&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/21&#34;&gt;PR #21: image pipeline → Python/HF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/24&#34;&gt;PR #24: copilot-setup-steps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/62&#34;&gt;PR #62: pagination&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/64&#34;&gt;PR #64: search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/68&#34;&gt;PR #68: daily-post workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PR #79–#86: hardening fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/102&#34;&gt;PR #102: baseline validation in setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/105&#34;&gt;PR #105: a11y runner fix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/119&#34;&gt;PR #119: example content PR (Rate Limiting)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>.NET Conf 2023 Review</title>
      <link>https://blog.csmac.nz/post/dotnetconf-2023-review/</link>
      <pubDate>Fri, 01 Dec 2023 11:18:13 +1300</pubDate>
      
      <guid>https://blog.csmac.nz/post/dotnetconf-2023-review/</guid>
      <description>&lt;p&gt;This year I watched a bunch of the sessions from .NET Conf, both live streams and in the days following. I&amp;rsquo;ve collated my top recommendations and my reviews and thoughts on others that may be of interest to some Developers in the Microsoft ecosystem.&lt;/p&gt;
&lt;p&gt;Without any further ado, we&amp;rsquo;ll crack into the must-watch list for 2023.&lt;/p&gt;
&lt;h2 id=&#34;must-watch&#34;&gt;Must Watch&lt;/h2&gt;
&lt;p&gt;Why not kick into it with the main keynote? This talk gives a great overview of all the great new advancements released as part of .Net 8 so you can learn more about what you want to dive deeper into.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/mna5fg7QGz8?si=dacpISAhXWlxlj-2&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Follow this up with a deeper dive into all the enhanced cloud-native capabilities delivered to us this year as well, including your first look at the new &lt;a href=&#34;https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview&#34;&gt;.Net Aspire stack&lt;/a&gt;.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/z1M-7Bms1Jg?si=lM3S7yGHrTUyhDad&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Pivoting to C# 12 which drops with .Net 8, check out the newest features to learn what&amp;rsquo;s been added to the language.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/by-GL-SjHdc?si=VgQodH7EAqNPozuN&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;And if you are still on .Net 6 or a few versions behind on what has been developing, here is a wider look across the last few releases to catch up on what you&amp;rsquo;ve missed.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/Ci-FTnC-j84?si=39lYE-hDo-5pC4jn&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;But to round that off with the question &amp;ldquo;What should I do with all this new info?&amp;rdquo; I recommend Bill Wagner&amp;rsquo;s pragmatic view of Everyday C# to guide you in how to pick and choose the best bits for you.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/xZk8T-9kI3w?si=Ae-vb1ZvIw7TGmEG&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&#34;a-focus-on-aspnet-core&#34;&gt;A focus on ASP.Net Core&lt;/h2&gt;
&lt;p&gt;We now switch focus to the API hosting application space with ASP.Net Core. This part is probably not relevant to all Developers so I&amp;rsquo;ve kept it out of must-watch. However, if you are a web app or MVC Developer then these are probably still on your &amp;ldquo;must-watch&amp;rdquo; list according to me.&lt;/p&gt;
&lt;p&gt;If you want a really good high-level overview, look no further than ASP.NET Basics for experts with Layla - covering minimal APIs, open telemetry and the new Aspire tooling.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/GDCMiBu_2gI?si=nQ4pFChTWSa60Nx1&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;For a more targeted look at Open Telemetry, I highly recommend this video, especially if you haven&amp;rsquo;t started your journey in this space as it has become easier to enable than ever.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/BnjHArsYGLM?si=p6o5rAWlaqo5Bw4I&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Similarly, whether you haven&amp;rsquo;t looked at Polly, or are already on the Polly train, this resiliency talk is a must-see.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/BDZpuFI8mMM?si=9eiaoA1iv_phOp1t&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&#34;dive-deeper-into-specifics&#34;&gt;Dive deeper into specifics&lt;/h2&gt;
&lt;p&gt;Here are some great deep dives into areas you may have some familiarity with but want to get a deep look into.&lt;/p&gt;
&lt;p&gt;Starting with a configuration Deep dive, to catch you up on the power of the IConfiguration patterns built into .Net.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/aOXaBZFB0-0?si=v8Zw4K1hLwobfCFC&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;And if you are working with containers at all you&amp;rsquo;ll watch to check out the latest advancements here&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/scIAwLrruMY?si=_aVsNFlyBPHub_tp&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;
&lt;p&gt;There were some great architecture talks, especially for organising your code in large systems.&lt;/p&gt;
&lt;p&gt;Starting with a great Vertical Slice Architecture talk that opens with a brilliant overview of spaghetti, layered, and clean architecture to set the scene first.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/T-EwN9UqRwE?si=O4Lp4Aqp6Pant3u3&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;(Here is an earlier presentation to help fill the gaps where the live demo gods failed us on the day -
&lt;a href=&#34;https://youtu.be/dMgj1MdwrRE&#34;&gt;Pick a Side - Clean vs Vertical Slice Architecture | Luke Parker&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;And if you are still sold on Clean Architecture after those videos, you will want to check out this great talk from Steve Smith.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/yF9SwL0p0Y0?si=gBtfFCPUUCbw_5_6&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&#34;blazor&#34;&gt;Blazor&lt;/h2&gt;
&lt;p&gt;Blazor is going to be a small subset of Developers still, so whether you are new to it and want to learn more, or use it and want to see what is new, this video will satisfy you.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/YwZdtLEtROA?si=y56PMdQlZdcF3XKc&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&#34;niche-pro-user-tools&#34;&gt;Niche pro-user tools&lt;/h2&gt;
&lt;p&gt;For those already more familiar with most of what .Net has to offer, there were some great deep-dives into some technologies that won&amp;rsquo;t be for every day, but have some very specific use cases you may cross paths with.&lt;/p&gt;
&lt;p&gt;Starting with the new source generators:&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/Yf8t7GqA6zA?si=UP-BqhOAsoqPLevk&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;And a great reverse-proxy solution called YARP (Yet Another Reverse Proxy)&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/P8y8NAroVKk?si=tgJNJhm9ikn_atES&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;And for the Swagger/OpenAPI users, we get an introduction to &lt;a href=&#34;https://learn.microsoft.com/en-us/openapi/kiota/overview&#34;&gt;Kiota&lt;/a&gt; - an opinionated cross-platform client code generator for open API specifications.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/sQ9Pv-rQ1s8?si=WNItKbCTxDohjnHF&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;If you want to build and distribute &lt;code&gt;dotnet new&lt;/code&gt; templates of your own, take a look at Making templates with Rob Conery:&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/XzD-95qfWJM?si=C9npWhtL-QU7Rsjs&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&#34;and-more&#34;&gt;And more&lt;/h2&gt;
&lt;p&gt;This is by no means the total list of all the sessions. If you haven&amp;rsquo;t seen what you were looking for here, there is a &lt;a href=&#34;https://sessionfinder.dotnetconf.net/&#34;&gt;Session Finder&lt;/a&gt; to search for more videos to watch and learn.&lt;/p&gt;
&lt;p&gt;The conference website as always is found at &lt;a href=&#34;https://www.dotnetconf.net/&#34;&gt;dotnetconf.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See you all for the next one in 2024! Happy viewing.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My idea of an ideal CICD pipeline</title>
      <link>https://blog.csmac.nz/post/my-idea-of-an-ideal-cicd-pipeline-2023/</link>
      <pubDate>Tue, 01 Aug 2023 05:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/my-idea-of-an-ideal-cicd-pipeline-2023/</guid>
      <description>&lt;p&gt;This article represents my current thoughts around building and deploying software (circa 2023). It is a general straw man. As usual in software development, the caveats apply that there is no one size fits all silver bullet pattern. This is where I start as a &amp;ldquo;given no further constraints&amp;rdquo; approach. It is highly likely to be too complex for a single-dev piece of software and is equally as likely not to be suitable for large monolithic applications either. However, for software somewhere in between those two it may fit your needs as it does mine.&lt;/p&gt;
&lt;h2 id=&#34;why-cicd&#34;&gt;Why CICD?&lt;/h2&gt;
&lt;p&gt;My definition of &lt;code&gt;CICD&lt;/code&gt; is continuous static analysis, build, test, publish, deploy, verification and releasing to customers, for every change. While &lt;code&gt;CI&lt;/code&gt; stands for &lt;code&gt;Continuous Integration&lt;/code&gt;, CD ambiguously stands for either &lt;code&gt;Continuous Delivery&lt;/code&gt; or &lt;code&gt;Continuous Deployment&lt;/code&gt;, where &lt;code&gt;Delivery&lt;/code&gt; and &lt;code&gt;Deployment&lt;/code&gt; are equally ambiguous and have debatable definitions. So, while I will use the acronym here, see my definition above for what that means to me.&lt;/p&gt;
&lt;p&gt;The crux of &lt;code&gt;CICD&lt;/code&gt; is: always shipping, always automatically.&lt;/p&gt;
&lt;p&gt;This unintuitively implies having automated gates that can stop and halt these deployments, and that somewhere right at the beginning the automation is kicked off by an initial interaction or contribution (such as a file change in a code repository). Also, do have a rollback plan handy.&lt;/p&gt;
&lt;p&gt;The benefits we are trying to achieve are faster feedback loops, and changing mindset to help find and fix issues sooner, much closer to where the associated change was thought through and implemented. This is often referred to as &lt;a href=&#34;https://devopedia.org/shift-left&#34;&gt;Shift Left&lt;/a&gt;. In other cases, it allows us to reduce the time between a production issue being discovered, and the last time that component was being worked on by a human (which could be the difference between months in between, and hours/minutes in between thanks to CICD).&lt;/p&gt;
&lt;h2 id=&#34;a-brief-digression-into-testing&#34;&gt;A brief digression into testing&lt;/h2&gt;
&lt;p&gt;Testing could be its own series of blog posts, so we will gloss over it slightly here. But it is necessary to say that automated testing is a large part of doing CICD well. And the ability to perform enough manual testing when required needs to be accounted for. This is how we achieve our safety and trust to enable straight-shot pipelines all the way to being in front of customers. We can look at a high-level view of these briefly.&lt;/p&gt;
&lt;h3 id=&#34;automated-testing&#34;&gt;Automated Testing&lt;/h3&gt;
&lt;p&gt;Automated testing should cover as much of the application as possible. This can range across unit tests, property-based tests, composition tests, mutation tests, boundary tests, snapshot tests, integration tests, acceptance tests, specification tests, regression tests, end-to-end tests, UI tests, smoke tests and any other kinds of tests you can think of to have run automated before code can go to production.&lt;/p&gt;
&lt;p&gt;A new project might aim for a minimal subset of the above (such as unit, integration, and smoke) while a more established piece of software may have most or all of these in place.&lt;/p&gt;
&lt;p&gt;The main goal in terms of CICD is to ensure most of your testing runs before merging in changes to a release candidate, and enough validation testing is run during and after deployment to ensure fidelity.&lt;/p&gt;
&lt;h3 id=&#34;manual-testing&#34;&gt;Manual Testing&lt;/h3&gt;
&lt;p&gt;Manual testing requires enough real dependencies to be meaningful, or else you may as well just automate any task that you are testing using fakes or mocks. Largely this is exploratory testing or deep testing of something complex requiring a human eye for validation.&lt;/p&gt;
&lt;p&gt;The two tools I would lean on here are having a feature flagging and dark release pattern in your development process and having a secondary manual test environment to deploy pre-release changes to.&lt;/p&gt;
&lt;p&gt;Feature flagging allows you to deploy to preproduction and production with inert functionality (sometimes called a shadow release). You can then enable this functionality either isolated to a canary server instance, per environment (e.g. preproduction only) or per user in a way that enables testers or beta users to interact with the flagged changes before a wider release.&lt;/p&gt;
&lt;p&gt;Having an additional pre-production environment you can deploy changes to will enable Pull Requests or feature branches to be deployed there and manually tested before they are merged into a production candidate release.&lt;/p&gt;
&lt;h2 id=&#34;reliability-engineering&#34;&gt;Reliability Engineering&lt;/h2&gt;
&lt;p&gt;One aspect that makes this all come together and work is the developer thinking through production, and how they will know and trust it is working. Ongoing monitoring and alerting in place is a key part of this strategy. Without monitoring and alerting detecting and escalating issues you are effectively in chaos.&lt;/p&gt;
&lt;p&gt;Automated tests catch the known failure scenarios, making sure they do not occur, or regress. But there are unknown failure scenarios, as well. We can detect these using signals such as error log count, &lt;code&gt;400&lt;/code&gt; or &lt;code&gt;500&lt;/code&gt; HTTP status codes, or request/response time spikes. These don&amp;rsquo;t tell us what the problem is but are great at signalling we do have a problem.&lt;/p&gt;
&lt;p&gt;The feedback loop of monitoring tools alerting the developer who wrote the code (or their on-call proxy who can reach out to them) is what gives the confidence to release changes straight to production, complementing the other testing guards in place that catch the known issues before they reach customers so we can also catch these unknown issues after they reach customers.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve left automated rollback out of this pipeline currently, as it adds additional challenges in understanding what is safe and when it isn&amp;rsquo;t. However, this is the next step you would consider as you delved into the CICD space. Having a manual plan, though, is essential. (I often use roll-forward to roll back. Either with a re-deploy of an older version, or with a patch+merge+release - often both together.)&lt;/p&gt;
&lt;h2 id=&#34;a-side-note-on-the-shape-of-software&#34;&gt;A side note on the shape of software&lt;/h2&gt;
&lt;p&gt;What is it that we are testing and deploying?  My philosophy is to include everything that makes up this component. By which I mean the application, any infrastructure (using configuration-as-code) and any side-car utilities (such as queues, caches, stores etc) not shared with other components.&lt;/p&gt;
&lt;p&gt;It follows that all our static verification and testing also covers these infra and sidecar deployments as well.&lt;/p&gt;
&lt;p&gt;If you do have queues, stores, or caches that are shared, you will want to extract these as their own components and deployments separately. But I&amp;rsquo;ve found where these are coupled and self-contained to a particular application, then having them co-located in a repository and deployed in the same pipeline is a simplification worth having.&lt;/p&gt;
&lt;p&gt;Also note that your configuration-as-code for anything in the permanent storage capacity has appropriate backups, as well as the right checks and balances to restrict the pipeline from doing anything destructive automatically.&lt;/p&gt;
&lt;p&gt;If feasible, you might also leverage configuration as code for your monitoring and alerting tools in the same way through this pipeline.&lt;/p&gt;
&lt;h2 id=&#34;the-pipeline&#34;&gt;The pipeline&lt;/h2&gt;
&lt;p&gt;CICD is a pipeline, and these are the key phases and steps in that pipeline in my ideal model:&lt;/p&gt;



&lt;div class=&#34;goat svg-container &#34;&gt;
  
    &lt;svg
      xmlns=&#34;http://www.w3.org/2000/svg&#34;
      font-family=&#34;monospace&#34;
      
        viewBox=&#34;0 0 1376 57&#34;
      &gt;
      &lt;g transform=&#39;translate(8,16)&#39;&gt;
&lt;path d=&#39;M 0,0 L 120,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 168,0 L 200,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 248,0 L 360,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 408,0 L 584,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 632,0 L 776,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 824,0 L 968,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1016,0 L 1128,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1176,0 L 1360,0&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 120,16 L 144,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 216,16 L 240,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,16 L 400,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 584,16 L 624,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 776,16 L 816,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 968,16 L 1008,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1128,16 L 1168,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 0,32 L 120,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 168,32 L 200,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 248,32 L 360,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 408,32 L 584,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 632,32 L 776,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 824,32 L 968,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1016,32 L 1128,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1176,32 L 1360,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 0,0 L 0,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 120,0 L 120,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 120,16 L 120,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 248,0 L 248,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,0 L 360,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,16 L 360,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 408,0 L 408,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 584,0 L 584,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 584,16 L 584,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 632,0 L 632,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 776,0 L 776,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 776,16 L 776,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 824,0 L 824,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 968,0 L 968,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 968,16 L 968,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1016,0 L 1016,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1128,0 L 1128,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1128,16 L 1128,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1176,0 L 1176,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 1360,0 L 1360,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;152.000000,16.000000 140.000000,10.400000 140.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 144.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;248.000000,16.000000 236.000000,10.400000 236.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 240.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;408.000000,16.000000 396.000000,10.400000 396.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 400.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;632.000000,16.000000 620.000000,10.400000 620.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 624.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;824.000000,16.000000 812.000000,10.400000 812.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 816.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;1016.000000,16.000000 1004.000000,10.400000 1004.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 1008.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;1176.000000,16.000000 1164.000000,10.400000 1164.000000,21.600000&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 1168.000000, 16.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 168,0 A 16,16 0 0,0 152,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 200,0 A 16,16 0 0,1 216,16&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 152,16 A 16,16 0 0,0 168,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 216,16 A 16,16 0 0,1 200,32&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;16&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;24&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;32&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;40&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;56&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;R&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;64&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;72&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;q&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;80&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;88&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;96&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;104&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;T&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;b&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;-&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;496&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;D&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;504&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;512&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;520&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;528&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;536&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;544&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;552&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;560&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;568&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;648&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;656&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;664&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;680&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;688&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;696&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;704&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;720&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;V&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;728&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;736&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;744&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;752&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;f&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;760&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;840&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;848&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;856&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;864&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;880&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;D&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;888&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;896&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;904&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;912&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;920&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;928&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;936&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;944&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;952&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1032&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1040&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1048&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1056&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1072&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;V&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1080&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1088&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1096&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1104&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;f&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1112&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1192&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;R&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1200&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1208&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1216&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1224&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1232&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1240&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1256&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;N&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1264&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1272&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1280&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1288&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;f&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1296&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1304&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1312&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1320&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1328&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1336&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;1344&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;/g&gt;

    &lt;/svg&gt;
  
&lt;/div&gt;&lt;p&gt;We will break this into a few chunks for a deeper discussion.&lt;/p&gt;
&lt;h3 id=&#34;pre-merge&#34;&gt;Pre merge&lt;/h3&gt;
&lt;p&gt;Ideally, I want trunk (e.g. &lt;code&gt;main&lt;/code&gt; branch) to always be production capable. Achieving this means ensuring the quality and fidelity of any changes before they are merged in. This may look like a Pull Request with automated pre-build checks (e.g. GitHub Actions) and code reviews. It may also look like git commit hooks that are run and confirmed ahead of a merge. Exactly what you implement here is dependent on the software in question, and the engineers working on it.&lt;/p&gt;
&lt;p&gt;For me, this encompasses linting and other static analysis, security scanning, compiling, and executing all tests, and producing candidate artifacts that can also be verified and validated here too.&lt;/p&gt;
&lt;p&gt;Ideally, for the fasted feedback, you want this to take as little time as possible. If this takes more than 10 minutes (ideally 5 or less) you will want to consider reducing scope, performance tuning, or potentially splitting something monolithic up somehow.&lt;/p&gt;
&lt;h3 id=&#34;trunk-build&#34;&gt;Trunk Build&lt;/h3&gt;
&lt;p&gt;At all times, you want to be able to validate trunk against the same lint, build and test as you would for any candidate commit. Ensuring you can run the same checks in both places maintains the validity of your trunk.&lt;/p&gt;
&lt;p&gt;In addition, we would also take the generated artifacts and make them available to the further deployment processes coming up next in the pipeline. So our trunk build also publishes artifacts somewhere.&lt;/p&gt;
&lt;h3 id=&#34;preproduction-deploy-and-verify&#34;&gt;Preproduction deploy and verify&lt;/h3&gt;
&lt;p&gt;It is important to have an environment that is production-like but isn&amp;rsquo;t serving customers to first test your artifacts in. Despite your best efforts of testing, some bugs and misconfigurations can&amp;rsquo;t be spotted until you run a real deployment, and watch the software interact with real dependencies (or at least their preproduction equivalents).&lt;/p&gt;
&lt;p&gt;Before deploying to production proper you will want to run through deployment and post-deployment verification testing in such an environment to provide extra automated confidence before reaching real customers.&lt;/p&gt;
&lt;p&gt;This post-deployment verification is also your last chance to have automated checks catch issues before they get released out to real customers.&lt;/p&gt;
&lt;p&gt;In some situations, this may be a canary or an early-adopters group, though ideally you want something without real customers to do this testing on, and instead use feature flags for beta user test groups, and any A/B testing.&lt;/p&gt;
&lt;h3 id=&#34;production-deploy-and-verify&#34;&gt;Production Deploy and Verify&lt;/h3&gt;
&lt;p&gt;It is now time to deploy to production. You&amp;rsquo;ve satisfied your tests and verified that it can work in a deployed environment after deploying, mitigating any issues in the production deployment process (which assumes your pre-prod and prod deployment processes are near-identical).&lt;/p&gt;
&lt;p&gt;We repeat our deployment and verify steps once more only this time against our customer-facing production environment. Our change has now reached production.&lt;/p&gt;
&lt;p&gt;If you do find production issues, you will want to go back and add regression checks to the testing at the appropriate point in the pipeline to make sure the same issue halts deployments in the future. This is one of the feedback cycles you need to adhere to when taking on CICD in this way, to strengthen the reliability and trust in the process.&lt;/p&gt;
&lt;h3 id=&#34;notification&#34;&gt;Notification&lt;/h3&gt;
&lt;p&gt;Once you have a deployed and verified production deployment, you&amp;rsquo;ll want to make sure anyone (or any system) that wants to know about it can do so.&lt;/p&gt;
&lt;p&gt;Specifically, you want to have release notes publish, to have any APM systems notified of the release, Internal Comms published on something like Slack or Discord, as well as any documentation related to the changes updated and published.&lt;/p&gt;
&lt;p&gt;Ideally, all of this is automated and automatic. For documentation and release notes, having a way to derive these from the source itself, or from the Source Control revision history or commit messages, or Pull Request titles etc. This saves a bunch of manual busy work which would otherwise distract a human on every deployment.&lt;/p&gt;
&lt;p&gt;The same goes for using APIs to post to Slack or other chat systems to notify other internal or external stakeholders of the change. A great way to identify the cause of a system outage can be to know which of your dependencies have made releases around the time an outage was introduced. Be nice to your API consumers.&lt;/p&gt;
&lt;h2 id=&#34;wrap-up&#34;&gt;Wrap Up&lt;/h2&gt;
&lt;p&gt;The above largely outlines a strawman of my MVP. Ideally, I would go through and set up at least the skeleton of this for any new service where I expect it to live in production for any period of time. (If I don&amp;rsquo;t think this code will be productionised and is merely a toy or demo, such overhead isn&amp;rsquo;t worth investing in). This would largely be even before any functionality is implemented (e.g. deploying the new empty project).&lt;/p&gt;
&lt;p&gt;Having the Pipeline in place, we continue to extend the testing to improve confidence in the deployment process, and this goes hand-in-hand with building out the functionality.&lt;/p&gt;
&lt;p&gt;Iteratively and continuously build and ship the software to meet the requirements of the project of work.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>An almost seamless transition from Ghost to Hugo</title>
      <link>https://blog.csmac.nz/post/an-almost-seamless-transition-from-ghost-to-hugo/</link>
      <pubDate>Tue, 10 Aug 2021 20:30:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/an-almost-seamless-transition-from-ghost-to-hugo/</guid>
      <description>&lt;p&gt;Well, I finally did it. Ghost has been sitting on an older version for a long time, my certs were expiring, and I did something about it.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR;&lt;/h2&gt;
&lt;p&gt;My blog engine and hosting were deteriorating fast, so I moved to GitHub Pages, Hugo, and Static Site Generation, (mostly) without losing or breaking anything.&lt;/p&gt;
&lt;h2 id=&#34;synopsys&#34;&gt;Synopsys&lt;/h2&gt;
&lt;p&gt;Years ago I moved from WordPress to Ghost. This let me get on with writing and not worrying about the hosting. I moved it to Azure and even added a dynamic SSL certificate rotator using Lets Encrypt.&lt;/p&gt;
&lt;p&gt;Eventually, the cert rotator broke, and the blog engine got enough major versions behind to make the upgrade path non-trivial to fix. Not to mention Google Ads decided my site wasn&amp;rsquo;t good enough for them and so disabled any ads that could have shown up. Hosting costs on Azure, while small, were a factor to think about too.&lt;/p&gt;
&lt;p&gt;Around the time I decided to do something about it, I also started paying attention to other people using static site generation to host their blogs. It didn&amp;rsquo;t take long to find a few really great articles that showed how simple this was going to be. The simplest of which seemed to be &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; on &lt;a href=&#34;https://pages.github.com/&#34;&gt;GitHub Pages&lt;/a&gt;. So that is the path I went down.&lt;/p&gt;
&lt;h2 id=&#34;what-went-well&#34;&gt;What went well&lt;/h2&gt;
&lt;p&gt;My initial research was well-founded, and I very easily found the tool &lt;a href=&#34;https://github.com/jbarone/ghostToHugo&#34;&gt;jbarone/ghostToHugo&lt;/a&gt; designed for the job.&lt;/p&gt;
&lt;p&gt;Initially, everything was super simple, and I had my content in Hugo in under an hour. Mainly I was following youngkin&amp;rsquo;s article: &lt;a href=&#34;https://youngkin.github.io/post/createafreeblogsite/&#34;&gt;Create a Free Blog Site Using GitHub Pages and Hugo&lt;/a&gt;, and then using ghostToHugo for my content.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/getting-started/installing/&#34;&gt;Install Hugo CLI locally&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;create basis repository setup with the suggested theme &lt;a href=&#34;https://youngkin.github.io/post/createafreeblogsite/&#34;&gt;youngkin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ghost.org/help/the-importer/&#34;&gt;export my Ghost backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;install &lt;a href=&#34;https://github.com/jbarone/ghostToHugo&#34;&gt;ghostToHugo&lt;/a&gt; tool&lt;/li&gt;
&lt;li&gt;run ghostToHugo to migrate posts into the site&lt;/li&gt;
&lt;li&gt;run locally to test&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(I&amp;rsquo;m not repeating details here, because &lt;a href=&#34;https://youngkin.github.io/post/createafreeblogsite/&#34;&gt;youngkin&lt;/a&gt; has it nailed.)&lt;/p&gt;
&lt;p&gt;Getting this running on GitHub Pages was easy following that article too. Even setting a CNAME and DNS (a temporary subdomain while testing of course) was nice and easy to get working. (I use &lt;a href=&#34;https://dnsimple.com/&#34;&gt;DNSimple&lt;/a&gt;.) Job done. Right?&lt;/p&gt;
&lt;h2 id=&#34;what-went-wrong&#34;&gt;What went wrong&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;RSS.&lt;/strong&gt; My RSS feed has been a bit of an issue really. I knew it would probably break, and it wasn&amp;rsquo;t even available out of the box on Hugo either. So I fevered away adding RSS generation to the site generation and getting a fair approximation of my old feed. I knew it wouldn&amp;rsquo;t be perfect, but I learned a bit about how the templating engine worked along the way. And when that hot cutover day came, it certainly failed. I had a few bugs to fix and all 50 people who have added this blog to their feed probably got a bit of a noisy mess. But hopefully, as they now read this article they now understand why. Also, there are now sub-categories with sub-category RSS feed URLs linked to from the right-hand sidebar now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom Theming.&lt;/strong&gt; I built my custom theme way back when I moved to Ghost. And I didn&amp;rsquo;t really feel like losing it. So I painstakingly mapped it from the Ghost templating engine to the one Hugo uses. This sucked. and it took ages (weeks) to get it right. Along the way, I probably did make some improvements that will be valuable later, like fixing the sidebar and better image handling possibilities. But this was probably the most time-consuming part of the whole process. In the end, retrologs&amp;rsquo; &lt;a href=&#34;https://retrolog.io/blog/creating-a-hugo-theme-from-scratch/&#34;&gt;Creating a Hugo Theme From Scratch&lt;/a&gt; was super useful at figuring out what went where, but I don&amp;rsquo;t actually understand some parts of the collection lookup code I wrote in some places yet. But it worked. At the very least, my CSS appears to have held the test of time (surprisingly!).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Permalinks.&lt;/strong&gt; Turns out Ghost had a few permalink redirect capabilities. And also the default URLs in Ghost were &lt;code&gt;/slug-for-page/&lt;/code&gt; while Hugo is &lt;code&gt;/post/slug-for-page/&lt;/code&gt;. Luckily the &lt;a href=&#34;https://gohugo.io/content-management/urls/#aliases&#34;&gt;Aliases feature in Hugo&lt;/a&gt; allowed me to add both the draft/preview link (&lt;code&gt;/p/&amp;lt;GUID&amp;gt;/&lt;/code&gt;) as well as the old URL so that hopefully, no one loses my content, and instead get bounced to the right place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disqus.&lt;/strong&gt; See the comments at the bottom? I&amp;rsquo;ve been using Disqus to make them available. Turns out this was quite useful in moving to a static hosted solution. For the most part, this went well, because Disqus actually have a &lt;a href=&#34;https://help.disqus.com/en/articles/1717068-migration-tools&#34;&gt;migration tools feature&lt;/a&gt; available to use to move the URL associated with a page. The what went wrong part was that I prepared all the pages that looked like the normal post URL (&lt;code&gt;/slug-for-page/&lt;/code&gt;) before I cut over my DNS, but didn&amp;rsquo;t map any of the preview URLs (&lt;code&gt;/p/&amp;lt;GUID&amp;gt;/&lt;/code&gt;) across. I think what happened is that Ghost provided an id to Disqus as well as a URL, and it uses the first URL it sees as the identifying one. When I preview drafts, that preview URL is the one it saves. Since Hugo is just using the actual URL and not the id anymore, I lost my mapping over a few pages which I neglected to migrate. (My incorrect assumption was the draft ids didn&amp;rsquo;t have comments 😢.) I was without comments on some pages while I remedied that across a couple of evenings. It wasn&amp;rsquo;t too bad to put together a new CSV file for that though in the end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Ads.&lt;/strong&gt; Turns out they are still not happy with my website (and neither am I to be fair) so there is a bit more work to get them reenabled. It barely makes dollars a month, to be honest, but with it not working it makes a lot less of course.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Content.&lt;/strong&gt; I spent far too much time looking at my content. While Ghost had tags, Hugo has both &lt;a href=&#34;https://blog.csmac.nz/tags/&#34;&gt;Tags&lt;/a&gt; and &lt;a href=&#34;https://blog.csmac.nz/categories/&#34;&gt;Categories&lt;/a&gt;. I went through every historic post (193 over 13 and a half years if you can believe it) and updated many tags (deleting a bunch, adding a few) and creating categories for my content. I could have spent days (and still might) tidying up some of the content that never had any attention since coming out of WordPress and getting auto-converted to markdown all those years ago. But I held back, since I wanted to actually get this process done and back to writing. There was a little bit of work migrating some of the image functionality over too, but for the most part that was fine, too.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Would I choose to do it again? Yes. I am certainly in a better place. So far, I think I&amp;rsquo;ve backed the right horse in Hugo. The workflow seems about as good as it was before, and I am aware of a few tools such as &lt;a href=&#34;https://cloudcannon.com/&#34;&gt;CloudCannon&lt;/a&gt; for better CMS management workflows if I desire. I might miss the Ghost app for drafts, but I mostly write on my desktop anyway. And since it is in GitHub, anything that can commit markdown to there is a way to draft.&lt;/p&gt;
&lt;p&gt;Now that I have that done, the next step is likely to repeat the whole process with &lt;code&gt;csmac.nz&lt;/code&gt; as well and fix its certs, ads, and content. (That last one has been bugging me since I moved to Ghost to be fair&amp;hellip; &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Failed to query available provider packages - Terraform NewRelic Provider :facepalm:</title>
      <link>https://blog.csmac.nz/post/terraform-newrelic-provider-facepalm/</link>
      <pubDate>Tue, 13 Jul 2021 19:18:43 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/terraform-newrelic-provider-facepalm/</guid>
      <description>&lt;p&gt;Recently I tried upgrading from Terraform 0.12 to 1.0.1. I think the key here is leaving 0.12.&lt;/p&gt;
&lt;p&gt;Anyway, there was a breaking change in 0.13 around how providers worked, and we got this cryptic error.&lt;/p&gt;
&lt;p&gt;(Caveat: I don&amp;rsquo;t actually know how much of this has to do with a newrelic provider update as well or instead, but was what we got the week of 2021/07/12.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Initializing provider plugins...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Reusing previous version of newrelic/newrelic from the dependency lock file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Finding latest version of hashicorp/newrelic...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Using previously-installed newrelic/newrelic v2.23.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;╷&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt; Error&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; Failed to query available provider packages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt; Could not retrieve the list of available versions &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; provider hashicorp/newrelic&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; provider registry registry.terraform.io does not have a provider 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt; named registry.terraform.io/hashicorp/newrelic
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt; Did you intend to use newrelic/newrelic? &lt;span style=&#34;color:#66d9ef&#34;&gt;If&lt;/span&gt; so, you must specify that source address &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; each module which requires that provider. To see which      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt; modules are currently depending on hashicorp/newrelic, run the following command&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;     terraform providers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So I&amp;rsquo;d already added this at my root module but this error still occurred.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;required_providers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    newrelic &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      source  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;newrelic/newrelic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.23.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;provider&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;newrelic&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  api_key    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;12345&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  account_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;12345&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It took a while to find the right docs to understand this one.&lt;/p&gt;
&lt;p&gt;The key message from above is the &lt;code&gt;You must specify that source address in each module which requires that provider.&lt;/code&gt; message. We are using modules, and the breaking change to 0.13 and above is that modules can specify &lt;code&gt;required_providers&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What they don&amp;rsquo;t tell you clearly, is that when trying to resolve &amp;ldquo;newrelic&amp;rdquo; provider by default, it will look for &amp;ldquo;hashicorp/newrelic&amp;rdquo;. However the actual provider source is &amp;ldquo;newrelic/newrelic&amp;rdquo;. So to make this work the optional &lt;code&gt;required_providers&lt;/code&gt; is actually mandatory, and actually needs the &lt;code&gt;source  = &amp;quot;newrelic/newrelic&amp;quot;&lt;/code&gt; property.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;required_providers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    newrelic &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      source &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;newrelic/newrelic&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adding this to every module that uses newrelic solved the problem.&lt;/p&gt;
&lt;p&gt;If you are doing this, you might also need to migrate your state over as well. Do this after running &lt;code&gt;terraform init&lt;/code&gt; from inside your config folder. This migrates the data in your state file to correctly map to the new provider.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;terraform state replace-provider newrelic newrelic/newrelic
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;More details here: &lt;a href=&#34;https://www.terraform.io/docs/cli/commands/state/replace-provider.html&#34;&gt;https://www.terraform.io/docs/cli/commands/state/replace-provider.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you do migrate 0.12 to 0.13 first, instead of stupidly jumping straight to 1.0.1, you can follow a more useful migration guide and the &lt;code&gt;0.13upgrade&lt;/code&gt; command instead. 🤦‍♂️&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.terraform.io/docs/cli/commands/0.13upgrade.html&#34;&gt;https://www.terraform.io/docs/cli/commands/0.13upgrade.html&lt;/a&gt;
&lt;a href=&#34;https://www.terraform.io/upgrade-guides/0-13.html&#34;&gt;https://www.terraform.io/upgrade-guides/0-13.html&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Kotlin, TeamCity and reflection</title>
      <link>https://blog.csmac.nz/post/kotlin-teamcity-and-reflection/</link>
      <pubDate>Tue, 11 May 2021 17:42:06 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/kotlin-teamcity-and-reflection/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been getting stuck into upskilling in Kotlin. Mostly for TeamCity build automation and trying to produce quality tested code in a space where automation was retrofitted in.&lt;/p&gt;
&lt;p&gt;Today&amp;rsquo;s fun little problem was the error message:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Runtime error RootProjectId: kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns$3[92]: java.lang.AssertionError: Built-in class kotlin.Any is not found&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The canonical stack overflow question that (at the time of writing this) had no answer: &lt;a href=&#34;https://stackoverflow.com/questions/67199546/why-am-i-getting-java-lang-assertionerror-built-in-class-kotlin-any-is-not-fou&#34;&gt;https://stackoverflow.com/questions/67199546/why-am-i-getting-java-lang-assertionerror-built-in-class-kotlin-any-is-not-fou&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The repro was the simplest piece of code in the end. I was even able to point it at a teamcity class over my own (&lt;code&gt;Project&lt;/code&gt;):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;import kotlin.reflect.full.declaredMemberProperties

val props = Project::class.declaredMemberProperties
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(For reference, i tried a few version configurations, but they were mainly kotlin version 1.3.31 teamcity version 2019.2 and kotlin version 1.4.31 and teamcity version 202.2.2)&lt;/p&gt;
&lt;p&gt;At this point in time and with some further testing, I&amp;rsquo;ve come to the conclusion that &lt;strong&gt;reflection just isn&amp;rsquo;t supported on teamcity with Kotlin&lt;/strong&gt;. I&amp;rsquo;ve found one or two Issue links to back that up too: &lt;a href=&#34;https://youtrack.jetbrains.com/issue/TW-59901&#34;&gt;https://youtrack.jetbrains.com/issue/TW-59901&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(¬_¬ )&lt;/p&gt;
&lt;p&gt;If anyone else managed to find a solution that works, or if any future version adds the missing puzzle pieces that make this work, I would be greatful to hear.&lt;/p&gt;
&lt;p&gt;For now, I have replaced the reflection with good ol&amp;rsquo; verbose fragile code.&lt;/p&gt;
&lt;p&gt;Luckily, the tests allow reflection no problem so at least the fragility of this case is covered. If someone adds a property then at least a test fails until the verbose code had been amended.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bluetooth Devices keep disconnecting</title>
      <link>https://blog.csmac.nz/post/bluetooth-devices-keep-disconnecting/</link>
      <pubDate>Mon, 09 Nov 2020 07:11:07 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/bluetooth-devices-keep-disconnecting/</guid>
      <description>&lt;p&gt;It all started when I installed Windows Update 20H2 in October 2020.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve had a stable machine (HP ZBook laptop for reference) for months and months with the same Bluetooth hardware, no issues. But that fateful day I installed the 20H2 update from Microsoft, everything changed.&lt;/p&gt;
&lt;p&gt;Suddenly I was having disconnect issues. I have a Bluetooth keyboard and Bluetooth mouse connected (I think they are both low energy?) And I found that one of them would reconnect, and the other wouldn&amp;rsquo;t. If I turned one-off, the other would reconnect, but the first one wouldn&amp;rsquo;t be able to when turned back on.&lt;/p&gt;
&lt;p&gt;As a temporary fix, I was able to connect the first device, then delete and re-add the second device. After somewhere between 10 minutes and half an hour, one device would disconnect again.&lt;/p&gt;
&lt;p&gt;I tried all the solutions from googling this issue, but the only one that worked was to update the Intel Bluetooth drivers.&lt;/p&gt;
&lt;p&gt;In Device Manager on Windows, under Bluetooth, the device is listed as &amp;ldquo;Intel(R) Wireless Bluetooth(R) and no amount of Windows Update to resolve new drivers helped.  But then I found the official driver support from intel: &lt;a href=&#34;https://www.intel.com/content/www/us/en/support/intel-driver-support-assistant.html&#34;&gt;Intel Driver Support Assistant&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I installed the tool and let it run. Lucky for me, there was a newer Bluetooth Driver for Windows 10 that I could download and install (amongst a few other Intel drivers as well).&lt;/p&gt;
&lt;p&gt;After installing the latest intel Bluetooth driver, I haven&amp;rsquo;t noticed any other issues since. It is back to business as usual now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Nullable and notnull Serialisation Properties</title>
      <link>https://blog.csmac.nz/post/nullable-and-notnull-serialisation-properties/</link>
      <pubDate>Sun, 26 Jul 2020 02:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/nullable-and-notnull-serialisation-properties/</guid>
      <description>&lt;p&gt;The C# 8 feature Nullable has been well received by myself and others into our workflows and has improved code bases immensely.  However, there is one niggly workaround that I&amp;rsquo;m not a fan of, and that is &lt;code&gt;= default!;&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;problem-definition&#34;&gt;problem definition&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// This class is used to serialise/deserialise a payload from a server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyContractDTO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;!;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My codebase is now littered with this code hack to get it to compile because nullable says it can&amp;rsquo;t guarantee that this property is not null.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a closer look at what we are saying.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// With the Nullable feature enabled, I need to ensure Value is not null:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - either in the constructor from a notnull argument&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - or giving it a default non-null value.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Initialise the property to its default value (which for reference types like string is null)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// The &amp;#39;!&amp;#39; says to treat the value as if it is notnull, the developer knows better&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;!;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What does this achieve? Well, the compiler ignores the fact that it could be null, and we initialise it to be null. This is a contradiction if ever I saw one, and I don&amp;rsquo;t like it.&lt;/p&gt;
&lt;h2 id=&#34;normal-solutions&#34;&gt;Normal solutions&lt;/h2&gt;
&lt;p&gt;There are two solution paths to take here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Acknowledge that it might be null and make it nullable.&lt;/li&gt;
&lt;li&gt;Initialise in the constructor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These work great with normal codebases and in some cases, one is better than the other.  If you know it certainly can be null, use the first option. If you know you never expect or want it to be null, use the second.&lt;/p&gt;
&lt;p&gt;Bonus points once you have the constructor is to make the type immutable.
For all domain and application logic, This is what I have done successfully so far and will continue doing.&lt;/p&gt;
&lt;h2 id=&#34;but-serialisation&#34;&gt;But serialisation&lt;/h2&gt;
&lt;p&gt;Here is the problem. Serialisation.&lt;/p&gt;
&lt;p&gt;When we have a type that is going to be used to deserialise transport models we again have the same choices as above, but a few more points to consider.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The JSON may or may not include the field&lt;/li&gt;
&lt;li&gt;The JSON may have the field set to null&lt;/li&gt;
&lt;li&gt;The Deserialiser might not support constructors&lt;/li&gt;
&lt;li&gt;The Deserialiser doesn&amp;rsquo;t know about Nullable and can&amp;rsquo;t ensure the safety is upheld.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again we can make the call to acknowledge that it might be null and make it nullable.  But there are drawbacks here. If you do this, you have to add all the error-handling for dealing with nullable checks. And if you control both server and client in this situation, then you might be writing and testing code for something you never plan to, nor may never need to ever support. Being null is an exceptional/fatal situation you don&amp;rsquo;t want to have to constantly guard against.&lt;/p&gt;
&lt;p&gt;Which leads us back to the de-facto solution currently being advocated and used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;!;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m still not happy. So why don&amp;rsquo;t we work on that?&lt;/p&gt;
&lt;h2 id=&#34;the-json-may-or-may-not-include-the-field-or-it-might-be-null&#34;&gt;The JSON may or may not include the field or it might be null&lt;/h2&gt;
&lt;p&gt;Luckily for us, this concern is fairly easy to address. Say we are using Newtonsoft.Json and want this extra piece of reassurance.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;[JsonProperty(Required = Required.Always)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;!;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Required&lt;/code&gt; attribute annotation is designed for exactly this situation. When we use Newtonsoft.Json as our deserialiser, we can get a &lt;code&gt;JsonSerializationException&lt;/code&gt; for free.&lt;/p&gt;
&lt;p&gt;This ensures we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have minimal code doing the null checking&lt;/li&gt;
&lt;li&gt;don&amp;rsquo;t have to guard every access to a nullable property&lt;/li&gt;
&lt;li&gt;Treat null or missing as fatal errors as part of an existing serialisation error handling process (which we should always have anyway).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This still doesn&amp;rsquo;t stop any other piece of code from creating an invalid object state, though. But this may be the easiest solution to add those missing guarantees alongside using &lt;code&gt;default!&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;use-constructors&#34;&gt;Use Constructors&lt;/h2&gt;
&lt;p&gt;Newtonsoft.Json helps once again by supporting constructors. Make sure all the mandatory non-nullable properties are in the constructor. And as long as there is no default constructor (which when doing nullable right you can&amp;rsquo;t anyway) and the constructor parameters have names matching the properties, this just works as expected.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public class MyContractDTO
{
    public MyContractDTO(string value)
    {
        if(value is null) throw new ArgumentNullException(nameof(value));
        Value = value;
    }
    
    public string Value { get; set; };
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You do however have to write your null-guard into the constructor to ensure it fails with an appropriate error message. Without this, null might still sneak through, even if you annotate the property.&lt;/p&gt;
&lt;p&gt;Once more, Newtonsoft.Json with constructors also means support for read-only (immutable) objects.&lt;/p&gt;
&lt;h2 id=&#34;what-about-not-using-newtonsoftjson&#34;&gt;What about not using Newtonsoft.Json?&lt;/h2&gt;
&lt;p&gt;There is a new kid on the block - &lt;code&gt;System.Text.Json&lt;/code&gt;. However, this is one area where it doesn&amp;rsquo;t shine so bright compared to Newtonsoft.Json.&lt;/p&gt;
&lt;p&gt;Pretty much none of the above works. Constructors are not supported. Required annotation is not supported. Along with many other things.&lt;/p&gt;
&lt;p&gt;More on &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to&#34;&gt;what does and does not translate across from Newtonsoft.Json is documented here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Instead, you will need to write your own converter and manually deserialise your object with your own explicit null checks (which could be done inside the constructor).&lt;/p&gt;
&lt;p&gt;For example, given our simple type above, we might do the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;[System.Text.Json.Serialization.JsonConverter(typeof(MyContractDTOConverter))]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyContractDTO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; MyContractDTO(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArgumentNullException(nameof(&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Value = &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Made using the examples given at https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#required-properties&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Your decisions may vary.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// e.g. this only supports {&amp;#34;value&amp;#34;: &amp;#34;...&amp;#34;} format, no extra properties allowed.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// For a more complex object, you would probably be more flexible.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Better guides here: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyContractDTOConverter&lt;/span&gt; : JsonConverter&amp;lt;MyContractDTO&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; JsonEncodedText ValueName = JsonEncodedText.Encode(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; Implementation Read(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; Utf8JsonReader reader,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Type typeToConvert,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        JsonSerializerOptions options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (reader.TokenType != JsonTokenType.StartObject)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; JsonException();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;string?&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        reader.Read();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// One property must exist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (reader.TokenType != JsonTokenType.PropertyName)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; JsonException();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// That property must have the right name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (reader.ValueTextEquals(ValueName.EncodedUtf8Bytes))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; = ReadProperty(&lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; reader, options);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; JsonException();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        reader.Read();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// There must be no other properties&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (reader.TokenType != JsonTokenType.EndObject)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; JsonException();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyContractDTO(&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; ReadProperty(&lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; Utf8JsonReader reader, JsonSerializerOptions options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        reader.Read();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; reader.GetString();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; WriteProperty(Utf8JsonWriter writer, JsonEncodedText name, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; stringValue, JsonSerializerOptions options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        writer.WritePropertyName(name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        writer.WriteStringValue(stringValue);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Write(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Utf8JsonWriter writer,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Implementation implementation,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        JsonSerializerOptions options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        writer.WriteStartObject();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        WriteProperty(writer, ValueName, implementation.Value, options);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        writer.WriteEndObject();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At which point you now have a bunch more code and logic to look after, but can achieve the same/similar results to what Newtonsoft.Json could do. Depending on your situation, maintaining this code may be more effort than declaring it nullable and maintaining checks around that in consuming code. Up to you.&lt;/p&gt;
&lt;h2 id=&#34;decisions-decisions&#34;&gt;Decisions, Decisions&lt;/h2&gt;
&lt;p&gt;So what would I recommend?&lt;/p&gt;
&lt;p&gt;Firstly, don&amp;rsquo;t just use &lt;code&gt;default!&lt;/code&gt; on your serialised types.&lt;/p&gt;
&lt;p&gt;For maximum effect, make your classes have constructors for notnull values, and maybe even make your properties Immutable, if that makes sense. Have your constructors guard against nulls so that your compile-time assurances have runtime verifications. Especially is this is a client library you provide to others.&lt;/p&gt;
&lt;p&gt;If you are using Newtonsoft.Json you should at least apply the &lt;code&gt;[JsonProperty(Required = Required.Always)]&lt;/code&gt; to all your notnull properties. But add the constructors as well because you can. If you can stick with Newtonsoft.Json, your life will be very easy.&lt;/p&gt;
&lt;p&gt;If you are using (or have to use) System.Text.Json, write custom converters for your types so that you can have those constructors mentioned above. Make sure you keep them flexible enough to ignore any extra properties you might add in the future to avoid breaking backwards compatibility.&lt;/p&gt;
&lt;p&gt;This experiment has a companion GitHub repo of tests (a mixture of proof they work, and proof they fail tests) &lt;a href=&#34;https://github.com/csMacnzBlog/NullableSerialisationExperiments&#34;&gt;available here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy Null-Hunting.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>We are all 10x engineers, but I don&#39;t think it means what you think it means</title>
      <link>https://blog.csmac.nz/post/we-are-all-10x/</link>
      <pubDate>Mon, 15 Jul 2019 09:50:55 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/we-are-all-10x/</guid>
      <description>&lt;p&gt;If your reading this blog, and used twitter in the past few days, you have probably already seen this tweet, or some of the replies coming through from the community:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;en&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;10x engineers&lt;br&gt;&lt;br&gt;Founders if you ever come across this rare breed of engineers, grab them. If you have a 10x engineer as part of your first few engineers, you increase the odds of your startup success significantly.&lt;br&gt;&lt;br&gt;OK, here is a tough question.&lt;br&gt;&lt;br&gt;How do you spot a 10x engineer?&lt;/p&gt;&amp;mdash; Shekhar Kirani (@skirani) &lt;a href=&#34;https://twitter.com/skirani/status/1149302828420067328?ref_src=twsrc%5Etfw&#34;&gt;July 11, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;p&gt;As a developer who tries to be good at their job, I have thoughts on this. As a Human, I like to be heard. (Note that being heard is not the same thing as being agreed with, or being right.) So here I am giving my opinion on this idea of a 10x developer, and specifically these &amp;ldquo;10 signs&amp;rdquo; put up online.&lt;/p&gt;
&lt;p&gt;I like the idea that there are no 10x people, instead, you can strive to produce 10x teams.&lt;/p&gt;
&lt;h2 id=&#34;1-meetings&#34;&gt;1. Meetings&lt;/h2&gt;
&lt;p&gt;A lot of people don&amp;rsquo;t like meetings. But unfortunately, communication is a big part of effective teams and businesses. While it is true that some people love meetings, and some meetings don&amp;rsquo;t hold productivity, the key here is communication. If you can find an effective means of communication within a team that works, that is most important.  Having a team full of people that don&amp;rsquo;t have meetings doesn&amp;rsquo;t make a 10x team. If meetings are causing you or your team problems, it is work looking at other strategies for effective communication. There are alternatives out there.&lt;/p&gt;
&lt;h2 id=&#34;2-office-hours&#34;&gt;2. Office Hours&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Nine to Five&amp;rdquo; is such an old fashioned idea these days. Not only do some countries have alternative ideas like 4 day weeks, long lunch hours, &amp;ldquo;flexitime&amp;rdquo;, but more and more business work across locations and across timezones. We are asking people to work outside these hours for various reasons already, so why not some give and take here?&lt;/p&gt;
&lt;p&gt;Most people would love flexible work hours. It turns out that if people can work around their own schedule, they put their best work forward when they are present. I would much rather have someone contribute 100% at 9 pm at night because their kids are in bed and they can concentrate rather than pay them to sit at their desk for several hours texting and calling their family. Just a thought.&lt;/p&gt;
&lt;p&gt;We are so fortunate that in our industry is so capable and adjustable to different working hours that it is a shame not to support this. It is not that &amp;ldquo;10x developers are the people who like this&amp;rdquo;, it is actually that most employees want this, and it can be done.&lt;/p&gt;
&lt;h2 id=&#34;3-screen-colour-and-worn-keyboards&#34;&gt;3. Screen colour and worn keyboards&lt;/h2&gt;
&lt;p&gt;If I saw a sports star on the field/pitch/court wearing badly worn shoes, I wouldn&amp;rsquo;t think &amp;ldquo;This is a superstar&amp;rdquo;, I would probably think &amp;ldquo;he isn&amp;rsquo;t paid enough&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Why are you letting your developers use worn-out equipment? Buying the required hardware and software is such an important thing, just do it! In all seriousness, though, giving staff the right tools to get their job done is always a good idea.&lt;/p&gt;
&lt;p&gt;There is an interesting dichotomy with custom technical tools as well. If you have one developer that goes against the grain of the team with customisation, then it both makes it harder for them to use other machines (e.g. during pairing/mobbing) and for others to use theirs. There is some efficiency to using the out of the box defaults too. You can get up and running faster, and waste less time doing customisations every time you refresh your machine or change jobs and get new hardware.&lt;/p&gt;
&lt;p&gt;Also, if you have to have everything customised your own way, you won&amp;rsquo;t be able to acclimatise to new situations, new tools, new teams. Not someone you want to add to your team.&lt;/p&gt;
&lt;h2 id=&#34;4-good-memory&#34;&gt;4. Good memory&lt;/h2&gt;
&lt;p&gt;One my big comparisons between my generation and the one before me (that is the one with the access to Google, but not access to iPads) was that at school we were no longer taught to memorise and recall information. Instead, we were taught, and learned, the importance of finding and referencing information. There is too much information for us all to hold in our heads. knowing where to look and what to look for is far more important that memorised information for a technology that will be obsolete in 3 years (if you are lucky), let alone memorising a dozen of them over time.&lt;/p&gt;
&lt;p&gt;Yes, it is great to get people who know the domain really well, and for some people, it really is a skill. But people can&amp;rsquo;t know what they haven&amp;rsquo;t seen yet, and new hires always start as a blank slate. Not to mention tomorrow will bring a new set of libraries, applications and services that need to be learned and understood.&lt;/p&gt;
&lt;p&gt;Scott Hanselman talks of the experience-groundhog-day scenario.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;en&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Do you have 10 years’ experience, or the same year 10 times? &lt;a href=&#34;https://t.co/LhIeWiWl3H&#34;&gt;https://t.co/LhIeWiWl3H&lt;/a&gt;&lt;/p&gt;&amp;mdash; Scott Hanselman (@shanselman) &lt;a href=&#34;https://twitter.com/shanselman/status/1001495109836226560?ref_src=twsrc%5Etfw&#34;&gt;May 29, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;5-full-stack&#34;&gt;5. Full Stack&lt;/h2&gt;
&lt;p&gt;Don&amp;rsquo;t you love buzz words? FullStack. A full-stack would be from the HTML/CSS/js to the backend code, to the database. But it is also understanding how the TCP/HTTP layer works with packets and routing. How does your platform infrastructure run, do you manage and patch the servers? Database backups and data security, not to mention how the hardware scales, can you write the assembly to work with arm processors too?&lt;/p&gt;
&lt;p&gt;Jack of all trades, master of none. That is a saying that acknowledges you are spread too thin. You can&amp;rsquo;t be an expert in everything, so instead, you can hire an expert in each thing. Yes, you want everyone to be a generalist, but make sure you have coverage with all of the specialists, too.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t say I&amp;rsquo;ve met too many people who can design and build an amazing user experience, and also optimise a large scale database, and run a datacentre. Oh and also works well with others&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;6-wait-wat&#34;&gt;6. Wait, WAT?&lt;/h2&gt;
&lt;p&gt;This one I just have to quote it in two parts:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;10x engineers can convert &amp;ldquo;thought&amp;rdquo; into &amp;ldquo;code&amp;rdquo; in their mind and write it in an iterative fashion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just for a second, imagine with me, that you could replace the words &amp;ldquo;10x engineer&amp;rdquo; with &amp;ldquo;a developer&amp;rdquo;. Crazy idea, but it might actually work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given a product feature, they can write that entire feature in one or two sittings of 4 to 6 hours with a caffeinated drink without distraction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We all have good days where we fire on all cylinders. Or a task or feature fits into just the right hole in a system.  Cherish the days when it happens, but realise its more about the stars aligning and less about the ability of your developer. We are all capable of this. But the rest of the time it&amp;rsquo;s just a Monday.&lt;/p&gt;
&lt;h2 id=&#34;7-good-memory-part-deux&#34;&gt;7. Good Memory. Part Deux&lt;/h2&gt;
&lt;p&gt;We talked about this. Enough said.&lt;/p&gt;
&lt;h2 id=&#34;8-learning&#34;&gt;8. Learning&lt;/h2&gt;
&lt;p&gt;This is another one of those things with a dichotomy. If you are always learning something new, you never get to master anything. There is a benefit to having people who are masters, and people who can learn, and people who can teach and share. You need balance both as a developer and person, but also in and within a team. If you don&amp;rsquo;t have this yet, look at hiring the capabilty, but don&amp;rsquo;t use it to rule in or out talented people.&lt;/p&gt;
&lt;h2 id=&#34;9-terrible-leaders&#34;&gt;9. Terrible leaders&lt;/h2&gt;
&lt;p&gt;Yes. I think exactly what you want to do is hire someone who cannot teach how the system works to new staff. That will help you grow. No, not really. The team is only as strong as its weakest point. And the ability to both cover for, and teach and grow newer talent is key to growth and success.&lt;/p&gt;
&lt;p&gt;Also, while it is true that some people will be amazing on your team, but will interview poorly, I can&amp;rsquo;t say there is a direct reverse correlation here, either. Sorry.&lt;/p&gt;
&lt;h2 id=&#34;10&#34;&gt;10. &lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;10x engineers rarely job hunt or move out of the company. They move out because you make their life miserable with the process, meetings, training, and other non-value-added activities. If you come across them, hold on to them. Celebrate them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So close. This is the first point I almost agree with. Just go ahead and replace &amp;ldquo;10x engineers&amp;rdquo; again with &amp;ldquo;developers&amp;rdquo;, Or even just &amp;ldquo;employees&amp;rdquo; will do.&lt;/p&gt;
&lt;h2 id=&#34;01x-developers&#34;&gt;0.1x developers&lt;/h2&gt;
&lt;p&gt;While there are seeds in here that make for an interesting debate, they have nothing to with &amp;ldquo;10&amp;rdquo; or &amp;ldquo;X&amp;rdquo;. The best summary of the whole situation is this: The scale is off.  I think the truth of the matter is that there are developers who might contribute to failings in a team (and some warning signs appear above, under the wrong inversion, though). We can call them the 0.1x developers. They are the ones to truly watch out for.&lt;/p&gt;
&lt;p&gt;As founders and employers, you will want to be doing all the right things to attract and keep good talent, and that is more important than going after a mythical creature known as the 10x developer.&lt;/p&gt;
&lt;p&gt;What someone needs to do is follow the footsteps of Dylan Beattie&amp;rsquo;s &lt;a href=&#34;https://github.com/RockstarLang/rockstar&#34;&gt;Rockstar programming language&lt;/a&gt; and make a language or piece of hardware board and call it &amp;ldquo;10x&amp;rdquo;. Then we can all be Rockstar Programmers and 10x Engineers.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Snuffleupagus-Oriented Programming</title>
      <link>https://blog.csmac.nz/post/snuffleupagus-oriented-programming/</link>
      <pubDate>Mon, 08 Jul 2019 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/snuffleupagus-oriented-programming/</guid>
      <description>&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;en&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;An impromptu introduction to Snuffleupagus-Oriented Programming (SOP): &lt;a href=&#34;https://t.co/jPkjPRgqQr&#34;&gt;https://t.co/jPkjPRgqQr&lt;/a&gt;&lt;/p&gt;&amp;mdash; Casey Muratori (@cmuratori) &lt;a href=&#34;https://twitter.com/cmuratori/status/623332420855541764?ref_src=twsrc%5Etfw&#34;&gt;July 21, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;p&gt;Sometimes naming something is the best way to start talking about a topic that lots of people do but don&amp;rsquo;t realise or haven&amp;rsquo;t pulled together as a concept. This is one of those ideas that finally has a good (?) name.&lt;/p&gt;
&lt;p&gt;How do you build out a new API? Here we are meaning programming contracts effectively.  You can hack away until you have something functional, and then start consuming it. Better yet, build it out as code to do a job and then ship it to someone else to try and use.&lt;/p&gt;
&lt;p&gt;Most developers get to a point where they see the value in having contract design up front across team boundaries, layer boundaries, reusable components, HTTP/Soap boundaries etc. An evolved design for these will never be as good as an intentional one. And on the flip side, we have all used clunky library APIs in various languages, BCL or otherwise.&lt;/p&gt;
&lt;h3 id=&#34;what-is-mr-snuffleupagus&#34;&gt;What is Mr Snuffleupagus&lt;/h3&gt;
&lt;p&gt;The name comes from Sesame Street. Muppets basically. Big Bird and Bert and Ernie, Elmo etc. There was a storyline decades ago where Big Bird kept seeing Mr Snuffleupagus and talking about him, but no one else ever saw him. They concluded it was an imaginary creature for a long time. In the show, it was very ambiguous what the truth was. Eventually, they actually saw the Snuffleupagus too and concluded it wasn&amp;rsquo;t imaginary after all. &lt;a href=&#34;https://www.smithsonianmag.com/smart-news/brief-history-sesame-streets-snuffleupagus-iidentity-crisis-180957351/&#34;&gt;More here.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;enter-sop&#34;&gt;Enter SOP&lt;/h3&gt;
&lt;p&gt;The ideas from this story match an approach to building your API.&lt;/p&gt;
&lt;p&gt;First, we are going to imagine that what we want to use exists. Then we are going to write code against the API, crafting our usage case, without implementing anything.  Once we are happy that our API is usable, we implement it and make it actually exist, make it real. There may be a few tweaks once the realities and limitations of the implementation are taken into account, but the idea is to try and keep it as usable as the original usage cases as possible, usability intact.&lt;/p&gt;
&lt;div style=&#34;padding-top:72.800%;position:relative;&#34;&gt;&lt;iframe src=&#34;https://gifer.com/embed/9YHg&#34; width=&#34;100%&#34; height=&#34;100%&#34; style=&#39;position:absolute;top:0;left:0;&#39; frameBorder=&#34;0&#34; allowFullScreen&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://gifer.com&#34;&gt;via GIFER&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;tdd&#34;&gt;TDD&lt;/h3&gt;
&lt;p&gt;This is a great candidate approach to work with TDD as well, just with more implementation code along the way to produce passing tests. Like Mr Snuffleupagus, this implementation code is imaginary until you have enough test cases to make it real, and refactor.&lt;/p&gt;
&lt;h3 id=&#34;thanks&#34;&gt;Thanks&lt;/h3&gt;
&lt;p&gt;Go forth and start sharing SOP, Snuffleupagus-Oriented Programming. Imagine, Build Usage, Make it Real.  Thanks &lt;a href=&#34;https://twitter.com/cmuratori&#34;&gt;Casey Muratori&lt;/a&gt; for coining the term and making it stick. See more of his programming on &lt;a href=&#34;https://handmadehero.org/&#34;&gt;HandMade Hero&lt;/a&gt; (&lt;a href=&#34;https://www.youtube.com/handmadehero&#34;&gt;YouTube&lt;/a&gt;), and his company &lt;a href=&#34;https://mollyrocket.com/nexus&#34;&gt;Molly Rocket&lt;/a&gt; for games and more.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking Back on C# 7: Pattern matching</title>
      <link>https://blog.csmac.nz/post/looking-back-on-csharp7-pattern-matching/</link>
      <pubDate>Mon, 01 Jul 2019 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/looking-back-on-csharp7-pattern-matching/</guid>
      <description>&lt;p&gt;With C# 8 on our doorstep, I figure it is a good time to reflect on recent additions to the language that have come before. There are some great improvements you may have missed, some that I really enjoy using, and some I consider have reached canonical usage status that I think are all worth some reflection.&lt;/p&gt;
&lt;p&gt;Pattern matching is a powerful feature that has been unlocked against various language constructs in C#.  The idea is to take existing features like &lt;code&gt;case&lt;/code&gt; from switches and &lt;code&gt;is&lt;/code&gt; and extract their capabilities into a &amp;ldquo;pattern matching&amp;rdquo; concept over types and values. This can then be applied back to these language features, and other places in the future.&lt;/p&gt;
&lt;p&gt;Before the new concept of patterns, &lt;code&gt;case&lt;/code&gt; accepted a constant as an argument, and &lt;code&gt;is&lt;/code&gt; would accept a type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Check the type of the variable &amp;#34;is assignable to&amp;#34; Shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(widget &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; Shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; ((widget &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; Shape).Type)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// When value matches the constant &amp;#34;Square&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Square&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the introduction of C# 7.0, both of these language features have been enhanced to use the new Pattern Matching syntax.  This is a backwards-compatible change, meaning that the pattern type can be a const or a type. As well as these existing cases, it also includes &lt;code&gt;when&lt;/code&gt; clauses and var patterns as well.&lt;/p&gt;
&lt;h3 id=&#34;is-expression&#34;&gt;is Expression&lt;/h3&gt;
&lt;p&gt;Originally, &lt;code&gt;is&lt;/code&gt; was able to check a type. This could create more readable code but often left casting or &lt;code&gt;as&lt;/code&gt; operator usage in the aftermath.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (widget &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; Shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; myShape = widget &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; Shape;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// var myShape = (Shape)widget;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This has been improved by the pattern matching. First, we have constant checking:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (widget.Type &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (widget.Type &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;FOO&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As well as this, the Type checking Pattern now includes support to create a scoped variable of the correct type, similar to the new out parameter functionality. This language feature is collectively known as &amp;ldquo;expression variables&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (widget &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; Shape shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ... use `shape`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;switch-statement&#34;&gt;Switch Statement&lt;/h3&gt;
&lt;p&gt;A switch used to only match on constants, but with the new pattern matching, we can do so much more.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SwitchIt(&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; result = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// We can still switch on constants, even when the types don&amp;#39;t match&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// We can switch on type, and even create a scoped variable (like with `is`)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; IEnumerable&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; childSequence:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; item &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; childSequence)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                result += (item &amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) ? item : &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// using `when`, we can do range or bounds checking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; n when n &amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            result += n;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// We can constant check against null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; NullReferenceException(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Null found in sequence&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; InvalidOperationException(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Unrecognized type&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is another new pattern that is useful with switch, which is the var pattern. The &amp;ldquo;var pattern&amp;rdquo; is similar to the type pattern, except that it always matches, but creates a variable with the assigned value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt;(shape)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; Circle c:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;circle with radius {c.Radius}&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; Rectangle s when (s.Length == s.Height):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;{s.Length} x {s.Height} square&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; Rectangle r:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;{r.Length} x {r.Height} rectangle&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; s:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Always matches (similar to default) but gives access to the value as `s`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;This is some kind of {s.Name} shape&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is worth pointing out that the order of your &lt;code&gt;case&lt;/code&gt; arguments now matters. while not a logical breaking change, since it never mattered what order constants where declared, it would always match the right answer, this is a conceptual change you need to be aware of. Mixing and matching patterns in a switch mean that the order does matter, and the first pattern that matches will get executed. To repeat, when all cases are constants this wouldn&amp;rsquo;t make any difference to the outcome but more advanced checks will.&lt;/p&gt;
&lt;p&gt;In C# 7.1, the patterns were extended to work correctly with generic variables as well. In C# 7.0, you could use these type patterns as expected by first casting the &lt;code&gt;T foo&lt;/code&gt; value to an &lt;code&gt;Object&lt;/code&gt; (which could cause Boxing) and then the type checking would all work. In C# 7.1, this cast is no longer necessary, and also avoids any boxing and unboxing along the way. &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch#type-pattern&#34;&gt;The docs&lt;/a&gt; go over this is more detail with an example comparing the two implementations, as there are a few subtle differences, especially around null/default cases.&lt;/p&gt;
&lt;h3 id=&#34;pattern-matching-coming-soon&#34;&gt;Pattern Matching coming soon&lt;/h3&gt;
&lt;p&gt;This feature is an interesting one in the sense that it is both newer and probably under-used and less known. You can program away happily in C# never needing to use it and not coming across it.&lt;/p&gt;
&lt;p&gt;But with C# 8, there is a bunch of new features that will be using this existing pattern matching coming, so you might want to get on board with this in preparation, because soon you will need to understand code using it, and probably see a lot more of it around.&lt;/p&gt;
&lt;p&gt;Bring on the Switch Expression!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking Back on C#: async and await</title>
      <link>https://blog.csmac.nz/post/looking-back-on-csharp-async-await/</link>
      <pubDate>Mon, 24 Jun 2019 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/looking-back-on-csharp-async-await/</guid>
      <description>&lt;p&gt;With C# 8 on our doorstep, I figure it is a good time to reflect on recent additions to the language that have come before. There are some great improvements you may have missed, some that I really enjoy using, and some I consider have reached canonical usage status that I think are all worth some reflection.&lt;/p&gt;
&lt;p&gt;Multithreaded programming has always been a difficult thing to get your head around, and there are many pitfalls easily stumbled into. To help combat this, Microsoft gave us async/await in C#.&lt;/p&gt;
&lt;p&gt;Async/Await is a language feature that has been around since Visual Studio 2012 and C# 5 and hides a bunch of the boilerplate state machine code required to safely park a logical thread of execution while it waits for some work to complete or to respond from another thread, IO, or network device.  This allows code to be more logically procedural and linear, therefore easier to read and comprehend.&lt;/p&gt;
&lt;p&gt;Since it first came out there has been a raft of improvements across different versions of C#.&lt;/p&gt;
&lt;h2 id=&#34;the-basics&#34;&gt;The basics&lt;/h2&gt;
&lt;p&gt;The foundation of how it all works rests on the shoulders of a Library, the Task Parallel Library, or TPL. Tasks have been around since 2010 and were part of the .Net 4 Framework. Similar to what &lt;a href=&#34;https://developers.google.com/web/fundamentals/primers/promises&#34;&gt;Promises provide in javascript&lt;/a&gt;, this library allowed a logical chain of execution across waiting for blocking or longrunning execution while releasing the UI thread from being blocked. This was the introduction of &lt;code&gt;TaskFactory&lt;/code&gt; and &lt;code&gt;Task&lt;/code&gt;, in a fairly similar form to what we have today.  This was a huge improvement from the days of callback chaining because it reduced heavy nesting of lambdas into more of a linear pipeline and a clear place for error handling to take place.&lt;/p&gt;
&lt;p&gt;When C# 5 introduced async/await as a first-class language feature, it was able to leverage the library and extend on it to give us more readable code. It even handled Exceptions by throwing them in the place where &lt;code&gt;await&lt;/code&gt; appeared, making &lt;code&gt;try/catch&lt;/code&gt; blocks useful in asynchronous code.&lt;/p&gt;
&lt;p&gt;What does async/await look like in C# 5?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// A classic synchronous method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; MakeAWebRequest(Uri uri)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// WebClient has synchronous methods, but it is recommended to use HttpClient for newer apps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; client = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; WebClient();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; client.DownloadString(uri);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// It&amp;#39;s async younger brother&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;async&lt;/span&gt; Task&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt; MakeAWebRequestAsync(Uri uri)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// I use WebClient again for better comparing. Use HttpClient!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; client = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; WebClient();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; client.DownloadStringAsync(uri);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are two distinctive features in this comparison. The return type is wrapped in a &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt;, and there is a keyword &lt;code&gt;async&lt;/code&gt; on the method signature with &lt;code&gt;await&lt;/code&gt; beside method calls that return &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt; results. Otherwise, the linear execution flow is largely unchanged.&lt;/p&gt;
&lt;p&gt;You can easily use the return type without the keywords. In this case, the code works and operates as normal, passing object references around without any async state. The result object captures the state required for the caller to do the asynchronous work in the future, or respond to its completion.  However, if you do use &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;, then you should always return either &lt;code&gt;Task&lt;/code&gt; (where usually returns void) or &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt; (where usually returns T). (In my opinion, there are no reasons left to ever do async without Task - there used to be but not anymore.)&lt;/p&gt;
&lt;p&gt;Now we have that out of the way, let&amp;rsquo;s move forward to C# 6 and beyond!&lt;/p&gt;
&lt;h2 id=&#34;async-and-exceptions&#34;&gt;Async and Exceptions&lt;/h2&gt;
&lt;p&gt;Exception handling was a big part of this feature on day one. You could simply wrap your async calls in a &lt;code&gt;try{}catch{}&lt;/code&gt; and it would work as you would expect it to. The task you are awaiting throws an Exception, your catch triggers.&lt;/p&gt;
&lt;p&gt;But initially, this did not work inside the catch or finally blocks in any expected way. In fact, it caused a compiler error. In C# 6 await in &lt;code&gt;catch&lt;/code&gt;/&lt;code&gt;finally&lt;/code&gt; blocks were given proper compiler support to do the right thing.&lt;/p&gt;
&lt;p&gt;Using the example from &lt;a href=&#34;https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#await-in-catch-and-finally-blocks&#34;&gt;The new language feature docs&lt;/a&gt; directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resource res = &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    res = &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; Resource.OpenAsync(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// You could do this.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt;(ResourceException e)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; Resource.LogAsync(res, e);         &lt;span style=&#34;color:#75715e&#34;&gt;// Now you can do this …&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (res != &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; res.CloseAsync(); &lt;span style=&#34;color:#75715e&#34;&gt;// … and this.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;async-and-console-apps&#34;&gt;Async and Console Apps&lt;/h2&gt;
&lt;p&gt;The language version was C# 7. We had async everywhere, and the &lt;code&gt;NetStandard&lt;/code&gt;s and Frameworks were full of async API calls and interfaces. It was a contagious thing, and you really had to jump through hoops to try &lt;a href=&#34;https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/&#34;&gt;to call a red function from a blue one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And then there was main. That pesky little entry point into your application. The one the compiler generates for you that kicks off all of the application execution. The one that had to call into your top-most async method to &lt;code&gt;RunAsync&lt;/code&gt;. And it had to be &lt;code&gt;public static void Main(string[] args)&lt;/code&gt; or &lt;code&gt;public static int Main()&lt;/code&gt;. That is not an async method.&lt;/p&gt;
&lt;p&gt;Luckily, with the first ever minor language update, C# 7.1, we were given the mighty and powerful async main!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// You can finaly use Task&amp;lt;int&amp;gt;!
public static async Task&amp;lt;int&amp;gt; Main()
{
...
}

// Also available in no return value flavour!
public static async Task Main()
{
...
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;async-and-tests&#34;&gt;Async and Tests&lt;/h2&gt;
&lt;p&gt;We have a tonne of async methods in our system. But we should also be testing that code.  And our testing frameworks were synchronous.&lt;/p&gt;
&lt;p&gt;Luckily our testing frameworks have finally caught up, and with XUnit we can write tests that return Task and are async&lt;code&gt;, and we also have the &lt;/code&gt;IAsyncLifetime` interface.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// This is what we had to do to test async
public class MyTestCase
{
    private readonly MyClass _systemUnderTest;

    public MyTestCase()
    {
        _systemUnderTest = MyClass();
        
        Task.Run(async () =&amp;gt; await _systemUnderTest.Init()).GetAwaiter().GetResult();
    }
    
    public void CanRunSuccessfully()
    {
    
        var result = Task.Run(async () =&amp;gt; await _systemUnderTest.Run()).GetAwaiter().GetResult();
        
        Assert.True(result);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using &lt;code&gt;Task.Run&lt;/code&gt; and &lt;code&gt;GetAwaiter&lt;/code&gt; or other synchronising methods can be very error-prone, and &lt;a href=&#34;https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html#preventing-the-deadlock&#34;&gt;prone to deadlocks&lt;/a&gt;. Avoiding these is the best approach always (though still not always avoidable).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The best way to tet with &lt;span style=&#34;color:#66d9ef&#34;&gt;async&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyTestCase&lt;/span&gt; : IAsyncLifetime
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; MyClass _systemUnderTest;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; MyTestCase()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _systemUnderTest = MyClass();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;async&lt;/span&gt; Task InitializeAsync()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; _systemUnderTest.Init();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Task DisposeAsync()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Task.CompletedTask;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;async&lt;/span&gt; Task CanRunSuccessfully()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; result = &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; _systemUnderTest.Run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Assert.True(result);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m not sure if other test runners are able to handle async as well as XUnit does, so I always just use XUnit.&lt;/p&gt;
&lt;h2 id=&#34;valuetask&#34;&gt;ValueTask&lt;/h2&gt;
&lt;p&gt;The original implementation of the async/await language feature was strongly tied to the &lt;code&gt;Task&lt;/code&gt; and `Task&lt;T&gt; types.&lt;/p&gt;
&lt;p&gt;In C# 7, the language feature was enhanced, similar to other features, to use a pattern based on method signatures (like the &lt;a href=&#34;https://blog.csmac.nz/looking-back-on-csharp6-initializers/&#34;&gt;Add for the initialiser syntax&lt;/a&gt;). Specifically, the &lt;code&gt;GetAwaiter&lt;/code&gt; method must be available on the type used with the &lt;code&gt;await&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;Along with this change was the introduction of a new type to leverage this pattern, &lt;code&gt;ValueTask&lt;/code&gt;. A &lt;code&gt;ValueTask&lt;/code&gt; is a value type (struct) that will be stack-allocated and copied by value. If your method uses caching, and most of the time returns a simple value instead of an awaited execution, the &lt;code&gt;ValueTask&lt;/code&gt; may be more efficient than the &lt;code&gt;Task&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;This is because the overheads of Heap-allocation of the reference type &lt;code&gt;Task&lt;/code&gt; can have an impact on performance. If you detect this as an issue, you can use the new &lt;code&gt;ValueTask&lt;/code&gt; instead. This will be a stack-allocated value type containing the response value and copied around.&lt;/p&gt;
&lt;p&gt;Guidance for this: if you mostly return a value, but occasionally call an actual asynchronous IO execution, &lt;code&gt;ValueTask&lt;/code&gt; will probably add value (e.g. heavy result caching). If you actually await most of the time, &lt;code&gt;Task&lt;/code&gt; should be fine. As usual, measure and test before making the change arbitrarily.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Async programming is becoming the canonical way of building apps with IO in most languages. And in practice, most of the apps I write are IO-bound apps. C# and dotnet make this simple with &lt;code&gt;async/await&lt;/code&gt; and the language keeps improving our experience using this successfully. This is a must-use feature that is unavoidable, but knowing the limitations and extensions available to use it well is still very important to do. Use it, but make sure you know enough about how it works to use it well.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking Back on C# 7: refs enhancements</title>
      <link>https://blog.csmac.nz/post/looking-back-on-csharp7-refs/</link>
      <pubDate>Mon, 17 Jun 2019 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/looking-back-on-csharp7-refs/</guid>
      <description>&lt;p&gt;With C# 8 on our doorstep, I figure it is a good time to reflect on recent additions to the language that have come before. There are some great improvements you may have missed, some that I really enjoy using, and some I consider have reached canonical usage status that I think are all worth some reflection.&lt;/p&gt;
&lt;p&gt;We talked about the out variables &lt;a href=&#34;https://blog.csmac.nz/looking-back-on-csharp7-out-variables&#34;&gt;in the previous post in the series&lt;/a&gt;, but there are a few other enhancements related to &lt;code&gt;ref&lt;/code&gt; as well.&lt;/p&gt;
&lt;p&gt;Hopefully, the concepts of values, pointers, stacks and heaps make sense to you at a conceptual level. These are crucial concepts to using and understanding &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;out&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a quick recap, stack memory is local to a function and the function call stack. This memory is semantically &amp;ldquo;pushed&amp;rdquo; to for each method call, and &amp;ldquo;popped&amp;rdquo; from on each return (the call stack, stack overflow etc). The heap is a shared memory space where objects are allocated and stored, which is acted on by the Garbage Collector.&lt;/p&gt;
&lt;p&gt;Values are mostly stack-allocated. They are copied around so that setting a value variable does not affect any other variable. Primitive types and structs are Value types. Reference types are the classes in C#. Classes are always stored on the heap, and all variables of class types are pointers or references. Assigning a reference to a new variable will point to the same value on the heap. Changing a field value on a reference type will be reflected in both variables. (Boxing values onto the heap is another thing, too.)&lt;/p&gt;
&lt;p&gt;We already have &lt;code&gt;out&lt;/code&gt; that allows the caller to declare a variable on the current stack that it passes by address (pointer, reference, or ref) that the method is contracted to set for you. This essentially gives us some of the power of reference types from a stack-allocated value. When we use &lt;code&gt;ref&lt;/code&gt;, we gain all of the power of passing by reference that we have from heap allocated class types. We are essentially saying that the caller can use the existing value of the reference, and also set a new value to the stack variable if it wants to as well. Basically, all the restrictions that &lt;code&gt;out&lt;/code&gt; imposes are taken off. A ref may not just be a stack variable, but could also be a field on a class that you want to access directly by reference, instead of having to constantly dereference it.&lt;/p&gt;
&lt;p&gt;Pass by &lt;code&gt;ref&lt;/code&gt; has been in C# since the beginning, but like the &lt;code&gt;out&lt;/code&gt; parameters, only works in method signatures. However, from the beginning, you could never declare a &lt;code&gt;ref&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;In C# 7, &lt;code&gt;ref&lt;/code&gt; has been extended to work with return types, and with variables. You can return a value by reference. And so that it the returned result can be assigned to something in a useful way, we also now have &lt;code&gt;ref&lt;/code&gt; variable typing.  Like most C# language features, there is safety built in.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You must add the &lt;code&gt;ref&lt;/code&gt; keyword to the method signature and to all return statements in a method.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;ref&lt;/code&gt; return may be assigned to a value variable (by copy) or a &lt;code&gt;ref&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;You can&amp;rsquo;t assign a standard method return value to a &lt;code&gt;ref&lt;/code&gt; local variable.&lt;/li&gt;
&lt;li&gt;You can&amp;rsquo;t return a &lt;code&gt;ref&lt;/code&gt; to a variable whose lifetime doesn&amp;rsquo;t extend beyond the execution of the method.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These rules ensure the safety of your code and ensure readability, that it is clear about what is happening.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to blatantly steal &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#ref-locals-and-returns&#34;&gt;the Microsoft examples&lt;/a&gt; for this because I don&amp;rsquo;t want to invent an example and get it wrong.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// We declare the method as returning by reference (rather than copy)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Find(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; number, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;[] numbers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &amp;lt; numbers.Length; i++)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (numbers[i] == number)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// All returns must use the `ref` keyword&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; numbers[i]; &lt;span style=&#34;color:#75715e&#34;&gt;// return the storage location, not the value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// We can still throw an exception if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; IndexOutOfRangeException(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;{nameof(number)} not found&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// arrays are already allocated to the heap and passed by reference rather than by value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// (see the `stackalloc` keyword for stack allocating arrays, though)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;[] array = { &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt;, -&lt;span style=&#34;color:#ae81ff&#34;&gt;39&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;14&lt;/span&gt;, -&lt;span style=&#34;color:#ae81ff&#34;&gt;12&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// We have to use `ref` to call the method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// We choose to declare `place` as a reference&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; place = &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; Find(&lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;, array); &lt;span style=&#34;color:#75715e&#34;&gt;// aliases 7&amp;#39;s place in the array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;place = &lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// replaces 7 with 9 in the array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WriteLine(array[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;]); &lt;span style=&#34;color:#75715e&#34;&gt;// prints 9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above example, we could have chosen to declare &lt;code&gt;place&lt;/code&gt; without the &lt;code&gt;ref&lt;/code&gt; keyword and the value returned would be copied instead. However, in this case, the assignment of &lt;code&gt;place = 9;&lt;/code&gt; would be overriding the local copy, and not modifying the original array.&lt;/p&gt;
&lt;p&gt;Why would you use these pass by reference additions? Huge performance enhancements can be achieved by avoiding stack and heap copying or dereferencing of values in certain algorithms. Performance is the name of the game here.&lt;/p&gt;
&lt;p&gt;In C# 7.2, the conditional operator (&lt;code&gt;isTrue ? x : y&lt;/code&gt; syntax) can now evaluate to a reference result when both operands (&lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; above) are also references.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ref var r = ref (arr != null ? ref arr[0] : ref otherArr[0]);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In 7.2 we also got &lt;code&gt;ref readonly&lt;/code&gt;, which allows returned references to disallow modification enforced by the compiler. This may save time constantly dereferencing a child field in a scenario that you need to get the latest value, for instance in a loop. Again, performance is the target use-case.&lt;/p&gt;
&lt;p&gt;The first version of &lt;code&gt;ref&lt;/code&gt; variables was immutable only. Whatever you declared them to point to was what they always referred to for their lifetime. In C# 7.3, they were updated so you can reuse a variable to point to a different reference instead.&lt;/p&gt;
&lt;p&gt;To complement the safety of the &lt;code&gt;out&lt;/code&gt; restrictions compared to &lt;code&gt;ref&lt;/code&gt; we also get the &lt;code&gt;in&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;Declaring a method parameter with &lt;code&gt;in&lt;/code&gt; essentially makes it a read-only reference. the method is not allowed to modify the value passed in but gets all the benefits of being passed by reference rather than by value (copied). The &lt;code&gt;in&lt;/code&gt; keyword will make the compiler ensure that the method is not allowed to modify the original passed in value. If necessary it will create a defensive shadow-copy to ensure that is true.&lt;/p&gt;
&lt;p&gt;This is well paired with another new feature, &lt;code&gt;readonly struct&lt;/code&gt;.  Declaring a struct as read-only means the compiler will ensure you are indeed read-only. (It will disallow &lt;code&gt;public int Foo { get; private set; }&lt;/code&gt; for example.) You can use the &lt;code&gt;in&lt;/code&gt; keyword for any methods that you want to take a ref to one of these structs again to ensure clarity when reading the code, but also enforced by the compiler.&lt;/p&gt;
&lt;p&gt;I mentioned the defensive shadow copy above. The language and runtime do not guarantee that the internal implementation detail of a Property or Method is non-mutable from the contracts, so the compiler will get defensive, and make copies before calling anything that might cause a mutation. This way, the language guarantees the expectations of passing a read-only reference, but maybe doesn&amp;rsquo;t match performance expectations in the process. As a developer, by making the type a &lt;code&gt;readonly struct&lt;/code&gt; instead, the compiler can rely on the guarantees and won&amp;rsquo;t make any copies. The struct won&amp;rsquo;t compile if it mutates any of its internal state, so we have stronger guarantees at compile-time and run-time.&lt;/p&gt;
&lt;p&gt;These features are certainly power features, and when you need them they will be useful. But like most advanced features, you may be sacrificing readability for performance and optimisation. Use sparingly, but maybe measure first and then sprinkle in and measure again.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking Back on C# 7: Out variables</title>
      <link>https://blog.csmac.nz/post/looking-back-on-csharp7-out-variables/</link>
      <pubDate>Mon, 10 Jun 2019 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/looking-back-on-csharp7-out-variables/</guid>
      <description>&lt;p&gt;With C# 8 on our doorstep, I figure it is a good time to reflect on recent additions to the language that have come before. There are some great improvements you may have missed, some that I really enjoy using, and some I consider have reached canonical usage status that I think are all worth some reflection.&lt;/p&gt;
&lt;h3 id=&#34;what-are-out-parameters&#34;&gt;What are out parameters?&lt;/h3&gt;
&lt;p&gt;Sometimes you want a method to pass back a value by reference. In &lt;code&gt;C&lt;/code&gt; and &lt;code&gt;C++&lt;/code&gt; this is done by passing the address in as an argument. In C#, we use the &lt;code&gt;out&lt;/code&gt; keyword.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; HasCount(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; length)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    length = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (str.Length &amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        length = str.Length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; myString = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;A String&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (HasCount(myString, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; length))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Do some stuff here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A method must initialise the out parameter value, but the caller doesn&amp;rsquo;t have to initialise it first. Callers must use the &lt;code&gt;out&lt;/code&gt; keyword when calling a method with an out parameter. This helps with readability making it unambiguous how it works.&lt;/p&gt;
&lt;p&gt;More details of this for those unfamiliar with the concept can be &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier&#34;&gt;found here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the libraries, there are a few methods that use this, for instance &lt;code&gt;Int32.TryParse&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (Int32.TryParse(numberAsString, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; number))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// use `number` as an integer value. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It also comes in useful when you are building C-style interops. But not something you see very much these days.&lt;/p&gt;
&lt;h3 id=&#34;new-out-variables&#34;&gt;New out variables&lt;/h3&gt;
&lt;p&gt;This syntax always felt a bit clunky. Modern APIs would suggest using a return value over an out parameter, and the early use cases tended to be either cross-compatibility with C libraries or parse scenarios. Primarily it was discouraged for readability reasons, though there are benefits from using it in certain places.&lt;/p&gt;
&lt;p&gt;However, with C# 7, a new syntax was introduced, allowing inline declaration of out parameters.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (Int32.TryParse(numberAsString, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; number))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// use `number` as an integer value. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can now declare the parameter inline, without needing the empty declaration line that was essentially wasting line-count. The other benefit is you can now use &lt;code&gt;var&lt;/code&gt; instead of an explicit type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (Int32.TryParse(numberAsString, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; number))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// use `number` as an integer value. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In C# 7.3, this &lt;code&gt;out&lt;/code&gt; variable syntax was extended to include field initializers, property initializers, constructor initializers, and query clauses. Basically, you have the power to use this everywhere that you can use out parameters.&lt;/p&gt;
&lt;p&gt;With the new changes, readability has hugely increased, the risk of using the value before initialisation has been removed, and it is probably something worth encouraging using again in those methods that could benefit with having out parameters for clean APIs, and performance.&lt;/p&gt;
&lt;p&gt;A small but simple improvement to the language that I would replace in every place you use &lt;code&gt;out&lt;/code&gt; parameters.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking Back on C# 7: Local functions</title>
      <link>https://blog.csmac.nz/post/looking-back-on-csharp7-local-functions/</link>
      <pubDate>Mon, 03 Jun 2019 10:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/looking-back-on-csharp7-local-functions/</guid>
      <description>&lt;p&gt;With C# 8 on our doorstep, I figure it is a good time to reflect on recent additions to the language that have come before. There are some great improvements you may have missed, some that I really enjoy using, and some I consider have reached canonical usage status that I think are all worth some reflection.&lt;/p&gt;
&lt;h2 id=&#34;lambdas---a-recap&#34;&gt;Lambdas - a recap&lt;/h2&gt;
&lt;p&gt;All the way back in C# 3 we were given lambdas. These are anonymous functions that can be passed around as what are essentially function pointers.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Anonymous&amp;rdquo; refers to the fact that the function has no name, and is not tied to an actual class or instance. The term comes from functional programming.&lt;/p&gt;
&lt;p&gt;In terms of implementation details, there are two categories of lambdas, those which stand alone and are pure functions, and those that have a captured scope, known as a closure. Closure, again, is a functional programming term. We capture variables from the scope of the parent and encapsulate them into this anonymous function instance.&lt;/p&gt;
&lt;p&gt;Pure functions can easily be refactored into a public static function in a static class very easily, and the compilation is very similar.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Action&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; GetRandomValueFunction()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Use static value for counter: {0}&amp;#34;&lt;/span&gt;, counter);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; () =&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// These two methods are the same as the above&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Action&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; GetRandomValueFunction()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Use static value for counter: {0}&amp;#34;&lt;/span&gt;, counter);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; StaticValueFunction;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; StaticValueFunction()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is no simple construct equivalent for closures. Hopefully, by example, we can see how these transform into simple static methods anyway. (In an example stolen from &lt;a href=&#34;https://stackoverflow.com/a/5438331/2118268&#34;&gt;SO&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Action CreateShowAndIncrementAction()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Random rng = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Random();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; counter = rng.Next(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Initial value for counter: {0}&amp;#34;&lt;/span&gt;, counter);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; () =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Console.WriteLine(counter);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        counter++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Given the above C# code, the compiled code will more closely resemble the below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Action CreateShowAndIncrementAction()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ActionHelper helper = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ActionHelper();        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Random rng = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Random();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    helper.counter = rng.Next(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Initial value for counter: {0}&amp;#34;&lt;/span&gt;, helper.counter);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; helper.DoAction;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ActionHelper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; counter;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; DoAction()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Console.WriteLine(counter);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        counter++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because the compiler generates these, it also controls access and visibility, so that you cannot actually access it in this way from your code directly. But it does all this automatically for you, and with fewer lines of code to achieve the same logical execution. It is also clearer from the lambda version that the calling method is the owner of the function, and no one else can or should share it.&lt;/p&gt;
&lt;p&gt;Clearly, lambdas reduce our lines of code and are superior.&lt;/p&gt;
&lt;h2 id=&#34;working-with-lambdas&#34;&gt;working with lambdas&lt;/h2&gt;
&lt;p&gt;Sometimes, though, your lambdas get complicated. When you have big complicated lambdas inside LINQ pipelines, it gets messy fast.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; List&amp;lt;Widget&amp;gt; GetWidgetsByPlumbob(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; plumb, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; restrictionNumber)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; restriction =  _store.GetRestriction(restrictionNumber);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// This `where` clause is only going to get more complicated from here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .GetWidgets()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Where(w =&amp;gt; (w.PlumbBob.StartsWith(plumbob) || w.PlumbBob.EndsWith(plumbob)) &amp;amp;&amp;amp; w.Restriction == restriction)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Select(Map)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .ToList();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have a few options prior to C# 7:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; List&amp;lt;Widget&amp;gt; GetWidgetsByPlumbob(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; plumb, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; restrictionNumber)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; restriction =  _store.GetRestriction(restrictionNumber);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .GetWidgets()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Where(w =&amp;gt; Filter(w, plumb, restriction))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Select(Map)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .ToList();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; Filter(Widget widget, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; plumb, Restriction restriction)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (w.PlumbBob.StartsWith(plumbob) || w.PlumbBob.EndsWith(plumbob)) &amp;amp;&amp;amp; w.Restriction &amp;gt; restriction;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are a couple of problems with this. We are now passing all the parameters through to the nested function. This is fine, but from a maintenance point of view, we might add more parameters and we now end up maintaining two signatures every time we change.&lt;/p&gt;
&lt;p&gt;Also, we open up for another function to start using the &amp;ldquo;sharable&amp;rdquo; filter function. Now we would be coupled to that new function. We can&amp;rsquo;t change our own filter without affecting that other new function, and that adds brittle fragility. Sometimes duplicating logic that has different reasons to change is worth the duplication, but the architecture of this code does not guard against this.&lt;/p&gt;
&lt;p&gt;Another example is to pull the lambda into a variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; List&amp;lt;Widget&amp;gt; GetWidgetsByPlumbob(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; plumb, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; restrictionNumber)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; restriction =  _store.GetRestriction(restrictionNumber);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; filter = w =&amp;gt; (w.PlumbBob.StartsWith(plumbob) || w.PlumbBob.EndsWith(plumbob)) &amp;amp;&amp;amp; w.Restriction == restriction);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .GetWidgets()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Where(filter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Select(Map)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .ToList();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking at the example, it adds some simplification. Because like the original example this lambda is a closure, the lambda can match the expected signature of the &lt;code&gt;Where&lt;/code&gt; LINQ Extension.&lt;/p&gt;
&lt;p&gt;However, sometimes this approach causes issues with type interpolation. That is, if you pull out into a variable, often you can&amp;rsquo;t use &lt;code&gt;var&lt;/code&gt; or need to add explicit type casting to help the compiler out, or it will not compile.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think we have actually helped with the readability as much as we would like. It may not be obvious on the first pass of reading the function that this is a lambda, not a statement. This is also a simple example, and they can get more complex fast.&lt;/p&gt;
&lt;h2 id=&#34;put-functions-inside-your-functions&#34;&gt;Put functions inside your functions!&lt;/h2&gt;
&lt;p&gt;With C# 7, we can now use a nested function. This gives us the benefits of not polluting the namespace of the class, while also making it more readable. It also makes it clearer that the function is owned by the caller as the only consumer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; List&amp;lt;Widget&amp;gt; GetWidgetsByPlumbob(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; plumb, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; restrictionNumber)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; restriction =  _store.GetRestriction(restrictionNumber);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; Filter(Widget widget)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (w.PlumbBob.StartsWith(plumb) || w.PlumbBob.EndsWith(plumb)) &amp;amp;&amp;amp; w.Restriction &amp;gt; restriction;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _store
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .GetWidgets()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Where(Filter)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Select(Map)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .ToList();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our compiler now ensures no one else can use this function. It is only callable from this method and gives the reader the knowledge that this is a specific implementation detail for this function only and not a shared common piece of logic. (Encapsulation.)&lt;/p&gt;
&lt;p&gt;In this example it also still allows us to use the simplified &lt;code&gt;Where&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;The best example of where this is really useful is recursion.&lt;/p&gt;
&lt;p&gt;Often a recursive algorithm has a bootstrap function, that then calls the recursive part. Let&amp;rsquo;s print a tree of items with indentations.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; PrintLines(TextWriter &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;, Tree items)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;.WriteLine(items.Title);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; node &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; items.Children)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Print(&lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;, node, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Print(TextWriter &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;, TreeNode node, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; indent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{0}{1}&amp;#34;&lt;/span&gt;, indent, items.Title);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(node.HasChildren)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; node &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; items.Children)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Print(&lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;, node indent + &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;    &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For simplicity you can now write this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cs&#34; data-lang=&#34;cs&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; PrintLines(TextWriter &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;, Tree items)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Print(TreeNode node, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; indent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{0}{1}&amp;#34;&lt;/span&gt;, indent, items.Title);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(node.HasChildren)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; node &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; items.Children)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Print(&lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;, node indent + &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;    &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;.WriteLine(items.Title);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; node &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; items.Children)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Print(node, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example may not reduce lines of code by much, but the cognitive load of the encapsulation can be hugely beneficial when in a class with more service methods as well.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;The cliché &amp;ldquo;another tool in the toolbelt&amp;rdquo; comes to mind but this is certainly that, and sprinkled through code strategically can really help with readability and maintainability. Not a &amp;ldquo;use often&amp;rdquo; but certainly something I can and have used in my dotnet apps.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>