<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Stephen Walsh</title>
    <description>The latest articles on Forem by Stephen Walsh (@stphnwlsh).</description>
    <link>https://forem.com/stphnwlsh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F165299%2F75a73cd6-b05d-4e54-a439-cff2bda9873c.png</url>
      <title>Forem: Stephen Walsh</title>
      <link>https://forem.com/stphnwlsh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stphnwlsh"/>
    <language>en</language>
    <item>
      <title>Full Stack Engineers Don't Exist!</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Fri, 03 Nov 2023 16:27:32 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/full-stack-engineers-dont-exist-1ap6</link>
      <guid>https://forem.com/stphnwlsh/full-stack-engineers-dont-exist-1ap6</guid>
      <description>&lt;p&gt;There's a problem with those thousands of jobs available for Full Stack Engineers or Developers on LinkedIn, like a unicorn, that person isn't real. Insert spit-take, read it, then tell me what you think.&lt;/p&gt;




&lt;p&gt;There I said it, you might think this is a controversial or unpopular opinion but if you hear me out maybe you'll agree with me, maybe not, but that's what makes life worth living. I've believed this for a long time now, but it's time to put a little more thought and time to flesh it out. &lt;/p&gt;

&lt;p&gt;As for the term Developer or Engineer, yes technically they have different scopes but they mostly cover the same disciplines and principles, so I'll use them interchangeably from here on out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Defining a Full Stack Developer
&lt;/h2&gt;

&lt;p&gt;To say something doesn't exist, I should probably first define what people think it is. So Looking across the internet to &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A full-stack developer is a developer or engineer who can build both the front end and the back end of a website. The front end (the parts of a website a user sees and interacts with) and the back end (the behind-the-scenes data storage and processing) require different skill sets. Since full-stack developers are involved with all aspects of the development process, they must have expertise in both.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Coursera - What Is a Full-Stack Developer?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A full-stack developer can be defined as a developer or an engineer who works with both the front and back end development of a website, web application or desktop application. This means they can lead platform builds that involve databases, user-facing websites, and working with clients during the planning phase of projects.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Wikipedia - Solution Stack - Full Stack Developer&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sounds reasonable, which has led to the rise of this term to become part of engineering culture. This may have been reasonable but the world isn't run by the LAMP stack anymore, the role of a software engineer isn't as simple as it once was.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demands on the Modern-Day Software Engineer
&lt;/h2&gt;

&lt;p&gt;Being an engineer isn't as simple as writing code anymore. The definitions above hint at it but the expectations of what an engineer is capable of has grown exponentially over the last few years. Every day is different, and every workplace is different, but the point remains that software engineering is a much larger beast than it once was.&lt;/p&gt;

&lt;p&gt;Not even covering all bases, the engineer finds themselves; defining work, estimating work, writing test cases, writing unit or integration or e2e tests, creating or coding build and/or  deployment pipelines, defining metrics for monitoring, analyzing application logs, bug fixing, designing solution or system architecture, creating infrastructure as code and commiting, merging and rebasing code. Notice I didn't even mention the actual work of writing the code to deliver features. Now cover those bases across data storage, backend systems, and frontend applications.&lt;/p&gt;

&lt;p&gt;Maybe a "developer" doesn't get as full a scope as the "engineer" but it's pretty similar. The point here is the expectations of engineers and developers are wide-ranging and the expectation for one to be an expert or senior across all of those disciplines is unrealistic at best.&lt;/p&gt;




&lt;h2&gt;
  
  
  Keeping Up is Hard
&lt;/h2&gt;

&lt;p&gt;Taking all these disciplines into account, now think about how on earth you stay current and/or skilled in all of them at the same time. The idea of "Full Stack" is that you ask skilled or highly skilled across the scope of your role. &lt;br&gt;
The overload of information and constant change make this impossible.&lt;/p&gt;

&lt;p&gt;From Udemy to YouTube, to documentation, to official training courses and certifications, staying up to date with what you currently know is hard enough. Now add library releases and updates, new technology, and new products into that mix. To stay current, will become a full-time job without doing any delivery work at all.&lt;/p&gt;

&lt;p&gt;If you do web development with JavaScript, I could stop here you know the pain. How many different libraries, frameworks, and build tools have you learned over the last few years…I'll wait…it's a long list.&lt;/p&gt;




&lt;h2&gt;
  
  
  Think Differently About Engineers
&lt;/h2&gt;

&lt;p&gt;Now obviously I'm not saying that people can't have a lot of skills at one time. It's more that the expectation that someone should be equally skilled across an ever-expanding set of disciplines is challenging and unrealistic.&lt;br&gt;
A better expectation is to become/hire/build a team of T-Shaped engineers, but even T-Shaped is a rough definition to hold to.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A T-shaped software engineer is a developer who specializes in one area, but also has a broad range of skills in other areas. The term "T-shaped" is used as a metaphor for an individual's strengths. The vertical line of the T represents expertise in a particular field, while the horizontal line represents cross-discipline competencies.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Building a shallow but broad range of skills is difficult too.&lt;/p&gt;

&lt;p&gt;I like to think of Pii Shaped Engineers, learning multiple skills is a must! Becoming an expert/senior at more than one is very beneficial too, but the journey (much like Pii) is never-ending. They might not know everything but they like to learn.&lt;/p&gt;




&lt;h2&gt;
  
  
  Curious Engineers are the New Black
&lt;/h2&gt;

&lt;p&gt;I interview engineers all the time, The thing I look for is a broader set of knowledge regardless of depth, but the trait underlying is curiosity.&lt;/p&gt;

&lt;p&gt;The best engineers love solving problems, but they are curious about the best way to solve them. They continue to learn better techniques, and newer technologies and constantly seek to improve. The top engineers can communicate well enough to explain what they are capable of learning and where they are lacking. Humility helps a lot.&lt;/p&gt;

&lt;p&gt;When hiring terms like Full Stack and even T-Shaped can be handcuffs. They get you something but it's not always what you need. As an engineer, it's a nice label but it's impossible to live up to.&lt;/p&gt;

&lt;p&gt;Forget a specific set of skills, if you become a curious engineer who can do few things but is always keen to learn, you will figure out the rest.&lt;/p&gt;




&lt;p&gt;Given all this, the actual percentage of real Full Stack Engineers has to be continually approaching zero. Don't get me wrong, there are unicorns out there but there aren't many, if any. When I read some job descriptions, I think this hope that an engineer will be able to live up to the full list of wants and needs is a bit misguided.&lt;/p&gt;

&lt;p&gt;The world of Applicant Tracking Systems makes it difficult for prospective employees to exist beyond the buzzwords, but maybe those who are hiring should look beyond the list of skills and look for that very useful personality trait, Curiosity.&lt;/p&gt;




&lt;p&gt;A bold and possibly unpopular opinion but let me know what you think.&lt;/p&gt;

</description>
      <category>developer</category>
      <category>interview</category>
      <category>softwareengineering</category>
      <category>learning</category>
    </item>
    <item>
      <title>A Cleaner Startup for .NET 6's Minimal Approach</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Wed, 29 Jun 2022 07:12:25 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/a-cleaner-startup-for-net-6s-minimal-approach-36pg</link>
      <guid>https://forem.com/stphnwlsh/a-cleaner-startup-for-net-6s-minimal-approach-36pg</guid>
      <description>&lt;p&gt;After reading the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60?view=aspnetcore-6.0&amp;amp;tabs=visual-studio"&gt;.NET Migration Documentation&lt;/a&gt; in the past week, I have formulated an alternative to the suggested methods from Microsoft. To be honest, I created this approach last year and recently refined it, to make it ready to share with others.&lt;/p&gt;

&lt;p&gt;The starting point was finding some posts about using the &lt;code&gt;Startup.cs&lt;/code&gt; file in the new .NET 6 minimal hosting model. I know I'm not alone in finding Microsoft's format more annoying than anything. With Microsoft removing the &lt;code&gt;Startup.cs&lt;/code&gt; file as the default, this lead me to assume they were proposing that &lt;code&gt;Program.cs&lt;/code&gt; would be a heavy and long mess. In reading the posts and Microsoft's documentation I've come to realise that they have a suggested implementation. Problem is I think the implementation is a little messy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Microsoft's Solution
&lt;/h2&gt;

&lt;p&gt;As I read through their documentation I found that...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Apps migrating to 6.0 don't need to use the new minimal hosting model&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was a surprise because I thought they'd killed the &lt;code&gt;Startup.cs&lt;/code&gt;file and it's a problem because I found that this eats away at their minimal model. The approach causes a few extra lines to be inserted into &lt;code&gt;Program.cs&lt;/code&gt; to handle all the service and middleware configuration. It creates a new format &lt;code&gt;Startup.cs&lt;/code&gt; file, that consists of two methods and an injected set of Configuration, easy enough and does the job.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Combined with the following &lt;code&gt;Startup.cs&lt;/code&gt; class&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Alternative Solution
&lt;/h2&gt;

