<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nick Proud</title>
    <description>The latest articles on DEV Community by Nick Proud (@nickproud).</description>
    <link>https://dev.to/nickproud</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%2F189886%2Fb19b1901-6f1b-4186-a09b-67a3b3ee60fc.jpg</url>
      <title>DEV Community: Nick Proud</title>
      <link>https://dev.to/nickproud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nickproud"/>
    <language>en</language>
    <item>
      <title>Is C# Good for Beginners?</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Thu, 01 Jul 2021 20:57:05 +0000</pubDate>
      <link>https://dev.to/nickproud/is-c-good-for-beginners-987</link>
      <guid>https://dev.to/nickproud/is-c-good-for-beginners-987</guid>
      <description>&lt;p&gt;Are you a programmer looking to dip your toes into a new language? Or are you starting from scratch and trying to find the best language to cut your teeth on. Whether you are a fresh-faced junior or a hardened FORTRAN veteran, C# is a fantastic language for people who need a general-purpose, object oriented language. But despite it's reasonably low barrier of entry. it may not be for everyone.&lt;/p&gt;

&lt;p&gt;Here are some key points on C# that may help you make a decision:&lt;/p&gt;

&lt;h2&gt;
  
  
  It's Not Just for Windows
&lt;/h2&gt;

&lt;p&gt;Being a C# developer grants you membership of an extremely diverse and welcoming family of developers working within Microsoft's &lt;a href="https://en.wikipedia.org/wiki/.NET_Framework"&gt;.NET Framework&lt;/a&gt;, a platform originally built by Microsoft to develop Windows applications that now following the release of .NET Core and more recently .NET 5, allows users to develop multi-platform desktop and mobile applications as well as fully realized web applications.&lt;/p&gt;

&lt;p&gt;You can write the same app and publish it on Windows, Linux or Mac OS, and then if you want to, you can port the same app to a mobile version targeting iOS or Android.&lt;/p&gt;

&lt;p&gt;The documentation provided by Microsoft is extensive, with most areas of the .NET framework having a 'getting started' page that will help you understand how to write apps for the various supported platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web Applications Made Easy
&lt;/h2&gt;

&lt;p&gt;While a new JavaScript or web front-end framework appears every millisecond in the wild, Microsoft have consolidated the best parts of the top frameworks and now directly support them. You can run an ASP.NET back end in C# along with an Angular or Vue JS front end with extensive boilerplating and template projects to get your started.&lt;/p&gt;

&lt;p&gt;What's more, Microsoft have released their own front-end framework for SPA (Single-Page=Application Apps) in the form of &lt;a href="https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor"&gt;Blazor&lt;/a&gt;, which comes in two forms - Server and WebAssembly. Both allow you to easily abstract the front end of your site from the back end, with a server backend communicating with the front of SignalR, or with WebAssembly running in the browser. Microsoft has even teased their new 'native' features within Blazor for &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/"&gt;.NET 6,&lt;/a&gt; which should rival &lt;a href="https://www.electronjs.org/"&gt;Electron&lt;/a&gt; in the way it allows you to convert web applications to native desktop applications. If you're a web developer looking for a way to get into writing desktop applications, this could be a good entry-point.&lt;/p&gt;

&lt;h2&gt;
  
  
  C-Style Syntax, Great if you Already Know Java
&lt;/h2&gt;

&lt;p&gt;If you've already worked with syntactically similar languages like Java or JavaScript, you're in a great position to start learning C#. C# is particularly similar to Java in the way it looks. The main way it differs lies within the dependencies and libraries that you can work with out of the box.&lt;/p&gt;

&lt;p&gt;C# is also object-oriented, and while it is often argues that Java is not a 'pure' OOP language, it shares very similar class relationship paradigms with C#.&lt;/p&gt;

&lt;h2&gt;
  
  
  VIDEO GAMES!
&lt;/h2&gt;

&lt;p&gt;If you want to make video games, there are several well-supported game engines that are free to use and that support C#; one of the most popular engines being &lt;a href="https://unity.com/"&gt;Unity&lt;/a&gt;. Unity uses C# as it's main scripting language and is often used by beginners to learn the language as well as make cool video games. Unity has an extensive tutorial set for getting started and YouTube is saturated with guides on how to become an indie video game developer with C#.&lt;/p&gt;

&lt;h2&gt;
  
  
  How High (Or-Low) Can You Go?
&lt;/h2&gt;

&lt;p&gt;For the most-part, as C# is a languaged within a managed runtime, you don't need to worry about managing your resources as much as you would in a lower-level language like C or C++. However, with C#, you kind of have the best of both worlds. If you want to go lower level, the &lt;code&gt;unsafe&lt;/code&gt; keyword is your friend, as it allows you to say '&lt;em&gt;hey, you know that managed runtime that is running a garbage collector for me and basically tidying my room on autopilot, yeah turn that off. I'm going rogue.&lt;/em&gt;' (Be warned - it can also be your worst enemy. Respect it as you would respect the sea)&lt;/p&gt;

&lt;p&gt;What's more, if you want to really get into the guts of Windows specifically via C#, take a look at &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke"&gt;P/Invoke.&lt;/a&gt;Serious but powerful stuff,&lt;/p&gt;

&lt;h2&gt;
  
  
  An Amazing Community
&lt;/h2&gt;

&lt;p&gt;C# is widely supported on &lt;a href="https://stackoverflow.com/questions/tagged/c%23"&gt;StackOverflow&lt;/a&gt;. It has a huge amount of coverage within GitHub projects and now that Microsoft have open the gates to open-source contributors, it is easier than ever to get help from people online. At the time of writing, you could not only ask somebody about how a specific part of C# works under the hood, but you can even go to the &lt;a href="https://github.com/dotnet/roslyn"&gt;GitHub repo for the Roslyn C# compiler&lt;/a&gt; (a compiler for C# that is itself written in C#.....which is pretty damn cool) and take a look at it's inner workings. Get good enough at C# and you could even contribute to the project yourself!&lt;/p&gt;

&lt;h2&gt;
  
  
  So Is C# for Me?
&lt;/h2&gt;

&lt;p&gt;As usual, the really annoying answer is.....it depends. If you're an absolute beginner to programming, it's not the worst choice. It's taught in many colleges and universities around the world as they move away from the predilection for teaching Java. If you are a complete newcomer to the world of programming though, I might start with C#'s Great-Grandmother C, as it will teach you a very similar syntax and also give you a fantastic insight into how computers work on a low-level.&lt;/p&gt;

&lt;p&gt;However, if you're relatively experience in another language like Java, Python or JavaScript, then C# is a absolutely a great next step. Not only for the reason that it will expose you to a new style of syntax and some more concrete OOP principles, but it will also allow you to cast your net wider in terms of the projects you build, bringing you closer to that goal of becoming the 'Full-Stack Developer,' a term that while being really difficult to property define, is often attributed to people who are experienced in C#.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>career</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
    <item>
      <title>.NET TCPListener: Accepting Multiple Client Connections</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Mon, 18 Jan 2021 09:06:00 +0000</pubDate>
      <link>https://dev.to/nickproud/net-tcplistener-accepting-multiple-client-connections-108d</link>
      <guid>https://dev.to/nickproud/net-tcplistener-accepting-multiple-client-connections-108d</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol"&gt;TCP&lt;/a&gt;. It's a key component of the foundation of the internet. We take it for granted every day while we're online. Sometimes, it becomes necessary to leverage this amazing protocol to implement reliable and fast communication. Here's a brief explanation of how I used the .NET framework's &lt;em&gt;TCPListener&lt;/em&gt; to create a simple TCP server in the form of &lt;em&gt;&lt;a href="https://github.com/nickproud/Easy-TCP-Server"&gt;Easy-TCP-Server&lt;/a&gt;,&lt;/em&gt; a .NET core library which handles incoming TCP data from multiple clients via 'channels' of connections between the clients and the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Use Case
&lt;/h2&gt;

&lt;p&gt;The solution is built in order to allow the project which references it to quickly spin up a TCP server which can then listen for any incoming TCP traffic. The aim is to make it easy to create an endpoint that any client can send TCP requests to and receive responses from on a persistent, managed connection. (If needed.) This may be useful for many different reasons, with examples like using remote clients to trigger the execution of a remote process, or sending data to a server for persistence in a database to name just a few.&lt;/p&gt;

&lt;p&gt;I'll go into more detail about the overall development of the project in another post at some point, but for now, I want to explain how I was able to accept multiple connections on a .NET &lt;em&gt;TCPListener.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Accepting multiple clients
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcplistener?view=net-5.0"&gt;documentation's&lt;/a&gt; main example for &lt;em&gt;TCPListener&lt;/em&gt; demonstrates how to listen for a request, receive and receive it on the same thread. For our use case, we want to be able to receive any incoming request and then handle it on a separate thread, to prevent our listener from blocking.&lt;/p&gt;

&lt;p&gt;First of all, let's initialize a &lt;em&gt;TCPListener&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Listener&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IPAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1!), 12400); Listener.Start();
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we create a listener which will be listening on the localhost, on port 12400, before starting it.&lt;/p&gt;

&lt;p&gt;Now we need to start the listener and create a loop that while running, accepts incoming TCP clients before we do something with the incoming request. .NET presents a couple of options for receiving TCPClient connections within the &lt;em&gt;TCPListener&lt;/em&gt; class, with the main one being &lt;em&gt;AcceptTcpClient().&lt;/em&gt; This will allow us to listen out for incoming requests on our specified hostname and port, and would be fine if we wanted to block the current thread in order to handle the traffic, like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcceptTcpClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Do Something }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we don't want to block. We want to accept requests asynchronously so that on each request, we can make a different thread for handling the incoming traffic. To achieve this, we can still use a while loop, but instead of using &lt;em&gt;AcceptTcpClient()&lt;/em&gt; let's use &lt;em&gt;AcceptTcpClientAsync().&lt;/em&gt; Using this method, the thread will no longer be blocked, as we are awaiting any incoming requests. When a request is received, we can fire off our handler logic in the form of a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=net-5.0"&gt;Task&lt;/a&gt;, so that we are not blocking the program further. This will allow multiple clients to hit our listener and be handled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcceptTcpClientAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;//Do Something ); }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a more detailed example of the implementation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_running&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Running&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="k"&gt;get&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; 
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_running&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="k"&gt;set&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="n"&gt;_running&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt; 
     &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;Listener&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="k"&gt;try&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;Running&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="p"&gt;{&lt;/span&gt; 
                 &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcceptTcpClientAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;        
                 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;//Do something); &lt;/span&gt;
             &lt;span class="p"&gt;}&lt;/span&gt; 
          &lt;span class="p"&gt;}&lt;/span&gt; 
          &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SocketException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
          &lt;span class="p"&gt;{&lt;/span&gt;  
              &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
          &lt;span class="p"&gt;}&lt;/span&gt;  
     &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
        &lt;span class="n"&gt;Running&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
     &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I've provided a means to start the listener's accept loop and a means to gracefully close it. I've also added a handler for any SocketExceptions that may be thrown.&lt;/p&gt;

