<?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: Evgeny Urubkov</title>
    <description>The latest articles on DEV Community by Evgeny Urubkov (@russianguycoding).</description>
    <link>https://dev.to/russianguycoding</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%2F416301%2Ff64b08b9-85fd-4b25-b2ef-e8b03fd13684.JPG</url>
      <title>DEV Community: Evgeny Urubkov</title>
      <link>https://dev.to/russianguycoding</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/russianguycoding"/>
    <language>en</language>
    <item>
      <title>How to Represent a Graph in C#</title>
      <dc:creator>Evgeny Urubkov</dc:creator>
      <pubDate>Thu, 24 Sep 2020 00:32:15 +0000</pubDate>
      <link>https://dev.to/russianguycoding/how-to-represent-a-graph-in-c-4cmo</link>
      <guid>https://dev.to/russianguycoding/how-to-represent-a-graph-in-c-4cmo</guid>
      <description>&lt;p&gt;Job search for a software engineer in 2020 is synonymous with the word "algorithms". With the amount of data that are available for processing these days, the companies want to hire people who are really good at problem-solving and knowing when to use which data structure. But regardless of how much time I spend attempting to comprehend all of this information,  there is one topic that just seems harder than the rest of them. And that topic is "graphs".&lt;/p&gt;

&lt;p&gt;I understand what a graph is, why, and where it is used, and I even understand the basic traversal algorithms - BSF (Breadth-First Search) and DSF (Depth-First Search). The hardest part, however, is comprehending how a graph is represented in code. During my somewhat recently started career as a software engineer, I have only had to use it a couple of times outside the algorithm challenges on HackerRank, LeetCode, and resources alike. So in this post, I am going to attempt to explain a couple of different ways of representing a graph in C#, with the hope that I will finally remember how to do it. Because the best way to learn something is to teach someone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminology
&lt;/h2&gt;

&lt;p&gt;Imagine you are learning a different language. If words are just thrown at you without any context, and none of them sound familiar, it's unlikely that you will get very far. But if you had learned some words and developed a vocabulary, even a basic one, then even when you don't quite understand everything, you could still make sense of what was said to you and even attempt to reply. So let's apply the same concept here and learn some new vocabulary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graph
&lt;/h3&gt;

&lt;p&gt;It would be silly not to cover what a graph is. In simplest terms, it's just points connected by lines. Points can also be called Vertices (Vertex for singular) or Nodes, and lines are typically called "Edges".&lt;/p&gt;

&lt;h3&gt;
  
  
  Vertex
&lt;/h3&gt;

&lt;p&gt;This may sound like a bad dictionary, since we already covered it in a "Graph" section, but a vertex is just a point on a graph that can be connected by graph edges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Edge
&lt;/h3&gt;

&lt;p&gt;This was causing me some confusion for a long time because an "edge" in my mind represents the end of something, or as the internet would say, it is "the outside limit of an object". This is not the case in mathematical graphs though and an edge is just a line that connects two nodes (vertices).&lt;/p&gt;

&lt;h3&gt;
  
  
  Undirected Graph
&lt;/h3&gt;

&lt;p&gt;In an undirected graph, edges don't have the direction and you can get from node A to node B via the same edge as you would get from node B to node A.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directed Graph
&lt;/h3&gt;

&lt;p&gt;In the directed graph, each edge has a direction and you can only get from node A to node B if there is an edge pointing in that direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adjacent Vertices
&lt;/h3&gt;

&lt;p&gt;Vertices (nodes) that are connected with exactly one edge. &lt;em&gt;Note: a vertex cannot be adjacent to itself&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Edge Weight
&lt;/h3&gt;

&lt;p&gt;This is also referred to as the "cost" of the edge. This is used to define whether one path is better over another one to get from node A to node B. Smaller the weight - the better the path is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Abstract GraphBase Class
&lt;/h2&gt;

&lt;p&gt;Hopefully, with this new vocabulary, it will be easier for us to look at graph representations in code and not be completely lost. Since we're going to implement two different representations, I am going to start with defining an abstract class which I'll call GraphBase.&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;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GraphBase&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumVertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Directed&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;GraphBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numVertices&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;directed&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumVertices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Directed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;directed&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;abstract&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;weight&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;abstract&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAdjacentVertices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&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;abstract&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;GetEdgeWeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v2&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;abstract&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&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;int&lt;/span&gt; &lt;span class="n"&gt;NumVertices&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&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="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Adjacency Matrix Representation of a Graph
&lt;/h2&gt;

&lt;p&gt;The code here is pretty simple and self-explanatory. Now let's try to use it and implement a graph using an adjacency matrix. To make it easier to comprehend, I will post the code in chunks. Let's start with the Matrix field and the constructor, which in turn will call GenerateEmptyMatrix method to populate the matrix with empty values (or zeros). This Matrix is going to be our graph representation.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[,]&lt;/span&gt; &lt;span class="n"&gt;Matrix&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;AdjacencyMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numVertices&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;directed&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="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;directed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;GenerateEmptyMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GenerateEmptyMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matrix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&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="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If we have a graph with 9 vertices, the matrix will look like this after the constructor is called:&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/9-vertices-matrix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/9-vertices-matrix.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This contains 81 different cells though! That's right, the way it works is if we want to see if a vertex is connected to another vertex, we quickly look it up in this matrix. For example, if we want to see if vertex 0 is connected to vertex 8, we just look at the top right element in the matrix and quickly see that these two nodes aren't connected. Let's add a method to add edges now and see how it changes after we "connect" these two vertices.&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;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Vertices are out of bounds"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Weight cannot be less than 1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//In an undirected graph all edges are bi-directional&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;directed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&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;Nothing too complicated is going on here. We validate that the vertices are within the bounds of the matrix, verify that the weight is no less than 1, and create an edge between the given nodes. If it's not a directed graph, the edge should exist both ways and the matrix will appear to be symmetrical.&lt;/p&gt;

&lt;p&gt;Now, let's try adding the edge from vertex 0 to vertex 8 and see how it changes our matrix.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&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;adjMatrixGraph&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;AdjacencyMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&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="n"&gt;adjMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&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's what the matrix looks like after adding this edge:&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/0-to-8-edge-matrix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/0-to-8-edge-matrix.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, edges from 0 to 8, as well as edges from 8 to 0 were created because it's an undirected graph.&lt;/p&gt;