&lt;p&gt;The above code works just fine, it's maybe a little clunky looking but it does the job. The alternative approach that I made is just a simple use of extension methods. Nothing world changing but I have found it to be a leaner and cleaner look. The extension methods pass in the &lt;code&gt;WebApplicationBuilder&lt;/code&gt; and the &lt;code&gt;WebApplication&lt;/code&gt; objects. &lt;code&gt;WebApplication&lt;/code&gt; has access to the Environment configuration and both have access to the &lt;code&gt;IConfiguraiton&lt;/code&gt; as well. This keeps the spirit of the old &lt;code&gt;Startup.cs&lt;/code&gt; just like Microsoft's method but I've found it keeps the &lt;code&gt;Program.cs&lt;/code&gt; clean and clear as well.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Combined with the following ProgramExtensions.cs class&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;p&gt;This method is not going to change your life but I have found value in it. A little pedantic, yeah probably but I enjoy the simplicity those extension methods offer. If they blow out in size, it's possible to break them into separate files for each method. If any configuration gets even larger and more important, it's possible to make &lt;code&gt;ConfigureApplication&lt;/code&gt; and a &lt;code&gt;ConfigureExceptionHandling&lt;/code&gt; methods. The possibilities are endless with that pattern.&lt;/p&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, or want to checkout my other work, please connect with me on &lt;a href="https://www.linkedin.com/in/stphnwlsh"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/stphnwlsh"&gt;Twitter&lt;/a&gt; or &lt;a href="https://github.com/stphnwlsh"&gt;GitHub&lt;/a&gt;, and consider supporting me at [Buy Me a Coffee]&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What's your default .editorconfig?</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Mon, 27 Jun 2022 03:37:19 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/whats-your-default-editorconfig-199i</link>
      <guid>https://forem.com/stphnwlsh/whats-your-default-editorconfig-199i</guid>
      <description>&lt;p&gt;I've been using EditorConfig to bring consistency to the way that I write my code.  I also find it's been helpful to standardise the way teams I work on deliver with a similar style.  It takes a little while to find settings that work for everyone, but I'm wanting to learn from others what their default configurations are and why you chose them.&lt;/p&gt;




&lt;p&gt;If you're wondering what &lt;a href="https://editorconfig.org/"&gt;EditorConfig&lt;/a&gt; is this is taken straight from their website.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  What is EditorConfig?
&lt;/h3&gt;

&lt;p&gt;EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What I Use
&lt;/h2&gt;

&lt;p&gt;I've been using &lt;a href="https://github.com/RehanSaeed"&gt;RehanSaeed's&lt;/a&gt; &lt;a href="https://github.com/RehanSaeed/EditorConfig"&gt;EditorConfig&lt;/a&gt; project on GitHub, which is pretty great.  I have &lt;a href="https://github.com/stphnwlsh/EditorConfig"&gt;forked&lt;/a&gt; it and made some minor customisations that work for me. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Extensive code style settings for C# and VB.NET have been defined that require the latest C# features to be used. All C# related code styles are consistent with &lt;a href="https://github.com/DotNetAnalyzers/StyleCopAnalyzers"&gt;StyleCop's&lt;/a&gt; default styles, with the exception of the file header definition, which has been changed to a more modern format. All .NET naming conventions are consistent with the .NET Framework Design Guideline's &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines"&gt;Naming Guidelines&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Would love to see what others have as a default.  Please share your versions or repo links in the comments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options?view=vs-2022"&gt;.NET Fundamentals - Code-style rule options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/help/idea/editorconfig.html"&gt;JetBrains - EditorConfig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/editorconfig"&gt;DevHints - editorconfig cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://michaelcurrin.github.io/code-cookbook/recipes/other/editor-config.html"&gt;Michael Currin - Code Cookbook - EditorConfig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://editorconfig-specification.readthedocs.io/"&gt;EditorConfig Specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>tooling</category>
      <category>discuss</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Benchmarking to the Bottom — Iterating Arrays in .NET</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Tue, 21 Jun 2022 08:36:22 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/benchmarking-to-the-bottom-iterating-arrays-in-net-54fl</link>
      <guid>https://forem.com/stphnwlsh/benchmarking-to-the-bottom-iterating-arrays-in-net-54fl</guid>
      <description>&lt;p&gt;Finding the fastest way to iterate arrays while accessing their value in .NET using &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; validate performance at scale.&lt;/p&gt;




&lt;p&gt;I have spent some time recently looking through an older system, wondering how I can make it perform better. There are many avenues to make a system like this faster and more performant, but I wanted to avoid large scale refactoring to keep the risk to a minimum. Specifically I have focused on small items that can add up to make a bigger difference overall. The most obvious is a whole system upgrade but when that’s not an option, these small changes might be all an engineer has to make a difference.&lt;/p&gt;

&lt;p&gt;Doing this work has peaked my interest as to which is the best way of doing these every day small tasks in the first place. I’m slowly building out a small series of tasks. It might be consuming different libraries to complete a task vs the native features, or it might straight up comparisons of every day tasks. Either way lessons will be learned and fun will be had.&lt;/p&gt;




&lt;h2&gt;
  
  
  Iterating and Accessing Arrays
&lt;/h2&gt;

&lt;p&gt;Today I decided to look at many different ways that you can iterate over an &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Fprogramming-guide%2Farrays%2F"&gt;Array&lt;/a&gt;. It's not complicated in any way but given that software engineers are constantly using both lists and arrays in C#, there is value in addressing them as well.&lt;br&gt;
 &lt;br&gt;
Key to the outcome is actually assigning the item from the array to a variable. This will ensure that the value is being read, purely iterating without accessing the item could lead to skewed results.&lt;/p&gt;

&lt;p&gt;Below are the methods being used and tested via &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/iteration-statements#the-for-statement"&gt;For&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/iteration-statements#the-foreach-statement"&gt;ForEach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.array.foreach?view=net-6.0"&gt;Array ForEach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1.getenumerator?view=net-6.0"&gt;GetEnumerator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=net-6.0"&gt;Span For&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=net-6.0"&gt;Span ForEach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Theory
&lt;/h2&gt;

&lt;p&gt;Given the similarity to the &lt;a href="https://dev.to/stphnwlsh/benchmarking-your-way-to-the-bottom-iterating-lists-1li5"&gt;previous test&lt;/a&gt; I would imagine that the &lt;code&gt;Span&lt;/code&gt; methods are going to be our clear winner here. With no LINQ methods to pick on I'll choose the &lt;code&gt;GetEnumerator&lt;/code&gt; method to be the worst performing out of them all. I anticipate that the &lt;code&gt;for&lt;/code&gt; loop will be fairly close to the &lt;code&gt;Span&lt;/code&gt; and &lt;code&gt;foreach&lt;/code&gt; will be a little further back.&lt;/p&gt;


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

&lt;p&gt;Using &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; to create a console application makes running this benchmarking test very simple. To ensure older systems are being covered these tests will be run in both &lt;strong&gt;.NET Framework 4.8&lt;/strong&gt; and &lt;strong&gt;.NET 6.0&lt;/strong&gt; as these are the current Long Term Support versions of .NET. One for the older world and one for the new world.&lt;/p&gt;

&lt;p&gt;The premise is simple. Create a &lt;code&gt;Array&lt;/code&gt; of strings 100 and 10,000 deep. Then run the test to iterate through each item and do this on repeat until &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; is happy to give us a result. This should give us a reasonable assumption of the fastest way to do this going forwards.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;

&lt;p&gt;Next up is creating a method for each type of &lt;code&gt;Array&lt;/code&gt; iteration that I want to test. Each method does one thing to make it an even benchmark. Each method will iterate through each item in the &lt;code&gt;Array&lt;/code&gt;, access the item in the list and assign it to a variable. Once the all the items have been process it will finish and record the time taken to complete the task.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Thankfully for us, &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; includes a Rank column to make it clear which run of tests is the winner. As you read these results you can use the Mean column to compare the difference in runtime between each test. For some of these there is a clear winner and others the difference is negligible.&lt;/p&gt;

&lt;h3&gt;
  
  
  .NET Framework 4.8
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;ForEachLoop&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;305.9 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ForLoop&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;343.9 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ArrayForEach&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;451.1 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;10,561.3 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;ForEachLoop&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;30,064.2 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ForLoop&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;33,541.9 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ArrayForEach&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;43,825.3 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;1,055,741.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  .NET 6.0
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;SpanForEach&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;141.9 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ForLoop&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;173.6 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ForEachLoop&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;175.2 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;SpanFor&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;175.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ArrayForEach&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;370.7 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;6,190.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;SpanForEach&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;12,333.7 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ForLoop&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;16,181.6 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;SpanFor&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;16,187.0 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ForEachLoop&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;16,251.8 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ArrayForEach&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;36,155.1 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;611,853.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Results are formatted for clean and clear display, for the full output you peruse the output of the &lt;a href="https://github.com/stphnwlsh/Benchmarking/actions"&gt;actions on GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  .NET Framework 4.8
&lt;/h3&gt;