&lt;p&gt;There it is. A simple TCPListener that can accept multiple connections and handle them on a separate thread. This is a more simplified version of the server I wrote for the Easy-TCP-Server library, the source of which is available for your use here.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>tcp</category>
      <category>networking</category>
    </item>
    <item>
      <title>Azure Websocket Timeouts on Long-Living Connections</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Thu, 12 Nov 2020 09:39:00 +0000</pubDate>
      <link>https://dev.to/nickproud/azure-websocket-timeouts-on-long-living-connections-1m1p</link>
      <guid>https://dev.to/nickproud/azure-websocket-timeouts-on-long-living-connections-1m1p</guid>
      <description>&lt;p&gt;I've been recently working on a gateway service hosted in Azure that is primarily a TCP server. One of the key requirements of the project is that it allows clients running a desktop-based windows service to initiate a handshake over TCP when their respective service is started, and then keeps a connection open between the client and server for the receipt of messages at any given time.&lt;/p&gt;

&lt;p&gt;However, this presented a problem. Azure doesn't like me doing this.&lt;/p&gt;

&lt;p&gt;It seems that Azure apps (Azure Cloud Services in particular, which is what I am using), have an 'idle timeout.' According to Microsoft, this is usually between 4 and 30 minutes long, after which time, your client's connection is removed. Apparently, this is configurable.&lt;/p&gt;

&lt;p&gt;So if like me you are using Azure, you should be able to go into the app's config settings (I believe app.config for app service or Service.Definition for cloud services) and change the idle timeout property on any endpoints you have open on the app like so.&lt;/p&gt;

&lt;pre class="EnlighterJSRAW"&gt;&amp;lt;InputEndpoint name="MyEndpoint" protocol="tcp" localPort="80" port="80" idleTimeoutInMinutes="30" /&amp;gt;&lt;/pre&gt;

&lt;p&gt;The problem for me is, this wouldn't really fit my requirements as my clients' connections are still limited to a maximum idle timeout of 30 minutes. I want to be able to allow my clients to start their desktop service and then stay connected indefinitely.&lt;/p&gt;

&lt;p&gt;The solution in my case was relatively straightforward. The key thing to note in the timeout that Azure enforces is the word &lt;em&gt;idle. &lt;/em&gt;It only times out if the server receives zero data from a client within the defined timeout period. So sending an arbitrary command to the server keeps the connection alive.&lt;/p&gt;

&lt;p&gt;So in nearly all cases, when my client sends data to the server, it sends a command which can be interpreted by the server, usually to perform an action and then potentially return a responding command back to the client (not immediately. We're using WebSockets remember, not HTTP!) But in this case, I can send a command I usually call 'NOOP.' (Meaning 'no operation.) The server would receive this and simply do nothing. This would automatically reset the idle timeout so that the client's connection is kept alive. You could even change the command to 'KEEP ALIVE' and have the server perform other actions based on this if needed. Simply create a task that is called every x minutes and your connection is going to stay up.&lt;/p&gt;

&lt;p&gt;It's important to note that I am not using SignalR. I don't know if this applies to projects like mine that use SignalR, but if you are using it and this issue is affecting you, I hope this is an adequate solution for you.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Restricting Access To MVC Views</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Tue, 14 Jul 2020 21:01:33 +0000</pubDate>
      <link>https://dev.to/nickproud/restricting-access-to-mvc-views-4fh2</link>
      <guid>https://dev.to/nickproud/restricting-access-to-mvc-views-4fh2</guid>
      <description>&lt;p&gt;There are so many different mechanisms for authentication and for claims verification in .NET for MVC applications with ASP.NET Identity, JSON Web Tokens, and Azure Active Directory to name a few.&lt;/p&gt;

&lt;p&gt;But what if you are rolling your own authentication and need to restrict specific pages to specific users?&lt;/p&gt;

&lt;h2&gt;Time for a Session&lt;/h2&gt;

&lt;p&gt;.NET's &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.httpcontext?view=netframework-4.8"&gt;HTTPContext&lt;/a&gt; object contains a property called &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.httpcontext.current?view=netframework-4.8"&gt;Current&lt;/a&gt; which we will leverage in order to check the permissions of the person trying to load our restricted pages. &lt;/p&gt;

&lt;p&gt;'Current' allows us to get to the current &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.httpcontext.session?view=netframework-4.8"&gt;Session&lt;/a&gt; object, which itself stores various pieces of information relating to the individual HTTP requests sent to your MVC app. Thanks to this property, we can store information unique to the site visitor attempting to load the page. &lt;/p&gt;

&lt;p&gt;For example, if you have already authenticated the user by verifying their identity, you can store the date and time their session (as in time on your site / in your application) started, and their permissions. Using these saved properties, you can decide whenever a new page is requested, whether the current session (as in the visitor loading the page) is allowed to view it, and redirect them somewhere else if they are not. &lt;/p&gt;

&lt;p&gt;So how do we store session info? Well, let's assume your authentication process hashes an inputted password and verifies it against the password stored in a 'Users' database table. This table will also contain other values such as their email or contact info, but importantly, values that dictate what they can or cannot view, or which pages they are allowed to load. &lt;/p&gt;

&lt;p&gt;Your process returns the user object and this signifies a successful login. Now we can store this info in a session object to be checked on future page loads. &lt;/p&gt;

&lt;h2&gt;Make a User Session Class&lt;/h2&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;    public class UserSession
    {
        public DateTime StartedAt { get; }
        public DBUserRecord UserDetail { get; }

        public UserSession(DBUserRecord user)
        {
            StartedAt = DateTime.UtcNow;
            UserDetail = user;
        }
    }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here I have made a simple class which will contain the returned user data retrieved from the DB when the user logged in &lt;em&gt;(DBUserRecord user&lt;/em&gt;) as well as the date and time at which their session on our site began. (This could be useful later on if you want to implement time-restricted viewing of pages.)&lt;/p&gt;

&lt;p&gt;I have created a constructor, which passes our &lt;em&gt;DBUserRecord&lt;/em&gt; as a parameter and initializes it within the class. The constructor also sets the &lt;em&gt;StartedAt&lt;/em&gt; value to now. &lt;/p&gt;

&lt;p&gt;Great! We have an object that stores info about our user. It's easily extendable, either by adding further properties to this class or to the &lt;em&gt;DBUserRecord&lt;/em&gt; we pass in. &lt;/p&gt;

&lt;p&gt;So how to we store this in the current HTTPContext's session?&lt;/p&gt;

&lt;h2&gt;Storing a Session State&lt;/h2&gt;

&lt;p&gt;We will want to head to our login page's controller. Remember, this assumes you have a login page which has successfully logged somebody in and returned some user data as a result. The next logical step is to redirect the user either to the expected page (thanks to successful login) or to a message telling them to kindly go away. &lt;/p&gt;

&lt;p&gt;To that end, I will store the session state from within the Controller of the login page. (For more info on Controllers in MVC take a look &lt;a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/aspnet-mvc-controllers-overview-cs"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;It's pretty simple from this point. Controllers return a view to the user, which is what loads the requested page. We wrap a condition around this which authenticates them, and if it is successful, we create the session object we made earlier on, save it to the HTTPContext and then return the view. &lt;/p&gt;

&lt;p&gt;Here's an example&lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt; //add your authentication method
                    if (Authenticated(username, password)) 
                    {
                        //they're legit

                        //keep user data in an object and   pass to your session's constructor
                        var UserSession session = new UserSession(UserDataFromDB);

                        //create a session object named whatever you want and pass the usersession as a value
                        System.Web.HttpContext.Current.Session.Add("OpenSession", session);

                        //return the view. (Pass the name of the view as a string if different to the one associated with this controller
                        return View(); 
                    }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This takes care of getting them logged in, but what about when they change pages? How do we make it so that any other page requested only loads if the session is valid?&lt;/p&gt;

&lt;p&gt;It's nice and easy. You just have to add a check for the session on the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.actionresult?view=aspnetcore-3.1"&gt;ActionResult &lt;/a&gt;function that is called when the page is requested. For example, say our user now tries to load the 'Dashboard.' Requesting the page calls the ActionResult Function, &lt;em&gt;'Index.&lt;/em&gt;' Within this function, we just check to make sure the session we created exists. &lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;        public ActionResult Index()
        {
            if (System.Web.HttpContext.Current.Session["OpenSession"] != null)
            {
                var model = new Dashboard();
                return View(model);
            }
            else
            {
                return RedirectToAction("Index", "Login");
            }
        }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now, if the session exists, we know the user logged in successfully earlier on, and that they are ok to view the page. We return the requested view, passing in any models we need to. &lt;/p&gt;

&lt;p&gt;If the user is somewhere they shouldn't be, we call &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.controller.redirecttoaction?view=aspnet-mvc-5.2"&gt;RedirectToAction()&lt;/a&gt;, passing in the ActionResult method to be called and the controller in which it resides. In the example above, this will redirect them to the login screen. &lt;/p&gt;

&lt;p&gt;This can of course be extended further. If you want to restrict certain pages to authenticated users with specific permissions. you would cast the session object back to &lt;em&gt;UserSession&lt;/em&gt; and check the permissions before letting them in. &lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;        public ActionResult Index()
        {
            var session = (UserSession)System.Web.HttpContext.Current.Session["OpenSession"];
            if (session != null)
            {
                if (session.UserDetail.IsAdmin)
                {
                    var model = new Dashboard();
                    return View(model);
                }
            }
            return RedirectToAction("Index", "Login");
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In most cases, security requirements dictate that you roll a proven framework like JSON Web Tokens. However, if you're working with constraints that force you to roll your own authentication / fencing of content, the local session object is your friend. &lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Writing Code for an Audience</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Thu, 18 Jun 2020 09:13:52 +0000</pubDate>
      <link>https://dev.to/nickproud/writing-code-for-an-audience-3l26</link>
      <guid>https://dev.to/nickproud/writing-code-for-an-audience-3l26</guid>
      <description>&lt;p&gt;It seems like the most unnatural thing for many programmers; this notion of 'live coding.' The very idea that we would choose to opt-in to real-time scrutiny can be enough to make some coders pine for the safety of a dark room at 2am, complete with headphones and Mountain Dew.&lt;/p&gt;

&lt;p&gt;Stereotypes aside, as programming continues to be accepted as a mainstream discipline, it is becoming increasingly necessary to write code on the fly for a watching audience. Sure, the platform may be a conference, a live stream or a demo to a prospective client, but these are still pretty rare occurrences compared to the dreaded coding-test presented to candidates applying for programming positions every day. &lt;/p&gt;

&lt;p&gt;Tech jobs (IT and Software Engineering in particular) are plagued with conflicting opinions on coding standards, design patterns and choice of language, with debate on these subjects having their place as useful discourse. However, most troubling seems to be the abundance of ego in the industry. Imposter syndrome lurks in the shadows of development teams around the world, and it's seeds are often planted in the first contact between rookie coder and employer in the coding test. More and more, from day one, we are expected to hold our own as we write what we hope is stable software with eyes on us at all times. &lt;/p&gt;

&lt;h2&gt;Coding Tests&lt;/h2&gt;

&lt;p&gt;This is probably the most common introduction to public programming a developer receives, as they prove their skills in the hopes of getting a job. Every hiring process differs from company to company, but is there a universal way to cope with the fallout from coding tests, successful or not? I would say the most important thing to avoid is a dent to your self-esteem. &lt;/p&gt;

&lt;p&gt;There are a million different ways somebody could fail a coding test, and I find most aspects of them as contrived as traditional processes in terms of measuring a candidate's skill. I'm not however saying that they aren't valuable, just that they don't always reflect your true talents as a developer. &lt;/p&gt;

&lt;p&gt;Try to remind yourself that not passing one company's test doesn't mean that you are a failure as a programmer, or that the all-too-common imposter syndrome is not really a syndrome at all, and must be proof that you're a fraud. Instead, take the fact that you even managed to code in front of somebody as a victory. &lt;/p&gt;

&lt;p&gt;Programming is more personal than it seems. The way you write is a reflection of your style and thinking. To put that on show for everybody to see is no easy thing to do, especially when the prospect of employment is riding on it. &lt;/p&gt;

&lt;p&gt;Take your time and get your priorities in order. Personally, I see the coding test as a trade off between the problem you have been asked to solve and the time in which you have to do it. If you don't have a lot of time, your priority is to get the job done. As long as you make an effort to explain where you think you could refactor the code, you're doing well. On the flip side, if you have more time, once you have solved the problem, show that you can actively improve code quality by using the extra time to refactor. &lt;/p&gt;

&lt;h2&gt;Pair Programming&lt;/h2&gt;

&lt;p&gt;Commonly adopted in large teams, pair programming allows developers to solve issues together, as well as providing much needed mentorship to junior developers. If you're junior, or even if you're suffering from a classic case of imposter syndrome, don't shy away from opportunities to program with another developer. A fresh pair of eyes not only helps you get your job done quicker, it opens up your perspective to new ideas and ways of solving problems. With the right partner you could find a valuable mentor and begin solidifying a foundation in a particular technology. &lt;/p&gt;

&lt;p&gt;This obviously comes with a requirement; the need to code in front of somebody. Here we are again! The advice here is similar to that of the code test passage above, but by this point, it should be a little bit easier. &lt;/p&gt;

&lt;p&gt;It's now time to start letting your guard down a little more. &lt;/p&gt;

&lt;p&gt;When you're pair programming and you run into an area in which you have less knowledge, don't let your ego get the better of you. Be honest about what you don't know. It sets expectations for the person programming with you. What they choose to do with that is on them, but you can't say you weren't honest, and nine times out of ten, people are more respected for having the courage to say 'I don't know', especially in an industry where imposter syndrome is rife. &lt;/p&gt;

&lt;p&gt;The fact is, by the time you have had a few more 'I don't know' moments in a pair-programming session with a more experienced developer, you will soon be at the stage where you're saying 'I've seen this before,' and 'I'll take care of that.' Pretty soon a new, fresh-faced, less experienced junior developer has arrived, and before you know it, the student has become the master. :)&lt;/p&gt;

&lt;h2&gt;Welcoming criticism (constructive and not so constructive..)&lt;/h2&gt;

&lt;p&gt;Sheesh. This is the part everyone is scared of when is comes to programming in front of people. &lt;/p&gt;

&lt;p&gt;The reality is, whether you are programming in public or doing your darndest to code in solitude, you're going to be criticised. &lt;/p&gt;

&lt;p&gt;The tech industry is sadly still full of ego. It's getting better, and I'm optimistic that positive change is accelerating, but that doesn't change the fact that the criticism you receive may not always be constructive. &lt;/p&gt;

&lt;p&gt;Hang in there. Try to identify where somebody is genuinely trying to help you develop your skills and embrace it. Code reviews, pull requests, one-on-one meetings, these are all fantastic opportunities to get some easy to build-upon feedback on how you can be a better programmer. The &lt;em&gt;worst &lt;/em&gt;thing you could possibly do, is take a valid piece of feedback and take it to heart. Experienced programmers will spot it a mile off, and the main thing it will do is serve to show that you lack confidence, you're insecure and as a result, less mature as a developer. This is never going to help your career progression. So, swallow your pride and let it level your skills up. You'll appreciate it in the long run believe me :)&lt;/p&gt;