&lt;p&gt;Not so bad thus far but we're not done yet. In order for us to do the graph traversals, we need a way to find the adjacent vertices. Let's implement that next.&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;override&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAdjacentVertices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot access vertex"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;adjacentVertices&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;adjacentVertices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&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;adjacentVertices&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;As we can see, getting the adjacent vertices is as simple as iterating over the row in which the given vertex is located, and getting the matching vertices edges to which have a weight value of greater than zero.&lt;br&gt;
Let's add three edges: from 0 to 8, from 0 to 3, and from 8 to 4, and then get the adjacent vertices of the 0th vertex.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;adjMatrixGraph&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;AdjacencyMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&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="n"&gt;adjMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;adjMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;adjMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&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;adjacent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;adjMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAdjacentVertices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is what our matrix and adjacent vertices look like:&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/adjacent-vertices.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/adjacent-vertices.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we correctly got 3 and 8 as the vertices adjacent to vertex 0, and correctly ignored vertex 4 because it's adjacent to 8 but not 0. If we now call GetAdjacentVertices on vertex 8, we should get vertices 0 and 4 as adjacent to 8.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;adjacent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;adjMatrixGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAdjacentVertices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/adjacent-vertices2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/adjacent-vertices2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One last thing we have to do now is to implement the GetEdgeWeight method. With the matrix representation, it's as easy as getting the value of the "intersection" of vertex1 and vertex2.&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;override&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;GetEdgeWeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v2&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;This definitely wasn't too bad. Probably the most challenging part is remembering how 2D arrays work in C#.&lt;br&gt;
Now let's take a quick look at another implementation of a graph using an adjacency set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adjacency Set Representation of a Graph
&lt;/h2&gt;

&lt;p&gt;To help us with representing a graph using a set, let's define a class named Node that will hold the edges and allow us to easily access the adjacent vertices.&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;Node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;VertexId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AdjacencySet&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;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;vertexId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VertexId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vertexId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AdjacencySet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;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;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VertexId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The vertex cannot be adjacent to itself"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AdjacencySet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&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="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAdjacentVertices&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AdjacencySet&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;Each node will have a VertexId field so we could easily refer to it, as well as an Adjacency HashSet holding the edges. Adding an edge becomes as easy as adding a vertex to the set, and getting adjacent vertices is as simple as returning the AdjacencySet.&lt;br&gt;
Now let's look at the implementation of GraphBase using AdjacencySetGraph. As last time, let's begin with the constructor:&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;private&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vertexSet&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;AdjacencySetGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numVertices&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;directed&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="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;directed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertexSet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
       &lt;span class="k"&gt;for&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;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;vertexSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&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;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&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, we're creating another set to hold Nodes that represent vertices' information and populate it with the number of vertices specified at the creation of the graph object. Simple enough so far.&lt;/p&gt;

&lt;p&gt;Let's look at the AddEdge method:&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;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Vertices are out of bounds"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"An adjacency set cannot represent non-one edge weights"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertexSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ElementAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;//In an undirected graph all edges are bi-directional&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;directed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertexSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ElementAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AddEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&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;Did you notice a limitation of representing a graph this way? We can't have a weight whose value is not 1. Well, maybe having a GraphBase abstract class was a little premature.&lt;br&gt;
Adding an edge is as simple though as accessing the node with the given VertexId and calling an AddEdge method on it, which, as we remember, just adds the vertex to the set of adjacent vertices. Hence, getting adjacent vertices is as simple:&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;override&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAdjacentVertices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numVertices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot access vertex"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertexSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ElementAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;GetAdjacentVertices&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;And finally, we have to implement GetEdgeWeight method but since we can't have weights whose value is not a 1, we simply return 1:&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;override&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;GetEdgeWeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&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;I will leave it to you to figure out the pros and cons of each method, as well as possible issues that weren't handled in each implementation. Hopefully, it will help you on your journey to becoming a graph master. And I believe I am on track to finally "getting" it. If you want, try implementing a Depth-First Search or Breadth-First Search algorithms using either of these graph representations. And if you are reading this and have seen some errors or something you can't stand, leave a message in the comments section and we can discuss that. &lt;/p&gt;

&lt;h1&gt;
  
  
  Are graphs easy for you?
&lt;/h1&gt;

&lt;p&gt;P.S. I didn't cover a lot of things about graphs in this post. For example, cyclic vs acyclic graphs. This article is about representing basic graphs in code and if you would like more information about the topic, there are a lot of resources online that will help you get deeper into the subject.&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>algorithms</category>
      <category>graph</category>
      <category>csharp</category>
    </item>
    <item>
      <title>How to Test Your Unit Tests: Mutation Testing</title>
      <dc:creator>Evgeny Urubkov</dc:creator>
      <pubDate>Tue, 25 Aug 2020 10:16:41 +0000</pubDate>
      <link>https://dev.to/russianguycoding/how-to-test-your-unit-tests-mutation-testing-4pa3</link>
      <guid>https://dev.to/russianguycoding/how-to-test-your-unit-tests-mutation-testing-4pa3</guid>
      <description>&lt;p&gt;Let’s be honest - the idea of doing Test-Driven development only sounds nice on paper. Or if you have an infinite amount of time to actually do it. In the real world though, project managers, product managers, customers, the CTO, CEO, and everyone else at the company just want to see the final product. They couldn’t care less about tests. Yes, eventually they will realize how important it is to have them, especially if during the retrospective meeting they’re told that if we had more time to write unit or integration tests, it would have saved us from the last production fire. But the cycle keeps repeating because the “firefighters” arrived on time, nobody died (hopefully) and there are still a gazillion features that need to be developed. So a lot of times we have to balance the amount of code we write and the number of tests that cover it. &lt;/p&gt;

&lt;h3&gt;
  
  
  At least in our team, depending on what we work on and how important we think it is to have a good code coverage, we may have four different approaches:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Do full TDD from the beginning (rarely happens).&lt;/li&gt;
&lt;li&gt;Skip tests altogether (more like it).&lt;/li&gt;
&lt;li&gt;Write tests after the fact (if we have time).&lt;/li&gt;
&lt;li&gt;Make a ticket to write tests later (let’s be realistic, this ticket will likely never get done).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;...when we needed to add a new integration into our system, my friend and co-worker discovered that some of the tests were plainly wrong&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I love unit testing. As a former QA, it was one of the first things that I learned about when learning how to program. I gave presentations on it, helped other people write better tests when I had joined their projects, and I’ve always been on the lookout for better tooling that will make writing and maintaining them easier. Moq and NBuilder have been two of my favorite tools, but I’ve gone as gross as using HttpMock for testing one of our legacy systems until eventually we completely rewrote it and the need for using this tool faded. And of course, it was really exciting to watch the number of tests grow from 0 to several hundred, the code coverage go from 0% to upper 60’s or even higher, and, most importantly - not have any bug reports that could be proven to be caused by the code we wrote for the past several months. The problem arose later when no-one expected it - when we needed to add a new integration into our system, my friend and co-worker discovered that some of the tests were plainly wrong. He later wrote his own blog post on the subject to talk about the mistakes we made while writing tests: &lt;a href="https://www.alijahgreen.com/blog/mistakes-ive-made-unit-testing"&gt;https://www.alijahgreen.com/blog/mistakes-ive-made-unit-testing&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  What validates the validator?
&lt;/h3&gt;