&lt;p&gt;Well quite honestly this is quite the surprise, from the test results &lt;code&gt;foreach&lt;/code&gt; is the clear winner.  Given it's terrible performance on a &lt;code&gt;List&lt;/code&gt;, I really didn't see this coming.  It's faster at iterating the larger and smaller array than the &lt;code&gt;for&lt;/code&gt; loop.  Arrays have a new champion.  As expected GetEnumerator is the worst performer by absolute leaps and bounds.  The outcome here is clear though, time to refactor your code if you're &lt;code&gt;Array.Foreach&lt;/code&gt; in favour of &lt;code&gt;foreach&lt;/code&gt;.  You could take it or leave it with the &lt;code&gt;for&lt;/code&gt; loops as the difference is not massive.&lt;/p&gt;

&lt;h3&gt;
  
  
  .NET 6.0
&lt;/h3&gt;

&lt;p&gt;It's a familiar story for .NET 6.0 the &lt;code&gt;Span&lt;/code&gt; &lt;code&gt;foreach&lt;/code&gt; methods taking home the prize.  It's closely followed by &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;foreach&lt;/code&gt; and &lt;code&gt;Span&lt;/code&gt; &lt;code&gt;for&lt;/code&gt; which would lead me to say that it's not worth a major refactoring effort here.  There's only minor gains to be made, but any new code should use a &lt;code&gt;Span&lt;/code&gt; combined with a &lt;code&gt;foreach&lt;/code&gt;. &lt;code&gt;Array.ForEach&lt;/code&gt; is well behind here to and totally worth the refactor.  &lt;code&gt;GetEnumerator&lt;/code&gt; has been put down enough, it's just not worth your time. &lt;/p&gt;

&lt;h3&gt;
  
  
  ForEach FTW
&lt;/h3&gt;

&lt;p&gt;While not life changing in some areas the &lt;code&gt;foreach&lt;/code&gt; loop is the clear winner and should be implemented as the iterator of choice for &lt;strong&gt;.NET 6.0&lt;/strong&gt; and &lt;strong&gt;.NET Framework 4.8&lt;/strong&gt; applications.  Just remember with .NET 6.0 to make it a &lt;code&gt;Span&lt;/code&gt; as well. &lt;/p&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;All of this code is open sourced. You can find my benchmarking work on &lt;a href="https://github.com/stphnwlsh/Benchmarking"&gt;GitHub&lt;/a&gt;. The results are the output of a GitHub Action to run the benchmark tests, you should be able to find detailed output on that repository.&lt;/p&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, or want to checkout my other work, please connect with me on &lt;a href="https://www.linkedin.com/in/stphnwlsh"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/stphnwlsh"&gt;Twitter&lt;/a&gt; or &lt;a href="https://github.com/stphnwlsh"&gt;GitHub&lt;/a&gt;, and consider supporting me at &lt;a href="https://www.buymeacoffee.com/stphnwlsh"&gt;Buy Me a Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/stphnwlsh"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L5xQ8oDJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-1.svg" alt='"Buy Me A Coffee"' width="260" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>performance</category>
      <category>programming</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Making Software Engineering Interviews more Creative and Interesting</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Thu, 16 Jun 2022 04:21:11 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/making-software-engineering-interviews-more-creative-and-interesting-23ac</link>
      <guid>https://forem.com/stphnwlsh/making-software-engineering-interviews-more-creative-and-interesting-23ac</guid>
      <description>&lt;p&gt;If you're looking to grow through the ranks in your career as a software engineer, you're only going to take on more responsibility over time.  One consistent thing that happens for everyone is that you start to interview other software engineers.&lt;/p&gt;

&lt;p&gt;This can be daunting at first, and then easier over time as you gain skills in the area.  You might even find yourself in the position where you are helping other new interviewers learn how to interview people.&lt;/p&gt;

&lt;p&gt;Over time you will look for tips and tricks on how you can give people a great interview experience. That's why I've put a few tips together and am sharing a challenge that I have been using in my interviews lately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interviewer Tips
&lt;/h2&gt;

&lt;p&gt;I've run a fair few interviews now and these are my general interviewer principles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't Be a Dick&lt;/strong&gt; - Treat people with compassion and kindness, it's hard to put yourself out there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listen to the interviewee&lt;/strong&gt; - Don't judge on buzzwords, hear what they have to say, even if it's not what you're expecting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Ready to Pivot&lt;/strong&gt; - Following the same interview structure for everyone doesn't work because no two people are the same.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;One way I've tried to be &lt;strong&gt;creative&lt;/strong&gt; with the interview process lately is by developing an exercise that I can run with any Software Engineer on any level.  It's a &lt;strong&gt;simple structure&lt;/strong&gt; but it's open to creativity and &lt;strong&gt;change&lt;/strong&gt;, it's helped me feel like I understand the person on the other side of the table/camera better than when using just direct questions.&lt;/p&gt;

&lt;p&gt;It starts with a simple premise and then I ask a progressive set of questions.  At the end of the interview, I will have discussed a different set of technologies and approaches with each person.  I ask the same six questions each time but dive in different directions for a few deeper questions based on their answers.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Two notes about this process&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I'm not expecting the same thing from a junior as I am from a senior.  When I use this approach, I attempt to draw what knowledge the person being interviewed has in each area, but I'm looking to understand what they have learned through their experience.&lt;/li&gt;
&lt;li&gt;Let the person being interviewed know that you might take some notes for follow-up questions.  It can be off-putting if the interviewer is always looking away and you aren't sure what they're doing.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;It starts with a greenfield project.  Make it a website, an app, whatever you choose.  Make it a store, make it a service, and keep it open to keep the interviews different, but keep it simple and similar to keep your interviews fair.  All I say is we want data storage, a backend and a frontend involved.  That's where the fun begins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2Atj1NQofgnwDXPx-v" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F0%2Atj1NQofgnwDXPx-v" alt="Photo by Stanley Dai on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  What's your dream stack for this system?
&lt;/h3&gt;

&lt;p&gt;Start with what technology they know or desire to learn.  Let them know that they can choose anything, no wrong answer.  Some people choose tech because it solves a specific problem, others because of what they know, and some because they want to learn it.  Some people want to talk about infrastructure too, let them.  There's more room for that later but no harm bringing it up early.  All I'm looking for here is reasoning, why are you choosing that stack?  Tells you a lot about how people think.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Now that you have some features, how do you validate that it works?
&lt;/h3&gt;

&lt;p&gt;This question is all about testing.  There's a fair amount you can learn about an engineer and team fit in knowing their attitude and approach to testing their code.  &lt;a href="https://www.atlassian.com/continuous-delivery/software-testing/types-of-software-testing" rel="noopener noreferrer"&gt;Automated or manual&lt;/a&gt;, and why?  What layers of testing might you include, unit, integration and/or E2E?  Dig deeper and ask about code coverage, see how they value that metric.&lt;/p&gt;

&lt;h3&gt;
  
  
  You have more people join your team, how do you all work together on the same codebase?
&lt;/h3&gt;

&lt;p&gt;How does this person work in a team?  Do they like &lt;a href="https://www.pagerduty.com/resources/learn/what-is-a-pull-request" rel="noopener noreferrer"&gt;Pull Requests&lt;/a&gt;?  How about &lt;a href="https://smartbear.com/learn/code-review/what-is-code-review" rel="noopener noreferrer"&gt;Code Reviews&lt;/a&gt;?  &lt;a href="https://martinfowler.com/articles/on-pair-programming.html" rel="noopener noreferrer"&gt;Pair Programming&lt;/a&gt;?  How are they used to working with others....and source control?  You can dig into Agile experience and maturity here too, Stand-ups, Sprint Reviews and more. This is a moment to understand how people value teamwork, and learning from others, and whether they are willing to serve others.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's time to show your work to project stakeholders and your customers, how do you make your system available?
&lt;/h3&gt;

&lt;p&gt;Now we're onto (insert buzzword here) &lt;a href="https://www.atlassian.com/devops" rel="noopener noreferrer"&gt;DevOps&lt;/a&gt; and Infrastructure.  Experience with and approach to building and releasing software.  Do you have &lt;a href="https://docs.gitlab.com/ee/ci/pipelines" rel="noopener noreferrer"&gt;build pipelines&lt;/a&gt;, when do you run them?  What environments make sense to serve all people involved in a project.  How do you release the software?  What do you host it on or in?  &lt;a href="https://aws.amazon.com" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;, &lt;a href="https://azure.microsoft.com" rel="noopener noreferrer"&gt;Azure&lt;/a&gt;, &lt;a href="https://cloud.google.com" rel="noopener noreferrer"&gt;GCP&lt;/a&gt; or something else?  These aspects of projects people work on can quite often bring a great deal of frustration.  How does this person handle that?  How do they express it when telling you about it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Something is wrong, how can you get more information about what is happening?
&lt;/h3&gt;

&lt;p&gt;Oh boy it's time to problem solve.  How does this person approach solving a bug?  Who do they &lt;strong&gt;talk&lt;/strong&gt; to?  What systems do they use in partnership with their software to help them?  Do they use &lt;strong&gt;application logging&lt;/strong&gt;?  Where do they store their logs?  How do they track their progress on a bug?  What proactive steps would they take to stay ahead of future bugs?&lt;/p&gt;

&lt;p&gt;There are a lot of questions and avenues to go down here, don't dwell forever but depending on the role, this time could really help you know if you would want to work with this person.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customer demand is growing, how can you make sure your software is up to the challenge?
&lt;/h3&gt;