&lt;p&gt;As for not-so-constructive criticism, most of the time people who are outright rude are suffering from major insecurities themselves, not to mention a lack of maturity much like what we talked about above. If you're at work and you're getting abuse about the way you code (and I mean abuse) then discreetly speak to HR. There is &lt;em&gt;never&lt;/em&gt; any justification for personal attacks on your code, especially if you are less experienced. &lt;/p&gt;

&lt;p&gt;Failing that, if you've tried to get help and you're just not getting it, this could be a really good indication that it's time to change jobs. There are many companies out there looking to nurture developers and grow them in a fair, compassionate manner. You deserve better! :) &lt;/p&gt;

&lt;h2&gt;Face-time between devs and clients is increasing&lt;/h2&gt;

&lt;p&gt;It is becoming more and more the norm that developers have to interact with clients. As I've progressed in my career, I've found that I've had to balance my time between directly contributing to a product's codebase, building new features and fixing bugs, to developing more bespoke and client-focused software. This means more meetings and collaboration with external tech teams. &lt;/p&gt;

&lt;p&gt;With this comes more possibility that you will be coding in front of somebody. For example, I've developed many custom RPA solutions for customers who wanted something very bespoke. On many occasions, this has meant working with a technical representative from a company I am working with. I've found myself in situations where the person on the other end of the Zoom call would say, '&lt;em&gt;this feature should do X&lt;/em&gt; &lt;em&gt;but it doesn't quite do it. Is it fixable?&lt;/em&gt;', and I would end up writing the code changes 'live' as it were before testing with the client to make sure it is up to scope. &lt;/p&gt;

&lt;p&gt;The first time I did this was nerve-wracking, but before I knew it, I was writing entire classes with somebody on a video call whom I'd only known for a week. The first time you do that and everything works first time, you feel pretty badass. From there on, it's a snowball effect. &lt;/p&gt;

&lt;h2&gt;Practice leads to confidence&lt;/h2&gt;

&lt;p&gt;There's no doubt that coding in front of people over and over again has made me more confident. If you're naturally quite insecure or suffer from the dreaded imposter syndrome, confidence is your gasoline. It's a scarce resource, but when you have it, and when you can use it, you're unstoppable. The annoying part is, as much as you don't want to do it, the very act of doing it repeatedly is how you become more confident. &lt;/p&gt;

&lt;p&gt;When I was a fresh-faced junior, if my future-self had travelled through time and said to me: '&lt;em&gt;in the coming years, you're going to be writing a blog post about how valuable it has been coding in public' &lt;/em&gt;I'd have laughed in my face. (Right after I regained consciousness after fainting because I had just met my future self.)&lt;/p&gt;

&lt;h2&gt;Strings to your bow&lt;/h2&gt;

&lt;p&gt;You can never have too many strings. If you're a competent developer but also have the ability to hold a conversation and fix/develop solutions for customers in real-time, without worrying too much about how you look and instead seeing it as an opportunity for growth, you're a pretty valuable engineer. &lt;/p&gt;

&lt;p&gt; So what are you waiting for? Put that side-project code you've been working on onto GitHub, make that YouTube video, write that blog post. &lt;/p&gt;

&lt;p&gt;It's not easy, trust me, but in the long-run, it's totally worth it. &lt;/p&gt;

</description>
      <category>career</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Clean Up Your .NET With the Dispose Pattern</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Mon, 15 Jun 2020 16:02:35 +0000</pubDate>
      <link>https://dev.to/nickproud/clean-up-your-net-with-the-dispose-pattern-4207</link>
      <guid>https://dev.to/nickproud/clean-up-your-net-with-the-dispose-pattern-4207</guid>
      <description>&lt;p&gt;In the managed-code world of .NET, we can be sometimes spoiled by the seamless intervention of &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/"&gt;Garbage Collection&lt;/a&gt; which quite happily waits until our objects are no longer referenced and then scoops them up and destroys them. That 'Person' object you're no longer referencing? Gone. That 'Tesla' object you lovingly inherited from 'Car' and then added loads of 'door' properties to? Obliterated.&lt;em&gt; See ya&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;What about when our old-buddy-old-pal the collector can't pick up our trash? What do we do when we are using a resource which is &lt;em&gt;unmanaged&lt;/em&gt; and therefore cannot be picked up for us?&lt;/p&gt;

&lt;p&gt;In these scary, less comfortable unmanaged situations, it's time for us to roll up our sleeves and muck in with the dispose pattern. &lt;/p&gt;

&lt;h2&gt;Unmanaged Resources&lt;/h2&gt;

&lt;p&gt;Most of the time when we are working with .NET, we are in a managed environment, which means that once an object has no references, it becomes 'orphaned.' From this point on, they become a candidate for garbage collection, meaning that whenever the amount of memory in use goes over a particular threshold, .NET identifies orphaned objects and disposes of them for you. &lt;/p&gt;

&lt;p&gt;But this is not necessarily the case for some resources, in particular resources that represent interactions with the operating system, such as operations on files or connections to a database. For these kinds of resources, not cleaning up after ourselves when we are done can become a problem. &lt;/p&gt;

&lt;h2&gt;IDisposable and the Dispose Pattern&lt;/h2&gt;

&lt;p&gt;.NET gives us many handy interfaces which we can implement to enforce a contract of expected behaviour. For managing the disposal of resources, we can implement the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.idisposable?view=netframework-4.8"&gt;IDisposable &lt;/a&gt;interface. Implementing IDisposable provides us with a means of releasing our hold on any unmanaged resources we no longer need, so as to conserve memory and ensure that we do not disrupt the flow of our program. &lt;/p&gt;

&lt;p&gt;Implementing IDisposable forces us to add a Dispose() method. This method can sit in a class in which we expect to use unmanaged resources. We can provide whatever logic is required in order to release the resource in this method. In the example below, we close out database connection in the Dispose method. &lt;/p&gt;

&lt;pre class="wp-block-preformatted"&gt;public static SqlConnection connection = new SqlConnection(connectionString);
        public void SaveToDB(Metric metric)
        {
            connection.Open();
            //do stuff
        }

        void Dispose()
        {
            connection.Close();
        }&lt;/pre&gt;

&lt;h2&gt;
&lt;em&gt;Please &lt;/em&gt;don't do it like that. &lt;/h2&gt;

&lt;p&gt;Disposing of our SQL connection in the manner shown above is a bad way to dispose of unmanaged resources. We would most likely have to call Dispose manually. This is not always avoidable, but in this scenario, there is a better way.&lt;/p&gt;

&lt;p&gt;In C#, the &lt;em&gt;using&lt;/em&gt; statement allows us to instantiate an object representing an unmanaged resource, and then use that object in a block of code which will automatically dispose of the object when it falls out of scope. So let's change our example above to dispose of the SqlConnection object as soon as we are finished with it. &lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            //do stuff
        }
        //out of scope, connection is disposed. &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As long as the enclosing type representing the unmanaged resource (in this case SqlConnection) implements IDisposable, we can use the &lt;em&gt;using &lt;/em&gt;statement to cleanly dispose of objects without having to call the method ourselves. &lt;/p&gt;

&lt;h2&gt;What if we still need to use &lt;em&gt;Dispose()&lt;/em&gt;?&lt;/h2&gt;

&lt;p&gt;You might find situations where you need to use an unmanaged resource within a custom class in which you need to implement IDisposable and work with Dispose manually. If this happens, there are a few extra scenarios to consider.&lt;/p&gt;

&lt;p&gt;The Dispose method can be called directly or indirectly by our code, meaning that we are controlling when the resource is being disposed of and the manner in which it is disposed of. However, the dispose method could also be called automatically by the runtime, as part of a 'finalizer.'&lt;/p&gt;

&lt;h2&gt;Finalizers&lt;/h2&gt;