&lt;p&gt;It appears that while we do write or at least thinking about writing tests to validate whether the production code is correct, we don’t validate the validators. We could write tests for tests, but then we’d put ourselves into a never-ending loop. We would always have to write more tests to make sure that the tests that have already been written are valid and are testing the right things. So how do we fix this problem? &lt;/p&gt;

&lt;p&gt;If you’re into TDD, the most obvious solution that comes to mind is to do the “Red-Green-Refactor” approach, where we make sure that each test has failed before we write code that will make the test pass and call it “good”. The problem we run into though is that turning from “red” to “green” isn’t always enough. Maybe it was failing for a completely different reason from what we originally thought. Or maybe the cycle is OK for this particular condition, but did we make sure to cover all of the possible errors? For example, did we test all the boundaries? There’s nothing that tests whether our tests cover those cases or if they’re even correct in the first place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutation Testing to the Rescue of Your Tests
&lt;/h3&gt;

&lt;p&gt;As I was browsing Pluralsight last weekend to see if there’s anything interesting I could listen to while cooking, I found this talk from CodeMash conference: “Mutation Testing to the Rescue of Your Tests” by Nicholas Frankel. Surprisingly, I had never heard of such testing until I’ve listened to this talk. It did intrigue me though and I decided to learn more about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want those bastards dead and our tests “red”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What exactly is mutator testing? In simple words, it’s a program or a tool that hooks up to your source code and replaces conditions, string values, and other “mutators” within your code. For example, if we had this method &lt;br&gt;
&lt;code&gt;public int Sum(int x, int y) &lt;br&gt;
{ &lt;br&gt;
    return x+y;&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
it would have replaced “+” operator with the “-” operator and checked if the tests that cover this method still passed. If they did, that means that the “mutant” has survived - not really a good thing. We want those bastards dead and our tests “red”. That would mean that our tests passed the exam. &lt;/p&gt;

&lt;p&gt;Since the presenter was doing demos in Java, I decided to give it a try in C# and run it against the project where we discovered that some of the tests were incorrect. &lt;br&gt;
I found only a couple of “mutator” tools available for .Net. I went with the Stryker-mutator from &lt;a href="https://github.com/stryker-mutator/stryker-net"&gt;https://github.com/stryker-mutator/stryker-net&lt;/a&gt; that gets installed globally as a dotnet tool. &lt;/p&gt;

&lt;p&gt;It did take a couple of minutes to figure out the errors received upon trying to install it originally. It appears that in addition to running the command to install it mentioned in the “Readme”, I also needed to specify the version of the package I wanted to install. So instead of running "dotnet tool install -g dotnet-stryker” I had to run “dotnet tool install -g dotnet-stryker --version 0.18.0” because apparently it’s still in beta. After that, I had to navigate via command line to the desired tests project I wanted to run the mutator against, run “dotnet-stryker” and… it failed again. This time, because my project with tests contained references to more than one project and it wanted me to choose which one I wanted to mutate. Since third time is the charm, after finally running “dotnet-stryker -project-file=myProjectName” it gave me a bunch of warnings about some mutants not being able to compile, but finally it actually started doing some work. It estimated that this process will take about five minutes. After seven minutes, the results were produced and from looking at the numbers, I already had a bad feeling. Except, I didn’t know whether that was a feeling about our tests, our code, or the tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jLFmWCaJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qkjtv3nn3bmtpl6sm1ki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jLFmWCaJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qkjtv3nn3bmtpl6sm1ki.png" alt="Stryker-mutator cmd logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From 333 tests, we managed to kill only 70 mutants. 263 mutants have survived. And the final mutation score received? Soul-crushing 21.02%. Is it time to call Bruce Willis to save us from the mutant-apocalypse or is it too late?&lt;/p&gt;

&lt;p&gt;I thought to myself that it can’t be right! It is one of the projects we were most proud of for the amount of code coverage it got! There must be a report that it produced that I want to look at! OK, here it is (on the left there were file names but I cut those out since it wasn’t my personal code I ran it against).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VwrWTKk6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gxnkjfuijdv97k6elklq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VwrWTKk6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gxnkjfuijdv97k6elklq.png" alt="Stryker-net report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, from a few mutations I’ve looked at, it did a string replacement on endpoints, logs, and other things for which we didn’t even write tests. So that makes me feel a little better. Let’s see if there’s a way to exclude such mutations though. &lt;/p&gt;

&lt;p&gt;Looks like we have good and bad news. Yes, we can exclude certain mutations, but it won’t improve our score. Well, OK. Let’s run it again still with the “string” mutation excluded. And wait another 5-7 minutes.&lt;/p&gt;

&lt;p&gt;It appears that it automatically discarded some tests for which results would not have changed. So now it’s evaluating 220 tests instead of 333. After about five minutes of running, we got the results again. This time 69 mutants were killed and 151 survived. And even though the documentation said our mutation score wouldn’t improve, it went up to 31.36% (still less than desirable). Looks like this time we may have some real conditions we didn’t test for. One cool feature of the produced report is that I can click on the condition that it replaced, and it will show me the exact line it replaced it with. So that will make it easier for us to write more valid tests. &lt;/p&gt;

&lt;p&gt;One bug I noticed this tool has is that it doesn’t care whether the “+” sign is used as a mathematical operation or as a way to join two strings together. One of the errors I got is a “CompileError” where it tried to do this weird thing and replace “+” with “-” in string concatenation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C6Y9un12--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xxqv5scmxtzh8r2axwap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C6Y9un12--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xxqv5scmxtzh8r2axwap.png" alt='Stryker-net "plus" operator replacement bug'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obviously, it may not work the way we expected out of the box. I didn’t really change any configurations except excluding the string literals’ mutations in the run above. Hopefully, with a bit more exploration and configuration, I can add this tool to my arsenal and never ship a buggy code again (one can only wish). &lt;/p&gt;

&lt;p&gt;Later I ran it with a configuration file against a .Net Framework project and it failed to compile. First, because “nuget.exe” wasn’t in my PATH but it’s required for .NET Framework projects. Then it needed me to specify the project name. Then the solution name. Eventually, it tried to run… but it failed again. This time it could not compile one of the project dependencies. I was a bit disappointed but it’s probably my fault for choosing a beta version of the tool. Nevertheless, it was a good experience and can definitely help us start some more conversations about unit testing in general. I do see great potential for such a tool, especially after our fiasco, and hope it matures enough and we’ll be able to use it on legacy projects. But at least I was able to run it without too much trouble in .NET Core.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now, let’s talk about the potential advantages and disadvantages of using mutation testing.
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You obtain a tool that automatically tests your tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can be more confident that your application doesn’t have bugs in it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Customers are happier since there’re no bugs in the system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It won’t find all of your bugs. It will only run the mutations for as much code as it is covered by tests. So if you didn’t write tests in the first place, this tool will be useless.&lt;/li&gt;
&lt;li&gt;It is very time-consuming. Because it has to go through the whole codebase to replace different conditions and values, on a large codebase you may be waiting for several minutes before the results are produced.&lt;/li&gt;
&lt;li&gt;It won’t help you do black-box testing of the system since the tool makes changes in the source code itself.&lt;/li&gt;
&lt;li&gt;What will test the tool to make sure it doesn’t produce false-positives? This cycle will never end.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So will I start doing “Mutation Testing” from now on? The answer is, as with most things in software development, “it depends”. As I said earlier, if we don’t write any unit tests on any of our projects, it’s not going to magically write them for us. And depending on how often we’d want to utilize this method, it may require more time to have the reports generated, so we won’t know immediately what we have to change. I am definitely going to explore this idea further though and see how much benefit it will provide to our team, especially when I figure out how to set up all the right configurations. But, of course, where possible, I’d still prefer TDD. Immediate feedback and 100% code coverage sounds wonderful. Especially, when you like tracking such metrics in order to try becoming a better developer. The only problem is, 100% isn’t always 100% and I hope that Mutation Testing will help us make sure we’re not lying to ourselves.&lt;/p&gt;

&lt;h1&gt;
  
  
  Now it’s your turn. How do you test your code? Or do you?
&lt;/h1&gt;

</description>
      <category>unittesting</category>
      <category>testing</category>
    </item>
    <item>
      <title>How to Create Your Own Luck</title>
      <dc:creator>Evgeny Urubkov</dc:creator>
      <pubDate>Tue, 21 Jul 2020 10:32:39 +0000</pubDate>
      <link>https://dev.to/russianguycoding/how-to-create-your-own-luck-1ep2</link>
      <guid>https://dev.to/russianguycoding/how-to-create-your-own-luck-1ep2</guid>
      <description>&lt;p&gt;I don't think anyone would argue with the fact that developing software requires skill. Nobody just wakes up one day after having never programmed before and becomes a senior software architect. But getting a job, meeting the right people and even figuring out exactly which technologies to study requires not only skill but also luck.&lt;/p&gt;

&lt;p&gt;One great example of a combination of skills and luck in the same domain is a game of poker. Yes, you could have played every day for the last thirty years but there’s still a chance to be beaten by someone who has never played before and just learned the rules yesterday. And that’s the excitement that the game provides. If you’re playing tournaments, as long as you still have chips, you are still in the running for a potential win.&lt;/p&gt;

&lt;p&gt;My friends often call me lucky when I happen to win their money on Sunday nights. And that might be partially true but I am also putting myself in a position to allow myself to get lucky. There’s a term in poker - “implied pot odds”. In simpler words, it’s the estimation of the amount of money you can win after an opponent’s bet is matched. So I may not be getting the correct price to make certain calls at the moment, but if I read my opponent’s hand well and I know he’ll pay me off if I hit my miracle card, I may decide to take that chance and make what’s the wrong decision in the vacuum. That doesn’t really change much when you play another game - the game of life.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, you could have played every day for the last thirty years but there’s still a chance to be beaten by someone who has never played before and just learned the rules yesterday.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Most of us had a crappy but tolerable job
&lt;/h3&gt;

&lt;p&gt;Before I got into programming, I had a job that started as a somewhat fun job that also allowed me to do a lot of reading and studying during the downtime. I was working in a call-center but I got lucky enough to do chat support for one well-known company. From the time I had started and for the next few months, most of the time I had to answer only one chat, which meant that I never had to solve issues for more than one customer at the time. That allowed me to read the college textbooks for some of the general education classes whose context I can barely remember (the most memorable thing that I can recall is Anne Hutchinson but partially that’s because she’s my wife’s namesake) but if there is a benefit that such classes provide it is the teachings of a sense of urgency and the ability to meet deadlines. &lt;/p&gt;

&lt;p&gt;Fast-forward several months and what was a tolerable job with some free time for personal development had changed to be a stressful job that nobody wanted to go to. And like in most corporations, it came with a pay-decrease. Well, technically they considered it as a pay-increase because they added the whopping 20 cents an hour to our base salary. Except, if you were a high-performer like I had been, it meant a pay-cut for you since they got rid of performance bonuses. &lt;/p&gt;

&lt;h3&gt;
  
  
  The decision was made about leaving the crappy job
&lt;/h3&gt;

&lt;p&gt;By then, I had already decided that I was going to leave. Yes, I could have pursued a supervisory position there, but the idea of having to come in at 3 am to cover for European time zones or having to work six or seven days a week with no extra payment didn’t sound too convincing. Which, the payment itself was about $36,000 a year. At the time it sounded really good. When you’re making $10 per hour, that’s almost doubling your wages. But I had decided that it just wasn’t for me at the time, so I started looking at what I can do to acquire the skills to get into the IT industry.&lt;/p&gt;

&lt;p&gt;I have always liked messing with computers. Actually, now that I am writing this, even before we had a computer, I had taken apart pretty much all the electronics we had in the house when my age was barely 8 years. Of course, my parents didn’t appreciate it, but I also had never touched the TV. You know, that old-type TV with a tube inside. It was just too scary to accidentally get killed since I had thought that if an attempt was made to take it apart and mess something up, it would explode. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Regardless of how hard I tried, I never seemed to make any progress.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The choice to get into IT
&lt;/h3&gt;

&lt;p&gt;The choice to get into IT wasn’t always obvious though. It took me a few years to figure out what I really want to do as a career. Of course, if I had the cheat codes and could just allow myself to get an infinite amount of money so I didn’t have to work, the choice would have changed since I’d be able to try doing a new thing every day and never run out of options. But it took me a few years to realize that it wasn’t the reality and one can reach the American Dream only by putting in a lot of work into it and a lot of debt under them. But that’s a topic for a different conversation.&lt;/p&gt;

&lt;p&gt;I had found that CompTIA offers some IT certifications that are supposed to help you acquire technical skills and get a foot in the door into the IT industry if you’ve never studied it in college or never went to college. So I bought some books and online training and started learning. A lot of my time on and off the job was contributed to that. Except, regardless of how hard I tried, I never seemed to make any progress. A lot of it was reinforcement where I already knew what it was talked about but I may not have known the exact term for it. But some of it just seemed too irrelevant and those things are the hardest ones to memorize (a lot of it required more of memorization than understanding. For example, knowing which command prompt commands you can run to perform a particular task). So I had never felt like I was ready. And since I wasn’t in a rush to get it done, I just kept reading the books hoping that one day I will feel ready.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Setting a deadline was more than just putting a date on a calendar by when I should feel ready. It was about purchasing and scheduling the actual exam.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Overcoming the "Not Ready" excuse
&lt;/h3&gt;

&lt;p&gt;Except, that day never comes. I don’t think there’s a single person on the planet who ever just feels “ready” as in “I can solve any problem that is thrown at me in any amount of time given to me without having to Google anything”. If you are such a person, could you write me an email? I’d like to interview you.&lt;/p&gt;

&lt;p&gt;And then I had realized that I had to do two things. 1. Set a deadline. 2. Get immersed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting a deadline
&lt;/h4&gt;

&lt;p&gt;Setting a deadline was more than just putting a date on a calendar by when I should feel ready. It was about purchasing and scheduling the actual exam. When you’re making $10 per hour and your wife is not working because she got injured at work and had to seek a lawyer to get that taken care of, these few hundred bucks for the exam do seem like a fortune. And a lot of thoughts come into mind, like “what if I fail?”. So after talking for a bit, we decided that the money comes and goes but the skill remains. And if that can get me out of that toxic environment which I had started to truly hate, that’s worth it on its own. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;True story: I once asked a customer how she’s doing and her response was “irrelevant”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I had purchased what's called a bundle. It allowed for two tries for the exam and also came with a video course to help prepare for the exam. That’s how I had handled setting the deadline part. Of course, the deadline could always be moved a bit but I imagine at some point the purchase would expire and you’d have to pay for the exam again. I can’t recall with 100% certainty but I feel pretty confident that I did not have to reschedule. And here’s why.&lt;/p&gt;

&lt;h4&gt;
  
  
  Immersion
&lt;/h4&gt;

&lt;p&gt;Immersion. Yes, being able to read the books at work was a nice opportunity but there were a couple of problems that arose. Firstly, it wasn’t really that efficient. Having to juggle between answering the customers’ requests and learning definitely slowed the progress down quite a bit. And depending on the customer, sometimes you just had to take a break. True story: I once asked a customer how she’s doing and her response was “irrelevant”. Of course, she gave me a bad review after the chat since I asked irrelevant questions. The second problem was that it wasn’t an easy ride anymore and often we had to talk to two or three customers at once. So there was no downtime left. I had barely had time to respond to all of them fast enough. My performance started to suffer and I had made a decision to take unpaid time off. &lt;/p&gt;

&lt;p&gt;This was a really hard decision to make, especially since at the time we practically had no savings, and my wife’s job situation was still unclear. After some discussion, we decided that I should do it anyways. And that’s when immersion began. I didn’t just stay home for two weeks and watched TV. Instead, I studied for about 12 hours a day for the next two weeks with rare breaks to eat and go to the bathroom. After two weeks, I still didn’t feel “ready”. There were still things I was unsure about. But within the next week or two, I went to take the exam. And passed.&lt;/p&gt;

&lt;p&gt;I couldn’t really believe it! It did feel like I got lucky. But only those get lucky who take risks and buy lottery tickets or participate in other forms of risk activities (stock market, poker tournaments, etc.). This was my poker hand and I had played it well enough to make a profit. Or did I? &lt;/p&gt;

&lt;h3&gt;
  
  
  Applying for only two jobs and landing one of them
&lt;/h3&gt;

&lt;p&gt;Sometime before my exam, I applied for an IT position at one of the local universities through a referral. I had an interview and had thought I’d really enjoy working there. But a few weeks had passed, I told them I got my certificate and a week later they let me know that they decided to proceed with someone else. In hindsight, I realize that it was the best thing that ever happened to me - not getting a job there. Having to drive for 30 minutes and then wear trousers and a button-up shirt regardless of how hot it is doesn't seem very appealing anymore. Though, I’d probably still prefer it over the toxic environment I was in but not anymore.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;...I’d come home in the evenings and study everything I could find on the topics I didn’t understand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The only other job I applied for was a job as a technical operations specialist for a software company. Their job posting just had me excited and it was written with some humor mixed in. I wrote them a cover letter in a similar format with some joking in it, and the rest is history. It took me five months to become a Quality Assurance Analyst, and about a year and a half to secure a software development position.&lt;/p&gt;

&lt;p&gt;And yes, I did get lucky during that process as well. But I didn’t get lucky in a way you may imagine it. During my downtime in the “ops” world, I’d ask my boss if there’s anything else I can help him with. I also kept asking people how to get to the next step, which was a QA. And then I’d come home in the evenings and study everything I could find on the topics I didn’t understand (which was a lot of them!). &lt;/p&gt;

&lt;p&gt;After I was a QA for about a year, my boss told me that I should apply for a developer position that opened up. I told him my excuse that I’ve used my entire life - “But I am not ready”. He said that I am ready and should do it anyways. So I did. I did fail my first two or three first interviews. Though it feels like I failed all of them. Maybe I got lucky again. Or maybe even though I wasn’t quite ready yet, my work ethic had some weight on it (I am always there and always on time unless I had scheduled time off). Then I failed the second interview. Well, maybe not necessarily failed, but I wasn’t quite ready yet either. But instead of going around and being mad at decision-makers (which was half of our developers, if not more), I just asked what I can do better next time. &lt;/p&gt;

&lt;p&gt;Also, ever since I started in QA, I was a frequent presenter of interesting things in the form of cross-training, where QA and Developers would gather together and listen to a presenter and then ask questions. I had done quite a few of those, and one of them was a few days after my second interview. The topic was “Machine Learning”. It went pretty well and I went on vacation. While I was out for a week, or maybe two, they had interviewed a couple of other candidates and apparently one of them was so bad, they decided that my second interview wasn’t that terrible after all, and my machine learning presentation was impressive enough, and so I got a job offer. It was a nice pay jump from what I was making in QA at the time, so of course, I said “yes” without even negotiating. And yes, it’s probably more money than I would have ever seen at the company for which I was doing customer service. &lt;/p&gt;

&lt;p&gt;Lucky again? Probably. Did I put myself in a position to get lucky? Definitely! By applying for a job without being “ready”, by letting people know that I’d really like the job, by studying after hours (which I continue to do) and by being positive and not reacting toxically to failures, I have created my own luck. And yes, there are definitely people who have helped me get there to whom I am very thankful. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To summarize, these are a few important things I have defined that helped me go from working in a toxic environment doing a job with almost no potential to having a job that opens up an endless amount of opportunities.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Having a deadline
&lt;/h3&gt;

&lt;p&gt;You’ll never be ready. So you better tell yourself when is the readiest you can be without giving up more time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immersion
&lt;/h3&gt;

&lt;p&gt;This one is hard. Not everyone has an opportunity to do so for different reasons, whether it’s because you have kids who you want to play with after work or a spouse that wants to watch a movie. There are a couple of solutions. If you have downtime at work, use that to study and not watch Youtube videos of other people playing video games (unless, of course, you have your own Youtube channel and are seeking ideas on how to grow it). Otherwise, you’d have to either start getting up before anyone else or going to bed after everyone else. Or you can do as I did and just take time off, paid or unpaid. Just make sure you will use the time wisely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Being vocal about your wishes
&lt;/h3&gt;

&lt;p&gt;Let people know what your goals are. It’s amazing but people actually enjoy helping others achieve their goals. It’s good for society in general if all of us have a better standard of living.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reacting to failures
&lt;/h3&gt;

&lt;p&gt;It’s normal to be rejected. Just don’t go around and complain about anything. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;It is often hard to know what decision is the best decision, whether it’s a game of cards or life. I had gotten lucky and got great implied odds after having joined a software company. But it’s important to realize that I did take steps and put myself in a position to get lucky. Studying, getting a certificate, applying for a job, interviewing, having a great work ethic, letting people know what my goals are and etc. It all contributed towards hitting that miracle card that made me win. And while my goals are still a lot larger than just having a job, looking back at this journey helped me realize that getting lucky isn’t easy, requires a lot of work and includes weekends spent indoors when the weather outside is so nice.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Do you believe one can make his own luck?&lt;/p&gt;

</description>
      <category>tech</category>
      <category>career</category>
    </item>
    <item>
      <title>Learn Why They Are Doing It</title>
      <dc:creator>Evgeny Urubkov</dc:creator>
      <pubDate>Sun, 05 Jul 2020 18:55:45 +0000</pubDate>
      <link>https://dev.to/russianguycoding/learn-why-they-are-doing-it-34n4</link>
      <guid>https://dev.to/russianguycoding/learn-why-they-are-doing-it-34n4</guid>
      <description>&lt;p&gt;It is often easy to get frustrated when another person says or does something that seems abnormal to you. No, not in the “supernatural” sense, though it would definitely get me concerned, but rather when their behavior seems completely illogical to you.&lt;/p&gt;

&lt;p&gt;The problem is that if they’re doing it, it seems logical to them. They either have a good reason to do it, or don’t know of another, or better way to do it.&lt;/p&gt;

&lt;p&gt;I sometimes catch myself reading someone else’s piece of code and getting frustrated because they’ve done it a certain way that I don’t like. But if instead of immediately jumping to conclusions about the person and their ability to code, I find that some of the following reasons may apply:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; The feature of the language that you would use to accomplish the same task just didn’t exist when that code was written. There are plenty of examples of this I can find in our C# codebase at work, anything from string interpolation to async/await statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; They don’t know any better. Nobody has ever told them that their way is not the most performant or readable, so you can’t blame them for not knowing it. There are plenty of things that you do just because it’s the only way that you are aware of. That’s why code reviews are important. You could argue that they should be progressing by reading books or blogs, reading other people’s code, and taking extra courses, but let’s be realistic. If you look at any job posting, the number of technologies required for you to know easily averages 15+. So if I am learning something, it’s less likely I will ever be an expert in it unless that particular technology is what I work with most of my workweek.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; The way you think it should have been written is too complicated to understand. Yes, this is actually on you. A lot of times, it is okay to give up some performance improvements (not always) in exchange for readability. Especially on a team with a lot of junior developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; You’ve actually written that piece of code two years ago and hopefully, now you’re a more skilled developer than you were then, so that old piece of code may seem like it wasn’t the best approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; You’re very opinionated and their solution is no better or worse than yours. It’s just a matter of preference.&lt;/p&gt;

&lt;p&gt;I could probably come up with a number of other reasons. Someone was tired, or had to work overnight to meet a tight deadline, or implemented a naive solution to see if it will work and forgot to go back to fix it. Reasons can be many, and it’s important to figure out the logic behind them, instead of immediately starting to judge.&lt;/p&gt;

&lt;p&gt;The “learn why they are doing it” rule also applies to more general things outside of coding. Someone leaves work ten minutes early every day? Maybe instead of starting to gossip about their behavior, it’s better to approach them and find out the reason they’re doing it. It’s very likely their reason would be pretty valid (e.g. to pick the child from school). And yes, you still may not approve of that behavior, but at least knowing their “why” will give you a different perspective.&lt;/p&gt;

&lt;p&gt;I am by no means an example of a “good guy”. It is very hard for me not to judge people, but then I remember that one day I was just learning how to code and probably contributed a lot of terrible things to the codebase. Well, maybe not terrible but the ones that could have been done better. I also needed to take off time to take care of personal issues several times during my career. We’re all different and have our own sets of problems. The only thing that makes us alike - the fact that we all have problems.&lt;/p&gt;

&lt;p&gt;Also, and it may be hard to admit, but the solutions we have in our head may not be that optimal as well. There are always going to be people who are smarter than us and who can do a better job than we do. It’s important to understand that and make sure that if you somehow figured that you’re smarter than someone, instead of judging them, you need to learn why they’re doing it and offer to help.&lt;/p&gt;

&lt;p&gt;If all of us started to do it, then life would be a lot better and people wouldn’t refrain from asking questions on Stackoverflow.com because they wouldn’t want to be considered stupid or even get harassed by the “geniuses”.&lt;/p&gt;

&lt;p&gt;How often do you find judging others?&lt;/p&gt;

</description>
      <category>communication</category>
      <category>programming</category>
      <category>social</category>
      <category>general</category>
    </item>
    <item>
      <title>How to Add TinyLetter to Your Gatsby Website</title>
      <dc:creator>Evgeny Urubkov</dc:creator>
      <pubDate>Sun, 28 Jun 2020 21:23:28 +0000</pubDate>
      <link>https://dev.to/russianguycoding/how-to-add-tinyletter-to-your-gatsby-website-53j3</link>
      <guid>https://dev.to/russianguycoding/how-to-add-tinyletter-to-your-gatsby-website-53j3</guid>
      <description>&lt;p&gt;When I was planning how I was going to build this blog, one of the features in my to-do list was the subscription form. I didn't want to spend time building my own service, so as anyone else who can use a computer, I went to Google to do my research.&lt;/p&gt;

&lt;p&gt;It appears there are plenty of services that will help you with that task, except, some of them are overly complicated and almost all of them cost money. I wasn't willing to spend $20+ a month on an email collection service, especially on a brand-new blog that most likely won't get any new traffic for a while. The only service that offered anything for free was MailChimp. So I registered and immediately got lost. There are way too many options and I couldn't figure out how such a simple feature, collecting emails and then mass-sending some information to the collected emails, could be so overcomplicated.&lt;/p&gt;

&lt;p&gt;I do have another blog, which is in my native language, Russian, to which I managed to add MailChimp. But while on the 'Chimp, I saw a button that said "Need something simpler? Try TinyLetter", or something along those lines. I do like simpler, so I decided to give it a shot. And now, I am going to share the process with you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to Add TinyLetter To Your Gatsby Website&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Go to &lt;a href="http://tinyletter.com"&gt;tinyletter website&lt;/a&gt; and click the big "Sign Up Free" button in the middle of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eM1DR1JY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vqrk96t7acrco1bh7yxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eM1DR1JY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vqrk96t7acrco1bh7yxd.png" alt="TinyLetter Home page" title="TinyLetter Home page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Fill in the required details on the signup form and click "Sign Up".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6VvAWxHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/79swo2rp472e438nl1jz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6VvAWxHC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/79swo2rp472e438nl1jz.png" alt="TinyLetter signup form" title="TinyLetter signup form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Log in with your new account if it didn't auto-login.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Depending on the laws in your country, you may need to provide a physical address before you will be able to mass-send any emails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; This is where I spent some time trying to find the form that I can embed to my website. You can either get a link or an actual form. To do that, click "Share" on the left menu. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4x6UNKP4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cnt4bd9r2w83ddiw1hcp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4x6UNKP4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cnt4bd9r2w83ddiw1hcp.png" alt="TinyLetter Subscription Form" title="TinyLetter Subscription Form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look at the "onsubmit" method inside the form, you will see that there's some Javascript code inside the quotation marks. ReactJS, and therefore GatsbyJS, will "yell" at you with different error messages, from the "style" prop expecting a mapping from properties to values, to asking whether you meant "htmlFor" and not "for". So let's ignore this form but note the subscribe link.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.&lt;/strong&gt; Now it's time to open an editor and create a new component for your website. I called mine "SignupForm". &lt;/p&gt;

&lt;p&gt;And here is the code that I have in there:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;signup-form.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import './signup-form.css'
require('dotenv').config({
  path: `.env.${process.env.NODE_ENV}`,
})

const handleSubmit = e =&amp;gt; {
  window.open(
    `${process.env.GATSBY_TINY_LETTER_URL}`,
    'popupwindow',
    'scrollbars=yes,width=800,height=600'
  )
  return true
}

const SignupForm = () =&amp;gt; {
  return (
    &amp;lt;form
      action={`${process.env.GATSBY_TINY_LETTER_URL}`}
      method="post"
      target="popupwindow"
      onSubmit={handleSubmit}
      className="SignupForm"
    &amp;gt;
      &amp;lt;h2&amp;gt;Subscribe for more!&amp;lt;/h2&amp;gt;
      &amp;lt;div className="Wrapper"&amp;gt;
        &amp;lt;input
          aria-label="Email address"
          placeholder="Enter your email..."
          name="email"
          type="text"
          required
          id="tlemail"
        /&amp;gt;
        &amp;lt;input type="hidden" value="1" name="embed" /&amp;gt;
        &amp;lt;button type="submit"&amp;gt;OK&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
  )
}
export default SignupForm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;signup-form.css&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.SignupForm {
    display: flex;
    flex-direction: column;
    background: #f2f2f2;
    color: #2a2a2a;
    padding: 2rem;
  }
  .SignupForm h2 {
    margin-top: 0;
    margin-bottom: 1rem;
  }
  .SignupForm .Wrapper {
    display: flex;
    flex-direction: row;
    overflow:hidden;
  }
  .SignupForm input {
    color: #2a2a2a;
    width: 75%;
    border: none;
  }
  .SignupForm button, .SignupForm input {
    padding: 1rem 1.5rem;
  }
  .SignupForm button {
    display: inline-block;
    border: none;
    background-image: none;
    background-color: rgb(0, 122, 204);
    color: white;
    letter-spacing: 1px;
    transition: all 0.1s linear;
  }
  .SignupForm button:hover {
    cursor: pointer;
    background: #920303;
  }

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



&lt;p&gt;&lt;strong&gt;7.&lt;/strong&gt; If you're not using environment variables, feel free to replace&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;{`${process.env.GATSBY_TINY_LETTER_URL}`}&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 with the subscribe link from TinyLetter. &lt;br&gt;
Otherwise, you will need to add "GATSBY_TINY_LETTER_URL=YOUR_SUBSCRIBE_LINK" to .env.development file locally and you'd need to figure out where to add environment variables on your host provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8.&lt;/strong&gt; Now you have a component that you can add to different pages of your website. Just render &lt;code&gt;&amp;lt;SignupForm/&amp;gt;&lt;/code&gt; inside a page and you will have a simple subscription form that didn't take you any time to build. And the best part, it's free! (Or at least looks that way to me, until I get my first few thousand readers). &lt;/p&gt;

&lt;p&gt;What the final product looks like you can see and test on my website &lt;a href="https://russianguycoding.com/how-to-add-tinyletter-to-your-gatsby-website"&gt;https://russianguycoding.com/how-to-add-tinyletter-to-your-gatsby-website&lt;/a&gt;! Obviously, you can play with css styles and make it look better than what I have. &lt;/p&gt;

&lt;p&gt;How are you handling email subscription forms on your website? &lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>react</category>
      <category>email</category>
      <category>blog</category>
    </item>
    <item>
      <title>Seven Mistakes I Made When Learning How to Program</title>
      <dc:creator>Evgeny Urubkov</dc:creator>
      <pubDate>Thu, 25 Jun 2020 09:49:06 +0000</pubDate>
      <link>https://dev.to/russianguycoding/seven-mistakes-i-made-when-learning-how-to-program-2dml</link>
      <guid>https://dev.to/russianguycoding/seven-mistakes-i-made-when-learning-how-to-program-2dml</guid>
      <description>&lt;p&gt;Four years ago I thought I wanted to be a system administrator, dealing with people's IT problems, and setting up network configurations. At that point in time, my only experience with coding was taking an introductory Python course on Udacity. I thought programming was too hard and only geniuses can do it. But having landed a job in tech support for a software company changed my perspective a bit. No, I didn't become a genius or start thinking that programming is easy. What I did realize though was that I can do or be anything I want, as long as I am willing to put in the work. Especially when someone believes in you, as my boss did. But that's a story for another post. Today, I want to talk about &lt;strong&gt;SEVEN MISTAKES I MADE WHEN LEARNING HOW TO PROGRAM.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. NOT CHOOSING WHAT KIND OF DEVELOPER I WANT TO BE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn't know any better at the time and at the company I worked at every developer was expected to work on anything that was thrown at them. Whether it's designing APIs, creating new UIs for websites, or creating and managing SQL Servers. So my solution was easy: learning everything. And thinking back, I believe it was a wrong solution. What I should have done was figure out whether I am more interested in building websites, games, apps, enterprise software, or even designing machine learning algorithms. Of course, I was largely influenced by my surroundings, but if you don't have a job in a related field, figure out early what you want to specialize in, that will save you a lot of time and cut down the number of things you &lt;strong&gt;&lt;em&gt;don't&lt;/em&gt;&lt;/strong&gt; need to invest time in. For example, if you want to specialize in the backend code, it's not necessary for you to learn HTML and CSS, at least in the beginning. And also, you wouldn't have a problem choosing which programming language you need to learn, since depending on what you want to build, the choice may be more obvious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. NOT SPENDING ENOUGH TIME LEARNING AND IMPLEMENTING COMMON DATA STRUCTURES AND ALGORITHMS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It may seem like a waste of time since you most likely won't be reimplementing the wheel at a job, it's still important to understand the "how" and the "why" behind algorithms and data structures. Imagine that your skills are a house. You don't start building a house from the roof, you start with the fundamentals. In addition to that, you probably won't pass any interviews not being able to solve the programming assignments interviewers may come up with. And just knowing of the existence of certain things and how they work may help your code be more performant, and hence easier to scale and cheaper to host. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. GETTING STUCK IN THE TUTORIAL TRAP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have used multiple resources to help me learn how to code, anything from the CS50 at Harvard to Machine Learning on Udacity. The problem is, I was doing it all wrong. I would watch a course, follow along in the code editor, but upon the completion, I wouldn't remember most of it. It felt like I was succeeding since I was finishing courses, but my knowledge remained the same. Now I actually think my knowledge was degrading, since tutorials were giving me a false view of what I am able to do. If I had to start over, I would do it differently. I would choose a project that I want to work on, and then use tutorials as a guide when I am stuck or want to find a better way of doing something. That would have saved me time and helped me create a portfolio I could show to potential employers. And things would probably stick in my memory for longer periods of time since I'd also have to figure out multiple ways to do something and then pick which one is best. That leads not only to knowing how something is done but also understanding &lt;em&gt;why&lt;/em&gt; it is done that way. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. STARTING SIDE PROJECTS AND NOT FINISHING THEM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We do have to come up with the definition of "finished" here since in software development nothing is ever truly done. But in this context it would be a feature or a complete project that compiles, runs, and does what you expect it to do. Not choosing what kind of developer I wanted to become along with the tutorial trap left me with a lot of started but unfinished projects, which I eventually just purged from my Github account. Instead, I should have started just one project and worked on that one thing. This would have helped me to show the potential employers my ability to finish things. My current employer will tell you that I &lt;strong&gt;can&lt;/strong&gt; finish projects but I have nothing to prove it to anyone outside people I work with since all of the software I developed there is proprietary and I can't share the company's code. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. GETTING OVERWHELMED WITH ALL THE THINGS I HAVE TO LEARN&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is really just a continuation of the first mistake but even if you do choose what &lt;em&gt;kind&lt;/em&gt; of developer you want to be, there is still plenty of filtering down you have to do to avoid all the confusion and frustration that may come when you're just starting out. My advice to my past self would be to stick with one thing and learn it very well. It doesn't matter whether it's React or Angular or Vue.js, or whether you just want to write backend code in Python or C#. It's more important to understand the concepts that are behind the technologies you're learning. That way when you learn one of them, it's likely that picking up the other one won't be too difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. NOT HAVING A MENTOR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I probably wouldn't even be writing this today if I didn't make the mistake that has been a hindrance to my learning how to program. And that is going on this journey by myself. There were two reasons why I didn't intentionally search for someone who could help me succeed. First, I don't like wasting people's time when I can't give them anything in return. Yes, I could have hired someone to help me but at the time my bank account's balance wasn't letting me do that. Second, I am too afraid to look dumb so it's really scary to show my code to people. That has become a little easier with the introduction of code reviews at work but even then I am never sure if I did everything right. That's probably the perfectionist talking in me, and what I have been learning about myself is that perfection kills progress. It's better to do it wrong a bunch of times and be corrected every time than do it once in what you &lt;em&gt;think&lt;/em&gt; is a perfect way and find out you were doing it wrong this whole time. So note to my past self: find someone who already works in the field and ask them to help you. You do have to be careful here though and start with someone just a couple levels above you. You wouldn't go to a financial advisor who manages billions of dollars for people when you only have a few hundred bucks, so choose someone more reachable. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. STAYING IN THE COMFORT ZONE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I had to combine all of the mistakes I made into one, it would be "staying in the comfort zone". Tutorial trap, switching technologies just to find myself at the start of the road again, not discussing code with anyone, and sticking to only comfortable things are all the progress killers. It may only seem like you're progressing when in fact you're staying at the same place or even worse, regressing. Yes, you may be able to write a "for" loop in a dozen languages but the fact is - you made no progress wasting time on eleven of them since the concepts are the same in all of them.  Thus, when you learned a concept, go to the next one. Don't just walk around one thing that won't get you anywhere. And don't be afraid to take on new projects when they're offered to you. Unfortunately, I wasted over a year avoiding "hard" work since I wasn't sure if I was qualified to do it. Anybody can learn how to do things. One just has to put in some work and motivation to do it.&lt;/p&gt;

&lt;p&gt;To summarize, if you're just starting out with your programming career, pick who you want to be and what type of things you want to develop, start with the fundamentals, build something, find someone to go along with on this journey, and you will be on the right path. &lt;/p&gt;

&lt;p&gt;What were your biggest struggles when you were learning how to code? Have you made any of the mistakes mentioned here?&lt;/p&gt;

&lt;p&gt;P.S. I am just starting out my blogging career and would like your feedback! Feel free to leave comments under this post or on the website &lt;a href="https://dev.toRussian%20Guy%20Coding"&gt;https://russianguycoding.com/seven-mistakes&lt;/a&gt;. Thanks for reading!&lt;/p&gt;

</description>
      <category>motivation</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