&lt;p&gt;Finally, how would this person handle the need to scale their system.  How would they approach making sure their system was resilient?  Would they rely on cloud native features?  Would they configure automated, timed, or manual scaling?  Would this consideration change their infrastructure choices?  This section is tough because it's hard to do hypothetically.  Again, how does this person respond when given a problem?&lt;/p&gt;




&lt;h3&gt;
  
  
  More Questions
&lt;/h3&gt;

&lt;p&gt;These questions allow you to dig deeper and find more things to talk about.  I have no intention of leaving it there at the end of these six.  Now I have notes and things I have learned about them to dig a little deeper on and help me make my decision.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'm listening and looking for?
&lt;/h2&gt;

&lt;p&gt;I use this process to get a better sense of a person, than asking directly about their experience with a specific technology.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What they know and have experienced&lt;/li&gt;
&lt;li&gt;How they explain what these to me&lt;/li&gt;
&lt;li&gt;The details they include and leave out&lt;/li&gt;
&lt;li&gt;When I don't understand, how they teach me&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interviewing can be tough, but I've found this challenge and the tips above have allowed me to get people to open up a little and help me understand them.  As a person and as a software engineer.  I hope it helps you too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, checkout my other examples on &lt;a href="https://github.com/stphnwlsh" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and consider supporting me at &lt;a href="https://www.buymeacoffee.com/stphnwlsh" rel="noopener noreferrer"&gt;Buy Me a Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/stphnwlsh" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.buymeacoffee.com%2Fassets%2Fimg%2Fguidelines%2Fdownload-assets-sm-1.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>interviewing</category>
      <category>interviewer</category>
      <category>career</category>
      <category>challenge</category>
    </item>
    <item>
      <title>Benchmarking to the Bottom - Iterating Lists in .NET</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Thu, 10 Mar 2022 12:06:54 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/benchmarking-your-way-to-the-bottom-iterating-lists-1li5</link>
      <guid>https://forem.com/stphnwlsh/benchmarking-your-way-to-the-bottom-iterating-lists-1li5</guid>
      <description>&lt;p&gt;Finding the fastest way to iterate lists while accessing their value in .NET using &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; validate performance at scale.&lt;/p&gt;




&lt;p&gt;I have spent some time recently looking through an older system, wondering how I can make it perform better. There are many avenues to make a system like this faster and more performant, but I wanted to avoid large scale refactoring to keep the risk to a minimum. Specifically I have focused on small items that can add up to make a bigger difference overall. The most obvious is a whole system upgrade but when that’s not an option, these small changes might be all an engineer has to make a difference.&lt;/p&gt;

&lt;p&gt;Doing this work has peaked my interest as to which is the best way of doing these every day small tasks in the first place. I’m slowly building out a small series of tasks. It might be consuming different libraries to complete a task vs the native features, or it might straight up comparisons of every day tasks. Either way lessons will be learned and fun will be had.&lt;/p&gt;




&lt;h2&gt;
  
  
  Iterating and Accessing Lists
&lt;/h2&gt;

&lt;p&gt;Today I decided to look at many different ways that you can iterate over a &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.generic.list-1"&gt;list&lt;/a&gt;. The application I have been working on has many instances of long lists that are iterated for various reasons. It made me wonder what’s the fastest way to work through all the items in a &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.generic.list-1"&gt;list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On my initial run through, I neglected to assign the items being iterated to a variable. Purely iterating the &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.generic.list-1"&gt;list&lt;/a&gt; without accessing the item lead to skewed results. &lt;strong&gt;Both sets of results&lt;/strong&gt; will be listed in the outcomes.&lt;/p&gt;

&lt;p&gt;Below are the methods being used and tested via &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/iteration-statements#the-for-statement"&gt;For&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/iteration-statements#the-foreach-statement"&gt;ForEach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.foreach?view=net-6.0"&gt;LINQ ForEach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1.getenumerator?view=net-6.0"&gt;GetEnumerator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=net-6.0"&gt;Span For&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=net-6.0"&gt;Span ForEach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Theory
&lt;/h2&gt;

&lt;p&gt;I have read lately about how the &lt;code&gt;for&lt;/code&gt; loop is actually faster than the &lt;code&gt;foreach&lt;/code&gt; one. I'm anticipating that what I would find is for that to be slightly more performant on a &lt;code&gt;List&lt;/code&gt;. To cover multiple different ways to iterate through a list I have included LINQ and &lt;code&gt;for&lt;/code&gt; as other options. I would anticipate LINQ to be slightly slower and I have never used &lt;code&gt;Span&lt;/code&gt; before so I have no idea what to expect.&lt;/p&gt;




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

&lt;p&gt;Using &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; to create a console application makes running this benchmarking test very simple. To ensure older systems are being covered these tests will be run in both &lt;strong&gt;.NET Framework 4.8&lt;/strong&gt; and &lt;strong&gt;.NET 6.0&lt;/strong&gt; as these are the current Long Term Support versions of .NET. One for the older world and one for the new world.&lt;/p&gt;

&lt;p&gt;The premise is simple. Create a &lt;code&gt;List&lt;/code&gt; of strings 100 and 10,000 deep. Then run the test to iterate through each item and do this on repeat until &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; is happy to give us a result. This should give us a reasonable assumption of the fastest way to do this going forwards.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;

&lt;p&gt;Next up is creating a method for each type of &lt;code&gt;List&lt;/code&gt; iteration that I want to test. Each method does one thing to make it an even benchmark. Each method will iterate through each item in the &lt;code&gt;List&lt;/code&gt;, access the item in the list and assign it to a variable. Once the all the items have been process it will finish and record the time taken to complete the task.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Thankfully for us, &lt;a href="https://benchmarkdotnet.org"&gt;BenchmarkDotNet&lt;/a&gt; includes a Rank column to make it clear which run of tests is the winner. As you read these results you can use the Mean column to compare the difference in runtime between each test. For some of these there is a clear winner and others the difference is negligible.&lt;/p&gt;

&lt;h3&gt;
  
  
  .NET Framework 4.8
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;For&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;344.8 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ForEachLinq&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;559.9 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ForEach&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;659.4 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;659.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;For&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;33,562.8 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;ForEachLinq&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;53,895.5 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;63,317.0 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ForEach&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;63,356.6 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  .NET 6.0
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;SpanForEach&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;144.3 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;SpanFor&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;176.3 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ForEach&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;251.0 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;251.0 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;For&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;251.4 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;ForEachLinq&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;352.1 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;SpanForEach&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;12,260.4 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;SpanFor&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;16,088.1 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ForEach&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;24,109.4 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;GetEnumerator&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;24,111.0 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;For&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;24,113.8 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;ForEachLinq&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;34,713.9 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Results are formatted for clean and clear display, for the full output you peruse the output of the &lt;a href="https://github.com/stphnwlsh/Benchmarking/actions"&gt;actions on GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  .NET Framework 4.8
&lt;/h3&gt;

&lt;p&gt;After running the benchmark tests, the huge surprise to me here is how bad &lt;code&gt;foreach&lt;/code&gt; performs. It’s on par as the worst with &lt;code&gt;GetEnumerator&lt;/code&gt; and gets outperformed by LINQ &lt;code&gt;foreach&lt;/code&gt;. I will definitely not be using this in any older system any time soon. Would have been nice to have some &lt;code&gt;Span&lt;/code&gt; results to compare but that feature is not available for .NET Framework. The clear choice here is to refactor all &lt;code&gt;List&lt;/code&gt; iterations into &lt;code&gt;for&lt;/code&gt; loops and live a happy life.&lt;/p&gt;

&lt;h3&gt;
  
  
  .NET 6.0
&lt;/h3&gt;

&lt;p&gt;The .NET results are quite surprising to me. I started running this not knowing much about &lt;code&gt;Span&lt;/code&gt;, and now I’m ready to do a bit of research to understand more. When accessing the item, it appears that the &lt;code&gt;Span&lt;/code&gt; has an edge over the &lt;code&gt;for&lt;/code&gt;  and &lt;code&gt;foreach&lt;/code&gt; and it looks like it's worth refactoring your entire codebase for that performance gain. The key outcome here is that any iteration of a &lt;code&gt;List&lt;/code&gt; should look to convert that list to a &lt;code&gt;Span&lt;/code&gt;.  Outside of that there is some difference between &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;foreach&lt;/code&gt; when iterating a &lt;code&gt;Span&lt;/code&gt; but I'm not sure that it's worth changing all those over.&lt;/p&gt;

&lt;h3&gt;
  
  
  STOP USING LINQ FOREACH STATEMENTS
&lt;/h3&gt;