&lt;p&gt;When the garbage collector releases an unmanaged resource it will 'finalize' the process of disposing of the object automatically for us. However, when it comes to unmanaged resources, it does not. This is where issues can begin to occur if for some reason &lt;em&gt;Dispose&lt;/em&gt; was not called by a consumer of a type using unmanaged resources. The finalization process would have no knowledge of that open SQL connection and it would just stay there. However, if we could tell the finalization process what steps it needs to take to kill that DB connection, that would be much better. We can override the normally automatic call to the Garbage Collector's &lt;em&gt;Finalize&lt;/em&gt; method with the use of a destructor. A destructor is simply a method named after the object in which resides preceded by a tilde (~) which will run on finalization.  &lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;~DBConnectorClass()
   {
      connection.Close()
      //finalized.
   }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is great for cleaning up our unmanaged resource when the garbage collector starts to do its rounds, but what if we have a situation where we have a finalizer, but a consumer of our type could also call &lt;em&gt;Dispose?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;&lt;em&gt;Dispose() Overload&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;We can call Dispose and pass a boolean value to indicate whether the call is coming from a consuming type for disposal (true) or whether the finalizer is running through its normal process (false)&lt;/p&gt;

&lt;p&gt;If the boolean evaluates to true, a block will run for the purpose of releasing managed objects. Following this, regardless of true or false the unmanaged objects will be released. Microsoft outline a really good example below:&lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;using System;

class DerivedClass : BaseClass
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   
   // Protected implementation of Dispose pattern.
   protected override void Dispose(bool disposing)
   {
      if (disposed)
         return; 
      
      if (disposing) {
         // Free any other managed objects here.
         //
      }
      
      // Free any unmanaged objects here.
      //
      disposed = true;
      
      // Call the base class implementation.
      base.Dispose(disposing);
   }

   ~DerivedClass()
   {
      Dispose(false);
   }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that there is a destructor at the bottom of the class above. This means that if one of our consuming types called &lt;em&gt;Dispose&lt;/em&gt; (passing true), a finalizer would no longer need to be run as part of garbage collection. But the runtime doesn't know that. So, we can tell it so. Below, you can see that our non-overloaded Dispose method is still in use, and would take care of our initial call with &lt;em&gt;Dispose(true) &lt;/em&gt;but then also uses a method in the &lt;em&gt;GC&lt;/em&gt; class to tell the runtime that finalizers no longer need to run for the object we are passing in. In this case, &lt;em&gt;this,&lt;/em&gt; meaning the current instance of the object in which the method resides. &lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;public void Dispose()
{
   // Dispose of unmanaged resources.
   Dispose(true);
   // Suppress finalization.
   GC.SuppressFinalize(this);
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Bossing the garbage collector around&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;GC.SuppressFinalize&lt;/em&gt; is &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.gc?view=netframework-4.8"&gt;one of many ways&lt;/a&gt; we can explicitly instruct the garbage collector to deviate from its default behaviour. There are many more methods we can use. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;GC.KeepAlive() &lt;/em&gt;tells the garbage collector that a specific object is not eligible for collection. &lt;/p&gt;

&lt;p&gt;On the flip-side, &lt;em&gt;GC Collect()&lt;/em&gt; forces garbage collection. This is particularly useful in some scenarios where you have a long-running set of processes. It is difficult to know when the garbage collector is going to kick in, and sometimes it can be a resource-intensive process. &lt;/p&gt;

&lt;p&gt;If you don't want to risk having a collection during an important operation. &lt;em&gt;GC.Collect()&lt;/em&gt; can make sure we force a collection so that one is not needed again for some time.&lt;/p&gt;

&lt;h2&gt;I find it tricky to fully understand myself&lt;/h2&gt;

&lt;p&gt;There's no doubt that automatic garbage collection is one of the major selling points of the .NET Framework. I'm not afraid to admit however that I personally find it a difficult subject to fully grasp. One of the reasons I decided to outline my interpretation of its functionality in a blog post was to hopefully better understand it and reaffirm what I do and don't know about something that is running constantly as I build software.&lt;/p&gt;

&lt;p&gt; I'm sure I will have gotten something wrong somewhere and no doubt somebody will (hopefully kindly) &lt;a href="https://www.automationmission.com/contact/"&gt;correct me&lt;/a&gt;. It just goes to show, sometimes we can take the hand-holding .NET gives us for granted, making it harder to understand the immense array of tasks going on under the hood, and this has only been a little &lt;em&gt;peek &lt;/em&gt;at a larger world of managed code. I think putting pen to paper on this one might make me brave enough to dig a little deeper.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Tracking Customer Usage in Your Software - Getting Started</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Wed, 10 Jun 2020 09:16:54 +0000</pubDate>
      <link>https://dev.to/nickproud/tracking-customer-usage-in-your-software-getting-started-4n3o</link>
      <guid>https://dev.to/nickproud/tracking-customer-usage-in-your-software-getting-started-4n3o</guid>
      <description>&lt;p&gt;You're thinking of changing a feature or adding a new one to your app, but you don't know how important it is to implement it. &lt;/p&gt;

&lt;p&gt;Does anyone need it? &lt;/p&gt;

&lt;p&gt;Does anyone use something similar already?&lt;/p&gt;

&lt;p&gt;Are you focusing on the right aspects of your app, or are there areas that are being neglected without your knowledge?&lt;/p&gt;

&lt;p&gt;For me, one of the most frustrating aspects of trying to develop and prioritise my roadmap is knowing what to focus on. I'm in a fortunate position in that I get to inform what features should be going onto the roadmap and which bugs should be prioritised as well as being able to write a lot of the code that builds those features or fixes bugs. This is all great, but there's nothing worse than when I am halfway through a project when I start to doubt its validity. When I eventually ship, what if nobody uses what I've written? It would be fair to say that I have wasted a considerable amount of time developing something that might be pretty cool, but ultimately redundant. &lt;/p&gt;

&lt;p&gt;With SaaS applications or E-Commerce sites, this data is usually available from the beginning. The cloud model is more conducive to tracking the behaviour of the people who grace us with their presence. When it comes to desktop or even mobile apps, it's less likely that we have mechanisms in place to collect usage data from our users. &lt;/p&gt;

&lt;p&gt;It became too tempting for me to ignore. I know people are out there and are getting something valuable from my code but I don't know &lt;em&gt;what&lt;/em&gt; specifically they see the value in. I have to build a metrics system. &lt;/p&gt;

&lt;h2&gt;The Serverless Approach to Gathering Data&lt;/h2&gt;

&lt;p&gt;I built a metrics system for tracking customer usage in a desktop app and I can honestly say that it has changed the way I manage the application roadmap dramatically. &lt;/p&gt;

&lt;p&gt;Here is a basic architectural overview of how I used Microsoft Azure as an environment for gathering usage data. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zz_pSuZW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.automationmission.com/wp-content/uploads/2020/02/AzureMetrics-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zz_pSuZW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.automationmission.com/wp-content/uploads/2020/02/AzureMetrics-1.png" alt="" class="wp-image-188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Fishing for raw data&lt;/h2&gt;

&lt;p&gt;To start with, you're going to want to know which aspects of application usage you are most interested in tracking. In my case, I'm responsible for an app which provides many varying types of automation. One feature might automate inserting records into a spreadsheet,  while another might post to Twitter. It's an application which holds an eclectic array of features. As it stands, I know from experience talking to some customers which are the most utilised features. With some features though, I'm not sure if &lt;em&gt;anyone&lt;/em&gt; uses them. &lt;/p&gt;

&lt;p&gt;To begin with, identify the main groups of data you need. If your app is a CRM, you might want to track how many people are using a specific filter on their list of Sales Leads. If your app is an FTP server, you might want to see which file format is most commonly uploaded before you decide to stop supporting it. In order to reach the point where this data is available for you to post to Azure, you need to capture it. &lt;/p&gt;

&lt;h3&gt;Event-Based Approaches&lt;/h3&gt;

&lt;p&gt;There are two main types of data domains to track. Events that happen in real-time and metadata. For tracking things as they happen, an event-driven model works pretty well. The two domains have one thing in common however, in that they will most likely be persisted as something worth tracking. A metric. &lt;/p&gt;

&lt;p&gt; Say I'm using MVC, and one of my controller classes (we'll call it   'InvoiceController') controls the flow of data from a pre-defined invoice model to our front-end. The controller may have events that are fired from the click of a button. This would be a perfect place to track the click of a button which approves an invoice for payment.   &lt;/p&gt;

&lt;p&gt;I find it useful to use interfaces to describe specific attributes for objects. This way we can implement specific interfaces on classes containing things we want to track to say that they can be tracked and what needs to be implemented on that class for that to happen.  I'm a .NET guy primarily, so I'm going to use an example in C#. Let's create an interface called ITrackable. This will describe what needs to be implemented in a trackable class in order to track something. (This is only a very basic example for the sake of simplicity. It can become way more verbose as needed)&lt;/p&gt;



&lt;pre class="wp-block-code"&gt;&lt;code&gt;interface ITrackable
    {
        void SaveToDB(Metric metric);
        void CreateMetric(object sender);
    }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wherever we implement ITrackable, we have to include two methods. One to create our metric, sending the actual object that was caught in a click event, and then SaveToDB, which will evidently serialize our metric data. Speaking of metric data, what would that be? Well again, I want to give a simple example, so I'll create a very basic class which can hold information about something we are tracking. &lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt;class Metric
    {
        string Name;
        DateTime CapturedAt;

        public Metric() { }

        public Metric(string metricName)
        {
            Name = metricName;
            CapturedAt = DateTime.Now;
        }
    }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So with the Metric class, we have a Name property, which is just the name of the 'thing that was clicked,' (We'll get this from the object sender on the original click event.), and then we have a DateTime in CapturedAt, which is just set to the current date and time when Metric is constructed. &lt;/p&gt;

&lt;p&gt;This means that we have a way to grab the object sender from a click event, get its name and name a Metric object after it, noting the time the event was raised and then calling a method to save this data to a DB. &lt;/p&gt;

&lt;p&gt;Simple right? Now let's make one our InvoiceController trackable.&lt;/p&gt;

&lt;pre class="wp-block-code"&gt;&lt;code&gt; class InvoiceController : ITrackable
    {
        public void SaveToDB(Metric metric)
        {
            //save to DB logic here.
        }
       
        public void CreateMetric(object sender)
        {
            var objectName = sender.GetType().Name;
            var metric = new Metric(objectName);
            SaveToDB(metric);
        }
        

        btnInvoiceApprove_Click(object sender, EventArgs e)
        {
            CreateMetric(sender);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the top then, we have our InvoiceController, which before we did anything to do with metrics had various click events from the front-end (namely our btnInvoiceApprove_Click event which, you guessed it, gets fired when we click a button to approve an invoice) now implements our ITrackable interface, meaning that it is required to include CreateMetric and SaveToDB.&lt;/p&gt;

&lt;p&gt;You've probably noticed that we have called one of our ITrackable interface methods on the click event. This is kind of like raising another event. We pass the sender argument for the click event to CreateMetric, which in turn uses GetType().Name to get the name of the object as a string. In this case the name may be 'btnInvoiceApprove' or 'ApprovalBtn' but either way we will recognise this as a button that was pressed. &lt;/p&gt;

&lt;p&gt;Following this, we create a new metric, named after our button and set to the current date and time, before calling our SaveToDB method to persist the data. &lt;/p&gt;

&lt;p&gt;Congratulations! It might not be super clear what you actually tracked, and it might be a &lt;em&gt;teeny weeny bit &lt;/em&gt;generic, but we have a starting point for tracking something in realtime and then saving it somewhere for use later. &lt;/p&gt;

&lt;p&gt;The other domain we talked about was metadata, which is usually a snapshot of the environment at a given time. For example, you might have something that says 'at the same time every day / or if I am open at a certain time, create metrics objects for x and then save them to the DB.' If we use the example of a CRM app again, it might be that this timed event goes to the DB and checks how many leads are saved at a given time and how many were changed. &lt;/p&gt;

&lt;p&gt;Once your data, whether it be realtime events or meta has been saved somewhere, you need to be able to view it. At this point however, it's still on our intrepid user's machine. How do we get it to it? Well, we don't. We make &lt;em&gt;it &lt;/em&gt;come to &lt;em&gt;us&lt;/em&gt;. I did this using the serverless approach with Azure Functions. &lt;/p&gt;

&lt;p&gt;Similar to the timed approach of capturing metadata at a set regular time, I then package that data into a format like JSON or XML and call my Azure Function's public endpoint from the app, posting the data to it. The function exists simply to parse the data I send and then put it into cloud storage for me to render in an app on my side. &lt;/p&gt;

&lt;h2&gt;Always be Open with your Users about Tracking, even if it's Anonymous.&lt;/h2&gt;

&lt;p&gt;Even if you take a totally different approach to tracking, it's extremely important to remember that you need to provide your users with a manner of consenting to have their usage tracked. &lt;/p&gt;

&lt;p&gt;You may decide that you don't want to capture any data that contains personal information, just behaviour within the UI. You still need to provide a way for the user to opt-out. Trust me, no amount of data is valuable enough that it is worth compromising someone's privacy not to mention making you liable to legal action. Make it clear what you are doing and make it easy to turn tracking off. &lt;/p&gt;

&lt;h2&gt;Getting the Data into the Cloud. &lt;/h2&gt;

&lt;p&gt;I'll go into more details on how we can ship analytics data to the cloud for analysis in another post. Depending on your app and how you wish to track and analyse its usage, your metrics system could get quite complex. Needless to say, if you don't currently engage much with the people who use your product, it will certainly provide you with a new means of planning product roadmaps for the better. &lt;/p&gt;

</description>
      <category>startup</category>
      <category>azure</category>
      <category>design</category>
    </item>
    <item>
      <title>Continuous Integration Should NEVER be rushed</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Wed, 10 Jun 2020 09:07:28 +0000</pubDate>
      <link>https://dev.to/nickproud/continuous-integration-should-never-be-rushed-1ak6</link>
      <guid>https://dev.to/nickproud/continuous-integration-should-never-be-rushed-1ak6</guid>
      <description>&lt;p&gt;Continuous integration is a wonderful thing. The historical process of moving code around from person to person in various different version control systems before running a manual build is just that. &lt;em&gt;History.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But now the relatively young discipline of DevOps is gaining traction with the introduction of various cloud services and on-prem server solutions that boast the ability to bring Continuous Integration to your dev team's workflow. &lt;/p&gt;

&lt;blockquote class="wp-block-quote"&gt;&lt;p&gt;What are we waiting for! Chuck all of the code into an Azure DevOps / Github / GitLab repo STAT! I've put a pipeline together which will build all our code for us and even test a bit too! We're all set right?&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Wrong. &lt;/p&gt;

&lt;p&gt;Now, I am not a DevOps engineer at all. I am a software engineer, and I happen to think that the two roles differ significantly in a lot of areas. So I am certainly not qualified to tell you how you must implement your CI pipelines. However, I can (as someone on the dev side of the issue) tell you how &lt;em&gt;not to do it. &lt;/em&gt;(Or at least how you can best prepare before you even start) &lt;strong&gt;(This is also not an attack by any means on DevOps engineers, most of whose talent and knowledge easily eclipses mine! This is mostly for smaller companies looking to start from scratch with DevOps)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Don't just do 'what Microsoft or Netflix does.'&lt;/h2&gt;

&lt;p&gt;It's an easy mistake to make. Microsoft build Azure DevOps so surely we have to run our CI process exactly like them right? Well not necessarily. The obvious fact is, you're either Microsoft or you're not. You will most likely have very different ways of working to Microsoft, who have spent decades perfecting their development workflows for the many different products they produce. &lt;/p&gt;

&lt;p&gt;There are plenty of articles out there outlining how different companies like &lt;a href="https://azure.microsoft.com/en-gb/resources/videos/ignite-2018-how-microsoft-builds-software-and-services-like-windows-office-bing-minecraft-and-others-powered-by-azure-devops/"&gt;Microsoft &lt;/a&gt;and &lt;a href="https://medium.com/netflix-techblog/how-we-build-code-at-netflix-c5d9bd727f15"&gt;Netflix&lt;/a&gt; run their workflows. While these are valuable insights and can certainly be a source of inspiration, it doesn't change the fact that you most likely have very different needs. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You may have a smaller team. A workflow designed to cater for hundreds of commits to a single branch per day might be overkill if you have a team of 5 developers working on one product. &lt;/li&gt;
&lt;li&gt;Legacy software such as codebases running VB6 or heavily ActiveX driven code is not a good fit for a lot of pipeline solutions, particularly Azure Pipelines. &lt;/li&gt;
&lt;li&gt;You may have different levels of reporting requirements from your leadership team, changing the number of approvals for each process which in turn can even affect the kinds of branches you use. &lt;/li&gt;
&lt;li&gt;Your software may need to be tested in a wide number of environments for cross-platform compatibility or account for extremely specific situations / environmental configurations. This can call into question whether you use a containerized approach to CI.&lt;/li&gt;
&lt;li&gt;You may want to enforce automation for code standards such as linting &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the companies who's workflows you may find it easier to simply emulate have very particular policies when it comes to shipping code. It has been rumoured for example that some sites like GitHub will ship directly to production, opting to fix with patches as issues are found by the community. If it's true, it must be working for GitHub, but can you honestly say that would work for your highly sensitive banking app?&lt;/p&gt;

&lt;p&gt;The above points are only a fraction of the many idiosyncracies found within software teams and companies, which leads me to my next point.&lt;/p&gt;

&lt;h2&gt; There is no 'One Size Fits All' Approach to CI&lt;/h2&gt;

&lt;p&gt;I hope I've conveyed in the above that it is naive to think that there is one, universal standard for CI. A &lt;a href="https://cmustrudel.github.io/papers/fse18cd.pdf"&gt;recent research paper&lt;/a&gt; conducted in partnership between the National University of Defense Technology, China,  Carnegie Mellon University and the University of California looked into the application of standardized CI frameworks specifically with the containerization behemoth Docker and reached the conclusion that:&lt;/p&gt;

&lt;blockquote class="wp-block-quote"&gt;&lt;p&gt;Most of our survey findings were confirmed in the data, but some were not, emphasizing the power of mixed methods to produce holistic findings. Our findings indicate that developers face trade-offs when choosing between different CD workflows with respect to config-urability, simplicity, requirements, performance, stability, developer experience, etc., and we were able to distill some implications for different stakeholders &lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The sentiment is also put across quite nicely by consultancy &lt;a href="https://www.version1.com/devops-adoption-challenges/"&gt;Version1.com&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote class="wp-block-quote"&gt;
&lt;p&gt;There is no “one size fits all” when it  comes to DevOps implementation and processes. It should vary depending  on what you’re doing, what type of organisation and software  applications you use, deploy or manage... &lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2&gt;Build a Process &lt;em&gt;with &lt;/em&gt;Developers, not &lt;em&gt;for &lt;/em&gt;them&lt;/h2&gt;

&lt;p&gt;The introduction of any new process can rock even the sturdiest of boats, but if there is anyone who stereotypically despises change it is the Software Developer.  &lt;/p&gt;

&lt;p&gt;I may be being presumptuous, but I know from experience that if a process is introduced that affects the way you deliver, you want to be consulted. &lt;/p&gt;

&lt;p&gt;This need for involvement doesn't stem from an infantile need to have our own way but instead comes from a desire for collaborations and a yearning for good communication between Development and DevOps teams. &lt;/p&gt;

&lt;p&gt;It's win-win to work together to implement CI. Your developers fully understand their process, what works well and the technical hurdles that may arise when automation is applied. Putting this together with the expertise of the DevOps engineers who understand the capabilities of the myriad CI tools at your disposal and you are on your way to winning the war, together. &lt;/p&gt;

&lt;p&gt;We're also forgetting the QA guys. In a lot of organisations, they are the last people to handle code before it goes out into the world. It might be a good idea for them to be in the loop from the beginning so that you can better design the process that ultimately prepares the product for their sign-off.&lt;/p&gt;

&lt;h2&gt;Take it Slow&lt;/h2&gt;

&lt;p&gt;I have limited experience with CI tools but I have worked mostly with Azure DevOps and JetBrain's TeamCity. I like them both, but they have one challenge in common; the sheer amount of potential configurations. &lt;/p&gt;

&lt;p&gt;Of course, there are going to be so many different ways to configure a CI solution, seeing as there are so many different ways to build your code. What I would ultimately advise anyone looking to start their treacherous journey into the realms of release automation is to walk before you can run. &lt;/p&gt;

&lt;p&gt;Maybe try automating just one of your low-impact repos first and have a gameplan for how you can switch back to your original configuration if something goes terribly wrong. Maybe you could run a side-by-side comparison of your current process along with your proposed shiny new one, to see if you have any '&lt;em&gt;if it aint broke don't fix it&lt;/em&gt;' areas to retain.&lt;/p&gt;

&lt;p&gt;The whole point of CI, in general, is to make you ship code quickly whilst maintaining a high level of quality. In many cases, rushing to use a new process will certainly allow you to ship code quicker, but will it be stable or riddled with bugs? It's very hard to say and for me, jumping blindly into this with production code, without a test or even staging run before it reaches customers is too high a risk. &lt;/p&gt;

&lt;p&gt;I totally believe in the old maxim that says '&lt;em&gt;shipping is a feature.' &lt;/em&gt;I also think that your product becoming drastically more unstable because you rushed into a sexy new process should not be. &lt;/p&gt;

&lt;p&gt;Remember, slow and steady builds the pipeline. &lt;/p&gt;

</description>
      <category>devops</category>
      <category>startup</category>
      <category>agile</category>
    </item>
    <item>
      <title>How to Make an IoT Network Uptime Alarm</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Sat, 17 Aug 2019 15:50:16 +0000</pubDate>
      <link>https://dev.to/nickproud/how-to-make-an-iot-network-uptime-alarm-65m</link>
      <guid>https://dev.to/nickproud/how-to-make-an-iot-network-uptime-alarm-65m</guid>
      <description>&lt;p&gt;For those of who manage multiple network-attached devices, website or servers, it's important to know when they are down as soon as possible.&lt;/p&gt;

&lt;p&gt;Whether you are responsible for keeping a website up, a file server running smoothly, or if you just want to know if your home router goes down, microcontrollers are making it even easier for people to build monitoring solutions.&lt;/p&gt;

&lt;p&gt;Recently, I dove into the world of the Internet of Things to develop a simple alarm device which checks a pre-defined IP Address / DNS name every 5 seconds and sounds an alarm if the host does not reply to ping.&lt;/p&gt;

&lt;p&gt;Its the kind of project which can be easily put together with a fantastic, inexpensive microcontroller called the ESP8266 and I am going to show you how you can build one of these yourself to monitor your servers, websites or even your smart fridge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Do I Need?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  An ESP8266
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DolGchhJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.automationmission.com/wp-content/uploads/2019/08/ESP8266.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DolGchhJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.automationmission.com/wp-content/uploads/2019/08/ESP8266.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the NodeMCU version of the EDP8266 which is the version I used to build this device.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/ESP8266"&gt;ESP8266&lt;/a&gt; is an amazing (and very cheap at roughly $6 dollars) piece of equipment.&lt;/p&gt;

&lt;p&gt;It is a WiFi microchip that is able to exploit the full TCP/IP stack. Whats more, it's a microcontroller, so you can program it in the same what you would an Arduino Uno or Arduino Mega controller board.&lt;/p&gt;

&lt;p&gt;This means that with just this board, a breadboard, a few jumper wires and an active buzzer, we have the hardware we need to build our alarm.&lt;/p&gt;

&lt;p&gt;I'll quickly go over how we connect this to the rest of our hardware so that we can get to the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boards and Wires and Buzzers Oh My!
&lt;/h3&gt;

&lt;p&gt;This guide is mostly about the code we're writing to develop the network monitoring functionality, so a basic familiarity with circuits is assumed. However the diagram below should be enough to show you how to build a circuit for the ESP8266 and a buzzer on a breadboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--19mPD4An--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.automationmission.com/wp-content/uploads/2019/08/Circuit-2-1024x647.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--19mPD4An--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.automationmission.com/wp-content/uploads/2019/08/Circuit-2-1024x647.png" alt=""&gt;&lt;/a&gt;&lt;em&gt;From left going clockwise: 1. ESP8266 board connected via USB, 2. connection to buzzer from VIn\&lt;br&gt;
pin on ESP8266, 3. Ground connection from buzzer to GND pin on EDP8266, 4.connection to NPN BC337 Transistor from buzzer\&lt;br&gt;
, 5. connection from transistor to a 1k Ohm Resistor, 6. connection from resistor to D1 pin on ESP8266.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can also find a more in-depth guide to the circuit on circuito.io &lt;a href="https://www.circuito.io/static/reply/index.html?solutionId=5d56a46438405c0030eb9a74&amp;amp;solutionPath=storage.circuito.io"&gt;here&lt;/a&gt;. This will show you how to put it together in more detail. There is a code sample from circuito.io which uses the buzzer.h library to send signals to the buzzer. I am not using this for the purposes of this device. I instead will be sending signals to the D1 -- digital pin connected to the buzzer.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;I'll be walking through how I wrote the code for the device so feel free to follow along. However, if you want to build the circuit and flash the code straight onto it, or even adapt my code for yourself, you can find the repo on &lt;a href="https://github.com/nickproud/IoTNetworkAlarm"&gt;Github.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Pre-Requisites
&lt;/h3&gt;

&lt;p&gt;Before you dive into the main device sketch below, make sure you have installed the &lt;a href="https://www.arduino.cc/en/Main/Software"&gt;Arduino IDE&lt;/a&gt; and then within that, &lt;a href="https://www.arduino.cc/en/guide/libraries"&gt;install the ESP8266-ping Arduino IDE library by within the IDE&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add the Header Files
&lt;/h3&gt;

&lt;p&gt;We will be writing this program in C so a familiarity with the language is certainly a help, but in terms of complexity, this is quite a simple program.&lt;/p&gt;

&lt;p&gt;We need two libraries in order to make this device work. The ESP8266Wifi library will be required so that we can use your local WiFi network to contact our remote host. Secondly, the Pinger library which we installed in the IDE before we started writing our code.&lt;/p&gt;

&lt;p&gt;In C, we add these dependencies in the form of header files referenced at the top of our code as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;ESP8266WiFi.h&amp;gt;
#include &amp;lt;Pinger.h&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then it's time to declare our variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const char* ssid = "your_ssid";
const char* password = "your_password";
const char* hostIP = "ip_of_host_you_are_monitoring";
#define D5 14
int SpeakerPin = 14;
Pinger pinger;
bool success = false;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Shown above, we are declaring three constants to hold the SSID of our WiFi network, the WiFi password and the the IP of the host we wish to monitor. This could be the IP of a website or a device for which you wish to receive alarms if it were to go down. You can also supply a DNS name, as the Pinger library is capable of targeting hosts by name rather than by IP.&lt;/p&gt;

&lt;p&gt;After defining our char constants, we use the #define keyword to translate the ESP8266's pin 14 to D5, which is the digital pin we are using to send a signal to our buzzer. This means that when we set our SpeakerPin variable to the integer 14, we are really pointing to D5. This can be confusing, but we are really just accouting for a mismatch in pin assignments on the ESP8266. Take a look &lt;a href="https://techtutorialsx.com/2017/04/02/esp8266-nodemcu-pin-mappings/"&gt;here&lt;/a&gt; for more information on how pins are mapped on the ESP8266&lt;/p&gt;

&lt;p&gt;Finally, we have set a Pinger object, which is an instance created from the Pinger.h library responsible for the pings being sent to our monitored host, as well a boolean to track successful pings. We will use this boolean to detirmine if the alarm should sound.&lt;/p&gt;

&lt;p&gt;Next we will make a method to connect to our WiFi network called ConnectToWiFi(), which can itself be called in the Setup() method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void connectToWiFi()
{
  Serial.print("\n\nConnecting...");

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.print("Connected to router on IP address: ");
  Serial.println(WiFi.localIP());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next up, we are writing a basic method for the alarm sound. The below Alarm() method simply writes a signal to the D5 pin supply current to the buzzer (which makes it sound), waits for half a second and then stops the current to stop the buzzer before repeating the same process several times with a half-second delay between each signal change. This allows us to make the buzzer sound when we call Alarm()&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void Alarm()
{

//digitalWrite() is a method that sends current to a pin which is either   HIGH (on) or LOW(off). We are sending the current to the SpeakerPin which we defined at the top of our program. (Pin D5 on the board)

  digitalWrite(SpeakerPin, HIGH);
  delay(100);
  digitalWrite(SpeakerPin, LOW);
  delay(100);
  digitalWrite(SpeakerPin, HIGH);
  delay(100);
  digitalWrite(SpeakerPin, LOW);
  delay(100);
  digitalWrite(SpeakerPin, HIGH);
  delay(100);
  digitalWrite(SpeakerPin, LOW);
  delay(100);
  digitalWrite(SpeakerPin, HIGH);
  delay(100);
  digitalWrite(SpeakerPin, LOW);

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we define the logic within our Setup() method. This is called before our program loop. In this method we use pinmode() to define our D5 pin as an output for the buzzer current. Then we call our ConnectToWifi() method and then we add an event to the Pinger object to handle what happens when the ping request has finished.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(SpeakerPin, OUTPUT);
  connectToWiFi();

  pinger.OnEnd([](const PingerResponse&amp;amp; response)
  {
    if(response.TotalReceivedResponses &amp;gt; 0)
    {
      Serial.print("Host online\n");
      success = true;
      return true;
    }
    else
    {
      Serial.print("ERROR: Unable to reach host. Sounding alarm\n");
      success = false;
      return false;
    }

  });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The pinger.OnEnd event checks the ping response from the remote host and decides whether the alarm needs to be sounded. If the response is greater than 0, all is well and the success boolean we set at the top of the program is set to true, otherwise, we log an error to the serial port and set success to false. Then we can finish the program by define the method that will run continuously after Setup() is complete, Loop():&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("pinging....\n");
  pinger.Ping(hostIP);
  if(!success)
  {
    Alarm();
  }
  delay(5000);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Loop() is nice and simple. We are just pinging our remote host every 5 seconds. If the success variable was set to true, we do nothing, otherwise, we call the Alarm() method to sound the buzzer.&lt;/p&gt;

&lt;p&gt;If the circuit is connected correctly and the code is without error, we have ourselves bona fide network uptime alarm! For use in production, you could put this in a small enclosure and attach a battery to it so that it will just monitor your network for you and alert you as soon as something is wrong.&lt;/p&gt;

&lt;p&gt;Take a look at the alarm I built in &lt;a href="https://www.automationmission.com/wp-content/uploads/2019/08/VID_20190812_231029.mp4"&gt;this video.&lt;/a&gt; I configured it to monitor my main development machine. As soon as I disabled the WiFi adapter on the machine, taking it off the network, the alarm started to sound. It did not stop until the machine was back on the network.&lt;/p&gt;

</description>
      <category>c</category>
    </item>
    <item>
      <title>The New Golden Age of .NET is Upon Us</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Wed, 31 Jul 2019 19:39:38 +0000</pubDate>
      <link>https://dev.to/nickproud/the-new-golden-age-of-net-is-upon-us-1iig</link>
      <guid>https://dev.to/nickproud/the-new-golden-age-of-net-is-upon-us-1iig</guid>
      <description>&lt;p&gt;One framework to rule them all. Is it a good thing? Is it dangerous, or is it the best thing to happen to Software Developers since the creation of Javascript? (&lt;a href="https://en.wikipedia.org/wiki/JavaScript"&gt;In 10 days...&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Depending on which software eco-system you spend most of your time in, you may have conflicting ideas on the questions above. You may have never touched .NET. Maybe because it has largely been a Microsoft-centric framework for a long time, skewed towards a more 'corporate' user-base.&lt;/p&gt;

&lt;p&gt;Until the (still relatively recent) introduction of .NET Core, the .NET Framework has been a framework which ties you to Windows.&lt;/p&gt;

&lt;p&gt;Windows Forms.&lt;/p&gt;

&lt;p&gt;Windows Presentation Foundation.&lt;/p&gt;

&lt;p&gt;Universal Windows Apps.&lt;/p&gt;

&lt;p&gt;Windows Store Apps.&lt;/p&gt;

&lt;p&gt;For a long time, if you have been developing desktop apps in .NET, you've lived in Windows. Even on the web, for ages you were usually deploying to IIS, looking to other runtimes like Mono to deploy elsewhere.&lt;/p&gt;

&lt;p&gt;.NET Core has been a liberating arrival for developers wanting to take their code cross-platform but we still had this segreation of frameworks, this division between .NET Framework and .NET Core.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;How long will it take us to port our code to .NET Core? I want to run this stuff on Linux!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This has been a &lt;em&gt;big&lt;/em&gt; part of my dev-life recently.&lt;/p&gt;

&lt;p&gt;Even running with the policy of '&lt;em&gt;new code might as well use .NET Core&lt;/em&gt;' isn't bullet-proof. You may have experienced that common issue where one of your key dependencies is not yet supported in Core.&lt;/p&gt;

&lt;p&gt;You may have also had major a dilemma when looking to move a VB.NET codebase to .NET Core in that you had to wait until 2018. (By which time you may have already re-written it in C#, which I think is a good idea to be fair.)&lt;/p&gt;

&lt;h2&gt;
  
  
  What's my stance on .NET Core?
&lt;/h2&gt;

&lt;p&gt;Put simply, I think it's awesome.&lt;/p&gt;

&lt;p&gt;Microsoft's decision to open-source huge amounts of the .NET Framework has introduced fixes and amazing new features we may never have seen had it stayed closed.&lt;/p&gt;

&lt;p&gt;It has democratised the code-base so much that, while it may be governed by Microsoft, it feels like a more open, agnostic framework.&lt;/p&gt;

&lt;p&gt;I mean, take C#. I can safely say it is my main language. It's the language I use the most on a day-to-day basis. For me, it's the cream of .NET. So when the &lt;a href="https://github.com/dotnet/roslyn"&gt;C# Roslyn compiler became open-source&lt;/a&gt;, it blew my mind.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You're telling me I can go through this thing's guts and even change it if I want to!?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So yeah, I sometimes still can't believe .NET Core is actually a thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  So Isn't this a Golden Age Already?
&lt;/h2&gt;

&lt;p&gt;I don't think so. I think the best is yet to come. I think the Golden Age will arrive in the form of &lt;a href="https://devblogs.microsoft.com/dotnet/introducing-net-5/"&gt;.NET 5.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is .NET 5?
&lt;/h2&gt;

&lt;p&gt;.NET 5 is the next release to follow .NET Core 3.0. That means no .NET Core 4.0, just one single framework.&lt;/p&gt;

&lt;p&gt;In fact, it takes the innovations brought to us by .NET core and expands on them, meaning that with a single framework, we will be able to write applications for Windows, Linux, macOS, iOS, Android, tvOS, watchOS and WebAssembly to name a few.&lt;/p&gt;

&lt;p&gt;Microsoft has openly admitted that this next iteration on the framework will be a combination of the best bits of .NET, .NET Core, Mono and Xamarin combined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does this Matter?
&lt;/h2&gt;

&lt;p&gt;It matters because it takes the democratisation I referred to above and feeds it a shipping container's worth of Red Bull.&lt;/p&gt;

&lt;p&gt;Having all the benefits of Core in one place, one visual studio project, one CLI and knowing that I can deploy it pretty much anywhere, as well as fix any bugs in the framework myself is pretty much God-Mode for any .NET developer.&lt;/p&gt;

&lt;p&gt;It's the icing on the cake if you already love .NET, and it may be the very reason developer's who don't currently touch it pull up a seat at the table.&lt;/p&gt;

&lt;p&gt;There's a hell of a lot of competition out there still for .NET. For example, I'm fascinated with the things developers are churning out with speedy languages like Go and how new versions of the language like &lt;a href="https://github.com/tinygo-org/tinygo"&gt;TinyGo&lt;/a&gt; are challenging Microsoft in the IoT space.&lt;/p&gt;

&lt;p&gt;But who is to say that the new phase in .NET's life-cycle will not be the catalyst in a movement of new, .NET inspired languages?&lt;/p&gt;

&lt;p&gt;Most of us are used to the fact that C++, C++, Javascript and Java are heavily influenced by (or even abstracting on top of) C. Just as Go gives developers the power of a lower-level C-like language with some handy memory management to boot.&lt;/p&gt;

&lt;p&gt;Now that the .NET framework is being unified on top of being open-sourced, could we see a new off-shoot of C# as TinyGo is to Go, or Go is to C?&lt;/p&gt;

&lt;p&gt;What's certain is that competition can only be a good thing, and so it will be fascinating to see how other frameworks from players like Google and Apple will respond to the great 'Microsoft Unification' to come.&lt;/p&gt;

&lt;p&gt;In the meantime, while we eagerly await the arrival of .NET 5, take a look back on the evolution of .NET on &lt;a href="https://dotnetcore.show/episode-30-reflections-on-net-with-pablo-santos-and-phil-haack/"&gt;this great episode of the Dot Net Core Podcast&lt;/a&gt; which looks back on how far .NET has come throughout the years.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>There Are No Stupid Questions, Just Insecure Developers</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Tue, 23 Jul 2019 20:51:48 +0000</pubDate>
      <link>https://dev.to/nickproud/there-are-no-stupid-questions-just-insecure-developers-i04</link>
      <guid>https://dev.to/nickproud/there-are-no-stupid-questions-just-insecure-developers-i04</guid>
      <description>&lt;p&gt;Letting people know you don't know something isn't easy but it's better in the long run.&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%2Fwww.automationmission.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fcamylla-battani-AoqgGAqrLpU-unsplash-1024x683.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.automationmission.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fcamylla-battani-AoqgGAqrLpU-unsplash-1024x683.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the amount of people entering the tech industry grows, so does the competition. A heightened atmosphere of competition brings with it a growing sense of insecurity for developers, and guess who doesn't like to show they don't know something that others do; Insecure people.&lt;/p&gt;

&lt;p&gt;'Imposter Syndrome' is the feeling that you do not belong in a particular environment and that one day, you are going to be exposed for the fraud that you are before being ejected from your profession with your reputation in tatters.&lt;/p&gt;

&lt;p&gt;You might suffer from this all too common affliction, feeling like everyone else in your team has a firmer grasp of a particular technology or codebase. I know I have felt like this in the past. I studied Music and Drama at university, not computer science, and so when thrown into a team of people who did go to school for CS, it's easy to feel like an imposter.&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%2Fwww.automationmission.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fjon-tyson-RUsczRV6ifY-unsplash-225x300.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.automationmission.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fjon-tyson-RUsczRV6ifY-unsplash-225x300.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For software developers in particular, one of the most dangerous aspects of Imposter Syndrome is its ability to deter you from ever asking questions.&lt;/p&gt;

&lt;p&gt;Let's say you are sitting in a meeting and one of your colleagues mentions a particular JavaScript framework and how it can be applied to one of your requirements. Your colleague talks about the framework implicitly, assuming everyone understands what he is talking about, and sure enough, the other developers in the room are nodding along, except you.&lt;/p&gt;

&lt;p&gt;Well, you may be nodding along, but that certainly doesn't mean that you understand. This is often the starting point of a lot of anxiety for developers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm the only one who doesn't understand. I can't let anyone know that I'm clueless!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's impossible at that moment to know for sure, but chances are you are not the only developer in the room scratching their head. What is for sure though is that you &lt;em&gt;can&lt;/em&gt; let slip that you don't understand. In fact, you ought to.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Don't Know What That Means. Can you explain it to me?
&lt;/h2&gt;

&lt;p&gt;It's perfectly ok to say that you don't know something. People with Imposter Syndrome think it's a bad idea, but actually, admitting you don't know something and asking for someone to explain it has some real benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You identify gaps in your knowledge.&lt;/li&gt;
&lt;li&gt;  Knowing which gaps you have, you can plug them.&lt;/li&gt;
&lt;li&gt;  You grow as a developer&lt;/li&gt;
&lt;li&gt;  Somebody else gets to reinforce their knowledge through teaching.&lt;/li&gt;
&lt;li&gt;  You and the team are more confident and competent.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;But won't I be judged for not knowing Framework X?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Honestly? I don't know. Neither can you truly know what people think when you admit to not having expertise in a particular area. One thing I do find in this situation is that the way people react serves as a fantastic barometer for understanding the attitudes of people in your company.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yes. Some People Are Judgemental.
&lt;/h2&gt;

&lt;p&gt;If people judge instantly, it's a sure sign that there is a culture problem. I'll admit, it's difficult to give advice on how to deal with this dilemma because I don't have a huge amount of experience of dealing with judgemental, egotistical tech people. The one place I worked at where this happened to me, I found my current day-job and everyone there is understanding and happy to help. So I count myself quite lucky.&lt;/p&gt;

&lt;p&gt;So I guess if you find yourself in the above situation, maybe you have some soul-searching to do to know if you are in the right place. That doesn't mean all is lost. You might find that actually asking for guidance appeals to the ego of some more judgemental people. At the very least, you will learn something, and hey, it might propel you towards a better job with friendlier people like it did for me.&lt;/p&gt;

&lt;p&gt;What I do find however is that most people respect you more for admitting that you don't know something. Even more so when you actually ask for help.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's Worse The Longer You Leave It.
&lt;/h2&gt;

&lt;p&gt;I've worked with developers who didn't put their hand up when the time was right; the crucial stage at the beginning of a project where roles are being assigned and you have that opportunity to say &lt;em&gt;'this is new to me, I will need a little help getting started.'&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A month down the line, they hadn't delivered, and they were so swallowed up by their need to hide their inexperience in a particular area that they became a liability. This is where things become actually damaging to them. It damages the team, it damages the project and damages your professional reputation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are You Afraid Of?
&lt;/h2&gt;

&lt;p&gt;Maybe you couldn't quite believe you won the role you're in, or maybe you find yourself on a particularly strong team that looks from the outside to be a bustling hive of 'uber-programmers' that can do anything.&lt;/p&gt;

&lt;p&gt;Appearences are deceiving. Its extremely likely that if you have been programming for at least a year that you have experience in a certain area that the lead developer on your team has none in. You just don't get the opportunity to use it at work.&lt;/p&gt;

&lt;p&gt;The answer to this might be to actually take the opportunity to lead on a project so that you can bring in some new ideas based on areas that you have expertise in. If you think for example, '&lt;em&gt;nobody here has ever done anything with Angular but I know it really well,'&lt;/em&gt; maybe you have an opportunity to become a mentor to more experienced developers by leading a prototype in that framework on your next project.&lt;/p&gt;

&lt;p&gt;That said, be careful, based on the above example, if Angular didn't suit the project, don't pitch it just because you know it better than everyone else. That can be a recipe for disaster and even being able to evaluate which technologies are best suited to a project is a skill in it's own right.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm New and I Want To Make a Good First Impression.
&lt;/h2&gt;

&lt;p&gt;It's easier said than done to be open about your weaker areas when you are new at a company and looking to make a good first impression. Imposter Syndrome is at it's most previlant in this early stage of your tenure at your new company and it is tempting to nod along and pretend you know what everyone is talking about.&lt;/p&gt;

&lt;p&gt;But think about the first impression you give for your first deliverable. When you deliver something of low quality because you scraped by pretending to know what you were doing, you've delivered the very poor impression you were looking to avoid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put Your Hand Up and Ask For Help
&lt;/h2&gt;

&lt;p&gt;I like to think that I can tell when someone is pretending to understand something they don't. It's awkward and it's hard to use the phrase '&lt;em&gt;does that make sense?'&lt;/em&gt; too many times because you don't want to appear arrogant or patronising. But I personally always have respect for people who say that it doesn't make sense to them when it doesn't.&lt;/p&gt;

&lt;p&gt;I know &lt;em&gt;that&lt;/em&gt; person is going to improve.&lt;/p&gt;

&lt;p&gt;I know &lt;em&gt;that&lt;/em&gt; person cares about their own personal development as a programmer.&lt;/p&gt;

&lt;p&gt;I know &lt;em&gt;that&lt;/em&gt; person cares about the quality of their code and I know the one day &lt;em&gt;that&lt;/em&gt; person will be mentoring someone else in the very subject at which they are today a novice.&lt;/p&gt;

&lt;p&gt;To anyone who might be suffering from the debilitating Imposter Syndrome all too common in the tech industry, please take solace in knowing that nobody can know everything. It doesn't mean you don't deserve a seat at the table.&lt;/p&gt;

&lt;p&gt;Take your seat. You're welcome here.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>S.O.L.I.D Windows Forms</title>
      <dc:creator>Nick Proud</dc:creator>
      <pubDate>Mon, 22 Jul 2019 18:22:32 +0000</pubDate>
      <link>https://dev.to/nickproud/s-o-l-i-d-windows-forms-86n</link>
      <guid>https://dev.to/nickproud/s-o-l-i-d-windows-forms-86n</guid>
      <description>&lt;p&gt;We all know that Windows Forms is old. Like &lt;em&gt;really&lt;/em&gt; old. (Especially so in software terms). Windows Forms shipped with the &lt;a href="https://en.wikipedia.org/wiki/.NET_Framework_version_history"&gt;version 1.0 of the .NET framework back on 13th February 2002&lt;/a&gt;, long before I had committed myself to a life of coding.&lt;/p&gt;

&lt;p&gt;Windows Forms may have already been a seasoned UI framework when I started my programming career but like a lot of developers starting out with .NET (or even VB6), the Windows Form editor is where you get your first taste after playing with the console.&lt;/p&gt;

&lt;p&gt;I always thought they would be dropped quickly. Soon I would be mostly developing front-ends for desktop applications using XAML, or even exploiting the benefits of &lt;a href="https://electronjs.org/"&gt;Electron&lt;/a&gt; to deploy web applications as native desktop applications.&lt;/p&gt;

&lt;p&gt;But no. I still find myself confronted with requirements to support Windows Forms apps and you know what?&lt;/p&gt;

&lt;p&gt;That's &lt;em&gt;fine.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But does that mean we have to structure our code in a archiac way? Of course not!&lt;/p&gt;

&lt;p&gt;The last decade has seen the proliferation of a fantastic new movement in software engineering practice in the &lt;em&gt;Clean Code Movement.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Clean code pioneers like Robert C. (Uncle Bob) Martin have paved the way for easier to read, manageable and maintainable code, etching in stone the new holy commandments to which all developers should take note:&lt;/p&gt;

&lt;h4&gt;
  
  
  The S.O.L.I.D. Principles
&lt;/h4&gt;

&lt;p&gt;Most developers these days have come across some mention of these new principles but in case you need a solid &lt;em&gt;(meheh)&lt;/em&gt; definition &lt;a href="https://en.wikipedia.org/wiki/SOLID"&gt;check out the wikipedia entry for them.&lt;/a&gt; There are many easier to digest explanations in book form. I recommend Robert C. Martin's classic &lt;em&gt;&lt;a href="https://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?keywords=clean+code&amp;amp;qid=1563476866&amp;amp;s=gateway&amp;amp;smid=A3P5ROKL5A1OLE&amp;amp;sr=8-1"&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Yeah but who cares about SOLID in Windows Forms?!
&lt;/h4&gt;

&lt;p&gt;I like to think that I adhere to these principles as much as possible. It's not easy but nothing worth doing is at first. However, when it comes to developing code for UI, I have to admit that can sometimes get a little lazy.&lt;/p&gt;

&lt;p&gt;I'm more of a 'back-end' developer. I like building the engine. Of course, I want everything to look nice and be easy to use, but I don't get as excited about front-end development. This started to show when I was recently developing the front-end for my Windows Event Log automation tool, &lt;em&gt;AutoEvent,&lt;/em&gt; which just so happens to use Windows Forms. (Yes I still use Windows Forms from time to time. I prefer web front-ends but sometimes Windows Forms is all you need!)&lt;/p&gt;

&lt;p&gt;I was writing code to manage the way the main page renders UI controls and making different controls visible/hidden when a particular tab was clicked. A basic toggle.&lt;/p&gt;

&lt;p&gt;It's common to have to add new functionality on top of small blocks of code as you progress through your UI development in a basic app but I found myself writing some sloppy toggle logic. Take the below button event for example, which changes the UI elements that are visible based on whether I click the *'*Settings' or 'Triggers' tab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; private void RibbonControlAdv1_SelectedTabItemChanged(object sender, SelectedTabChangedEventArgs e)
        {
            switch(ribbonControlAdv1.SelectedTab.Text)
            {
                case "Settings":
                    panelSettings.Visible = true;
                    panel1.Visible = false;
                    lblMailServerConfig.Visible = true;
                    lblProcessLog.Visible = true;
                    lblSMTPPassword.Visible = true;
                    lblSMTPPort.Visible = true;
                    lblSMTPUsername.Visible = true;
                    lblProcessLog.Visible = true;
                    txtProcessLog.Visible = true;
                    textSMTPPassword.Visible = true;
                    textSMTPPort.Visible = true;
                    textSMTPServerName.Visible = true;
                    textSMTPUsername.Visible = true;
                    break;
                case "Triggers":
                    panel1.Visible = true;
                    panelSettings.Visible = false;
                    lblMailServerConfig.Visible = false;
                    lblProcessLog.Visible = false;
                    lblSMTPPassword.Visible = false;
                    lblSMTPPort.Visible = false;
                    lblSMTPUsername.Visible = false;
                    lblProcessLog.Visible = false;
                    txtProcessLog.Visible = false;
                    textSMTPPassword.Visible = false;
                    textSMTPPort.Visible = false;
                    textSMTPServerName.Visible = false;
                    textSMTPUsername.Visible = false;
                    break;
                default:
                    break;
            }
        }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Depending on your viewpoint, it might be obvious that this is dirty. Or you might have little to gripe about it. It works right?&lt;/p&gt;

&lt;p&gt;Well yeah, it's...functional but it's not very maintainable. For example, the the event started with the management of just a view controls, but I kept adding more. Soon I had to manage a new tab which in itself had more and more controls to show when it is clicked.&lt;/p&gt;

&lt;p&gt;I'm not even done with the number of tabs I need to add at this point. The potential result is an ugly, long switch statement.&lt;/p&gt;

&lt;p&gt;But how does this break SOLID?&lt;/p&gt;

&lt;h4&gt;
  
  
  S is for 'Single Responsibility'
&lt;/h4&gt;

&lt;p&gt;Does this code 'do one thing?' Well I guess it does, but not obviously. In fact, it does several things that should be encapsulated. It checks through lots of different potential button clicks and then sets control visibility values one by one, in the same event.&lt;/p&gt;

&lt;p&gt;Doesn't is seem to be a lot of 'stuff' all crammed into a single UI event? How can we clean it up?&lt;/p&gt;

&lt;h4&gt;
  
  
  Hello Abstraction! How I love you so.
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public abstract class MainFormLayout
    {
        protected frmMain FormInstance;

        public MainFormLayout(ref frmMain formInstance)
        {
            this.FormInstance = formInstance;
        }

        public abstract void Activate();
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I created an abstract base class called &lt;em&gt;MainFormLayout&lt;/em&gt;. This class will serve as the template for a set of derived classes which take in a form (in our case the main form we want to toggle controls on) and then allow us to call a single &lt;em&gt;Activate()&lt;/em&gt; method which simply turns on all the correct UI controls based on the navigational tab you clicked. So if you clicked &lt;em&gt;Triggers&lt;/em&gt;, instead of looping through a dirty, clumsy set of switch cases in the very event that the button-click fires, it just grabs an instance of the &lt;em&gt;TriggersLayout&lt;/em&gt; class, derived from our base class and takes care of the control rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public class TriggersLayout : MainFormLayout
    {

        public TriggersLayout(ref frmMain formInstance):base(ref formInstance)
        {

        }
        //here is our Activate method, overriden from base class.
        public override void Activate()
        {
            //We can make Activate() call some methods as needed.
            DisableSettingsPanel();
            EnableTriggerPanel();
        }

        private void EnableTriggerPanel()
        {
            ((Panel)(FormInstance.Controls["panel1"])).Visible = true;
            foreach(Control control in FormInstance.Controls["panel1"].Controls)
            {
                control.Visible = true;
            }
        }

        private void DisableSettingsPanel()
        {
            var settingsPanel = ((Panel)(FormInstance.Controls["panelSettings"]));
            if(settingsPanel != null) settingsPanel.Visible = false;
        }

    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This class already knows which controls to pick from the requested layout, and with a single method call, it performs the necessary iterations over the controls we need and makes them visible, but how do we get the class?&lt;/p&gt;

&lt;h4&gt;
  
  
  Open for Extension only! (Thanks to the Factory)
&lt;/h4&gt;

&lt;p&gt;We create a static class using the &lt;em&gt;Factory Pattern.&lt;/em&gt; A factory class does a simpler version of what the logic was doing at the top level of abstraction. It checks which layout you have asked for and then sends it back. It's a little more functional in that you send a request and it just gives you an answer; in this case, the answer being the layout you require. Nothing more, nothing less. In this example, I have created a &lt;em&gt;MainFormUIController.&lt;/em&gt; It may be referred to as a controller but it is still really just a factory class as it fetches and activate the desired configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public static class MainFormUIController
    {
        public static void SwitchLayout(frmMain form, string layout)
        {
            var thisLayout = GetLayout(ref form, layout);
            thisLayout.Activate();
        }

        private static MainFormLayout GetLayout(ref frmMain form, string layout)
        {
            switch(layout.ToLower())
            {
                case "triggers":
                    return new TriggersLayout(ref form);
                case "settings":
                    return new SettingsLayout(ref form);
            }

            return new UnknownLayout(ref form);
        }

    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This methodology is more conducive to the Open/Closed principle of SOLID, because we do not have to modify any underlying logic to add more layouts. We can simply make a new derived layout class and add it to the switch list. Yes, we had a switch list to begin with, but can you imagine how big the list would get in the event!? If you're not convinced, look at the event's new code since we created out factory and layout classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; private void RibbonControlAdv1_SelectedTabItemChanged(object sender, SelectedTabChangedEventArgs e)
        {
                MainFormUIController.SwitchLayout(this,  ribbonControlAdv1.SelectedTab.Text);
        }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The logic for switching controls on a tab click in now one line. ONE LINE.&lt;/p&gt;

&lt;p&gt;What's more, we are satisfying another chunk of the SOLID paradigm: Dependency Inversion.&lt;/p&gt;

&lt;p&gt;This event no longer depends on directly knowing anything about how the UI controls are found, which controls are needed, where they are arranged etc. It has one dependency going down and the underlying code has minimal dependancies coming from the highest abstraction layer in the form of a reference to the main form and the name of a layout.&lt;/p&gt;

&lt;p&gt;We can even eliminate a dependency on null checking. For example, what if we send the factory a layout it doesn't recognize? Do we return null?&lt;/p&gt;

&lt;p&gt;Please no. Stop returning null.&lt;/p&gt;

&lt;p&gt;Instead, I return a layout which is designed to catch the error and throw an exception.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public class UnknownLayout : MainFormLayout
    {
        public UnknownLayout(ref frmMain formInstance):base(ref formInstance)
        {

        }

        public override void Activate()
        {
            throw new Exception("Requested from layout was not recognised");
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When the factory tries to call &lt;em&gt;Activate()&lt;/em&gt; an automatic exception is thrown with a clear error message which can be shown in a Messagebox. I'm still not sure whether this 'null avoiding' design pattern fits neatly into one of the SOLID areas so if anyone can enlighten me, feel free to get in touch.&lt;/p&gt;

&lt;p&gt;So there you have it. Windows Forms may be old but it is just as deserving of SOLID design practices as sexy UI frameworks like Angular or Vue. You may have to use this old-timer of a platform yet, and why not? It still allows Enterprises to build extremely powerful applications quickly, saving time and money. Microsoft as even confirmed that Windows Forms will not only &lt;a href="https://blogs.windows.com/windowsdeveloper/2018/12/04/announcing-open-source-of-wpf-windows-forms-and-winui-at-microsoft-connect-2018/"&gt;be open sourced&lt;/a&gt;, it will be &lt;a href="https://devblogs.microsoft.com/dotnet/introducing-net-5/"&gt;supported in .NET 5.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So until someone sadly puts Windows Forms out to pasture, (which could be a while), keep em' SOLID.&lt;/p&gt;

</description>
      <category>design</category>
      <category>architecture</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