&lt;p&gt;They are a performance killer in both &lt;strong&gt;.NET 6.0&lt;/strong&gt; and &lt;strong&gt;.NET Framework 4.8&lt;/strong&gt; and far slower than the alternatives.  Refactor those immediately. It's incredibly poor for something that does get used by a lot of people.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;All of this code is open sourced. You can find my benchmarking work on &lt;a href="https://github.com/stphnwlsh/Benchmarking"&gt;GitHub&lt;/a&gt;. The results are the output of a GitHub Action to run the benchmark tests, you should be able to find detailed output on that repository.&lt;/p&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, or want to checkout my other work, please connect with me on &lt;a href="https://www.linkedin.com/in/stphnwlsh"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/stphnwlsh"&gt;Twitter&lt;/a&gt; or &lt;a href="https://github.com/stphnwlsh"&gt;GitHub&lt;/a&gt;, and consider supporting me at &lt;a href="https://www.buymeacoffee.com/stphnwlsh"&gt;Buy Me a Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/stphnwlsh"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L5xQ8oDJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-1.svg" alt='"Buy Me A Coffee"' width="260" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>performance</category>
      <category>programming</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Build Your Personal Brand with a Profile Page using GitHub Pages and Hugo</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Sun, 13 Feb 2022 03:14:20 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/build-a-profile-page-using-github-pages-and-hugo-2fnl</link>
      <guid>https://forem.com/stphnwlsh/build-a-profile-page-using-github-pages-and-hugo-2fnl</guid>
      <description>&lt;p&gt;There are a lot more people are thinking about personal brands and all sorts of extra bits and pieces outside of just plain on being a software engineer these days.  Recently I created a simple personal profile site that links to my blog, GitHub, Twitter and LinkedIn and thought that others might find a quick how to useful so here we go.&lt;/p&gt;

&lt;p&gt;I have tried many other frameworks and even different themes.  I've done this all slowly over a few months but now I'm happy with how simple my setup is, and how easy this is for others to do the same.  The following is a list of tools used to get the job done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosting - &lt;a href="https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website Framework - &lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website Theme - &lt;a href="https://github.com/jpanther/lynx" rel="noopener noreferrer"&gt;Lynx&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Publishing - &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Publishing Action - &lt;a href="https://github.com/peaceiris" rel="noopener noreferrer"&gt;Shohei Ueda's Template&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Create a GitHub Pages Repository
&lt;/h2&gt;

&lt;p&gt;Login to GitHub and create a new repository on the &lt;a href="https://github.com/new" rel="noopener noreferrer"&gt;new repository page&lt;/a&gt;.  You need to use the pattern "{username}.github.io", my username is &lt;code&gt;stphnwlsh&lt;/code&gt; so my name was &lt;code&gt;stphnwlsh.github.io&lt;/code&gt;.  Nothing earth shattering here.   &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmule35rbkhatlnt61f0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmule35rbkhatlnt61f0.png" alt="GitHub New Repository Screen - Naming your repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give it a &lt;code&gt;.gitignore&lt;/code&gt; file and choose none for the template (we'll update it later), even throw in a licence if you want to.  You choose it's your party.  Clone the new repository onto your machine and we're ready to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/{username}/{username}.github.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some side notes, if you manage an organisation, you can use the orgs name too.  Also, if you already have one, then well tough luck, each github user can only have one.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can only create one user or organization site for each account on GitHub. Project sites, whether owned by an organization or a user account, are unlimited.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're having any issues at this stage, checkout &lt;a href="https://pages.github.com/#user-site" rel="noopener noreferrer"&gt;the default setup instructions&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Install Hugo and Create a Site
&lt;/h2&gt;

&lt;p&gt;First things first you have to install Hugo onto your machine.  I'm on a Mac so it was easy as using &lt;a href="https://brew.sh/" rel="noopener noreferrer"&gt;Brew&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install hugo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aaaaaaand we're done!!!  For other systems checkout the &lt;a href="https://gohugo.io/getting-started/installing" rel="noopener noreferrer"&gt;install page on the Hugo website&lt;/a&gt;, that will get you where you need to go.&lt;/p&gt;

&lt;p&gt;Next up, use your favourite command line tool and navigate to your recently cloned repository to kickstart your journey with Hugo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hugo new site .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll find yourself with some new files and folders, this is the basic black skeleton from Hugo.  No content yet, but we'll get there.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Install a Hugo Theme
&lt;/h2&gt;

&lt;p&gt;I have shopped around for a few different themes.  Hugo is light and very powerful, and it has themes for everything.  You can choose on the &lt;a href="https://themes.gohugo.io/" rel="noopener noreferrer"&gt;Hugo Themes&lt;/a&gt; site or a few others, just give it a &lt;a href="https://lmgtfy.app/?q=Hugo+Themes" rel="noopener noreferrer"&gt;Google&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I went with &lt;a href="https://jpanther.github.io/lynx" rel="noopener noreferrer"&gt;Lynx&lt;/a&gt; because it was a plain and simple profile site with some nice link buttons and it's easy to customise....that's it.  &lt;/p&gt;

&lt;p&gt;You can just download the theme and dump it in a &lt;code&gt;themes\lynx&lt;/code&gt; folder, or you can use &lt;a href="https://github.com/jpanther/lynx#installation" rel="noopener noreferrer"&gt;hugo to install the theme&lt;/a&gt;. I didn't do that, I went down the submodule route, it's helpful if you ever need to customise the theme and then want to give back via a pull request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd themes
git submodule add https://github.com/jpanther/lynx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the contents of the &lt;code&gt;themes\lynx\exampleSite&lt;/code&gt; folder to your root repository folder and you have a default starting point ready to go.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Customise Your Content &amp;amp; Style
&lt;/h2&gt;

&lt;p&gt;There are four key areas to customise to make the site your own.  Hugo settings, custom css, page content and custom images. The first thing is to run your site locally with the following CLI command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hugo server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you run this command the output will have a localhost:port url in there copy and paste that into a browser and update the code.  There is a watch on changes so you will see live updates.&lt;/p&gt;

&lt;p&gt;The hugo settings are found in &lt;code&gt;config.toml&lt;/code&gt;.  You can set the site name, the main image and the links on the profile page here.  Compare &lt;a href="https://github.com/stphnwlsh/stphnwlsh.github.io/blob/main/config.toml" rel="noopener noreferrer"&gt;my settings&lt;/a&gt; with the &lt;a href="https://github.com/jpanther/lynx/blob/dev/exampleSite/config.toml" rel="noopener noreferrer"&gt;example settings&lt;/a&gt; to see how easy this is to update.&lt;/p&gt;

&lt;p&gt;To change the look and feel navigate to the &lt;code&gt;assets\css\custom.css&lt;/code&gt; file and just start playing around.  &lt;a href="https://github.com/stphnwlsh/stphnwlsh.github.io/blob/main/assets/css/custom.css" rel="noopener noreferrer"&gt;I didn't change much&lt;/a&gt;, just spacing and colours.  Inspect the code in the browser and go for it.&lt;/p&gt;

&lt;p&gt;For the text block on the page look at &lt;code&gt;content\_index.md&lt;/code&gt;, update the text block, then update the title, description and images for your meta tags and you are done.&lt;/p&gt;

&lt;p&gt;Finally drop your images into the static folder.  Use the &lt;code&gt;themes\lynx\static&lt;/code&gt; folder to guide you on the naming for your favicons, then set the profile image in the &lt;code&gt;config.toml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This isn't that descriptive but this is the creative part, you can adjust however you like and turn this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qu0kng4s8x0ew9ngszl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qu0kng4s8x0ew9ngszl.png" alt="Default Lynx Example Site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;into this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1c03kf6ujrpcwm97gb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1c03kf6ujrpcwm97gb6.png" alt="Updated Personal Site"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Push it to GitHub
&lt;/h2&gt;

&lt;p&gt;A couple of final steps before we push this to our repo. &lt;/p&gt;

&lt;p&gt;Add a &lt;code&gt;.nojekyll&lt;/code&gt; file to the root directory. Adding this file will bypass all the default Jekyll processing that GitHub Pages does by default. It's pretty old now but still works, see &lt;a href="https://github.blog/2009-12-29-bypassing-jekyll-on-github-pages/" rel="noopener noreferrer"&gt;GitHub's post on this feature&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;.gitignore&lt;/code&gt; file to match this one from &lt;a href="https://github.com/gohugoio/hugo/blob/master/examples/blog/.gitignore" rel="noopener noreferrer"&gt;Hugo examples&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;p&gt;Last step is to add a GitHub Action.  Lucky for us there is something that &lt;a href="https://github.com/peaceiris" rel="noopener noreferrer"&gt;Shohei Ueda&lt;/a&gt; prepared earlier.  Create a new file at &lt;code&gt;.github\workflows\github-pages.yml&lt;/code&gt;.  This will hold out action that will publish your site to a new branch &lt;code&gt;gh-pages&lt;/code&gt;.  This new branch will be used to host your site.  Copy the following code into your file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: GitHub Pages

on:
  push:
    branches:
      - main  # Set a branch to deploy
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: 'latest'
          # extended: true

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        if: ${{ github.ref == 'refs/heads/main' }}
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally push your code up to GitHub and navigate to your repository on the GitHub site.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Configure GitHub to Publish Your Site
&lt;/h2&gt;

&lt;p&gt;Finally head over to the GitHub Pages settings page to finish this up and checkout your new site.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/{username}/{username}.github.io/settings/pages 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your action has finished by time you get here, set the published branch to &lt;code&gt;gh-pages&lt;/code&gt; and the directory to root.  GitHub will likely need a few minutes to process everything but then your new site will be available at &lt;code&gt;{username}.github.io&lt;/code&gt;, congrats!!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0n7bkq9ovijhdhsl5ui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0n7bkq9ovijhdhsl5ui.png" alt="GitHub Pages Settings Screen"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That's all folks!  If you need any guidance please have a look at &lt;a href="https://github.com/stphnwlsh/stphnwlsh.github.io" rel="noopener noreferrer"&gt;my repository&lt;/a&gt;, there are expansive configuration instructions on the &lt;a href="https://github.com/jpanther/lynx" rel="noopener noreferrer"&gt;Lync GitHub repository&lt;/a&gt; as well if you are getting more creative than I did.&lt;/p&gt;

&lt;p&gt;Have a peek at &lt;a href="https://stphnwlsh.github.io/" rel="noopener noreferrer"&gt;my site in the wild&lt;/a&gt; if you like.  This reads like a long process but it was really simple in the end, just had to fail a fair bit with other sites to get it right.  Hope this helps you too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, checkout my other examples on &lt;a href="https://github.com/stphnwlsh" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and consider supporting me at &lt;a href="https://www.buymeacoffee.com/stphnwlsh" rel="noopener noreferrer"&gt;Buy Me a Coffee&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>profile</category>
      <category>github</category>
      <category>hugo</category>
      <category>branding</category>
    </item>
    <item>
      <title>Top 5 Things I Actually Like About Top {X} Posts</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Mon, 31 Jan 2022 23:56:08 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/top-5-things-i-actually-like-about-top-x-posts-32bc</link>
      <guid>https://forem.com/stphnwlsh/top-5-things-i-actually-like-about-top-x-posts-32bc</guid>
      <description>&lt;p&gt;I've been an engineer for a while now and always been a consumer of engineering blogs and feeds.  In the last few months, I've gone on the journey to do a little creating too.  It's fun, and a little scary sharing my thoughts with the real world.  Unfortunately, I have noticed a trait in me that I don't love.  I've added a little extra cynicism to my thought patterns these days and I think not in a healthy way.  So, I'm calling myself out.&lt;/p&gt;

&lt;p&gt;I have found myself hating the "Top X Things to Know About Y" posts.  It's not their content per se more the fact that it's the same thing over and over again.  I've noticed them the most with the release of C# 10 and the hundreds and thousands of posts with that type of tile, and same content.  I'm even adding to it here (hypocrisy, right?).  My attitude towards them has been terribly negative and I want to change that.&lt;/p&gt;

&lt;p&gt;To pivot back I'm going to find the positives in these posts to help me be less of a grump about it all and see the value in what they provide.  Come on the journey with me for my own personal top five.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Knowledge to Be Shared
&lt;/h2&gt;

&lt;p&gt;The best starting point here is that I don't know everything.  It's easy for engineers to always think they know a better way to do something, and that different approaches are wrong.  These articles are a good reminder that there are plenty of things changing all the time and that there are new things to learn.  Understanding different ideas and perspectives make me a better person and a better engineer.&lt;br&gt;&lt;br&gt;
There are also lots of these articles for technologies outside of my skillset. These articles provide a good viewpoint as to what technologies are gaining popularity and what might be worth investing my time into.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. People Have a Desire to Learn
&lt;/h2&gt;

&lt;p&gt;These articles are meeting a need.  There are software engineers of all levels out there looking to improve themselves and learn new things.  These articles provide an avenue to help people fulfill that desire to get better, even if it's only the entry point.  Iron sharpens iron, as one person learns and improves, we are all driven to follow.  Life without learning would be boring and these posts help us all on that journey.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Short and Sharp Avenue to Learn a New Thing
&lt;/h2&gt;

&lt;p&gt;Most of these articles would not be accused of being a long and difficult read.  They are short and sharp, and well that's kind of the point.  All they are meant to give you is more things to investigate, but they do it in a straightforward way that's easy to consume.  That's exactly what some people need and what others are looking for.  I started out looking for something new to learn and now I have five news things, great!!!&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Authors Gain Confidence to Contribute
&lt;/h2&gt;

&lt;p&gt;In taking my time to write this I can now call myself an author......maybe.  Jury's out but I'll barrel on anyway.  My main fear in even starting to write is that I might not actually have something to offer.  I might not have anything worth sharing. These posts are excellent starting points for people getting into writing and in need of building some confidence.  It was a big leap for me to even start and I have to give credit to those who take the risk too.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Provide Implementation Examples
&lt;/h2&gt;

&lt;p&gt;This last point might be a bit of a stretch, as not all posts do this, but engineers can get some simple implementation examples from them as well.  Quite often they're just taken from another source, but they still help engineers gain a better understanding via the code.  The great versions of these posts have a more real-world example of an implementation and I find that to be helpful.  The real winners combine more than one concept together, I've noticed in looking for examples you always end up trying to mash two of them together to make your code do what you need it to do.&lt;/p&gt;




&lt;p&gt;Well, if you've hung in there till this point, I have nothing to say but thank you.  You stuck it out with me through an exercise in being positive, which is pretty cool.  I still may not love these but next time I see one, I'll be able to remember that they do have value.  They help people discover new things, who knows, I might even read it and share it with someone else.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>sharing</category>
      <category>engineering</category>
      <category>positive</category>
    </item>
    <item>
      <title>Bending DateTime in .NET to Test Your Code Better</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Wed, 19 Jan 2022 02:13:16 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/bending-datetime-in-net-to-test-your-code-better-2lon</link>
      <guid>https://forem.com/stphnwlsh/bending-datetime-in-net-to-test-your-code-better-2lon</guid>
      <description>&lt;p&gt;Okay I'll dial down the hyperbole, over my too many years (read I'm feeling old) as an engineer I have run into a problem where my code has contained a &lt;code&gt;DateTime.Now&lt;/code&gt; or &lt;code&gt;DateTime.UtcNow&lt;/code&gt;.  When I write a test, I can't validate the actual time because milliseconds have passed from when the code ran and then my test goes to validate.  It's not a huge problem but annoying as I like to validate everything to make sure I'm not accidentally manipulating those values somewhere else.&lt;/p&gt;

&lt;p&gt;There is an easy solution to this, and before I detail out the solution that I used, I need to call out the &lt;a href="https://github.com/stphnwlsh/SimpleDateTimeProvider#inspiration" rel="noopener noreferrer"&gt;inspirations&lt;/a&gt; for this.  The TL;DR is that you can consume my &lt;a href="https://www.nuget.org/packages/SimpleDateTimeProvider/" rel="noopener noreferrer"&gt;SimpleDateTimeProvider NuGet Package&lt;/a&gt; to help you solve this.  The implementation of the code for this lies below.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;I have created a &lt;code&gt;DateTimeProvider&lt;/code&gt; consisting of an interface, and two implementations of the interface.  One implementation returns the System values and the other returns Mocked values that are preset by the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Interface
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface IDateTimeProvider
{
    DateTime Now { get; }
    DateTime Today { get; }
    DateTime UtcNow { get; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The System Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SystemDateTimeProvider : IDateTimeProvider
{
    public DateTime Now =&amp;gt; DateTime.Now;
    public DateTime Today =&amp;gt; DateTime.Today;
    public DateTime UtcNow =&amp;gt; DateTime.UtcNow;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Mock Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MockDateTimeProvider : IDateTimeProvider
{
    public DateTime Now
    {
        get =&amp;gt; this.now.ThrowIfNotSet(DateTimeType.Now);
        set =&amp;gt; this.now = value;
    }
    public DateTime Today
    {
        get =&amp;gt; this.today.ThrowIfNotSet(DateTimeType.Today);
        set =&amp;gt; this.today = value;
    }
    public DateTime UtcNow
    {
        get =&amp;gt; this.utcNow.ThrowIfNotSet(DateTimeType.UtcNow);
        set =&amp;gt; this.utcNow = value;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bending Date and Time
&lt;/h2&gt;

&lt;p&gt;This is a simple solution and it's easy to get under way using the providers, simply inject the system provider under the &lt;code&gt;IDateTimeProvider&lt;/code&gt; interface in your functional code. If you are using another library, you'll know the syntax but follow the same formula.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_ = services.AddSingleton&amp;lt;IDateTimeProvider, SystemDateTimeProvider&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next step is to create your class and use that registered &lt;code&gt;SystemDateTimeProvider&lt;/code&gt; that we just created via the &lt;code&gt;IDateTimeProvider&lt;/code&gt; interface. Then use the provider to set the &lt;code&gt;DateTime&lt;/code&gt; values in your class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Service
{
    private readonly IDateTimeProvider dateTimeProvider;

    public Service(IDateTimeProvider dateTimeProvider)
    {
        this.dateTimeProvider = dateTimeProvider;
    }

    public string DateTimeNow()
    {
        return $"DateTime.Now is {this.dateTimeProvider.Now}";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole purpose of this was to allow for testable code. So now that you have your class above, you can inject the &lt;code&gt;MockDateTimeProvider&lt;/code&gt; in its place to control the &lt;code&gt;DateTime&lt;/code&gt; values in your tests. The following example shows how to write a test in &lt;a href="https://xunit.net/" rel="noopener noreferrer"&gt;XUnit&lt;/a&gt;, using &lt;a href="https://shouldly.io/" rel="noopener noreferrer"&gt;Shouldly&lt;/a&gt; for assertion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Fact]
public void Today_ShouldReturn_MockedToday()
{
    // Arrange
    var provider = new MockDateTimeProvider();
    var service = new Service(provider);
    var today = DateTime.Today;

    provider.Today = today;

    // Act
    var result = service.DateTimeToday();

    // Assert
    _ = result.ShouldBeOfType&amp;lt;string&amp;gt;();
    result.ShouldBe($"DateTime.Today is {today}");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where Can I Find This?
&lt;/h2&gt;

&lt;p&gt;All of this open sourced.  You can find my work on GitHub &lt;br&gt;
at &lt;a href="https://github.com/stphnwlsh/SimpleDateTimeProvider" rel="noopener noreferrer"&gt;SimpleDateTimeProvider Repository&lt;/a&gt; and the published package at &lt;a href="https://www.nuget.org/packages/SimpleDateTimeProvider/" rel="noopener noreferrer"&gt;SimpleDateTimeProvider NuGet&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, checkout my other examples on &lt;a href="https://github.com/stphnwlsh" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and consider supporting me at &lt;a href="https://www.buymeacoffee.com/stphnwlsh" rel="noopener noreferrer"&gt;Buy Me a Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/stphnwlsh" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.buymeacoffee.com%2Fassets%2Fimg%2Fguidelines%2Fdownload-assets-sm-1.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>testing</category>
      <category>validation</category>
      <category>nuget</category>
    </item>
    <item>
      <title>Respectful Naming Conventions</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Mon, 06 Dec 2021 22:39:22 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/respectful-naming-conventions-1311</link>
      <guid>https://forem.com/stphnwlsh/respectful-naming-conventions-1311</guid>
      <description>&lt;p&gt;Originally written on the 16th of June in 2020.  I'm moving this post from Medium to here as I'm going to write things here instead of there now.  This is a light touch on a heavy topic, but I'm genuinely interested how other engineers are approaching this topic more than a year later.  Would love to hear other suggestions or how your codebases have changed or not changed.&lt;/p&gt;




&lt;p&gt;This is my first post. I’m not usually a blogger, I’m not after attention and I’m not trying to jump to a new job or career. I’m a regular old software developer, who’s been at it for over 15 years, and I still love what I do every day.&lt;/p&gt;

&lt;p&gt;The reason I’m writing this now is that I’m thinking through and processing all the events following the killing of George Floyd in Minneapolis. I’m just a software engineer in Australia who is far removed from the whole situation, but I figured there are things I can do in my life to break down barriers no matter how small. After reading about &lt;a href="https://medium.com/u/8df3bf3c40ae"&gt;GitHub&lt;/a&gt; moving away from naming the main branch in a repository “master” and being a Jenkins user seeing the terms master and slave every day, I figured I could do something along those lines too.&lt;/p&gt;

&lt;p&gt;I have a starting point of these 3 things but am looking to crowd source other naming conventions people are using out there&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renaming “master” branches to “main”.&lt;/li&gt;
&lt;li&gt;Renaming whitelist/blacklist to allowlist/denylist.&lt;/li&gt;
&lt;li&gt;Renaming master/slave in Jenkins to organiser/worker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d like to know what other naming conventions people are using to remove less respectful naming in their systems.&lt;/p&gt;




&lt;p&gt;As a footnote, this is the article I read about &lt;a href="http://https//www.bbc.com/news/technology-53050955"&gt;GitHub changing their naming&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Using GitHub Actions to Update .NET Dependencies Automatically</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Sat, 27 Nov 2021 20:45:31 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/using-github-actions-to-update-net-dependencies-automatically-4chb</link>
      <guid>https://forem.com/stphnwlsh/using-github-actions-to-update-net-dependencies-automatically-4chb</guid>
      <description>&lt;p&gt;It’s a tale as old as time, as a software engineer, you write some code, you’re happy with it and then you deliver it. End of story, right? No more work to be done! As usual there’s many more layers to deal with and one of those many layers is maintenance……boooooo!!!!!&lt;/p&gt;

&lt;p&gt;I know this isn’t the most amazing topic to write about, but it solves a real-world problem for me and I’m hoping for some of you too.&lt;/p&gt;

&lt;p&gt;I’m a backend engineer and write a lot of C#, which means I end up with solutions relying on NuGet packages. These do need to be updated all the time because there are other engineers out there doing amazing work keeping their packages up to date and I like to keep my dependencies up to date. This is where I find myself, with the problem of having to create a branch, update the packages, commit it, then seek PR approval, just to get some minor updates through. It’s annoying and I want to solve this.&lt;/p&gt;

&lt;p&gt;Before we get underway, are these instructions for me?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have a solution written in .NET…these instructions only work for code in .NET.&lt;/li&gt;
&lt;li&gt;The code already is, or you are about to host this solution in Github….so you can use Actions.&lt;/li&gt;
&lt;li&gt;You want to update your NuGet packages, engineers have valid reasons for doing or not doing things, no pressure here. I like to keep my packages up to date or at the very least alert me to when I need to make changes because of dependency updates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are in, it’s time to work with me here, Actions can be used to trigger many workflows. The most common being build and release pipelines for you project. The answer to our problem also lives in an Action. The time has come to create a new one.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to your GitHub Repository of choice&lt;/li&gt;
&lt;li&gt;Select the Actions tab&lt;/li&gt;
&lt;li&gt;Click that New Workflow button&lt;/li&gt;
&lt;li&gt;Ignore all the templates and select “Set up a Workflow Yourself”&lt;/li&gt;
&lt;li&gt;Delete all the sample code and we are good to go&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---HfqymQk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvaw7lgazrdf1yct39nz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---HfqymQk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvaw7lgazrdf1yct39nz.gif" alt="Create a New Black GitHub Action" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Create a schedule action
&lt;/h2&gt;

&lt;p&gt;This is the easiest part, this action will run once a week. You can change the schedule to anything you want. GitHub Action don’t run perfectly on time, but the do run. For more on scheduled jobs and setting the schedules, read the &lt;a href="https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule"&gt;GitHub Documentation&lt;/a&gt; and checkout the examples at &lt;a href="https://crontab.guru/examples.html"&gt;Crontab Guru&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Automated Dependency Updates
on:
    schedule:
        - cron:  '0 0 * * 0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Setup the Job
&lt;/h2&gt;

&lt;p&gt;Next up we set up the job. This is where we define what steps we want to run. We’re running this job on the latest version of Ubuntu. Next, we setup the default &lt;code&gt;actions/checkout&lt;/code&gt; step as well as &lt;code&gt;actions/setup-dotnet&lt;/code&gt; to install the version of the .NET SDK we need for our solution. I need .NET 6 for this job. You must that notice the changed token for the checkout &lt;code&gt;AUTOMATED_DEPENDENCY_UPDATES_TOKEN&lt;/code&gt;, this comes in handy in Step 5, I’ll explain what’s up down there.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    dependencies: 
        name: Update Dependencies
        runs-on: ubuntu-latest
steps:
    - name: Checkout
      id: checkout
      uses: actions/checkout@v2
      with:
          token: ${{ secrets.AUTOMATED_DEPENDENCY_UPDATES_TOKEN }}
    - name: Setup
      uses: actions/setup-dotnet@v1
      with:
          dotnet-version: 6.0.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Update those Dependencies
&lt;/h2&gt;

&lt;p&gt;These are the base steps of updating our NuGet packages. First, we need to install the &lt;a href="https://github.com/dotnet-outdated/dotnet-outdated"&gt;dotnet-outdated tool&lt;/a&gt; and then validate if we need to take any further action. If we run &lt;code&gt;dotnet outdated&lt;/code&gt; and there are not packages to update we should cancel the rest of the steps in this job.&lt;br&gt;
This is done but setting an output variable on the validate step that can be used by every other step in the job to determine if it should run or not. If there are no updates to be made, then we set the output variable to &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
If we have updates to make them, we run &lt;code&gt;dotnet outdated -u&lt;/code&gt; to force the NuGet updates. If this is successful, then we set the output variable to &lt;code&gt;true&lt;/code&gt; to allow the following steps to run.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Tools
  id: tools      
  run: dotnet tool install --global dotnet-outdated-tool     
- name: Update      
  id: update      
  run: |        
      OUTPUT=$(dotnet outdated)        
      if [[ $OUTPUT =~ "No outdated dependencies" ]]; then
          echo "::set-output name=updated::false"        
      else            
          dotnet outdated -u                    
          echo "::set-output name=updated::true"        
      fi      
  shell: bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Run your Tests
&lt;/h2&gt;

&lt;p&gt;After you’ve updated the NuGet packages you need to validate that the changes haven’t broken your code. The best way to do that is to build and test your solution. It’s a simple &lt;code&gt;dotnet test&lt;/code&gt; command to run all the tests on the solution. You can update this statement to suit your needs, the default should be to run all your tests.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Test
  id: test
  if: ${{ steps.update.outputs.updated == 'true' }}
  run: dotnet test -c Release -v minimal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Commit and Push
&lt;/h2&gt;

&lt;p&gt;The final step is to commit and then push the NuGet package updates, if the tests pass then this step runs and your automated package update is complete. When we used the &lt;code&gt;AUTOMATED_DEPENDENCY_UPDATES_TOKEN&lt;/code&gt; in the checkout step, that was to step around the fact that the inbuilt &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; will not trigger a follow-on workflow. If you generate a specific &lt;a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token"&gt;Personal Access Token&lt;/a&gt; to use when checking the code out then after the code is pushed, if you have another automated workflow, it will trigger.&lt;br&gt;
Finally, we set the commit message and author. This will register the commit to the GitHub Action user and not the user who setup the job.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Push
  id: push
  if: ${{ steps.update.outputs.updated == 'true' }}
  uses: stefanzweifel/git-auto-commit-action@v4
  with:
      commit_author: github-actions[bot] &amp;lt;41898282+github-actions[bot]@users.noreply.github.com&amp;gt;
      commit_user_name: github-actions[bot]
      commit_user_email: 41898282+github-actions[bot]@users.noreply.github.com
      commit_message: Automated Dependency Updates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  We’re Done!
&lt;/h2&gt;

&lt;p&gt;Now let’s put all the steps together in one easy Gist to use in any other repository. Hope this helps you automate that boring task too. This can work for any other CI/CD tool that allows for scheduled jobs. The concepts are the same just follow the Checkout, Update, Test and Push process.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;






&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;If you like this, checkout my other examples on &lt;a href="https://github.com/stphnwlsh"&gt;GitHub&lt;/a&gt; and consider supporting me at &lt;a href="https://www.buymeacoffee.com/stphnwlsh"&gt;Buy Me a Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/stphnwlsh"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L5xQ8oDJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-1.svg" alt='"Buy Me A Coffee"' width="260" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>dotnet</category>
      <category>nuget</category>
      <category>ci</category>
    </item>
    <item>
      <title>Dotnet Outdated - Install and Update</title>
      <dc:creator>Stephen Walsh</dc:creator>
      <pubDate>Sat, 27 Nov 2021 13:20:55 +0000</pubDate>
      <link>https://forem.com/stphnwlsh/dotnet-outdated-install-and-update-36ll</link>
      <guid>https://forem.com/stphnwlsh/dotnet-outdated-install-and-update-36ll</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/stphnwlsh"&gt;
        stphnwlsh
      &lt;/a&gt; / &lt;a href="https://github.com/stphnwlsh/dotnet-outdated-action"&gt;
        dotnet-outdated-action
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1 id="user-content-dotnet-outdated-action"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/dotnet-outdated-action#dotnet-outdated-action"&gt;Dotnet Outdated Action&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This action installs the &lt;code&gt;dotnet outdated&lt;/code&gt; dotnet tool and then attempts to update any NuGet packages that are available.&lt;/p&gt;
&lt;h2 id="user-content-inputs"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/dotnet-outdated-action#inputs"&gt;Inputs&lt;/a&gt;&lt;/h2&gt;
&lt;h2 id="user-content-location"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/dotnet-outdated-action#location"&gt;&lt;code&gt;location&lt;/code&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The location of the solution or project that needs to be checked for dependency updates. Default &lt;code&gt;""&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more information review the &lt;a href="https://github.com/dotnet-outdated/dotnet-outdated#specifying-the-path"&gt;Specifying the Path&lt;/a&gt; documentation on the &lt;code&gt;dotnet outdated&lt;/code&gt; GitHub&lt;/p&gt;
&lt;h2 id="user-content-includes"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/dotnet-outdated-action#includes"&gt;&lt;code&gt;includes&lt;/code&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A comma separated list of inputs to use to limit packages being analysed to ones &lt;strong&gt;including&lt;/strong&gt; those values. Default &lt;code&gt;""&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DO NOT INCLUDE SPACES&lt;/strong&gt; - this will break the step and cause your pipeline to fail.&lt;/p&gt;
&lt;p&gt;The following example will only include packages with the word 'microsoft' in their name, regardless of casing.&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;with&lt;/span&gt;
  &lt;span class="pl-ent"&gt;includes&lt;/span&gt;: &lt;span class="pl-s"&gt;microsoft&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This example will only include packages with the words 'microsoft' and 'automapper' in their name.&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;with&lt;/span&gt;:
  &lt;span class="pl-ent"&gt;includes&lt;/span&gt;: &lt;span class="pl-s"&gt;microsoft,automapper&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For more information review the &lt;a href="https://github.com/dotnet-outdated/dotnet-outdated#including-and-excluding-packages"&gt;Includes and Excludes&lt;/a&gt; documentation on the &lt;code&gt;dotnet outdated&lt;/code&gt; GitHub&lt;/p&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/stphnwlsh/dotnet-outdated-action"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/stphnwlsh/CleanGraphQLApi/blob/main/.github/workflows/dependency-updates.yml"&gt;https://github.com/stphnwlsh/CleanGraphQLApi/blob/main/.github/workflows/dependency-updates.yml&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/stphnwlsh"&gt;
        stphnwlsh
      &lt;/a&gt; / &lt;a href="https://github.com/stphnwlsh/CleanGraphQLApi"&gt;
        CleanGraphQLApi
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A template for an API using Clean Architecture and GraphQL.net.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1 id="user-content-clean-graphql-api"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/CleanGraphQLApi#clean-graphql-api"&gt;Clean GraphQL API&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/stphnwlsh/CleanGraphQLApi/actions/workflows/build-pipeline.yml"&gt;&lt;img src="https://camo.githubusercontent.com/6ab435a0409feff0160ff14c0e4ae64984fe876ccec65135683a37938da66f66/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f737470686e776c73682f436c65616e4772617068514c4170692f4275696c64253230506970656c696e653f6c6162656c3d4275696c64253230506970656c696e65266c6f676f3d676974687562266c6f676f436f6c6f723d7768697465267374796c653d666f722d7468652d6261646765" alt="GitHub Workflow Status"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/gh/stphnwlsh/CleanGraphQLApi" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/635b699ef4f38e3a7d281afcd14c37f4a0d879e5dc4e128bd4798c0b9ccd709e/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f737470686e776c73682f436c65616e4772617068514c4170693f6c6162656c3d436f6465253230436f766572616765266c6f676f3d636f6465636f76266c6f676f436f6c6f723d7768697465267374796c653d666f722d7468652d6261646765" alt="Codecov"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/c8e7c146047fbfc9e7215159ac7f59662de79f8920318f96c2ecd44e8c2a42ac/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f762f436c65616e4772617068514c4170692e54656d706c6174653f6c6162656c3d6e7567657425323074656d706c617465266c6f676f3d6e75676574266c6f676f436f6c6f723d7768697465267374796c653d666f722d7468652d6261646765"&gt;&lt;img src="https://camo.githubusercontent.com/c8e7c146047fbfc9e7215159ac7f59662de79f8920318f96c2ecd44e8c2a42ac/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f762f436c65616e4772617068514c4170692e54656d706c6174653f6c6162656c3d6e7567657425323074656d706c617465266c6f676f3d6e75676574266c6f676f436f6c6f723d7768697465267374796c653d666f722d7468652d6261646765" alt="Nuget"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a template API using &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="nofollow"&gt;Clean Architecture&lt;/a&gt; alongside a .net implementation of &lt;a href="https://github.com/graphql-dotnet/graphql-dotnet"&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="user-content-prerequisites"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/CleanGraphQLApi#prerequisites"&gt;Prerequisites&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This solution in built on the &lt;a href="https://dotnet.microsoft.com/download/dotnet/6.0" rel="nofollow"&gt;.net 6 SDK&lt;/a&gt;, you need to install that before it will work for you.  If you want to build the Dockerfile you will need to install  &lt;a href="https://www.docker.com/products/docker-desktop" rel="nofollow"&gt;Docker&lt;/a&gt; as well.&lt;/p&gt;
&lt;h2 id="user-content-installation"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/CleanGraphQLApi#installation"&gt;Installation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a template and you can install it using the &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-new" rel="nofollow"&gt;dotnet new cli&lt;/a&gt;.  To install the lastest version of the template run the following command.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;dotnet new --install CleanGraphQLApi.Template&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;To create a new solution using this template run the following command&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;dotnet new cleangraphqlapi --name {YOUR_SOLUTION_NAMESPACE} --au &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;{YOU_AUTHORS_NAME}&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2 id="user-content-docker"&gt;&lt;a class="heading-link" href="https://github.com/stphnwlsh/CleanGraphQLApi#docker"&gt;Docker&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There's a dockerfile included in the build folder and serves the purpose of restoring, building, testing, publishing and then creating a runtime image of the API.  Works on my machine.....you can add a version prefix and suffix to version the service…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/stphnwlsh/CleanGraphQLApi"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/stphnwlsh/CleanGraphQLApi"&gt;https://github.com/stphnwlsh/CleanGraphQLApi&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/stphnwlsh/CleanMinimalApi"&gt;https://github.com/stphnwlsh/CleanMinimalApi&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/stphnwlsh/SimpleDateTimeProvider"&gt;https://github.com/stphnwlsh/SimpleDateTimeProvider&lt;/a&gt;&lt;/p&gt;

</description>
      <category>actionshackathon21</category>
      <category>github</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
