<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bog's tech]]></title><description><![CDATA[Software engineering, coding tips and tricks, development on all kinds of platforms including your toaster and devops on not so fluffy clouds.]]></description><link>https://bognov.tech</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 13:00:40 GMT</lastBuildDate><atom:link href="https://bognov.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Communicating Sequential Processes in Golang]]></title><description><![CDATA[This blog post comes from a tech talk I gave internally at IKEA.I will introduce some key concepts to build a mental model to with with concurrency and then dive into Go with examples that you can find in this repo.
The goal of this blog post is to r...]]></description><link>https://bognov.tech/communicating-sequential-processes-in-golang</link><guid isPermaLink="true">https://bognov.tech/communicating-sequential-processes-in-golang</guid><category><![CDATA[golang]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[parallelism]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Sun, 01 Dec 2024 20:56:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733086345176/29c9350a-de27-47a0-9839-3e1b6aedebbd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post comes from a tech talk I gave internally at IKEA.<br />I will introduce some key concepts to build a mental model to with with concurrency and then dive into Go with <a target="_blank" href="https://github.com/bgdnvk/concurrency-talk">examples that you can find in this repo</a>.</p>
<p>The goal of this blog post is to refresh concepts for senior engineers and introduce topics of concurrency, parallelism, race conditions, deadlock, mutex and more to anyone who hasn’t had to deal with concurrent programming directly.</p>
<h1 id="heading-concurrency">Concurrency</h1>
<p>We can consider concurrency as parts of the program that execute independently in a non-deterministic order.</p>
<p>Concurrency is NOT Parallelism: depending on the hardware we can run parts of the program at the same time (in parallel) but just because we have concurrency it doesn’t mean we have parallelism.</p>
<p>What does it mean, “non-deterministic order”? It’s different behaviour on different runs but same result. For example processes(*) have a different trace of execution: ​ {1, 2a, 3a, 2b, 3b, 4}<br />​{1, 2a, 2b, 3a, 3b, 4}​<br />{1, 3a, 3b, 2a, 2b, 4}​ ​</p>
<p>*process: a series of actions or events to achieve a goal</p>
<p>We can look at a concurrent program with a non-deterministic trace of execution like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733067241579/89d010d2-5548-4bf5-80f8-4831db1779d9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-concurrency-vs-parallelism">Concurrency vs Parallelism​</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733067471391/1e5cc0e8-3d98-4fbd-a126-48e964eb8ba3.png" alt class="image--center mx-auto" /></p>
<p><strong>Concurrency: dealing with things happening out of order.</strong></p>
<p><strong>Parallelism: dealing with things happening at the same time.</strong></p>
<p>Parallelism will make your program faster while concurrency doesn’t have to. Concurrency can happen in a single core processor​. Parallelism can only happen in a multi-core processor.</p>
<p><strong>Concurrency can make your program slower, if you are on a single core machine or your logic doesn't need concurrency​. But it can make your program faster when you have to wait for something – by letting other parts of the program execute</strong>.</p>
<h2 id="heading-why-do-we-need-concurrency">Why do we need concurrency?</h2>
<ul>
<li><p>Enable parallelism</p>
</li>
<li><p>Let parts of the program execute independently</p>
</li>
<li><p>Remove the need to wait for an event</p>
</li>
</ul>
<p>If we look at our previous concurrent example but this time we have access to parallelism as well, we can see that the program will be much faster:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733068099554/2cfa7dd5-e591-45f9-9872-76ed0fc00a83.png" alt class="image--center mx-auto" /></p>
<p>Another picture to illustrate concurrency, parallelism and everything put together:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733068146026/0191bb4c-6ed6-452b-810f-54e5d45ce36b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-concurrency-problems">Concurrency Problems</h2>
<p>The main issue with concurrency comes from its non-deterministic nature that can produce race conditions.  </p>
<p>For example:<br />{1, 2a, 3a, 2b, 3b, 4}​<br />{1, 2a, 2b, 3a, 3b, 4}​<br />{1, 3a, 3b, 2a, 2b, 4}​<br />{1, 3a, 2a, 2b, 3b, 4} &lt;- Race condition</p>
<h2 id="heading-race-condition">Race Condition</h2>
<p>What is it and when does it happen?<br />- When two or more processes try to alter a shared resource simultaneously​.<br />- It happens when there's a fault in the timing or order of events​.<br />- Data Race is caused by a Race Condition</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733069475702/cc0b9fe6-76f1-4447-9c7d-e04c93fef85a.png" alt class="image--center mx-auto" /></p>
<p>How to avoid Race Conditions?</p>
<ul>
<li><p>Make the operations <strong>atomic</strong> for example make READ, MODIFY and STORE one operation​</p>
</li>
<li><p>Ensure that the <strong>shared resource</strong>, if being modified, is <strong>used by one process at a time</strong> – one atomic operation​</p>
</li>
<li><p>Atomicity adds more sequential order to our operations​</p>
</li>
</ul>
<p>Looking at the previous example we can make atomic operations and add a more sequential order that will prevent our program into running into race conditions, the drawback is that by adding deterministic outcome you reduce speed of execution.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733072682618/6e39781d-81fa-49c0-b576-154e82d704f8.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-mutex-lock">Mutex (Lock)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733073280019/4cc402de-c3df-4e7a-9a55-190c6006d581.png" alt class="image--center mx-auto" /></p>
<p>A great way to prevent race conditions is to use a Mutex: you can think of it as a lock that controls who has access on shared resources. We use a mutex for mutual exclusion to control concurrency.<br />Wikipedia has a great definition: a synchronization primitive that prevents state from being modified or accessed by multiple threads of execution at once. Locks enforce mutual exclusion concurrency control policies</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733073259109/f0dc8e85-308c-4503-87b4-0d77f5ebc70e.png" alt class="image--center mx-auto" /></p>
<p>I also like this <a target="_blank" href="https://stackoverflow.com/questions/34524/what-is-a-mutex/34558#34558">response from Stack Overflow</a> about using a rubber chicken to allow people talk in a heated discussion while others wait.</p>
<h2 id="heading-deadlock">Deadlock</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733073403496/b41211d2-aec7-4f5c-8fbd-b4967ab8aaee.png" alt class="image--center mx-auto" /></p>
<p>A possible issue with concurrency is having a deadlock, which happens when<br /><strong>- Two processes are waiting for each other<br />- Mutual exclusion is not present: we have no control over using the shared resource</strong></p>
<h2 id="heading-key-concurrency-concepts"><strong>Key Concurrency Concepts</strong></h2>
<ul>
<li><p>Use concurrency to <strong>enable parallelism</strong> and/or <strong>avoid waiting for events</strong>​</p>
</li>
<li><p>Make sure your shared resources don't produce race conditions by using <strong>mutual exclusion</strong> and <strong>atomic operations</strong></p>
</li>
</ul>
<h1 id="heading-golang">Golang</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733077270034/8fe32fb6-7add-4657-a7a0-9f89393a5b5d.png" alt class="image--center mx-auto" /></p>
<p>It’s a language designed to use for servers on the cloud. Go concurrency model is based on: Hoare's CSP (Communicating Sequential Processes) in 1978 and even Dijkstra's guarded commands (1975).<br />Golang's main difference from other similar languages is channels. Erlang is closer to the original CSP, where you communicate to a process by name rather than over a channel.</p>
<h2 id="heading-github-repo-with-examples">Github Repo with examples</h2>
<p>I will be using examples that are available <a target="_blank" href="https://github.com/bgdnvk/concurrency-talk">on my Github</a> and you can also find the links to go dev playground if you don’t want to run the code locally in there.</p>
<h2 id="heading-goroutines">Goroutines</h2>
<ul>
<li><p>Goroutine is a lightweight "thread" we use for concurrent operations​</p>
</li>
<li><p>Use goroutines for async programming: spin a goroutine to do something else while your program continues by using the <strong>go keyword before the function</strong>​</p>
</li>
<li><p>You can use anonymous functions with goroutines​</p>
</li>
<li><p>Goroutine is a wordplay related to Coroutine​</p>
</li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-comment">// print the ints in the loop</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printFrom</span><span class="hljs-params">(from <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++ {
        fmt.Println(from, <span class="hljs-string">":"</span>, i)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    printFrom(<span class="hljs-string">"direct"</span>)

    <span class="hljs-comment">// if you keep launching the program sometimes you will see goroutine2 first</span>
    <span class="hljs-keyword">go</span> printFrom(<span class="hljs-string">"goroutine1: runs concurrently"</span>)
    <span class="hljs-keyword">go</span> printFrom(<span class="hljs-string">"goroutine2: runs concurrently"</span>)

    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(msg <span class="hljs-keyword">string</span>)</span></span> {
        fmt.Println(msg)
    }(<span class="hljs-string">"anonymous goroutine"</span>)

    <span class="hljs-comment">// wait a second for goroutines to complete</span>
    <span class="hljs-comment">// otherwise the program finishes without displaying results from our goroutines</span>
    time.Sleep(time.Second)
    fmt.Println(<span class="hljs-string">"done"</span>)
}
</code></pre>
<h2 id="heading-channels">Channels</h2>
<ul>
<li><p>A channel is like a (UNIX) pipe: data goes in one end and comes out of another in the same order until the channel is closed​</p>
</li>
<li><p>Channels act as <a target="_blank" href="https://go.dev/ref/spec#Channel_types">first-in-first-out queues</a>​</p>
</li>
<li><p>Channels are bi-directional: you can restrict a channel's direction​</p>
</li>
<li><p>You can have multiple writers and readers on the same channel</p>
</li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    fmt.Println(<span class="hljs-string">"starting the program"</span>)
    <span class="hljs-comment">// make a new channel</span>
    messages := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)

    <span class="hljs-comment">// use an anymous  goroutine to send the string "ping" to the channel</span>
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> { messages &lt;- <span class="hljs-string">"first msg"</span> }()
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> { messages &lt;- <span class="hljs-string">"second msg"</span> }()

    <span class="hljs-comment">// we only loop twice becase we know we sent 2 messages</span>
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">2</span>; i++ {
        fmt.Println(&lt;-messages)
    }
}
</code></pre>
<p>In this example we can see how to send 2 messages concurrently to the same channel and read from the channel using a for loop.  </p>
<p>Key concepts about channels:</p>
<ul>
<li><p>Channel will block until someone reads the data, unless it's buffered​</p>
</li>
<li><p>You can have receive only or send only channels​</p>
</li>
<li><p>You can pass channels in between functions​</p>
</li>
<li><p>You can NOT send data to a closed channel</p>
</li>
</ul>
<h3 id="heading-deadlock-example-with-channels">Deadlock example with channels</h3>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    fmt.Println(<span class="hljs-string">"starting the program"</span>)
    <span class="hljs-comment">// make a new unbuffered channel</span>
    messages := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)

    <span class="hljs-comment">// we pass the channel in the function</span>
    <span class="hljs-comment">// share memory by communicating</span>
    deadlockExample(messages)
    <span class="hljs-comment">// normalLoop(messages)</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">deadlockExample</span><span class="hljs-params">(messages <span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-comment">// use an anymous  goroutine to send the string to the channel</span>
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> { messages &lt;- <span class="hljs-string">"first msg"</span> }()
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> { messages &lt;- <span class="hljs-string">"second msg"</span> }()
    <span class="hljs-comment">// Deadlock!</span>
    <span class="hljs-comment">// this loop is waiting forever on the channel</span>
    <span class="hljs-comment">// because the channel is never closed</span>
    <span class="hljs-keyword">for</span> msg := <span class="hljs-keyword">range</span> messages {
        <span class="hljs-comment">// display the data we got</span>
        fmt.Println(msg)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">normalLoop</span><span class="hljs-params">(messages <span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        <span class="hljs-comment">// send the data</span>
        messages &lt;- <span class="hljs-string">"first msg"</span>
        messages &lt;- <span class="hljs-string">"second msg"</span>
        <span class="hljs-comment">// close the channel</span>
        <span class="hljs-built_in">close</span>(messages)
    }()

    <span class="hljs-comment">// now that the channel is closed this for loop won't wait forever</span>
    <span class="hljs-keyword">for</span> msg := <span class="hljs-keyword">range</span> messages {
        <span class="hljs-comment">// get the data from the channel</span>
        <span class="hljs-comment">// display the data we got</span>
        fmt.Println(msg)
    }
}
</code></pre>
<p>Key Considerations:</p>
<ul>
<li><p>Range and For loops will wait to get data indefinitely from the channel until they are closed​</p>
</li>
<li><p>The sender should <strong>CLOSE</strong> the channel</p>
</li>
</ul>
<h3 id="heading-buffered-channels">Buffered channels</h3>
<p>For better performance we can use buffered channels if we know the capacity we will use.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    messages := []<span class="hljs-keyword">string</span>{<span class="hljs-string">"first msg"</span>, <span class="hljs-string">"second msg"</span>, <span class="hljs-string">"third msg"</span>}

    <span class="hljs-comment">// this channel only has capacity for 3</span>
    <span class="hljs-comment">// but we will use concurrency to share memory and send the latest message</span>
    <span class="hljs-comment">// we can use buffered channels so we never have to wait for the receiver to store the data</span>
    <span class="hljs-comment">// we store the data in the buffer, if the buffer is full we block</span>
    bufferedChannel := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>, <span class="hljs-number">3</span>)

    messages = addMessageToSlice(<span class="hljs-string">"last msg"</span>, messages)
    <span class="hljs-comment">// by enabling concurrency by using "go" keyword in front of this function</span>
    <span class="hljs-comment">// we send the latest message to the channel when the first one is out</span>
    <span class="hljs-comment">// if we remove the "go" keyword we will have a deadlock!</span>
    <span class="hljs-keyword">go</span> sendMessagesToChannel(messages, bufferedChannel)

    <span class="hljs-keyword">for</span> m := <span class="hljs-keyword">range</span> bufferedChannel {
        fmt.Println(m)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sendMessagesToChannel</span><span class="hljs-params">(messages []<span class="hljs-keyword">string</span>, bufchan <span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-keyword">for</span> _, m := <span class="hljs-keyword">range</span> messages {
        bufchan &lt;- m
    }
    <span class="hljs-comment">// remember to always close the channel</span>
    <span class="hljs-built_in">close</span>(bufchan)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addMessageToSlice</span><span class="hljs-params">(msg <span class="hljs-keyword">string</span>, messages []<span class="hljs-keyword">string</span>)</span> []<span class="hljs-title">string</span></span> {
    messages = <span class="hljs-built_in">append</span>(messages, msg)
    <span class="hljs-keyword">return</span> messages
}
</code></pre>
<p>If we remove the go keyword from go sendMessagesToChannel(messages, bufferedChannel) we will have <strong>bufchan &lt;- m</strong> <strong>waiting</strong> to send a 4th message but <strong>capacity is full</strong> and <strong>the for loop in main is waiting for the data</strong> to start to flow, creating a deadlock!</p>
<h2 id="heading-waitgroup">WaitGroup</h2>
<p>WaitGroup is an object from the sync package that will let you control the flow in a more sequential way, check the example below.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    messages := []<span class="hljs-keyword">string</span>{<span class="hljs-string">"first msg"</span>, <span class="hljs-string">"second msg"</span>, <span class="hljs-string">"third msg"</span>}
    moreMessages := []<span class="hljs-keyword">string</span>{<span class="hljs-string">"fourth msg"</span>, <span class="hljs-string">"fifth msg"</span>, <span class="hljs-string">"last msg"</span>}

    bufferedChannel := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>, <span class="hljs-number">3</span>)

    <span class="hljs-comment">// we make an object to control the flow of our execution</span>
    <span class="hljs-comment">// it contains a counter for each executed function</span>
    wg := sync.WaitGroup{}
    <span class="hljs-keyword">for</span> _, m := <span class="hljs-keyword">range</span> moreMessages {
        <span class="hljs-comment">// every time we spin a new goroutine we increase the counter</span>
        <span class="hljs-comment">// on how much we have to wait</span>
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-comment">// keep in mind the messages will not arrive in order because go routines spawn concurrently (non-deterministic behaviour)</span>
        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(m <span class="hljs-keyword">string</span>)</span></span> {
            messages = addMessageToSlice(m, messages)
            <span class="hljs-comment">// once the execution is done we let our WaitGroup know (this reduces the counter)</span>
            wg.Done()
        }(m)

    }

    <span class="hljs-comment">// we make sure we wait for the previous block to finish</span>
    wg.Wait()

    <span class="hljs-keyword">go</span> sendMessagesToChannel(messages, bufferedChannel)

    <span class="hljs-keyword">for</span> m := <span class="hljs-keyword">range</span> bufferedChannel {
        fmt.Println(m)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sendMessagesToChannel</span><span class="hljs-params">(messages []<span class="hljs-keyword">string</span>, bufchan <span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-keyword">for</span> _, m := <span class="hljs-keyword">range</span> messages {
        bufchan &lt;- m
    }
    <span class="hljs-comment">// remember to always close the channel</span>
    <span class="hljs-built_in">close</span>(bufchan)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addMessageToSlice</span><span class="hljs-params">(msg <span class="hljs-keyword">string</span>, messages []<span class="hljs-keyword">string</span>)</span> []<span class="hljs-title">string</span></span> {
    messages = <span class="hljs-built_in">append</span>(messages, msg)
    <span class="hljs-keyword">return</span> messages
}
</code></pre>
<h3 id="heading-dont-use-waitgroup-just-because-you-can">Don’t use WaitGroup just because you can</h3>
<p>Here’s an example of the same code as above but refactored to work as expected without using WaitGroup.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    messages := []<span class="hljs-keyword">string</span>{<span class="hljs-string">"first msg"</span>, <span class="hljs-string">"second msg"</span>, <span class="hljs-string">"third msg"</span>}
    moreMessages := []<span class="hljs-keyword">string</span>{<span class="hljs-string">"fourth msg"</span>, <span class="hljs-string">"fifth msg"</span>, <span class="hljs-string">"last msg"</span>}

    bufferedChannel := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>, <span class="hljs-number">3</span>)

    <span class="hljs-comment">// due to the concurrent nature of our program we can just keep sending messages to the channel</span>
    <span class="hljs-keyword">for</span> _, m := <span class="hljs-keyword">range</span> moreMessages {
        messages = addMessageToSlice(m, messages)
    }

    <span class="hljs-keyword">go</span> sendMessagesToChannel(messages, bufferedChannel)

    <span class="hljs-keyword">for</span> m := <span class="hljs-keyword">range</span> bufferedChannel {
        fmt.Println(m)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sendMessagesToChannel</span><span class="hljs-params">(messages []<span class="hljs-keyword">string</span>, bufchan <span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-keyword">for</span> _, m := <span class="hljs-keyword">range</span> messages {
        bufchan &lt;- m
    }
    <span class="hljs-built_in">close</span>(bufchan)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addMessageToSlice</span><span class="hljs-params">(msg <span class="hljs-keyword">string</span>, messages []<span class="hljs-keyword">string</span>)</span> []<span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">append</span>(messages, msg)
}
</code></pre>
<h3 id="heading-channel-key-points">Channel Key Points</h3>
<ul>
<li><p>Used to communicate by sharing memory​</p>
</li>
<li><p>Remember to close the channel (sometimes GC will take care of it)​</p>
</li>
<li><p>If you already know your channel's capacity use a buffered channel</p>
</li>
</ul>
<h2 id="heading-select">Select</h2>
<ul>
<li><p>The select statement lets a <strong>goroutine wait</strong> on <strong>multiple communication operations</strong>​</p>
</li>
<li><p>A <strong>select blocks until one of its cases can run</strong>, then it executes that case. It chooses one at random if multiple are ready</p>
</li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Create two channels</span>
    channel1 := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)
    channel2 := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)

    <span class="hljs-comment">// msg will arrive after 2 seconds</span>
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        time.Sleep(<span class="hljs-number">2</span> * time.Second)
        channel1 &lt;- <span class="hljs-string">"Message from Channel 1"</span>
    }()

    <span class="hljs-comment">// msg will arrive after 1 second</span>
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        time.Sleep(<span class="hljs-number">1</span> * time.Second)
        channel2 &lt;- <span class="hljs-string">"Message from Channel 2"</span>
    }()

    <span class="hljs-comment">// we will execute this block twice and check every</span>
    <span class="hljs-comment">// if we get a msg back</span>
    <span class="hljs-comment">// then print whichever is ready</span>
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">2</span>; i++ {
        <span class="hljs-comment">// select block waits for one of the channels to receive a msg</span>
        <span class="hljs-comment">// it waits for at least one channel to be ready</span>
        <span class="hljs-keyword">select</span> {
        <span class="hljs-keyword">case</span> msg1 := &lt;-channel1:
            fmt.Println(msg1)
        <span class="hljs-keyword">case</span> msg2 := &lt;-channel2:
            fmt.Println(msg2)
            <span class="hljs-comment">// we can add a default case for when we don't want to wait for a msg</span>
            <span class="hljs-comment">// default:</span>
            <span class="hljs-comment">//    fmt.Println("default")</span>
        }
    }
}
</code></pre>
<p>If you are unsure about the data arriving but want to proceed anyway have a default case in your select</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    channel := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)

    <span class="hljs-comment">// wait 2s and send data to the channel</span>
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        time.Sleep(<span class="hljs-number">2</span> * time.Second)
        channel &lt;- <span class="hljs-string">"Data from Goroutine"</span>
    }()

    <span class="hljs-comment">// infinite loop</span>
    <span class="hljs-keyword">for</span> {
        <span class="hljs-keyword">select</span> {
        <span class="hljs-keyword">case</span> msg := &lt;-channel:
            fmt.Println(msg)
            <span class="hljs-keyword">return</span> <span class="hljs-comment">// break infinite loop</span>

        <span class="hljs-comment">// default case simply simulates some work</span>
        <span class="hljs-comment">// we call it every time  until we get the other case</span>
        <span class="hljs-keyword">default</span>:
            fmt.Println(<span class="hljs-string">"No data yet, doing other work..."</span>)
            time.Sleep(<span class="hljs-number">500</span> * time.Millisecond) <span class="hljs-comment">// Simulate some work</span>
        }
    }
}
</code></pre>
<h2 id="heading-mutex">Mutex</h2>
<ul>
<li><p>Use a mutex to access your shared resources​</p>
</li>
<li><p>Think if you really want or need to have a shared state</p>
</li>
</ul>
<p><strong>Mutex ensures only one process is modifying the shared data at a time</strong>​.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-keyword">type</span> Container <span class="hljs-keyword">struct</span> {
    counters <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">int</span> <span class="hljs-comment">// shared resource that doesn't support concurrent writes</span>
    mu       sync.Mutex     <span class="hljs-comment">// protect the shared resource with a lock</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(c *Container)</span> <span class="hljs-title">inc</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-comment">// try removing the lock here and see what happens</span>
    <span class="hljs-comment">// the program will panic with an error</span>
    <span class="hljs-comment">// fatal error: concurrent map writes</span>
    c.mu.Lock()
    <span class="hljs-keyword">defer</span> c.mu.Unlock()
    c.counters[name]++
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(c *Container)</span> <span class="hljs-title">dec</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>)</span></span> {
    c.mu.Lock()
    <span class="hljs-keyword">defer</span> c.mu.Unlock()
    c.counters[name]--
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    c := Container{
        counters: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">int</span>{<span class="hljs-string">"a"</span>: <span class="hljs-number">0</span>, <span class="hljs-string">"b"</span>: <span class="hljs-number">0</span>}, <span class="hljs-comment">// map doesn't support concurrent access</span>
    }

    <span class="hljs-keyword">var</span> wg sync.WaitGroup

    increment := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>, n <span class="hljs-keyword">int</span>)</span></span> {
        <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; n; i++ {
            c.inc(name) <span class="hljs-comment">// increment counter</span>
        }
        wg.Done()
    }

    decrement := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>, n <span class="hljs-keyword">int</span>)</span></span> {
        <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; n; i++ {
            c.dec(name) <span class="hljs-comment">// decrement counter</span>
        }
        wg.Done()
    }

    <span class="hljs-comment">// if you WaitGroup counter is lower than needed your program will panic</span>
    <span class="hljs-comment">// if it's higher it will be blocked in a deadlock</span>
    wg.Add(<span class="hljs-number">3</span>)
    <span class="hljs-keyword">go</span> decrement(<span class="hljs-string">"a"</span>, <span class="hljs-number">1000</span>)
    <span class="hljs-keyword">go</span> increment(<span class="hljs-string">"a"</span>, <span class="hljs-number">1000</span>)
    <span class="hljs-keyword">go</span> increment(<span class="hljs-string">"b"</span>, <span class="hljs-number">1000</span>)

    wg.Wait()

    fmt.Println(<span class="hljs-string">"Final Counters:"</span>, c.counters)
}
</code></pre>
<h2 id="heading-theres-more-to-concurrency-in-go">There’s more to concurrency in Go!</h2>
<p>In this article you have things to get started and to understand the concurrency model but to master it going forward I’d recommend looking into patterns like Fan-In Fan-Out (Multiplexing) and Pipelines to get started.</p>
<p>Additionally once you start developing services it’s a good practice to rely con context for cancellation and more.</p>
]]></content:encoded></item><item><title><![CDATA[Popular Design Patterns: Dependency Injection, Factory, Singleton, Observer and Strategy]]></title><description><![CDATA[Patterns are everywhere

This great comic is from False Knees and it illustrates that you can find patterns everywhere, you can also check out this National Graphic article. Your code base is no different.
The objective of this article is to understa...]]></description><link>https://bognov.tech/popular-design-patterns-dependency-injection-factory-singleton-observer-and-strategy</link><guid isPermaLink="true">https://bognov.tech/popular-design-patterns-dependency-injection-factory-singleton-observer-and-strategy</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[dependency injection]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Wed, 01 Mar 2023 03:23:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677640977478/3c523a20-30c7-4bbf-9513-35b615433170.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-patterns-are-everywhere">Patterns are everywhere</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677350992071/b1c2716e-da3b-4e76-ba83-2cdb69e4e7cd.png" alt class="image--center mx-auto" /></p>
<p>This great comic is from <a target="_blank" href="https://twitter.com/FalseKnees/status/1389021082439532545/photo/1">False Knees</a> and it illustrates that you can find patterns everywhere, you can also check out this <a target="_blank" href="https://www.nationalgeographic.com/travel/article/spectacular-patterns-nature">National Graphic article</a>. Your code base is no different.</p>
<p>The objective of this article is to understand or refresh the memory of the different patterns and then jump into <a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> to do something cool.</p>
<h1 id="heading-resources">Resources</h1>
<p>You can find all of the code in <a target="_blank" href="https://github.com/bgdnvk/patterns">this repository</a> on my <a target="_blank" href="https://github.com/bgdnvk">Github</a>.</p>
<p>If you are kind of new or not sure what's all this about I recommend you read my previous blog post: <a target="_blank" href="https://bognov.tech/software-engineering-oop-principles-and-good-practices-to-avoid-spaghetti-code">Software Engineering OOP principles and good practices to avoid spaghetti code</a>.</p>
<p>Additionally, I highly recommend the site <a target="_blank" href="https://refactoring.guru/">Refactor Guru</a> to learn about design patterns and refactoring.<br />As well as <a target="_blank" href="https://www.youtube.com/@ChristopherOkhravi">Christopher Okhravi's Youtube Channel</a> for more in-depth videos and examples, he's a great teacher.</p>
<h4 id="heading-tip">Tip</h4>
<p>I recommend exploring all the resources above to have a better understanding of each pattern as my intention is to provide and simplify examples. Wikipedia is another great resource but it might be a bit too difficult for beginners.</p>
<h1 id="heading-strategy">Strategy</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677442828617/f6541c0c-6775-40c1-a76e-c22b2a37e7ba.png" alt class="image--center mx-auto" /></p>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Strategy_pattern">strategy pattern</a> allows you to select an algorithm at run time. The name is "strategy" because given a certain context you can select a strategy appropriate for that context.</p>
<p>This is directly related to one of the SOLID principles, the open-closed principle that states <em>software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.</em></p>
<p>Let's look at an example with TypeScript, and if you are using any other language the most important part is you understand how the classes and interfaces work together.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//define interface we will use for different strategies</span>
<span class="hljs-keyword">interface</span> Strategy {
    execute(str: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span>
}

<span class="hljs-comment">//define different strategies we could use</span>
<span class="hljs-keyword">class</span> upperCaseStrategy <span class="hljs-keyword">implements</span> Strategy {

    <span class="hljs-keyword">public</span> execute(str: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> str.toUpperCase()
    }
}

<span class="hljs-keyword">class</span> lowerCaseStrategy <span class="hljs-keyword">implements</span> Strategy {

    <span class="hljs-keyword">public</span> execute(str: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> str.toLowerCase()
    }
}

<span class="hljs-keyword">class</span> Context {

    <span class="hljs-comment">//we will be using a different strategy for every situation</span>
    <span class="hljs-comment">//however here we just define a parameter of type Strategy</span>
    <span class="hljs-comment">//that will be changed as we wish</span>
    <span class="hljs-keyword">private</span> strategy: Strategy

    <span class="hljs-comment">//while making the object we will include the strategy to use</span>
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">strategy: Strategy</span>) {
        <span class="hljs-built_in">this</span>.strategy = strategy
    }

    <span class="hljs-comment">//in case we want to change out strategy we have a method for that</span>
    <span class="hljs-keyword">public</span> setStrategy(strategy: Strategy) {
        <span class="hljs-built_in">this</span>.strategy = strategy
    }

    <span class="hljs-comment">//we will get back the modified string according to the strategy we use</span>
    <span class="hljs-keyword">public</span> executeStrategy(str: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span>{
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.strategy.execute(str)
    }
}


<span class="hljs-comment">//define a string we will be using for testing</span>
<span class="hljs-keyword">const</span> randomString = <span class="hljs-string">'rAnDoM sTrInG'</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'inittial string:'</span>, randomString)
<span class="hljs-comment">//make a new context with the upper case strategy</span>
<span class="hljs-keyword">const</span> context = <span class="hljs-keyword">new</span> Context(<span class="hljs-keyword">new</span> upperCaseStrategy())
<span class="hljs-comment">//use the current strategy (which is upperCase) to get an upper case String</span>
<span class="hljs-keyword">const</span> upperCaseString = context.executeStrategy(randomString)
<span class="hljs-comment">//check it's upper case</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'upper case:'</span>, upperCaseString)
<span class="hljs-comment">//change context's strategy</span>
context.setStrategy(<span class="hljs-keyword">new</span> lowerCaseStrategy())
<span class="hljs-comment">//get the lower case string with a different strategy</span>
<span class="hljs-keyword">const</span> lowerCaseString = context.executeStrategy(upperCaseString)
<span class="hljs-comment">//check it's lower case</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'lower case:'</span>, lowerCaseString)
</code></pre>
<p>In this example you can see how we will be able to use the same Context class throughout our entire program but by changing strategies we will be able to get different results when we call the executeStrategy method.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677450569658/e9b8916a-6af6-4896-baed-5ddf1ad4d750.png" alt class="image--center mx-auto" /></p>
<p>If you want more complex examples Refactoring Guru has a <a target="_blank" href="https://refactoring.guru/design-patterns/strategy/go/example">cache implementation in Go</a> and a <a target="_blank" href="https://refactoring.guru/design-patterns/strategy/java/example">payment method in Java</a>.</p>
<h2 id="heading-dependency-injection-vs-strategy">Dependency Injection vs Strategy</h2>
<p>If you are somehow familiar with DI and not sure why the strategy pattern is used, I'd recommend reading this <a target="_blank" href="https://stackoverflow.com/a/4176811/14356309">Stack Overflow Answer</a>.</p>
<h1 id="heading-observer">Observer</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677442954008/17f3f19d-f020-4a7b-8fb9-dd80dceb6373.png" alt class="image--center mx-auto" /></p>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Observer_pattern">observer pattern</a> relies on one principle: the observable (which often is called subject or event manager) needs to notify/update the observers (which can be called subscriber) it contains about an event.</p>
<p>The most common case would be a notification of some kind, you want to notify your users (or a specific set of users) about something that has happened so you take the observers and push their update method.</p>
<p>Note that for the observers to be notified they need to be somehow connected to the observable and the observable also needs to have a way to call the notify/update methods of the observables.</p>
<p>Let's look at the code, but keep in mind that I'm using the words observable, subject and event manager/dispatcher interchangeably. The same goes for observer and subscriber.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//subject or event manager/dispatcher</span>
<span class="hljs-keyword">interface</span> Observable {
    <span class="hljs-comment">//add the observers we want to track out observable</span>
    add(observer: Observer): <span class="hljs-built_in">void</span>
    <span class="hljs-comment">//same but delete</span>
    remove(observer: Observer): <span class="hljs-built_in">void</span>
    <span class="hljs-comment">//notify all of the observers</span>
    notify(): <span class="hljs-built_in">void</span>
}

<span class="hljs-comment">//event listener</span>
<span class="hljs-keyword">interface</span> Observer {

    name: <span class="hljs-built_in">string</span>
    <span class="hljs-comment">//the update method will be triggered when the observable uses it</span>
    <span class="hljs-comment">//you can pass the observable to get more context or not</span>
    update(observable: Observable): <span class="hljs-built_in">void</span>
}

<span class="hljs-comment">//since a lot of the examples use Subject instead of Observable let's call our class Subject</span>
<span class="hljs-comment">//it will be the one notifying the different observers</span>
<span class="hljs-keyword">class</span> Subject <span class="hljs-keyword">implements</span> Observable {

    name: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) {
        <span class="hljs-built_in">this</span>.name = name
    }

    <span class="hljs-comment">//using a Map but this can just be an array</span>
    <span class="hljs-keyword">private</span> observersMap: <span class="hljs-built_in">Map</span>&lt;Observer[<span class="hljs-string">'name'</span>], Observer&gt; = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>&lt;Observer[<span class="hljs-string">'name'</span>], Observer&gt;

    <span class="hljs-comment">//add the observer/subscriber to our observable/subject</span>
    <span class="hljs-keyword">public</span> add(observer: Observer): <span class="hljs-built_in">void</span> {

        <span class="hljs-built_in">this</span>.observersMap.set(observer.name, observer)
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`added observer <span class="hljs-subst">${observer.name}</span> to <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span>`</span>)
    }

    <span class="hljs-keyword">public</span> remove(observer: Observer): <span class="hljs-built_in">void</span> {

        <span class="hljs-built_in">this</span>.observersMap.delete(observer.name)
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`removed observer <span class="hljs-subst">${observer.name}</span> to <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span>`</span>)
    }

    <span class="hljs-comment">//we do a forEach on our map so we can press the update method in all of them and pass the current observable/subject</span>
    <span class="hljs-keyword">public</span> notify(): <span class="hljs-built_in">void</span> {

        <span class="hljs-comment">//note that we allow to pass the instance of our observable to every observer, check the interface</span>
        <span class="hljs-built_in">this</span>.observersMap.forEach(<span class="hljs-function">(<span class="hljs-params">v,k,m</span>) =&gt;</span> v.update(<span class="hljs-built_in">this</span>)) 
    }

    <span class="hljs-keyword">public</span> getName(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.name
    }

    <span class="hljs-comment">//example of a possible method will have the notify method inside, note how we call it at the end to notify our observers</span>
    <span class="hljs-comment">//this is a simple change of name but it could be anything</span>
    <span class="hljs-keyword">public</span> changeName(name: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">void</span> {

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`changing name from <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> to <span class="hljs-subst">${name}</span>..`</span>)
        <span class="hljs-built_in">this</span>.name = name

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`notifications being sent..`</span>)
        <span class="hljs-built_in">this</span>.notify()
    }
}

<span class="hljs-keyword">class</span> webObserver <span class="hljs-keyword">implements</span> Observer {

    name: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) {
        <span class="hljs-built_in">this</span>.name = name
    }
    update(observable: Subject): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> notification from <span class="hljs-subst">${observable.getName()}</span>`</span>)
    }
}

<span class="hljs-keyword">class</span> phoneObserver <span class="hljs-keyword">implements</span> Observer {

    name: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) {
        <span class="hljs-built_in">this</span>.name = name
    }
    update(observable: Subject): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> notification from <span class="hljs-subst">${observable.getName()}</span>`</span>)
    }
}

<span class="hljs-comment">//init all our objects</span>
<span class="hljs-keyword">const</span> subject = <span class="hljs-keyword">new</span> Subject(<span class="hljs-string">'THANOS SERVICE'</span>)
<span class="hljs-keyword">const</span> webObs = <span class="hljs-keyword">new</span> webObserver(<span class="hljs-string">'WEB'</span>)
<span class="hljs-keyword">const</span> phoneObs = <span class="hljs-keyword">new</span> phoneObserver(<span class="hljs-string">'PHONE'</span>)

<span class="hljs-comment">//make sure to subscribe/add the observers the observable</span>
subject.add(webObs)
subject.add(phoneObs)

<span class="hljs-comment">//notify all of our observers</span>
subject.notify()

<span class="hljs-comment">//now let's change the name</span>
<span class="hljs-comment">//this is just an example of a possible change of state inside the class, it could be a new item arrival for example or something else</span>
subject.changeName(<span class="hljs-string">'IRONMAN'</span>)
</code></pre>
<p>This is the output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677450050994/a849735a-5d3b-4418-8387-2e9b539a6c75.png" alt class="image--center mx-auto" /></p>
<p>If you want more examples feel free to check Refactoring Guru, here's <a target="_blank" href="https://refactoring.guru/design-patterns/observer/go/example">Go</a> and <a target="_blank" href="https://refactoring.guru/design-patterns/observer/java/example">Java</a>.</p>
<h2 id="heading-observer-vs-pubsub">Observer vs Pub/Sub</h2>
<p>You might have noticed that the observer pattern could end up being too tightly coupled and it's very similar to another architecture: pub/sub.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677450182771/13397ea0-e789-4608-a539-c47e8dfd79ca.png" alt class="image--center mx-auto" /></p>
<p>Pub/Sub is a bit different and adds complexity, however it's great if you decide to work with events as it provides a separate channel for subscribers.</p>
<h1 id="heading-singleton">Singleton</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677524517727/70be386e-1638-4892-a63f-7d5c262476d0.png" alt class="image--center mx-auto" /></p>
<p>If you want to ensure there's only one instance of the class then use the singleton pattern. Although some people might argue against it this pattern is widely used, especially with database connections.</p>
<p>The beauty of this design is its use of the private initializer.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Singleton {
    <span class="hljs-comment">//here's the best part, we use a static variable to store our singleton instance</span>
    <span class="hljs-comment">//and make it private so we can only get it through the getsingleton() method</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> singleton: Singleton

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'starting singleton..'</span>)
    }

    <span class="hljs-comment">//call this method every time we want a singleton</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> getSingleton(): Singleton {

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'getting singleton..'</span>)
        <span class="hljs-comment">//if the singleton instance (static singleton) is null we will initialize it</span>
        <span class="hljs-keyword">if</span>(!Singleton.singleton) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'no singleton available'</span>)
            Singleton.singleton = <span class="hljs-keyword">new</span> Singleton()
        }

        <span class="hljs-keyword">return</span> Singleton.singleton
    }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mainProgram</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">//... code</span>
    <span class="hljs-keyword">const</span> singleton1 = Singleton.getSingleton()
    <span class="hljs-keyword">const</span> singleton2 = Singleton.getSingleton()

    <span class="hljs-keyword">if</span>(singleton1 === singleton2) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'same instance'</span>)
    }

}
mainProgram()
</code></pre>
<p>This is the output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677526072381/4248cd59-fa95-43cc-bcf6-ae4cc3132fcc.png" alt class="image--center mx-auto" /></p>
<p>As always Refactoring Guru has examples in <a target="_blank" href="https://refactoring.guru/design-patterns/singleton/java/example">Java</a> and <a target="_blank" href="https://refactoring.guru/design-patterns/singleton/go/example">Go</a> as well.</p>
<h1 id="heading-factory">Factory</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677603089505/7dbb62f6-e06a-49b7-a951-e8f365c24401.png" alt class="image--center mx-auto" /></p>
<p>As you can see in the UML diagram the whole point of the factory pattern is to have a specific place (interface of the factory) where you can create the needed objects. The factory is called "creator" and the objects created are called "products".</p>
<p>Basically what we are doing is encapsulating the business logic (a particular way of constructing objects). The principle is very simple but you can make it as complex as you want, the idea is to always have a factory method available that you can move around your codebase and get the concrete objects you want or need.</p>
<p>I really like this definition from <a target="_blank" href="https://refactoring.guru/design-patterns/factory-method">Refactoring Guru</a>:</p>
<blockquote>
<p><strong>Factory Method</strong> is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.</p>
</blockquote>
<p>Let's look at a code example with TypeScript:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//pizza is going to be the product that a factory can make</span>
<span class="hljs-keyword">interface</span> Pizza {
    name: <span class="hljs-built_in">string</span>
    getName(): <span class="hljs-built_in">string</span>
    cookingTime(): <span class="hljs-built_in">void</span>
    eat(): <span class="hljs-built_in">void</span>
}

<span class="hljs-comment">//this is just an example, NY pizza is different from Chicago pizza</span>
<span class="hljs-keyword">class</span> NewYorkPizza <span class="hljs-keyword">implements</span> Pizza {

    name: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) {
        <span class="hljs-built_in">this</span>.name = name
    }

    getName(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.name
    }

    cookingTime(): <span class="hljs-built_in">void</span>{
       <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'15min'</span>) 
    }

    eat(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'eating NY pizza'</span>)
    }
}

<span class="hljs-keyword">class</span> ChicagoPizza <span class="hljs-keyword">implements</span> Pizza {

    name: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) {
        <span class="hljs-built_in">this</span>.name = name
    }

    getName(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.name
    }
    cookingTime(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'30min'</span>)
    }
    eat(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'eating Chicago pizza'</span>)
    }
}

<span class="hljs-comment">//this is our creator, we can use this interfece anywhere in order to make our products(pizzas)</span>
<span class="hljs-keyword">interface</span> PizzaFactory {
    makePizza(pizza: Pizza): Pizza
}

<span class="hljs-comment">//lets think of different restaurants that want to make pizzas</span>
<span class="hljs-keyword">class</span> NewYorkRestaurant <span class="hljs-keyword">implements</span> PizzaFactory {

    makePizza(): Pizza {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> NewYorkPizza(<span class="hljs-string">'best NY pizza'</span>)
    }
}

<span class="hljs-keyword">class</span> ChicagoRestaurant <span class="hljs-keyword">implements</span> PizzaFactory {

    makePizza(): Pizza {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ChicagoPizza(<span class="hljs-string">'best Chicago pizza'</span>)
    }
}

<span class="hljs-comment">//create our factories</span>
<span class="hljs-keyword">const</span> newYorkRestaurant: NewYorkRestaurant = <span class="hljs-keyword">new</span> NewYorkRestaurant()
<span class="hljs-keyword">const</span> chicagoRestaurant: ChicagoRestaurant = <span class="hljs-keyword">new</span> ChicagoRestaurant() 

<span class="hljs-comment">//get the product</span>
<span class="hljs-keyword">const</span> myNewYorkPizza = newYorkRestaurant.makePizza()
<span class="hljs-keyword">const</span> myChicagoPizza = chicagoRestaurant.makePizza()

<span class="hljs-comment">//here we use our products</span>
<span class="hljs-comment">//this is a simple example but remember you can add a lot more logic and extend the examples</span>
<span class="hljs-comment">//the point of the pattern is so that you could use the factories anywhere you need</span>
<span class="hljs-comment">//and modify the logic inside</span>
<span class="hljs-comment">//try adding a delivery method for example to one of the restaurants or something concrete to the pizzas</span>
<span class="hljs-keyword">const</span> newYorkPizzaName = myNewYorkPizza.getName()
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`NY pizza name is: <span class="hljs-subst">${newYorkPizzaName}</span>`</span>)
myNewYorkPizza.cookingTime()

<span class="hljs-keyword">const</span> chicagoPizzaName = myChicagoPizza.getName()
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`NY pizza name is: <span class="hljs-subst">${chicagoPizzaName}</span>`</span>)
myChicagoPizza.cookingTime()
</code></pre>
<p>This is the output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677618277758/35d2289e-a70c-49ec-8102-d538358e3c55.png" alt class="image--center mx-auto" /></p>
<p>Check out additional examples from RG: <a target="_blank" href="https://refactoring.guru/design-patterns/factory-method/java/example">Java</a> and <a target="_blank" href="https://refactoring.guru/design-patterns/factory-method/go/example">Go</a>.</p>
<h2 id="heading-abstract-factory">Abstract Factory</h2>
<p>The Factory method is usually used, or well, it evolves into an Abstract Factory. As the name says, what you do is abstract the factory so you can make more concrete factories that mix different implementations of the concrete products.</p>
<p>This UML from Wikipedia sums it up fairly well:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677619426365/b7d92f3c-feec-429c-9926-50c972aa8ade.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://refactoring.guru/design-patterns/abstract-factory">Refactoring Guru</a> uses a GUI example and I think is the best one for this pattern, so check it out:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677619968315/43182408-5adf-49e4-9a48-66963dda7b7f.png" alt class="image--center mx-auto" /></p>
<p>They also have <a target="_blank" href="https://refactoring.guru/design-patterns/abstract-factory">pseudocode</a> that illustrates everything going on. This <a target="_blank" href="https://en.wikipedia.org/wiki/Abstract_factory_pattern#Python_example">Python example</a> from Wikipedia is also pretty good.</p>
<h1 id="heading-dependency-injection">Dependency Injection</h1>
<p>DI is one of those concepts that can be either too easy to understand or too hard, and by this I mean even people who use it constantly might not be able to fully explain the cycle of what's going on or how it works.</p>
<p>My intention is to give you a general understanding so you could dive further in, or at least be able to use DI in your projects.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677623357516/abb671f6-fef1-4cee-b633-59dce18981ff.png" alt class="image--center mx-auto" /></p>
<p>The picture above is from <a target="_blank" href="https://dotnettutorials.net/lesson/introduction-to-inversion-of-control/">this article</a>. You don't have to read it, I just want to point out there's a lot going on. Additionally for a more in depth post on <a target="_blank" href="https://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a> I recommend this <a target="_blank" href="https://www.martinfowler.com/articles/injection.html">article from Martin Fowler</a> (if you don't know who he is then you should definitely check out his blog).</p>
<p>Dependency Injection relies on the Inversion of Control principle.</p>
<h2 id="heading-ioc">IoC</h2>
<p>As always one of the main problems when writing software is tight coupling, in OOP you get classes entangled with each other which makes it impossible to extend or modify. This issue is mainly because the <a target="_blank" href="https://bognov.tech/software-engineering-oop-principles-and-good-practices-to-avoid-spaghetti-code#heading-openclosed-principle">Open-Closed Principle</a> isn't followed.</p>
<p>We apply Inversion of Control to loosen and decouple our classes. Invert the control of dependencies. Instead of our current class controlling the creation of a new class we want to have something in between, a layer of abstraction that will have that control instead.</p>
<p>IoC isn't only applied to classes but I want to make this as simple as possible.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677628009643/ca1d24e8-505e-4a95-b1ae-95ff786f467d.png" alt class="image--center mx-auto" /></p>
<p>You can think about IoC as removing the dependency for further extension.</p>
<p>The picture above is from <a target="_blank" href="https://www.tutorialsteacher.com/ioc/inversion-of-control">this article</a> and has some examples.</p>
<h2 id="heading-di-example">DI Example</h2>
<p>The theory is the same as with IoC, we want to avoid hard-coded dependencies so we can maintain our code in the future. Interfaces and design patterns exist, let's use them.</p>
<p>Knowing all of the above let's think about how to implement Dependency Injection: the main thing we have to do is to relinquish the control of creating an object we need somewhere else. We are still going to use the object of course so we need to store it, but let's not worry about how it gets made.  </p>
<p>The best examples I could find are from <a target="_blank" href="https://www.digitalocean.com/community/tutorials/java-dependency-injection-design-pattern-example-tutorial">Digital Ocean (Java)</a> and <a target="_blank" href="https://developer.android.com/training/dependency-injection#java">Android (Kotlin, Java)</a> so feel free to dig in, I liked the example from Android so I'm going to simplify it with TypeScript.</p>
<blockquote>
<p><strong>Constructor Injection:</strong> You pass the dependencies of a class to its constructor.</p>
</blockquote>
<pre><code class="lang-typescript"><span class="hljs-comment">//dependency of car that we have extracted</span>
<span class="hljs-keyword">class</span> Engine {

    ignite(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'vroom vroom'</span>)
    }
}

<span class="hljs-comment">//car has the engine dependency</span>
<span class="hljs-comment">//but it's not in charge of constructing that dependency</span>
<span class="hljs-comment">//only of using it</span>
<span class="hljs-keyword">class</span> Car {
    <span class="hljs-comment">//we still need a variable to store the engine</span>
    engine: Engine

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">engine: Engine</span>) {
        <span class="hljs-built_in">this</span>.engine = engine
    }

    <span class="hljs-comment">//use of engine after getting its dependency</span>
    start(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">this</span>.engine.ignite()
    }
}

<span class="hljs-comment">//make a new engine</span>
<span class="hljs-keyword">const</span> engine = <span class="hljs-keyword">new</span> Engine()
<span class="hljs-comment">//INJECT the DEPENDENCY</span>
<span class="hljs-keyword">const</span> car = <span class="hljs-keyword">new</span> Car(engine)

<span class="hljs-comment">//do your business logic</span>
car.start()
</code></pre>
<p>You should get a 'vroom vroom' when you run it!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677633990696/645e8e7c-e787-4bc0-ba56-c6f3a8d96e97.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-tekbeans">Tekbeans</h3>
<p>If you made it all the way here congratulations!</p>
<p>I've started working on a TS package called <a target="_blank" href="https://www.npmjs.com/package/tekbeans">tekbeans, it's on npm</a> and of course you can check the source code on <a target="_blank" href="https://github.com/bgdnvk/tekbeans">Github</a>. It's on very early stages, however if you want to dig deeper into IoC and DI with TS then feel free to play with it. The package will be heavily inspired on Spring as it's the most famous framework with DI that uses explicit beans I believe.</p>
<h1 id="heading-fin">Fin</h1>
<p>As a reminder, you can find the code to all examples on my Github in the <a target="_blank" href="https://github.com/bgdnvk/patterns">patterns repository</a>, I will probably keep adding interesting stuff there.</p>
<p>You can also follow me here or reach out on <a target="_blank" href="https://twitter.com/tekbog">Twitter</a> or maybe even <a target="_blank" href="https://social.linux.pizza/@tekbog">Mastodon</a>.</p>
<p>It's 4 AM right now as I'm finishing this article, so if it has helped you in any way let me know, insults are welcome as well since this is the internet.</p>
]]></content:encoded></item><item><title><![CDATA[Solve graph problems with Breadth First Search (BFS) and Depth First Search (DFS) algorithms - JavaScript version]]></title><description><![CDATA[Intro

There's an xkcd for everything!
If you are preparing for interviews or just studying DSA you will eventually reach graph problems and then dynamic programming. This post is the step before recursion, we are going to see how BFS and DFS algorit...]]></description><link>https://bognov.tech/solve-graph-problems-with-breadth-first-search-bfs-and-depth-first-search-dfs-algorithms-javascript-version</link><guid isPermaLink="true">https://bognov.tech/solve-graph-problems-with-breadth-first-search-bfs-and-depth-first-search-dfs-algorithms-javascript-version</guid><category><![CDATA[data structures]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Computer Science]]></category><category><![CDATA[leetcode]]></category><category><![CDATA[algorithms]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Thu, 19 Jan 2023 05:00:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674040139987/576b1cee-e154-40ef-b755-6d3229070d5a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-intro">Intro</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674054133529/861e0547-6d76-4073-910b-3f88c456df7f.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://xkcd.com/2407/">There's an xkcd for everything!</a></p>
<p>If you are preparing for interviews or just studying DSA you will eventually reach graph problems and then dynamic programming. This post is the step before recursion, we are going to see how BFS and DFS algorithms work iteratively with examples in JavaScript since most people have touched it in one way or another.</p>
<p>Note that if this is the first time you hear about BFS and DFS I'd recommend you go through binary trees first before starting with graphs.</p>
<p>To understand how these algorithms work first we need to have a proper understanding of stack and queue data structures.</p>
<p>I will be using examples from <a target="_blank" href="https://www.programiz.com/dsa">Programiz</a> to illustrate some of my points. I'd recommend you check their content if this post isn't clear enough. <a target="_blank" href="https://www.structy.net/">Structy</a> is another great page with plenty of free resources to get started.</p>
<h1 id="heading-pre-requirements">Pre-requirements</h1>
<h2 id="heading-stack">Stack</h2>
<p>Stack follows the <strong>LIFO</strong> principle: <strong>Last In First Out</strong>. You can think of it as a pile of plates (or anything you have to <em>stack</em>), every new item you put on top of others, or better put: <strong>every new item is put on the previous item</strong> and in order to get the last item you just take it from the pile. However, <strong>only the last item is available to take out</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674024193291/bdac8bec-36aa-446e-b1b5-8c67c6ad8043.png" alt class="image--center mx-auto" /></p>
<p>In this illustration from <a target="_blank" href="https://www.programiz.com/dsa/stack">Programiz</a> you can see that you keep pushing elements/items in the stack and you keep pushing new elements on top of each other and if you want to retrieve them then you need to retrieve the elements starting from the <strong>Last In</strong> because it's the <strong>First Out</strong>.</p>
<p>If you are not doing OOP or you need to implement the data structure itself a simple JavaScript use would be to just make an array:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> stack = []
<span class="hljs-comment">//push element</span>
stack.push(<span class="hljs-number">1</span>)
<span class="hljs-comment">//get last element</span>
<span class="hljs-keyword">const</span> lastElement = stack.pop()
</code></pre>
<p>Additionally stack usually has a method/function that allows you to peek at the last element:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//peek</span>
<span class="hljs-keyword">const</span> getLast = stack[stack.length<span class="hljs-number">-1</span>]
</code></pre>
<h2 id="heading-queue">Queue</h2>
<p>Queue follows the FIFO principle: <strong>First In First Out</strong>. It follows the same principle as any queue, you get in line and wait until it's your turn, so if there are 5 people ahead of you and you are the number 6 then you need to wait for those 5 people to get in before you can go.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674026231288/7c1843c7-84bc-44b2-b0f9-455ea4143e22.png" alt class="image--center mx-auto" /></p>
<p>In this illustration from <a target="_blank" href="https://www.programiz.com/dsa/queue">Programiz</a> you can see two elements that get queued, the first to get in line (queue) is the first to get out.</p>
<p>The JavaScript implementation would be something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> queue = []
<span class="hljs-comment">//queue elements</span>
queue.push(<span class="hljs-number">1</span>) <span class="hljs-comment">//queue: [1]</span>
queue.push(<span class="hljs-number">2</span>) <span class="hljs-comment">//queue: [1,2]</span>
queue.push(<span class="hljs-number">3</span>) <span class="hljs-comment">//queue: [1,2,3]</span>
<span class="hljs-comment">//dequeue elements</span>
<span class="hljs-keyword">const</span> firstEle = queue.shift() <span class="hljs-comment">//this gets 1 and queue: [2,3]</span>
<span class="hljs-keyword">const</span> secondEle = queue.shift() <span class="hljs-comment">//this gets 2nd and queue: [3]</span>
<span class="hljs-keyword">const</span> lastEle = queue.shift() <span class="hljs-comment">//gets 3rd and queue: []</span>
</code></pre>
<p>The main difference between stack and queue is that we don't pop any elements from the queue, the pop method/function will give us the last element but since we are working with queues we want to get the <strong>First In</strong> element which will go <strong>First Out.</strong></p>
<p>You could also implement a queue in reverse order:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> queue = []
<span class="hljs-comment">//queue elements</span>
queue.unshift(<span class="hljs-number">1</span>)
queue.unshift(<span class="hljs-number">2</span>)
queue.unshift(<span class="hljs-number">3</span>)
<span class="hljs-comment">//dequeue elements</span>
<span class="hljs-keyword">const</span> first = queue.pop()
<span class="hljs-keyword">const</span> second = queue.pop()
<span class="hljs-keyword">const</span> third = queue.pop()
</code></pre>
<p>This is still a queue, the only difference is that we are inserting from the beginning (bottom) and popping the elements from the end (top).</p>
<h2 id="heading-time-complexity">Time complexity</h2>
<p>Just a quick pause to remind you that if you use any methods/functions that have to move all array elements (unshift for example) this becomes an additional cost on your algorithm since moving all elements it's O(n) so generally speaking, if you have to choose you might want to try the stack data structure first since your elements inside of the array don't have to move.</p>
<h1 id="heading-graphs">Graphs</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674033109830/b0bee3fe-7071-421c-89fe-f7be6f65604f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-preparing-the-data">Preparing the data</h2>
<p>When you are working with graphs the data/input for your function might be all over the place so you will need to organize it better or make it into something where you can easily apply the algorithms and data structures you are familiar with.</p>
<p>Before attempting to solve the problem you might want to first take a look at the data or input you are provided, and depending on what you need to do perhaps you should transform that data into something else, be it to avoid exponential runtime or just to see the problem better.</p>
<p>Just check if you might need a <a target="_blank" href="https://en.wikipedia.org/wiki/Set_(abstract_data_type)">set</a>, a <a target="_blank" href="https://stackoverflow.com/a/2592145/14356309">hashmap</a> or something else. With graph problems what we usually need is an <a target="_blank" href="https://www.programiz.com/dsa/graph-adjacency-matrix">adjacent matrix</a>.</p>
<p>So for example, if we are given this <a target="_blank" href="https://leetcode.com/problems/find-if-path-exists-in-graph/">LeetCode</a> problem (<strong>1971. Find if Path Exists in Graph)</strong> where the input is as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674034403110/0a3a8fde-d6f5-4ad1-b3c0-cbaf6b239aae.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-javascript">edges = [[<span class="hljs-number">0</span>,<span class="hljs-number">1</span>],[<span class="hljs-number">1</span>,<span class="hljs-number">2</span>],[<span class="hljs-number">2</span>,<span class="hljs-number">0</span>]]
</code></pre>
<p>We need to use a function to transform that array of edges into a matrix (I usually just call it getGraph since we want to get the graph from the array):</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> getGraph = <span class="hljs-function">(<span class="hljs-params">edges</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> graph = {}

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; edges.length; i++){
      <span class="hljs-keyword">let</span> [a, b] = edges[i]
      <span class="hljs-keyword">if</span>(!graph[a]) graph[a] = []
      <span class="hljs-keyword">if</span>(!graph[b]) graph[b] = []
      graph[a].push(b)
      graph[b].push(a)
    }

    <span class="hljs-built_in">console</span>.log(graph)
    <span class="hljs-keyword">return</span> graph
  }
</code></pre>
<p>If you run that function you should get this output which corresponds to the picture of the graph above:</p>
<pre><code class="lang-javascript">{ <span class="hljs-string">'0'</span>: [ <span class="hljs-number">1</span>, <span class="hljs-number">2</span> ], <span class="hljs-string">'1'</span>: [ <span class="hljs-number">0</span>, <span class="hljs-number">2</span> ], <span class="hljs-string">'2'</span>: [ <span class="hljs-number">1</span>, <span class="hljs-number">0</span> ] }
</code></pre>
<h2 id="heading-graph-adjacent-nodes-neighbours">Graph adjacent nodes (neighbours)</h2>
<p>In order to understand how BFS and DFS work one of the keys is to realise that we need to visit all the adjacent nodes of your current node, aka the neighbours. It might sound obvious and simple but you can miss it.</p>
<p>We will use a stack or a queue to keep track of our current node and then push the neighbour nodes into our stack or queue. The most important concept here is that we are working on our current node, aka the node which we took off from our stack or queue. This will make sense in a bit.</p>
<p>And why do we care about the neighbours so much? To avoid running over the same nodes, what is the best data structure if we want to think about unique values? A set! You get to store unique values and then check very fast if you already interacted with a value/element/node before.</p>
<p>In JavaScript if you want to make a set you do:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//name our set visited because we will track our visited nodes here</span>
<span class="hljs-keyword">const</span> visited = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>()
</code></pre>
<p>Now that we have our set if we are interacting over our current node to check the neighbours we just do a for loop:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> neighbour <span class="hljs-keyword">of</span> graph[currentNode]){
    <span class="hljs-comment">//check if our Set contains an adjacent node which means we already visited it</span>
    <span class="hljs-keyword">if</span>(!visited.has(neighbour) <span class="hljs-comment">//do something</span>
}
</code></pre>
<p>This would be the same loop:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> neighbourIndex = <span class="hljs-number">0</span>; neighbour &lt; graph[currentNode].length; neighbour++){
    <span class="hljs-keyword">if</span>(!visited.has(graph[neighbourIndex]) <span class="hljs-comment">//do something</span>
}
</code></pre>
<p>Now that we have the basic concepts down it should be easier to understand the implementation of both DFS and BFS. However, first I'd recommend you look up videos of what the algorithm does (without looking at the code). <a target="_blank" href="https://www.youtube.com/watch?v=tWVWeAqZ0WU">Here's a video from FreeCodeCamp and the creator of Structy</a>, you don't have to look at the entire video just until you understand how DFS and BFS work visually:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674036751304/f5f8aefe-3adc-4e23-84b6-78a8cde3999b.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-dfs-vs-bfs">DFS vs BFS</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674036826199/d2c0bce0-c394-4223-8381-20542a09aa44.png" alt class="image--center mx-auto" /></p>
<p>The best way to understand how DFS works is to think about its name, we are going to search <strong>in-depth</strong> first. This means that we will take our search in a specific direction until we hit a wall (or a null). If we were talking about trees DFS would just always go to the left or right node first, so basically we are just going to always go deep into one direction until we can't find anything.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674037189549/019dab33-4a2f-4a4d-b3cd-f8931a123cff.png" alt class="image--center mx-auto" /></p>
<p>On the other hand, if we are using BFS then before going in deeper we will look around us and check for any adjacent nodes and if they exist then we will visit those first. So instead of going deeper in one direction as with DFS here, we'd go more in a circular manner to find the neighbours first before committing to a specific direction.</p>
<p>I can't recommend <a target="_blank" href="https://youtu.be/tWVWeAqZ0WU?t=430">this video</a> enough to understand the core concepts. You can also visit the <a target="_blank" href="https://structy.net/">Structy</a> page directly.</p>
<h2 id="heading-dfs-implementation">DFS implementation</h2>
<p>Remember the previous <a target="_blank" href="https://leetcode.com/problems/find-if-path-exists-in-graph/description/">LeetCode problem: (<strong>1971. Find if Path Exists in Graph)</strong></a>? We will solve it using DFS and everything we have learned so far.</p>
<p>Let's write a DFS algorithm to find a solution and check if a path exists between two nodes. I've included a lot of console.logs so you can see what's happening and how the algorithm is working, you can run it and check the different test cases for it.</p>
<p>I recommend that you edit the test cases and just go step by step, the most important part here is to understand how we are using the stack data structure and adding all the neighbours.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number}</span> <span class="hljs-variable">n</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[][]}</span> <span class="hljs-variable">edges</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{number}</span> <span class="hljs-variable">source</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{number}</span> <span class="hljs-variable">destination</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{boolean}</span></span>
 */</span>
<span class="hljs-keyword">var</span> validPath = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">n, edges, source, destination</span>) </span>{
    <span class="hljs-keyword">const</span> adj = getGraph(edges)
    <span class="hljs-built_in">console</span>.log(adj)
    <span class="hljs-keyword">return</span> hasPath(adj, source, destination)
};

<span class="hljs-keyword">const</span> getGraph = <span class="hljs-function">(<span class="hljs-params">edges</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'inside getGraph'</span>)
    <span class="hljs-keyword">const</span> graph = {}
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; edges.length; i++){
        <span class="hljs-keyword">let</span> [a, b] = edges[i]
        <span class="hljs-keyword">if</span>(!graph[a]) graph[a] = []
        <span class="hljs-keyword">if</span>(!graph[b]) graph[b] = []
        graph[a].push(b)
        graph[b].push(a)
    }
    <span class="hljs-built_in">console</span>.log(graph)
    <span class="hljs-keyword">return</span> graph
}

<span class="hljs-keyword">const</span> hasPath = <span class="hljs-function">(<span class="hljs-params">graph, src, dst</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'inside haspath'</span>)
    <span class="hljs-keyword">let</span> visited = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>()
    <span class="hljs-keyword">let</span> stack = [src]
    <span class="hljs-keyword">while</span>(stack.length &gt; <span class="hljs-number">0</span>){
        <span class="hljs-keyword">let</span> curr = stack.pop()
        <span class="hljs-keyword">if</span>(curr === dst) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>

        visited.add(curr)

        <span class="hljs-built_in">console</span>.log(visited)
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'stack: '</span>)
        <span class="hljs-built_in">console</span>.log(stack)
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'curr:'</span>)
        <span class="hljs-built_in">console</span>.log(curr)
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'graph curr'</span>)
        <span class="hljs-built_in">console</span>.log(graph[curr])
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> n <span class="hljs-keyword">of</span> graph[curr]){
        <span class="hljs-built_in">console</span>.log(n)
        <span class="hljs-keyword">if</span>(!visited.has(n))stack.push(n) 
        }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
}
</code></pre>
<p>I recommend you go through the results on the console, in case you can't here's the console output for test case 2:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674052855239/cd4b7e7c-2426-4d08-a1a0-309dcd87675b.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">inside getGraph
{
  '0': [ 1, 2 ],
  '1': [ 0 ],
  '2': [ 0 ],
  '3': [ 5, 4 ],
  '4': [ 5, 3 ],
  '5': [ 3, 4 ]
}
{
  '0': [ 1, 2 ],
  '1': [ 0 ],
  '2': [ 0 ],
  '3': [ 5, 4 ],
  '4': [ 5, 3 ],
  '5': [ 3, 4 ]
}
inside haspath
Set(1) { 0 }
stack: 
[]
curr:
0
graph curr
[ 1, 2 ]
1
2
Set(2) { 0, 2 }
stack: 
[ 1 ]
curr:
2
graph curr
[ 0 ]
0
Set(3) { 0, 2, 1 }
stack: 
[]
curr:
1
graph curr
[ 0 ]
0
</code></pre>
<h2 id="heading-dfs-algorithm">DFS algorithm</h2>
<p>Here's the function without all the clutter and more comments, it's used to determine if a path exists between a source and destination node.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> hasPath = <span class="hljs-function">(<span class="hljs-params">graph, src, dst</span>) =&gt;</span> {
    <span class="hljs-comment">//init set to check if we have been here already</span>
    <span class="hljs-keyword">let</span> visited = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>()
    <span class="hljs-comment">//put the source node in our stack since we are starting here</span>
    <span class="hljs-keyword">let</span> stack = [src]
    <span class="hljs-comment">//as long as the stack isn't empty it means we are still checking nodes</span>
    <span class="hljs-keyword">while</span>(stack.length &gt; <span class="hljs-number">0</span>){
        <span class="hljs-comment">//we get our current node from the stack</span>
        <span class="hljs-keyword">let</span> curr = stack.pop()
        <span class="hljs-comment">//check if the current node is our destination</span>
        <span class="hljs-keyword">if</span>(curr === dst) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
        <span class="hljs-comment">//since we already visited this node we add it to our set of visited nodes</span>
        visited.add(curr)
        <span class="hljs-comment">//if we didn't visit the neighbours of our current node then add them to the stack</span>
        <span class="hljs-comment">//where we check if the current node is the destination</span>
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> n <span class="hljs-keyword">of</span> graph[curr]){
            <span class="hljs-keyword">if</span>(!visited.has(n)) stack.push(n) 
        }
    }
    <span class="hljs-comment">//if we can't find the destination then return false</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
}
</code></pre>
<h3 id="heading-javascript-shenanigans">JavaScript shenanigans</h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doSomething</span>(<span class="hljs-params">a,b,c</span>) </span>{
}
</code></pre>
<p>is the same as</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> doSomething = <span class="hljs-function">(<span class="hljs-params">a,b,c</span>) =&gt;</span> {
}
</code></pre>
<h2 id="heading-bfs-algorithm">BFS algorithm</h2>
<p>The main difference between DFS and BFS is how we get our current node (and therefore the way we store and iterate over the neighbours). With a stack you will always go in the same direction until the end of the graph while with a queue you will visit the nodes that are on the same "level" first.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674059079803/2734cd90-f23a-4694-a978-1ddadeae9c23.png" alt class="image--center mx-auto" /></p>
<p>Here's the modification of our current DFS algorithm into BFS:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> hasPath = <span class="hljs-function">(<span class="hljs-params">graph, src, dst</span>) =&gt;</span> {
    <span class="hljs-comment">//init set to check if we have been here already</span>
    <span class="hljs-keyword">let</span> visited = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>()
    <span class="hljs-comment">//init queue with the source node in</span>
    <span class="hljs-keyword">let</span> queue = [src]
    <span class="hljs-comment">//as long as the stack isn't empty it means we are still checking nodes</span>
    <span class="hljs-keyword">while</span>(queue.length &gt; <span class="hljs-number">0</span>){
        <span class="hljs-comment">//we get our current node from the queue</span>
        <span class="hljs-keyword">let</span> curr = queue.shift()
        <span class="hljs-comment">//check if the current node is our destination</span>
        <span class="hljs-keyword">if</span>(curr === dst) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
        <span class="hljs-comment">//since we already visited this node we add it to our set of visited nodes</span>
        visited.add(curr)
        <span class="hljs-comment">//if we didn't visit the neighbours of our current node then add them to the queue</span>
        <span class="hljs-comment">//where we check if the current node is the destination</span>
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> n <span class="hljs-keyword">of</span> graph[curr]){
            <span class="hljs-keyword">if</span>(!visited.has(n)) queue.push(n) 
        }
    }
    <span class="hljs-comment">//if we can't find the destination then return false</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
}
</code></pre>
<p>Note that if we try to run it we will pass almost all the test cases except the ones with a large input, this is due to BFS being more costly since it's using a queue instead of a stack.</p>
<p>A common case for BFS use in graph problems is to find the shortest path from one node to another, you could use something like this BFS helper function to get the distance:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> bfsHelper = <span class="hljs-function">(<span class="hljs-params">graph, node, target, visited</span>) =&gt;</span> {
  <span class="hljs-comment">//define queue which will store our current node and the distance count</span>
  <span class="hljs-keyword">let</span> queue = [[node, <span class="hljs-number">0</span>]]
  <span class="hljs-comment">//iterate until we don't have any current nodes left</span>
  <span class="hljs-keyword">while</span>(queue.length &gt; <span class="hljs-number">0</span>){
    <span class="hljs-comment">//extract the current nude and current distance</span>
    <span class="hljs-keyword">let</span> [curr, distance] = queue.shift()
    <span class="hljs-comment">//if our current node equals target then we are done with our algorithm and we return how many steps we had to take to find it </span>
    <span class="hljs-keyword">if</span>(curr === target) <span class="hljs-keyword">return</span> distance
    <span class="hljs-comment">//if the current node isn't our target then we add the current node to a visited set</span>
    visited.add(curr)
    <span class="hljs-comment">//iterate over our adjacent neighbours to add them to the queue if we haven't visited them yet</span>
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> neighbor <span class="hljs-keyword">of</span> graph[curr]) {
      <span class="hljs-keyword">if</span>(!visited.has(neighbor)) {
        queue.push([neighbor, distance+<span class="hljs-number">1</span>])
      }
    }
  }
  <span class="hljs-comment">//if we can't find the target then we return -1</span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
}
</code></pre>
<h1 id="heading-this-is-just-the-beginning">This is just the beginning</h1>
<p>The objective of this post was to establish some key concepts and see how DFS and BFS behave as well as approach the graph problems, the next steps would be to dive into recursion or perhaps go back to binary tree problems.</p>
<p>It might take a while to understand the best approaches or how things work, just keep practising and it will click eventually. And if you are tired of LeetCode or HackerRank I highly recommend <a target="_blank" href="https://www.codewars.com">CodeWars</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Modern API design with Golang, PostgreSQL and Docker]]></title><description><![CDATA[Intro
Go is a powerful language that's highly performant and it has concurrency built in the language itself making it perfect for micro services. Here we will make a small API focusing on understanding HTTP and overall API design.If you want to know...]]></description><link>https://bognov.tech/modern-api-design-with-golang-postgresql-and-docker</link><guid isPermaLink="true">https://bognov.tech/modern-api-design-with-golang-postgresql-and-docker</guid><category><![CDATA[Go Language]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Docker]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Mon, 21 Nov 2022 07:44:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1669015925691/ljZ3qyp7L.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-intro">Intro</h1>
<p>Go is a powerful language that's highly performant and it has concurrency built in the language itself making it perfect for micro services. Here we will make a small API focusing on understanding HTTP and overall API design.<br />If you want to know more about Go concurrency look into how go routines and channels work.</p>
<h2 id="heading-github-repo-andamp-more">Github repo &amp; more</h2>
<p>You can find all the code in <a target="_blank" href="https://github.com/bgdnvk/go-microservice-example">my repository</a>. I've been writing the article alongside the code so you can follow the <a target="_blank" href="https://github.com/bgdnvk/go-microservice-example/commits/main">commits</a>. If you find a bug feel free to submit a PR.  </p>
<p>You can also find me on <a target="_blank" href="https://www.linkedin.com/in/bogdan-novykov/">LinkedIn</a>, <a target="_blank" href="https://twitter.com/tekbog">Twitter</a> and <a target="_blank" href="https://social.linux.pizza/@tekbog">Mastodon</a>.</p>
<h2 id="heading-target-audience">Target audience</h2>
<p>This article is aimed at anyone who wants to build a CRUD micro service or a simple RESTful API using Go (or Golang for SEO purposes).  </p>
<h2 id="heading-additional-resources">Additional resources</h2>
<p>However if you are a junior dev or just starting out I'd recommend you check my <a target="_blank" href="https://bognov.tech/series/mern-stack">Node.js (MERN)</a> or <a target="_blank" href="https://bognov.tech/series/spring-boot">Spring Boot</a> series and if you are looking for more Go content I have a small example of a <a target="_blank" href="https://bognov.tech/introduction-to-golang-build-a-mini-twitter-clone">mini-twitter clone</a> you can check. Additionally if you are after video tutorials I highly recommend <a target="_blank" href="https://www.youtube.com/channel/UCC2ot8w_U6yQsq7jdpbECvQ/videos">Matt KØDVB's channel</a>.  </p>
<h2 id="heading-tech">Tech</h2>
<p>I'm on <strong>Go 1.18</strong>, for database we will use <strong>PostgreSQL</strong> and we will containerize our app with <strong>Docker</strong> and then use Docker Compose to link our app with the database. We will also include a small check for production environments in case you want to deploy it somewhere. </p>
<h3 id="heading-libraries">Libraries</h3>
<p>We will be using <a target="_blank" href="https://github.com/go-chi/chi">Chi</a> as our router and <a target="_blank" href="https://github.com/go-pg/pg">Go-PG</a> in order to communicate with our PostgreSQL database.</p>
<h2 id="heading-additional-implementation">Additional implementation</h2>
<p>We will be focusing on the CRUD part in this article however in the real world you will also need to add authentication, authorization, logging and testing.</p>
<h1 id="heading-the-code">The Code</h1>
<p>We will build a comments micro service, this means that you will have a CRUD API through which you will be able to create, read, update and delete comments.</p>
<h2 id="heading-docker-and-docker-compose">Docker and Docker Compose</h2>
<p>In order for the project to be able to run on any machine we will be using Docker and Docker Compose to help us set up the database, PostgreSQL in our case.</p>
<p>Start your project with</p>
<pre><code>go mod init go-microservice-example
</code></pre><p>this way we can track all the packages we are going to be using.</p>
<p>Then add a folder called cmd, inside a folder called server and inside that folder add main.go, call the package main as well. This will be where we build our binary and start the server.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668396227335/B7Eorp3HP.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Inside main.go paste the following:</p>
<pre><code>package main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"log"</span>
)

func main() {
    log.Print(<span class="hljs-string">"server has started"</span>)
}
</code></pre><p>Right now we are just making sure our program works with Docker so we are just printing one line.</p>
<p>Now add the Dockerfile (remember it doesn't have an extension):</p>
<pre><code>FROM golang

RUN mkdir /app

ADD . /app

WORKDIR /app

RUN go build -o main ./cmd/server/main.go

EXPOSE <span class="hljs-number">8080</span>
CMD [ <span class="hljs-string">"/app/main"</span> ]
</code></pre><p>What we are doing here is basically creating an ./app folder inside of our container, making it the work directory, building the binary, exposing the port and then calling the binary we just built so it can run our code.</p>
<p>Now since we are using PostgreSQL we will add our database using the Docker Compose file, so add docker-compose.yml with the following inside:</p>
<pre><code>version: <span class="hljs-string">'3.8'</span>

<span class="hljs-attr">services</span>:
  db:
    image: postgres
    <span class="hljs-attr">restart</span>: always
    <span class="hljs-attr">environment</span>:
      POSTGRES_PASSWORD: admin
  <span class="hljs-attr">api</span>:
    build: .
    ports:
      - <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span>
    <span class="hljs-attr">environment</span>:
      - PORT=<span class="hljs-number">8080</span>
      - DATABASE_URL=db
    <span class="hljs-attr">depends_on</span>:
      - db
</code></pre><p>Here we are declaring that we will be running 2 services, db and api, with api depending on db and making sure the ports are properly exposed: we will be working with the 8080 port. Additionally I've also added two environment variables that we will use later: PORT and DATABASE_URL.</p>
<p>With everything set up you can start your app with docker compose by typing:</p>
<pre><code>docker compose up --build
</code></pre><p>You might see that the api service starts before the database, <a target="_blank" href="https://docs.docker.com/compose/startup-order/">this isn't a bug</a>. Just shut it down with CTRL+C and restart it with:</p>
<pre><code>docker compose down; docker compose up --build
</code></pre><p>If everything went correctly you should see the message from the log:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668397246336/CCxYj-y8r.png" alt="image.png" class="image--center mx-auto" /></p>
<h2 id="heading-migrations">Migrations</h2>
<p>Before diving into the code we need to set up our database. Make a migrations folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668483852207/i1SL71y4V.png" alt="image.png" class="image--center mx-auto" /></p>
<p>This is the first migration to set up users, 1_users.up.sql:</p>
<pre><code>CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    name VARCHAR NOT NULL
);
</code></pre><p>And this is the second for comments, 2_comments.up.sql:</p>
<pre><code>CREATE TABLE IF NOT EXISTS comments (
    id SERIAL PRIMARY KEY,
    comment VARCHAR NOT NULL,
    comment_date DATE DEFAULT CURRENT_DATE,
    user_id BIGINT REFERENCES users(id)
);

INSERT INTO users(name) VALUES(<span class="hljs-string">'dev_test_user'</span>);
INSERT INTO comments (comment) VALUES(<span class="hljs-string">'first test comment'</span>);
</code></pre><h2 id="heading-connecting-to-the-db">Connecting to the DB</h2>
<p>Let's get Go-PG with</p>
<pre><code>go get github.com/go-pg/pg/v10
</code></pre><p>and since we are using migrations let's get the migrations package as well</p>
<pre><code>go get github.com/go-pg/migrations/v8
</code></pre><p>Create a db.go file now inside pkg/db folder</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668485223342/XrCE3FkX5.png" alt="image.png" class="image--center mx-auto" /></p>
<p>This should go inside your db.go file:</p>
<pre><code>package db

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"os"</span>

    <span class="hljs-string">"github.com/go-pg/migrations/v8"</span>
    <span class="hljs-string">"github.com/go-pg/pg/v10"</span>
)

func StartDB() (*pg.DB, error) {
    <span class="hljs-keyword">var</span> (
        opts *pg.Options
        err  error
    )

    <span class="hljs-comment">//check if we are in prod</span>
    <span class="hljs-comment">//then use the db url from the env</span>
    <span class="hljs-keyword">if</span> os.Getenv(<span class="hljs-string">"ENV"</span>) == <span class="hljs-string">"PROD"</span> {
        opts, err = pg.ParseURL(os.Getenv(<span class="hljs-string">"DATABASE_URL"</span>))
        <span class="hljs-keyword">if</span> err != nil {
            <span class="hljs-keyword">return</span> nil, err
        }
    } <span class="hljs-keyword">else</span> {
        opts = &amp;pg.Options{
            <span class="hljs-comment">//default port</span>
            <span class="hljs-comment">//depends on the db service from docker compose</span>
            <span class="hljs-attr">Addr</span>:     <span class="hljs-string">"db:5432"</span>,
            <span class="hljs-attr">User</span>:     <span class="hljs-string">"postgres"</span>,
            <span class="hljs-attr">Password</span>: <span class="hljs-string">"admin"</span>,
        }
    }

    <span class="hljs-comment">//connect db</span>
    <span class="hljs-attr">db</span> := pg.Connect(opts)
    <span class="hljs-comment">//run migrations</span>
    <span class="hljs-attr">collection</span> := migrations.NewCollection()
    err = collection.DiscoverSQLMigrations(<span class="hljs-string">"migrations"</span>)
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-keyword">return</span> nil, err
    }

    <span class="hljs-comment">//start the migrations</span>
    _, _, err = collection.Run(db, <span class="hljs-string">"init"</span>)
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-keyword">return</span> nil, err
    }

    oldVersion, newVersion, <span class="hljs-attr">err</span> := collection.Run(db, <span class="hljs-string">"up"</span>)
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-keyword">return</span> nil, err
    }
    <span class="hljs-keyword">if</span> newVersion != oldVersion {
        log.Printf(<span class="hljs-string">"migrated from version %d to %d\n"</span>, oldVersion, newVersion)
    } <span class="hljs-keyword">else</span> {
        log.Printf(<span class="hljs-string">"version is %d\n"</span>, oldVersion)
    }

    <span class="hljs-comment">//return the db connection</span>
    <span class="hljs-keyword">return</span> db, err
}
</code></pre><p>Both libraries have docs and examples, so check them out, for example this is for <a target="_blank" href="https://github.com/go-pg/migrations/blob/v8/example/main.go">migrations</a>.</p>
<h2 id="heading-setting-up-your-api">Setting up your API</h2>
<p>Now that we have our database set up let's start working on the API, get Chi with the following command:</p>
<pre><code>go get -u github.com/go-chi/chi/v5
</code></pre><p>and create a folder called api inside the pkg directory, then add an api.go file:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668488508199/an68QHDaM.png" alt="image.png" class="image--center mx-auto" /></p>
<p>To get started let's just make sure our Chi router works so let's make two routes, "/" and "/comments/" inside api.go:</p>
<pre><code>package api

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"net/http"</span>

    <span class="hljs-string">"github.com/go-chi/chi/v5"</span>
    <span class="hljs-string">"github.com/go-chi/chi/v5/middleware"</span>
    <span class="hljs-string">"github.com/go-pg/pg/v10"</span>
)

<span class="hljs-comment">//start api with the pgdb and return a chi router</span>
func StartAPI(pgdb *pg.DB) *chi.Mux {
    <span class="hljs-comment">//get the router</span>
    <span class="hljs-attr">r</span> := chi.NewRouter()
    <span class="hljs-comment">//add middleware</span>
    <span class="hljs-comment">//in this case we will store our DB to use it later</span>
    r.Use(middleware.Logger, middleware.WithValue(<span class="hljs-string">"DB"</span>, pgdb))

    r.Route(<span class="hljs-string">"/comments"</span>, func(r chi.Router) {
        r.Get(<span class="hljs-string">"/"</span>, getComments)
    })

    r.Get(<span class="hljs-string">"/"</span>, func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(<span class="hljs-string">"up and running"</span>))
    })

    <span class="hljs-keyword">return</span> r
}

func getComments(w http.ResponseWriter, r *http.Request){
    w.Write([]byte(<span class="hljs-string">"comments"</span>))
}
</code></pre><p>Afterwards go back to cmd/server/main.go:</p>
<pre><code>package main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"go-microservice-example/pkg/api"</span>
    <span class="hljs-string">"go-microservice-example/pkg/db"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"net/http"</span>
    <span class="hljs-string">"os"</span>
)

func main() {
    log.Print(<span class="hljs-string">"server has started"</span>)
    <span class="hljs-comment">//start the db</span>
    pgdb, <span class="hljs-attr">err</span> := db.StartDB()
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error starting the database %v"</span>, err)
    }
    <span class="hljs-comment">//get the router of the API by passing the db</span>
    <span class="hljs-attr">router</span> := api.StartAPI(pgdb)
    <span class="hljs-comment">//get the port from the environment variable</span>
    <span class="hljs-attr">port</span> := os.Getenv(<span class="hljs-string">"PORT"</span>)
    <span class="hljs-comment">//pass the router and start listening with the server</span>
    err = http.ListenAndServe(fmt.Sprintf(<span class="hljs-string">":%s"</span>, port), router)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error from router %v\n"</span>, err)
    }
}
</code></pre><p>Note how we are using the functions we have made from our DB and API packages: StartDB and StartAPI.  </p>
<p>Now start the app with docker by doing</p>
<pre><code>docker compose up --build
</code></pre><p>If you navigate to localhost:8080/ you should see "up and running" and if you navigate to localhost:8080/comments you should see "comments":</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668492336546/vVi8l5JYS.png" alt="image.png" class="image--center mx-auto" /></p>
<p>On the terminal you should be seeing the GET requests as well:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668492380752/lMwcgAWTF.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Now that we have set up everything let's dig into the logic, remember that there's no right answer for the structure of a project so if you don't like what I'm doing feel free to change it.</p>
<h2 id="heading-create-and-read-operations">Create and Read operations</h2>
<p>Let's write the basic POST (Create) and GET (Read) operations for our API. I recommend you go through every line and check what's going on, as well as the <a target="_blank" href="https://github.com/go-pg/pg">PG</a> and <a target="_blank" href="https://github.com/go-chi/chi">CHI</a> libraries.</p>
<p>First need to define how our app is going to communicate with the database, if you are coming from working with other frameworks or libraries you might think about this as doing our models (schemas) and making a repository - this basically means we will make a data struct (think of a POJO if you are coming from Java) that we will use to communicate with our database.</p>
<p>Make a models folder inside db then create two files:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668849626390/0Y1GQrhWd.png" alt="imagen.png" class="image--center mx-auto" /></p>
<p>This is inside user.go:</p>
<pre><code>package models

type User struct {
    ID   int64  <span class="hljs-string">`json:"id"`</span>
    Name string <span class="hljs-string">`json:"name"`</span>
}
</code></pre><p>Since we are not modifying the user we don't have any logic inside.  </p>
<p>This is our comment.go:</p>
<pre><code>package models

<span class="hljs-keyword">import</span> <span class="hljs-string">"github.com/go-pg/pg/v10"</span>

type Comment struct {
    ID      int64  <span class="hljs-string">`json:"id"`</span>
    Comment string <span class="hljs-string">`json:"comment"`</span>
    UserID  int64  <span class="hljs-string">`json:"user_id"`</span>
    User    *User  <span class="hljs-string">`pg:"rel:has-one" json:"user"`</span>
}

func CreateComment(db *pg.DB, req *Comment) (*Comment, error) {
    _, <span class="hljs-attr">err</span> := db.Model(req).Insert()
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-keyword">return</span> nil, err
    }

    <span class="hljs-attr">comment</span> := &amp;Comment{}

    err = db.Model(comment).
        Relation(<span class="hljs-string">"User"</span>).
        Where(<span class="hljs-string">"comment.id = ?"</span>, req.ID).
        Select()

    <span class="hljs-keyword">return</span> comment, err
}

func GetComment(db *pg.DB, commentID string) (*Comment, error) {
    <span class="hljs-attr">comment</span> := &amp;Comment{}

    <span class="hljs-attr">err</span> := db.Model(comment).
        Relation(<span class="hljs-string">"User"</span>).
        Where(<span class="hljs-string">"comment.id = ?"</span>, commentID).
        Select()

    <span class="hljs-keyword">return</span> comment, err
}

func GetComments(db *pg.DB) ([]*Comment, error) {
    <span class="hljs-attr">comments</span> := make([]*Comment, <span class="hljs-number">0</span>)

    <span class="hljs-attr">err</span> := db.Model(&amp;comments).
        Relation(<span class="hljs-string">"User"</span>).
        Select()

    <span class="hljs-keyword">return</span> comments, err
}
</code></pre><p>The logic is fairly simple, just make sure you understand the relation and how the library works. The ORM is making the SQL queries for us using the values we pass.</p>
<p>Now let's go back to our API folder and use all the functions we have made. Remember that we need to import the models package first. Then, in order to get the request or response from the server let's capture it through a struct (CommentResponse and CommentRequest) however be careful because first we need to decode and encode the data every time we send it back or receive it.</p>
<p>This is our current api.go file:</p>
<pre><code>package api

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"encoding/json"</span>
    <span class="hljs-string">"go-microservice-example/pkg/db/models"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"net/http"</span>

    <span class="hljs-string">"github.com/go-chi/chi/v5"</span>
    <span class="hljs-string">"github.com/go-chi/chi/v5/middleware"</span>
    <span class="hljs-string">"github.com/go-pg/pg/v10"</span>
)

<span class="hljs-comment">//start api with the pgdb and return a chi router</span>
func StartAPI(pgdb *pg.DB) *chi.Mux {
    <span class="hljs-comment">//get the router</span>
    <span class="hljs-attr">r</span> := chi.NewRouter()
    <span class="hljs-comment">//add middleware</span>
    <span class="hljs-comment">//in this case we will store our DB to use it later</span>
    r.Use(middleware.Logger, middleware.WithValue(<span class="hljs-string">"DB"</span>, pgdb))

    <span class="hljs-comment">//routes for our service</span>
    r.Route(<span class="hljs-string">"/comments"</span>, func(r chi.Router) {
        r.Post(<span class="hljs-string">"/"</span>, createComment)
        r.Get(<span class="hljs-string">"/"</span>, getComments)
    })

    <span class="hljs-comment">//test route to make sure everything works</span>
    r.Get(<span class="hljs-string">"/"</span>, func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(<span class="hljs-string">"up and running"</span>))
    })

    <span class="hljs-keyword">return</span> r
}

type CreateCommentRequest struct {
    Comment string <span class="hljs-string">`json:"comment"`</span>
    UserID  int64  <span class="hljs-string">`json:"user_id"`</span>
}

type CommentResponse struct {
    Success bool            <span class="hljs-string">`json:"success"`</span>
    <span class="hljs-built_in">Error</span>   string          <span class="hljs-string">`json:"error"`</span>
    Comment *models.Comment <span class="hljs-string">`json:"comment"`</span>
}

func createComment(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//get the request body and decode it</span>
    <span class="hljs-attr">req</span> := &amp;CreateCommentRequest{}
    <span class="hljs-attr">err</span> := json.NewDecoder(r.Body).Decode(req)
    <span class="hljs-comment">//if there's an error with decoding the information</span>
    <span class="hljs-comment">//send a response with an error</span>
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-attr">res</span> := &amp;CommentResponse{
            <span class="hljs-attr">Success</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-attr">Error</span>:   err.Error(),
            <span class="hljs-attr">Comment</span>: nil,
        }
        err = json.NewEncoder(w).Encode(res)
        <span class="hljs-comment">//if there's an error with encoding handle it</span>
        <span class="hljs-keyword">if</span> err != nil {
            log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
        }
        <span class="hljs-comment">//return a bad request and exist the function</span>
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//get the db from context</span>
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-comment">//if we can't get the db let's handle the error</span>
    <span class="hljs-comment">//and send an adequate response</span>
    <span class="hljs-keyword">if</span> !ok {
        <span class="hljs-attr">res</span> := &amp;CommentResponse{
            <span class="hljs-attr">Success</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-attr">Error</span>:   <span class="hljs-string">"could not get the DB from context"</span>,
            <span class="hljs-attr">Comment</span>: nil,
        }
        err = json.NewEncoder(w).Encode(res)
        <span class="hljs-comment">//if there's an error with encoding handle it</span>
        <span class="hljs-keyword">if</span> err != nil {
            log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
        }
        <span class="hljs-comment">//return a bad request and exist the function</span>
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//if we can get the db then</span>
    comment, <span class="hljs-attr">err</span> := models.CreateComment(pgdb, &amp;models.Comment{
        <span class="hljs-attr">Comment</span>: req.Comment,
        <span class="hljs-attr">UserID</span>:  req.UserID,
    })
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-attr">res</span> := &amp;CommentResponse{
            <span class="hljs-attr">Success</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-attr">Error</span>:   err.Error(),
            <span class="hljs-attr">Comment</span>: nil,
        }
        err = json.NewEncoder(w).Encode(res)
        <span class="hljs-comment">//if there's an error with encoding handle it</span>
        <span class="hljs-keyword">if</span> err != nil {
            log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
        }
        <span class="hljs-comment">//return a bad request and exist the function</span>
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//everything is good</span>
    <span class="hljs-comment">//let's return a positive response</span>
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:   <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comment</span>: comment,
    }
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding after creating comment %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    w.WriteHeader(http.StatusOK)
}

type CommentsResponse struct {
    Success  bool              <span class="hljs-string">`json:"success"`</span>
    <span class="hljs-built_in">Error</span>    string            <span class="hljs-string">`json:"error"`</span>
    Comments []*models.Comment <span class="hljs-string">`json:"comments"`</span>
}

func getComments(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//get db from ctx</span>
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-keyword">if</span> !ok {
        <span class="hljs-attr">res</span> := &amp;CommentsResponse{
            <span class="hljs-attr">Success</span>:  <span class="hljs-literal">false</span>,
            <span class="hljs-attr">Error</span>:    <span class="hljs-string">"could not get DB from context"</span>,
            <span class="hljs-attr">Comments</span>: nil,
        }
        <span class="hljs-attr">err</span> := json.NewEncoder(w).Encode(res)
        <span class="hljs-keyword">if</span> err != nil {
            log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
        }
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//call models package to access the database and return the comments</span>
    comments, <span class="hljs-attr">err</span> := models.GetComments(pgdb)
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-attr">res</span> := &amp;CommentsResponse{
            <span class="hljs-attr">Success</span>:  <span class="hljs-literal">false</span>,
            <span class="hljs-attr">Error</span>:    err.Error(),
            <span class="hljs-attr">Comments</span>: nil,
        }
        <span class="hljs-attr">err</span> := json.NewEncoder(w).Encode(res)
        <span class="hljs-keyword">if</span> err != nil {
            log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
        }
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//positive response</span>
    <span class="hljs-attr">res</span> := &amp;CommentsResponse{
        <span class="hljs-attr">Success</span>:  <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:    <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comments</span>: comments,
    }
    <span class="hljs-comment">//encode the positive response to json and send it back</span>
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding comments: %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    w.WriteHeader(http.StatusOK)
}
</code></pre><p>I've left all the error handlers so you know exactly what's going on.  Rebuild the Docker containers and start the app using</p>
<pre><code>docker compose up --build
</code></pre><h3 id="heading-curl">CURL</h3>
<p>We will be using CURL to make sure everything works, so include this request.json in the root of your project:  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668853969753/3YPfA9UKm.png" alt="imagen.png" class="image--center mx-auto" /></p>
<pre><code>{
    <span class="hljs-string">"comment"</span>: <span class="hljs-string">"test comment"</span>,
    <span class="hljs-string">"user_id"</span>: <span class="hljs-number">1</span>
}
</code></pre><p>Note that if you are on Windows and having some issues with the command just do:</p>
<pre><code>Remove-item alias:curl
</code></pre><p>Now open the terminal inside your project and type:</p>
<pre><code>curl -X POST localhost:<span class="hljs-number">8080</span>/comments -d <span class="hljs-string">"@request.json"</span> | jq
</code></pre><p>This will make a POST request to the /comments route and the function createComment will handle the rest. You should get this response if everything went correctly: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668854293033/I7zdHiDLK.png" alt="imagen.png" class="image--center mx-auto" /></p>
<p>Now to make sure the comment is stored let's make a GET request via:  </p>
<pre><code>curl -X GET localhost:<span class="hljs-number">8080</span>/comments
</code></pre><p>And you should get back the comments (or in this case just one) stored in your database: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668854411860/Tjx7JeMtx.png" alt="imagen.png" class="image--center mx-auto" /></p>
<p>If you are using VSCode you can separate the terminal which comes in handy when you are running a server, this is what my current terminal looks like: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668854481690/EMu96z-ej.png" alt="imagen.png" class="image--center mx-auto" /></p>
<p>Now that we know everything works go to request.json and delete the "comment" line then try to POST it again, you should see the following error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668855779342/5fb2hrN_m.png" alt="imagen.png" class="image--center mx-auto" /></p>
<h3 id="heading-dry">DRY</h3>
<p>DRY stands for "don't repeat yourself" so let's refactor a bit our api.go and introduce the error handling functions:</p>
<pre><code>package api

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"encoding/json"</span>
    <span class="hljs-string">"go-microservice-example/pkg/db/models"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"net/http"</span>

    <span class="hljs-string">"github.com/go-chi/chi/v5"</span>
    <span class="hljs-string">"github.com/go-chi/chi/v5/middleware"</span>
    <span class="hljs-string">"github.com/go-pg/pg/v10"</span>
)

<span class="hljs-comment">//start api with the pgdb and return a chi router</span>
func StartAPI(pgdb *pg.DB) *chi.Mux {
    <span class="hljs-comment">//get the router</span>
    <span class="hljs-attr">r</span> := chi.NewRouter()
    <span class="hljs-comment">//add middleware</span>
    <span class="hljs-comment">//in this case we will store our DB to use it later</span>
    r.Use(middleware.Logger, middleware.WithValue(<span class="hljs-string">"DB"</span>, pgdb))

    <span class="hljs-comment">//routes for our service</span>
    r.Route(<span class="hljs-string">"/comments"</span>, func(r chi.Router) {
        r.Post(<span class="hljs-string">"/"</span>, createComment)
        r.Get(<span class="hljs-string">"/"</span>, getComments)
    })

    <span class="hljs-comment">//test route to make sure everything works</span>
    r.Get(<span class="hljs-string">"/"</span>, func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(<span class="hljs-string">"up and running"</span>))
    })

    <span class="hljs-keyword">return</span> r
}

<span class="hljs-comment">// -- Responses</span>

type CreateCommentRequest struct {
    Comment string <span class="hljs-string">`json:"comment"`</span>
    UserID  int64  <span class="hljs-string">`json:"user_id"`</span>
}

type CommentResponse struct {
    Success bool            <span class="hljs-string">`json:"success"`</span>
    <span class="hljs-built_in">Error</span>   string          <span class="hljs-string">`json:"error"`</span>
    Comment *models.Comment <span class="hljs-string">`json:"comment"`</span>
}

type CommentsResponse struct {
    Success  bool              <span class="hljs-string">`json:"success"`</span>
    <span class="hljs-built_in">Error</span>    string            <span class="hljs-string">`json:"error"`</span>
    Comments []*models.Comment <span class="hljs-string">`json:"comments"`</span>
}

<span class="hljs-comment">//-- UTILS --</span>

func handleErr(w http.ResponseWriter, err error) {
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">Error</span>:   err.Error(),
        <span class="hljs-attr">Comment</span>: nil,
    }
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-comment">//if there's an error with encoding handle it</span>
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
    }
    <span class="hljs-comment">//return a bad request and exist the function</span>
    w.WriteHeader(http.StatusBadRequest)
}

func handleDBFromContextErr(w http.ResponseWriter) {
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">Error</span>:   <span class="hljs-string">"could not get the DB from context"</span>,
        <span class="hljs-attr">Comment</span>: nil,
    }
    <span class="hljs-attr">err</span> := json.NewEncoder(w).Encode(res)
    <span class="hljs-comment">//if there's an error with encoding handle it</span>
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error sending response %v\n"</span>, err)
    }
    <span class="hljs-comment">//return a bad request and exist the function</span>
    w.WriteHeader(http.StatusBadRequest)
}

<span class="hljs-comment">// -- handle routes</span>

func createComment(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//get the request body and decode it</span>
    <span class="hljs-attr">req</span> := &amp;CreateCommentRequest{}
    <span class="hljs-attr">err</span> := json.NewDecoder(r.Body).Decode(req)
    <span class="hljs-comment">//if there's an error with decoding the information</span>
    <span class="hljs-comment">//send a response with an error</span>
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//get the db from context</span>
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-comment">//if we can't get the db let's handle the error</span>
    <span class="hljs-comment">//and send an adequate response</span>
    <span class="hljs-keyword">if</span> !ok {
        handleDBFromContextErr(w)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//if we can get the db then</span>
    comment, <span class="hljs-attr">err</span> := models.CreateComment(pgdb, &amp;models.Comment{
        <span class="hljs-attr">Comment</span>: req.Comment,
        <span class="hljs-attr">UserID</span>:  req.UserID,
    })
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//everything is good</span>
    <span class="hljs-comment">//let's return a positive response</span>
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:   <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comment</span>: comment,
    }
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding after creating comment %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    w.WriteHeader(http.StatusOK)
}

func getComments(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//get db from ctx</span>
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-keyword">if</span> !ok {
        handleDBFromContextErr(w)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//call models package to access the database and return the comments</span>
    comments, <span class="hljs-attr">err</span> := models.GetComments(pgdb)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//positive response</span>
    <span class="hljs-attr">res</span> := &amp;CommentsResponse{
        <span class="hljs-attr">Success</span>:  <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:    <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comments</span>: comments,
    }
    <span class="hljs-comment">//encode the positive response to json and send it back</span>
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding comments: %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    w.WriteHeader(http.StatusOK)
}
</code></pre><h2 id="heading-get-comment-by-id">Get Comment By Id</h2>
<p>We already have the function to get a comment by id in our models package, let's add a route and a function to handle that route in our API package now: </p>
<pre><code>        <span class="hljs-comment">// here's the route</span>
        r.Get(<span class="hljs-string">"/{commentID}"</span>, getCommentByID)
</code></pre><p>And here's the function to handle it:</p>
<pre><code>func getCommentByID(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//get the id from the URL parameter</span>
    <span class="hljs-comment">//alternatively you could use a URL query</span>
    <span class="hljs-attr">commentID</span> := chi.URLParam(r, <span class="hljs-string">"commentID"</span>)

    <span class="hljs-comment">//get the db from ctx</span>
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-keyword">if</span> !ok {
        handleDBFromContextErr(w)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">//get the comment from the DB</span>
    comment, <span class="hljs-attr">err</span> := models.GetComment(pgdb, commentID)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">//if the retrieval from the db was successful send the data</span>
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:   <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comment</span>: comment,
    }
    <span class="hljs-comment">//encode the positive response to json and send it back</span>
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding comments: %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    w.WriteHeader(http.StatusOK)
}
</code></pre><h2 id="heading-put">PUT</h2>
<p>Now that we have READ and POST let's focus on updating our data by handling a PUT request. First let's edit our models package (comment.go) by adding this function:</p>
<pre><code>func UpdateComment(db *pg.DB, req *Comment) (*Comment, error) {
    _, <span class="hljs-attr">err</span> := db.Model(req).
        WherePK().
        Update()
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-keyword">return</span> nil, err
    }

    <span class="hljs-attr">comment</span> := &amp;Comment{}

    err = db.Model(comment).
        Relation(<span class="hljs-string">"User"</span>).
        Where(<span class="hljs-string">"comment.id = ?"</span>, req.ID).
        Select()

    <span class="hljs-keyword">return</span> comment, err
}
</code></pre><p>Then let's add the route inside the API package (api.go):</p>
<pre><code>r.Put(<span class="hljs-string">"/{commentID}"</span>, updateCommentByID)
</code></pre><p>And finally let's write the function that handles the request, gets it from the user then interacts with the database by updating  the data:</p>
<pre><code>func updateCommentByID(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//get the data from the request</span>
    <span class="hljs-attr">req</span> := &amp;CommentRequest{}
    <span class="hljs-comment">//decode the data</span>
    <span class="hljs-attr">err</span> := json.NewDecoder(r.Body).Decode(req)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-keyword">if</span> !ok {
        handleDBFromContextErr(w)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//get the commentID to know what comment to modify</span>
    <span class="hljs-attr">commentID</span> := chi.URLParam(r, <span class="hljs-string">"commentID"</span>)
    <span class="hljs-comment">//we get a string but we need to send an int so we convert it</span>
    intCommentID, <span class="hljs-attr">err</span> := strconv.ParseInt(commentID, <span class="hljs-number">10</span>, <span class="hljs-number">64</span>)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">//update the comment</span>
    comment, <span class="hljs-attr">err</span> := models.UpdateComment(pgdb, &amp;models.Comment{
        <span class="hljs-attr">ID</span>:      intCommentID,
        <span class="hljs-attr">Comment</span>: req.Comment,
        <span class="hljs-attr">UserID</span>:  req.UserID,
    })
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
    }
    <span class="hljs-comment">//return successful response</span>
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:   <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comment</span>: comment,
    }
    <span class="hljs-comment">//send the encoded response to responsewriter</span>
    err = json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding comments: %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//send a 200 response</span>
    w.WriteHeader(http.StatusOK)
}
</code></pre><p>Note that we have to convert the string commentID into the int ID, there's a difference between receiving data as json and how we handle the data inside structs, that's why inside structs you have things like </p>
<pre><code>type Comment struct {
    ID      int64  <span class="hljs-string">`json:"id"`</span>
    Comment string <span class="hljs-string">`json:"comment"`</span>
    UserID  int64  <span class="hljs-string">`json:"user_id"`</span>
    User    *User  <span class="hljs-string">`pg:"rel:has-one" json:"user"`</span>
}
</code></pre><p>For example the ID is how we name the commentID in our codebase but if we send or receive that ID through JSON then we will just name it "id".</p>
<p>Now modify your request.json (change the comment data) and use this command to send a PUT request:</p>
<pre><code>curl -X PUT localhost:<span class="hljs-number">8080</span>/comments/<span class="hljs-number">1</span> -d <span class="hljs-string">"@request.json"</span> | jq
</code></pre><p>If everything went well you should see this in your terminal:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668960520106/OX7fgB4cZ.png" alt="image.png" class="image--center mx-auto" /></p>
<h3 id="heading-succresponse-dry">SuccResponse DRY</h3>
<p>Since our success response is the same everywhere let's refactor it to follow the DRY principle, we will call this function succ because I'm childish, so refactor the code in our API package:</p>
<pre><code>func succCommentResponse(comment *models.Comment, w http.ResponseWriter) {
    <span class="hljs-comment">//return successful response</span>
    <span class="hljs-attr">res</span> := &amp;CommentResponse{
        <span class="hljs-attr">Success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">Error</span>:   <span class="hljs-string">""</span>,
        <span class="hljs-attr">Comment</span>: comment,
    }
    <span class="hljs-comment">//send the encoded response to responsewriter</span>
    <span class="hljs-attr">err</span> := json.NewEncoder(w).Encode(res)
    <span class="hljs-keyword">if</span> err != nil {
        log.Printf(<span class="hljs-string">"error encoding comment: %v\n"</span>, err)
        w.WriteHeader(http.StatusBadRequest)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">//send a 200 response</span>
    w.WriteHeader(http.StatusOK)
}
</code></pre><h2 id="heading-delete">Delete</h2>
<p>Let's finish this, go to your models package and add the Delete function:</p>
<pre><code>func DeleteComment(db *pg.DB, commentID int64) error {
    <span class="hljs-attr">comment</span> := &amp;Comment{}

    <span class="hljs-attr">err</span> := db.Model(comment).
        Relation(<span class="hljs-string">"User"</span>).
        Where(<span class="hljs-string">"comment.id = ?"</span>, commentID).
        Select()
    <span class="hljs-keyword">if</span> err != nil {
        <span class="hljs-keyword">return</span> err
    }

    _, err = db.Model(comment).WherePK().Delete()

    <span class="hljs-keyword">return</span> err
}
</code></pre><p>And inside the API package add the route and the function to handle that route:</p>
<pre><code>r.Delete(<span class="hljs-string">"/{commentID}"</span>, deleteCommentByID)
</code></pre><pre><code>func deleteCommentByID(w http.ResponseWriter, r *http.Request) {
    <span class="hljs-comment">//parse in the req body</span>
    <span class="hljs-attr">req</span> := &amp;CommentRequest{}
    <span class="hljs-attr">err</span> := json.NewDecoder(r.Body).Decode(req)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">//get the db from ctx</span>
    pgdb, <span class="hljs-attr">ok</span> := r.Context().Value(<span class="hljs-string">"DB"</span>).(*pg.DB)
    <span class="hljs-keyword">if</span> !ok {
        handleDBFromContextErr(w)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">//get the commentID</span>
    <span class="hljs-attr">commentID</span> := chi.URLParam(r, <span class="hljs-string">"commentID"</span>)
    intCommentID, <span class="hljs-attr">err</span> := strconv.ParseInt(commentID, <span class="hljs-number">10</span>, <span class="hljs-number">64</span>)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">//delete comment</span>
    err = models.DeleteComment(pgdb, intCommentID)
    <span class="hljs-keyword">if</span> err != nil {
        handleErr(w, err)
    }

    <span class="hljs-comment">//send successful response</span>
    succCommentResponse(nil, w)
}
</code></pre>]]></content:encoded></item><item><title><![CDATA[Discovering Ruby on Rails: is it dead or alive?]]></title><description><![CDATA[It's alive BUT
There are huge codebases of RoR from famous companies such as Github, Gitlab, Airbnb, Shopify, Groupon and even Twitch that are still using it. However the ecosystem is definitely in decline and companies are struggling to recruit seni...]]></description><link>https://bognov.tech/discovering-ruby-on-rails-is-it-dead-or-alive</link><guid isPermaLink="true">https://bognov.tech/discovering-ruby-on-rails-is-it-dead-or-alive</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[full stack]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Thu, 04 Aug 2022 18:28:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659636315989/SuNaFm6rW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-its-alive-but">It's alive BUT</h1>
<p>There are huge codebases of RoR from famous companies such as <a target="_blank" href="https://github.blog/2019-09-09-running-github-on-rails-6-0/">Github</a>, <a target="_blank" href="https://about.gitlab.com/blog/2022/07/06/why-were-sticking-with-ruby-on-rails/">Gitlab</a>, Airbnb, Shopify, Groupon and even <a target="_blank" href="https://blog.twitch.tv/en/2022/03/30/breaking-the-monolith-at-twitch/">Twitch</a> that are still using it. However the ecosystem is definitely in decline and companies are struggling to recruit senior developers.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659572484754/xmvfZ2FZ_.png" alt="image.png" /></p>
<p>Overall taking the approach of saying "tech X is dead" has never worked - and be cautious of whoever tells you otherwise. In the web dev world we have been hearing about how PHP has been dead for a while yet there are still millions of jobs and the ecosystem keeps evolving with amazing frameworks like Laravel. There are still jobs for COBOL devs FFS, so no, Ruby on Rails isn't dead but it's harder to get in as a beginner compared to other frameworks and languages although I consider it a great starting full stack framework, let me elaborate.</p>
<h1 id="heading-its-a-pain-to-start-on-windows">It's a pain to start (on Windows)</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659633894579/Akip9sody.png" alt="image.png" class="image--center mx-auto" />
As a developer you should be using Linux, of course, but I'm on my Windows machine right now and it has been an absolute hellish experience, so as DX goes RoR takes a big L from the start if you are a Windows user.  </p>
<p>Let me help you a bit with the installation.</p>
<h2 id="heading-how-to-install-ruby-on-rails-on-windows">How to install Ruby on Rails on Windows</h2>
<p>There are guides out there but the best resource to not run into any compatibility or dependency issues is just to follow this 27 minutes video from <a target="_blank" href="https://youtu.be/fmyvWz5TUWg">FreeCodeCamp</a> and you should be good to go. No, it's not a joke.  </p>
<p>Alternatively you can use <a target="_blank" href="https://www.hanselman.com/blog/ruby-on-rails-on-windows-is-not-just-possible-its-fabulous-using-wsl2-and-vs-code">WSL2 with Docker</a>. Good luck!</p>
<h3 id="heading-how-to-switch-between-ruby-on-rails-versions-on-windows">How to switch between Ruby on Rails versions on Windows</h3>
<p>If you happily installed the latest version of ruby and have decided to fork a project that uses an older version, well, it's not compatible so tough luck. Luckily you can use a 12 years old no longer maintained project called <a target="_blank" href="https://github.com/vertiginous/pik">PIK</a> to switch Ruby versions. Again, not a joke.</p>
<p><a target="_blank" href="https://notepad.onghu.com/2021/ruby27-windows-install-hello_world/">This</a> article has been very helpful and it guides you through the whole process. Overall <a target="_blank" href="https://notepad.onghu.com/#blog">Onghu's blog</a> seems very helpful if you are a Ruby developer.</p>
<h1 id="heading-good-for-beginners">Good for beginners</h1>
<p>A fairly famous site to get into Web Development called <a target="_blank" href="https://www.theodinproject.com/paths">The Odin Project</a> teaches Ruby on Rails to beginners, while it might seem overwhelming at first I believe RoR will teach anyone good foundations to understand how a full stack application works, let's see why.  </p>
<p>Funnily enough even The Odin Project doesn't have a guide on how to <a target="_blank" href="https://www.theodinproject.com/lessons/ruby-installing-ruby">install RoR on Windows</a>.</p>
<h2 id="heading-mvc">MVC</h2>
<p>Ruby on Rails allows you to develop a <a target="_blank" href="https://medium.com/@dan_manges/the-modular-monolith-rails-architecture-fb1023826fc4">modular monolith</a> following the <a target="_blank" href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC</a> pattern. It's a heavily opinionated framework that will make you understand MVC and stick to it, you want it or not, enforcing the good practices - something that's excellent for a beginner.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659575041538/tRUZbefmj.png" alt="image.png" class="image--center mx-auto" />
<a target="_blank" href="https://www.techgeekbuzz.com/blog/mvc-architecture/">image source</a></p>
<p>You will understand how everything is interconnected inside your application: anything data related is handled by your Model, the controller is there to apply business logic to the data you extract through the Model and the View is there to display and get the data from the user.  </p>
<p>I feel as if I started as a developer with RoR I'd have an easier time understanding how a full stack application works (or software in general). </p>
<h1 id="heading-double-edged-sword-of-abstraction">Double edged sword of abstraction</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659634138682/RBlJYxouS.png" alt="image.png" class="image--center mx-auto" />
As someone who just saw a glimpse of RoR, I feel like the framework can abstract too much away or have too many layers if you just want to jump in and start working. This means that you need to read and study a bit before getting your hands dirty in code. For me this is another negative point when it comes to developer experience.  </p>
<p><strong>I don't mean that RoR is bad but it is harder to get started</strong> than a lot of other frameworks which is something that might discourage developers from learning it, at the end of the day you want to build your project for fun, not read outdated docs and posts just to get started.<br />Which is another issue: you have a lot of posts and answers on SO that are fairly old and while they might be helpful it's confusing for newer devs as things have changed since then.  </p>
<p><strong>I believe it's not easy to start but once you put enough time you will get excellent results as the abstraction and all the built in features allow you to make a CRUD app blazingly fast.</strong><br />You won't have microservices but instead you will have a solid modular monolith, which I'd say in a lot of cases is far better.</p>
<h1 id="heading-get-weird-with-ruby">Get weird with Ruby</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659634443681/ODguullOf.png" alt="image.png" class="image--center mx-auto" />
After using Ruby for a bit the adjective that comes to my mind is fun. Depending who you are or how you work it might be the best or the worst thing ever. Here's a <a target="_blank" href="https://stackoverflow.com/a/1426835/14356309">Stackoverflow post asking for a difference between &amp;&amp; vs and</a> to illustrate my point.   </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659577657401/6y6DNvlax.png" alt="image.png" class="image--center mx-auto" />
<a target="_blank" href="http://phrogz.net/ProgrammingRuby/language.html#table_18.4">Image source</a>  </p>
<p>Ruby is a language that allows you to write code however you want, there are various ways of doing the same thing which might sound wonderful BUT if you are working in a team your beautiful one-liner or the way you did something might confuse your less experienced co-workers.</p>
<p><strong>Overall I think Ruby is amazing and it seems to allow a lot of freedom</strong> but there's a cost to having so many choices: your team needs to follow and enforce a particular code style.<br />If you want to dig a bit deeper then check this article about <a target="_blank" href="https://blog.appsignal.com/2018/09/04/ruby-magic-closures-in-ruby-blocks-procs-and-lambdas.html">closures in Ruby</a>.</p>
<h1 id="heading-ror-gets-magically-fast">RoR gets magically fast</h1>
<p>Once you learn a bit of the framework you can make a full CRUD app in a few hours thanks to the <code>generate</code> <a target="_blank" href="https://guides.rubyonrails.org/command_line.html#bin-rails-generate">command</a> which allows you to make all the files you'd need for your CRUD operations, including routes and testing.<br />Here's an article that dives a bit in <a target="_blank" href="https://www.rubyguides.com/2020/03/rails-scaffolding/">scaffolding with the generate command</a> and keep in mind all these files will be created inside an already well structured project so all you have to do is write a bit of logic and you are good to go.  </p>
<p>Additionally you have partials and concerns, to sum it up very poorly (the links explain it much better):</p>
<ul>
<li><a target="_blank" href="https://guides.rubyonrails.org/layouts_and_rendering.html#using-partials">partials</a>: view components that you can move around</li>
<li><a target="_blank" href="https://blog.appsignal.com/2020/09/16/rails-concers-to-concern-or-not-to-concern.html">concerns</a>: mixins that allows you dependency injection</li>
</ul>
<p>If you are unfamiliar with the terms mixin or DI, <a target="_blank" href="https://dev.to/software_writer/how-rails-concerns-work-and-how-to-use-them-gi6">this article</a> explains concerns a bit more in detail.<br />I like that the second paragraph is as follows:<br /><em>
"The Rails API documentation doesn't help, either. It starts with the assumption that the reader is already familiar with the problem concerns are trying to solve, and goes on to provide the solution, only adding to the confusion"</em>  </p>
<p>It really illustrates the struggles of someone who is new to the ecosystem and one of the biggest negative points about RoR right now.</p>
<h1 id="heading-pros-and-cons">Pros and Cons</h1>
<p>Ruby on Rails is great if</p>
<ul>
<li>You are a beginner and want to learn fundamentals of a full stack app</li>
<li>You want to make a fast CRUD app with a bit of time investment beforehand</li>
<li>You are a senior software engineer who wants to transition into a new ecosystem</li>
</ul>
<p>Ruby on Rails is bad if</p>
<ul>
<li>You have services where performance is <strong>extremely</strong> important </li>
</ul>
<p>Let me quote a post from <a target="_blank" href="https://about.gitlab.com/blog/2022/07/06/why-were-sticking-with-ruby-on-rails/">Gtilab</a>: <em>"while Rails is excellent technology for our purposes, it does have a few drawbacks, one of them being performance. Luckily, only a tiny part of most codebases is actually performance critical. We use our own gitaly daemon written in Go to handle actual git operations, and PostgreSQL for non-repository persistence"</em>.</p>
<p>However the biggest con of Ruby on Rails is its lack of support in terms of documentation, up to date tutorials and overall DX.<br />If the RoR community doesn't put more effort into its ecosystem and training junior developers or anyone coming from other frameworks it will suffer a slow and agonizing death where top companies will fight for a small portion of talent and others will try to rewrite their codebase by any means necessary due to lack of RoR developers.</p>
<h1 id="heading-fin">Fin</h1>
<p>If you have enjoyed this article or you want to scream at me because I'm wrong feel free to leave a comment, subscribe for more or hit me up on <a target="_blank" href="https://twitter.com/tekbog">Twitter @tekbog</a>.</p>
<p>PS: if you want to learn Ruby on Rails and don't know where to start then head to their page and click on <a target="_blank" href="https://guides.rubyonrails.org/getting_started.html">Getting Started</a>.</p>
]]></content:encoded></item><item><title><![CDATA[NodeJS auth: JWT, cookies, express, mongoose and more!]]></title><description><![CDATA[Intro
Here is the source code of the project from my Github.   
This post is part of the MERN series, if you are lost or don't feel confident I'd recommend you read through the series to get familiar with NodeJS and Express. However you will find add...]]></description><link>https://bognov.tech/nodejs-auth-jwt-cookies-express-mongoose-and-more</link><guid isPermaLink="true">https://bognov.tech/nodejs-auth-jwt-cookies-express-mongoose-and-more</guid><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[authentication]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Mon, 25 Jul 2022 21:16:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658782620400/e5NPF5zLz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-intro">Intro</h1>
<p>Here is the <a target="_blank" href="https://github.com/bgdnvk/nodejs-auth">source code</a> of the project from my <a target="_blank" href="https://github.com/bgdnvk">Github</a>.   </p>
<p>This post is part of the <a target="_blank" href="https://bognov.tech/series/mern-stack">MERN series</a>, if you are lost or don't feel confident I'd recommend you read through the series to get familiar with NodeJS and Express. However you will find additional resources and links throughout the article.  </p>
<p>If you want to yell at me you can find me on <a target="_blank" href="https://twitter.com/tekbog">Twitter @tekbog</a>.</p>
<h1 id="heading-auth">Auth</h1>
<p>What some people might call <strong>AUTH</strong> in reality is <strong>authentication</strong> and <strong>authorization</strong>. To sum it up I like to think about it this way:</p>
<blockquote>
<p>Authentication: who are you?  </p>
<p>Authorization: what can you do?</p>
</blockquote>
<p>Authentication is about knowing the identity of the user while authorization is knowing what action the user is allowed to do, I'm paraphrasing from <a target="_blank" href="https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api">this .NET article</a>.  </p>
<p>If you still want to read more or a comparison check out this <a target="_blank" href="https://auth0.com/docs/get-started/identity-fundamentals/authentication-and-authorization">auth0 article</a>.</p>
<h1 id="heading-protect-the-password">Protect the password</h1>
<p>In order to make our database secure for our users we will deal with the passwords by hashing and salting them. So bad agents can't access your user's data like pic related.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657401533886/vDq-YeUFe.png" alt="image.png" class="image--center mx-auto" /></p>
<p>I'd recommend you read more about these concepts but here's a very quick summary that define them fairly well and you can also watch this video from <a target="_blank" href="https://www.youtube.com/watch?v=zt8Cocdy15c">ByteByteGo</a>.</p>
<blockquote>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Hash_function">Hashing</a>: map data of arbitrary size to fixed-size values</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Salt_(cryptography)">Salting</a>: random data that is used as an additional input to a one-way function that hashes data</p>
</blockquote>
<p>We are going to put user's data through a hash function with salt to make it secure. In order to do that we will use the <a target="_blank" href="https://www.npmjs.com/package/bcryptjs">bcrypt.js library</a>.</p>
<h1 id="heading-tokens">Tokens</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658692200939/n7zpz4L4D.png" alt="image.png" class="image--center mx-auto" />
<a target="_blank" href="https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/">Picture source</a></p>
<p>For us to identify (authenticate) the user every time the user wants to do something (authorize) we will be using <a target="_blank" href="https://jwt.io/introduction">JWT (JSON Web Token)</a>. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658692511571/UEVzq5pob.png" alt="image.png" class="image--center mx-auto" />
<a target="_blank" href="https://notsosecure.com/crafting-your-way-through-json-web-tokens">Picture source</a></p>
<p>We generate a new token for every user that registers and store it in the database, afterwards we verify that the token is correct by comparing it with the same secret string we used to make the token.  </p>
<p>So, to simplify:</p>
<ol>
<li>User registers or logs in and gets a token</li>
<li>The token is stored in a cookie in our browser</li>
<li>Every time the user wants to do something the user sends the token</li>
<li>Every time the server gets a request from the user it checks if the token is correct  </li>
</ol>
<p>By using tokens the user doesn't have to log in every time, however the tokens expire after a while so from time to time we need to log in again.  </p>
<p>We will see how tokens work and how to use them by storing them in a cookie.  </p>
<p>To use JWT with NodeJS we will be using <a target="_blank" href="https://www.npmjs.com/package/jsonwebtoken">jsonwebtoken</a> and to read (parse) cookies we will be using <a target="_blank" href="https://www.npmjs.com/package/cookie-parser">cookie-parser</a></p>
<h1 id="heading-disclaimer">Disclaimer</h1>
<p>Before we start keep in mind this isn't a final product and it's just a tutorial (not ready for prod), if you are going to be implementing auth in production check <a target="_blank" href="https://www.npmjs.com/package/cookie-parser">passport.js</a> and of course remember <a target="_blank" href="https://helmetjs.github.io/">Helmet</a>.<br />Additionally remember to ask your users for a strong password and make sure you don't make users without the right parameters.</p>
<h1 id="heading-the-project">The Project</h1>
<h2 id="heading-setup">Setup</h2>
<p>For testing the REST API I will be using <a target="_blank" href="https://www.postman.com/">Postman</a> and as the database I'm running <a target="_blank" href="https://www.mongodb.com/try/download/community">Mongodb</a> locally, however you can use Atlas or Docker.<br />For local variables I will use an .env file through the package <a target="_blank" href="https://www.npmjs.com/package/dotenv">dotenv</a>. You can store your secrets there and afterwards use them inside your NodeJS project by typing process.env.YOUR_VAR.  </p>
<p>If you are confused by any of this I'd recommend you start with the first entry of this series that you can find <a target="_blank" href="https://bognov.tech/mern-stack-how-to-build-a-restful-api-with-nodejs-and-express">here</a>. Or pick one from my <a target="_blank" href="https://bognov.tech/series/mern-stack">MERN series</a>.</p>
<h2 id="heading-dependencies">Dependencies</h2>
<p>Initialize the project with</p>
<pre><code>npm <span class="hljs-keyword">init</span>
</code></pre><p>Let's install everything we will need: </p>
<pre><code>npm i bcryptjs cookie-<span class="hljs-keyword">parser</span> dotenv express jsonwebtoken mongoose
</code></pre><p>Add the dev dependency</p>
<pre><code><span class="hljs-built_in">npm</span> -D nodemon
</code></pre><p>Finally modify your package.json scripts like this:</p>
<pre><code>  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"node index.js"</span>,
    <span class="hljs-string">"dev"</span>: <span class="hljs-string">"nodemon index.js"</span>
  }
</code></pre><p>Now you can do <code>npm start</code> or <code>npm run dev</code>, if you are not familiar with <a target="_blank" href="https://www.npmjs.com/package/nodemon">nodemon</a> then just know that it reloads the server with every change you make.</p>
<h2 id="heading-project-structure">Project structure</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658711640426/haObzVaFy.png" alt="image.png" /></p>
<p><em>NB: Before you freak out keep in mind I've separated the files a lot so it would be easier to navigate, there's no unique way that every project has to be structured so just do whatever works for you as long as it makes sense: some people prefer more files and imports/exports while others prefer to keep one file with all the logic inside. </em>   </p>
<p><em>Additionally keep in mind instead of routes you can have a folder with controllers and no services, I think it depends a lot on your background and what you are used to. This structure works for me, however it shouldn't work for you or your organization.</em> </p>
<h3 id="heading-structure-tldr">Structure TL;DR</h3>
<p><strong>API folder</strong>: this is where our API is going to be aka our endpoints, I've made testroute.js so you start by getting familiar with imports/exports and making sure the server runs and you get familiar with <a target="_blank" href="https://expressjs.com/en/guide/routing.html">express.Router()</a>.  </p>
<p>Then inside <strong>api/session-exporer</strong> we will have a router with two routes to explore what tokens and cookies are.  </p>
<p>Afterwards there's a <strong>middleware folder</strong> with <a target="_blank" href="http://expressjs.com/en/guide/using-middleware.html#using-middleware">middleware</a> to check cookies and verify tokens as well as to check if the logged user is an admin.  </p>
<p>The last <strong>auth folder</strong> is where our REST api is located, we have one router and inside the routes folder you will find the different routes/endpoints. However the logic is stored inside <strong>servicess folder</strong> which has a subfolder for utils functions.  </p>
<p>The last folder I haven't mentioned is <strong>models</strong> that contains our <a target="_blank" href="https://mongoosejs.com/docs/guide.html">mongoose schema</a>.</p>
<h2 id="heading-env">.env</h2>
<p>One of the first things we should do is generate the signature key for our server, we can it with <a target="_blank" href="https://stackoverflow.com/a/52996809/14356309">this command</a>:  </p>
<pre><code><span class="hljs-attribute">node</span> -e <span class="hljs-string">"console.log(require('crypto').randomBytes(256).toString('base64'));"</span>
</code></pre><p>Then store the result in our .env file (which is included in .gitignore)</p>
<pre><code><span class="hljs-attribute">PORT</span>=<span class="hljs-number">5000</span>
<span class="hljs-attribute">TOKEN_KEY</span>=<span class="hljs-number">8</span>bf<span class="hljs-number">0698</span>c<span class="hljs-number">0908</span>f<span class="hljs-number">00</span>edf<span class="hljs-number">6</span>b<span class="hljs-number">4</span>efeb<span class="hljs-number">837</span>cd<span class="hljs-number">52</span>baef<span class="hljs-number">165</span>b<span class="hljs-number">9029</span>c<span class="hljs-number">7</span>a<span class="hljs-number">06648</span>ef<span class="hljs-number">23</span>e<span class="hljs-number">0</span>a<span class="hljs-number">0</span>fdfda<span class="hljs-number">1</span>cdd<span class="hljs-number">758</span>e<span class="hljs-number">67597480</span>f<span class="hljs-number">74424793848596</span>
</code></pre><h2 id="heading-database">Database</h2>
<p>Note that you might need to modify this, depending where your database is located but overall your db.js file should look something likes this:</p>
<pre><code>const mongoose <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);
const localDB <span class="hljs-operator">=</span> <span class="hljs-string">"mongodb://localhost:27017/auth"</span>;

const connectDB <span class="hljs-operator">=</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  <span class="hljs-keyword">try</span> {
    mongoose.connect(localDB, {
        useNewUrlParser: <span class="hljs-literal">true</span>,
        useUnifiedTopology: <span class="hljs-literal">true</span>,
    });
    console.log(<span class="hljs-string">"MongoDB Connected..."</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    console.error(err.message);
    process.exit(<span class="hljs-number">1</span>);
  }
};

module.exports <span class="hljs-operator">=</span> connectDB;
</code></pre><h2 id="heading-entry-point-indexjs">Entry point: index.js</h2>
<p>This is the file Node runs when you start the server</p>
<pre><code><span class="hljs-comment">//interact with our .env file</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
<span class="hljs-comment">// --- routers ---</span>
const authRouter <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"./api/auth/router"</span>);
const sessionExplorerRouter <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./api/session-explorer/router'</span>);
const { routerTest } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./api/testroute'</span>);

<span class="hljs-comment">//get our db connection</span>
const connectDB <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"./db"</span>);
<span class="hljs-comment">//import express package</span>
const express <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-comment">//middleware to read cookies</span>
<span class="hljs-comment">//http://expressjs.com/en/resources/middleware/cookie-parser.html</span>
const cookieParser <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'cookie-parser'</span>);

<span class="hljs-comment">//get our express app</span>
const app <span class="hljs-operator">=</span> express();
<span class="hljs-comment">//get port from our .env file</span>
const PORT <span class="hljs-operator">=</span> process.env.PORT <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-number">5000</span>;

<span class="hljs-comment">// -- MIDDLEWARE</span>
app.use(express.json());
app.use(cookieParser());
<span class="hljs-comment">// -- MIDDLEWARE</span>

<span class="hljs-comment">// -- ROUTES --</span>

<span class="hljs-comment">//hello world on: http://localhost:5000/</span>
app.get(<span class="hljs-string">"/"</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> res.<span class="hljs-built_in">send</span>(<span class="hljs-string">"Hello World!"</span>));

<span class="hljs-comment">//make sure everything is set up correctly</span>
<span class="hljs-comment">//http://localhost:5000/test</span>
app.use(<span class="hljs-string">'/test'</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> res.<span class="hljs-built_in">send</span>(<span class="hljs-string">"from test!"</span>));

<span class="hljs-comment">//router test to make sure you know how to use middleware and imports/exports</span>
<span class="hljs-comment">//call example: http://localhost:5000/api/cookie</span>
app.use(<span class="hljs-string">'/api'</span>, routerTest);

<span class="hljs-comment">//session explorer endpoints to understand cookies and jwt</span>
app.use(<span class="hljs-string">'/api'</span>, sessionExplorerRouter);

<span class="hljs-comment">//get the router from api/auth/router and use the endpoints (routes) from api/auth/routes</span>
<span class="hljs-comment">//call example: http://localhost:5000/api/auth/login</span>
app.use(<span class="hljs-string">'/api/auth'</span>, authRouter);

<span class="hljs-comment">// -- ROUTES --</span>

<span class="hljs-comment">//connect to db</span>
connectDB();

<span class="hljs-comment">//start listening on the designed port</span>
app.listen(PORT, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> console.log(`Example app listening on port ${PORT}<span class="hljs-operator">!</span>`));


<span class="hljs-comment">// The unhandledRejection listener</span>
<span class="hljs-comment">//The unhandledRejection event is emitted whenever a promise rejection is not handled. </span>
<span class="hljs-comment">//NodeJS warns the console about UnhandledPromiseRejectionWarning and immediately terminates the process. </span>
<span class="hljs-comment">//The NodeJS process global has an unhandledRejection event.</span>
process.on(<span class="hljs-string">'unhandledRejection'</span>, <span class="hljs-function"><span class="hljs-keyword">error</span> =&gt; </span>{
    console.error(<span class="hljs-string">'unhandledRejection'</span>, <span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
});
</code></pre><h2 id="heading-user-schema">User schema</h2>
<p>Inside models/user.js you will find the <a target="_blank" href="https://mongoosejs.com/docs/guide.html">Mongoose schema</a> that we will use to interact with MongoDB. You make a schema for your data, export it and then you can interact with the data in your database through Mongoose predefined methods like User.findById().  </p>
<p>The most complicated thing we will be doing is updating the database, if you are unfamiliar with the term <strong>atomic</strong> check out <a target="_blank" href="https://masteringjs.io/tutorials/mongoose/update">this article</a>.</p>
<pre><code><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>)

<span class="hljs-keyword">const</span> UserSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
    username: {
        <span class="hljs-keyword">type</span>: <span class="hljs-built_in">String</span>,
        required: <span class="hljs-literal">true</span>,
        unique: <span class="hljs-literal">true</span>
    },
    password: {
        <span class="hljs-keyword">type</span>: <span class="hljs-built_in">String</span>,
        required: <span class="hljs-literal">true</span>,
        minlength: <span class="hljs-number">6</span>,
    },
    role: {
        <span class="hljs-keyword">type</span>: <span class="hljs-built_in">String</span>,
        <span class="hljs-keyword">default</span>: <span class="hljs-string">'Basic'</span>,
        required: <span class="hljs-literal">true</span>
    },
    token: {
        <span class="hljs-keyword">type</span>: <span class="hljs-built_in">String</span>
    }
})

<span class="hljs-keyword">const</span> User = mongoose.model(<span class="hljs-string">'User'</span>, UserSchema)
<span class="hljs-built_in">module</span>.<span class="hljs-built_in">exports</span> = User;
</code></pre><h2 id="heading-services">Services</h2>
<p>Before going into our API let's check our logic that lives inside the services folder. Each service gets exported so it's easier to use inside our API folder, however this is on the over-complicated side.<br />Depending on your project you could just add everything into your routes/controllers or perhaps you'd want to add responses to services as well and break it into more folders or files.<br />As I said the file structure and overall organization depends on you, this is what I found useful for this project. Later you will see how we just import our authService inside our API folder and use the various functions (if you are familiar with OOP you can consider the auth service as our main object and functions the methods that we call after initializing the object through an import).  </p>
<p>authService.js contains the main chunk of logic however we also have a small token.js file inside our utils folder.</p>
<p>authService.js: </p>
<pre><code>const User <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/user'</span>)
const bcrypt <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'bcryptjs'</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config()
const utils <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./utils/token'</span>)

exports.getUserByUsername <span class="hljs-operator">=</span> async (username) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    console.log(<span class="hljs-string">'inside authService'</span>)
    <span class="hljs-keyword">return</span> await User.findOne({ username })
}

exports.getUserById <span class="hljs-operator">=</span> async (id) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-keyword">return</span> await User.findById(id)
}

exports.getUserByIdAndDelete <span class="hljs-operator">=</span> async (id) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-keyword">return</span> await User.findByIdAndDelete(id)
}

exports.registerUser <span class="hljs-operator">=</span> async (username, password) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {

    <span class="hljs-comment">//generate salt, it can take a while so we use await</span>
    const salt <span class="hljs-operator">=</span> await bcrypt.genSalt(<span class="hljs-number">10</span>);
    <span class="hljs-comment">//hash password</span>
    const hashedPassword <span class="hljs-operator">=</span> await bcrypt.hash(password, salt);

    <span class="hljs-comment">//2 hours to expire in seconds</span>
    const maxAge <span class="hljs-operator">=</span> <span class="hljs-number">2</span> <span class="hljs-operator">*</span> <span class="hljs-number">60</span> <span class="hljs-operator">*</span> <span class="hljs-number">60</span>
    <span class="hljs-comment">//get token from our utils folder</span>
    const token <span class="hljs-operator">=</span> utils.getToken(username, maxAge)
    console.log({ token })
    <span class="hljs-comment">//create new user using mongoose schema from models</span>
    const newUser <span class="hljs-operator">=</span> await User.create({
        username: username,
        password: hashedPassword,
        token: token
    });

    console.log(<span class="hljs-string">'making USER after token b4 cookie----'</span>)
    console.log({ newUser })
    <span class="hljs-comment">//return all the elements we are going to use</span>
    <span class="hljs-keyword">return</span> { newUser, token, maxAge }

}

exports.loginUser <span class="hljs-operator">=</span> async (username, password) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//get the user</span>
    const user <span class="hljs-operator">=</span> await User.findOne({ username })
    <span class="hljs-comment">//validate the hashed password we have in our database</span>
    const validPassword <span class="hljs-operator">=</span> await bcrypt.compare(password, user.password)
    <span class="hljs-comment">//2 hours to expire in seconds</span>
    const maxAge <span class="hljs-operator">=</span> <span class="hljs-number">2</span> <span class="hljs-operator">*</span> <span class="hljs-number">60</span> <span class="hljs-operator">*</span> <span class="hljs-number">60</span>
    <span class="hljs-comment">//set up the jwt token</span>
    const token <span class="hljs-operator">=</span> utils.getToken(username, maxAge)

    <span class="hljs-comment">//add token to the user</span>
    user.token <span class="hljs-operator">=</span> token
    <span class="hljs-comment">//remember to save your modification</span>
    <span class="hljs-comment">//https://masteringjs.io/tutorials/mongoose/update</span>
    await user.save()

    console.log({ token })

    <span class="hljs-keyword">return</span> { user, validPassword, token, maxAge }
}

exports.updateUser <span class="hljs-operator">=</span> async (id) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {

    <span class="hljs-comment">//get the user</span>
    const userToUpdate <span class="hljs-operator">=</span> await User.findById(id)
    <span class="hljs-comment">//check if the user is already an admin</span>
    <span class="hljs-keyword">if</span>(userToUpdate.role <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'Admin'</span>){
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'The user is already an admin'</span>)
    }
    userToUpdate.role <span class="hljs-operator">=</span> <span class="hljs-string">"Admin"</span>
    userToUpdate.save()

    <span class="hljs-keyword">return</span> userToUpdate
}
</code></pre><p>utils/token.js</p>
<pre><code>const jwt <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>)

<span class="hljs-comment">//sign and make a new token for the user</span>
exports.getToken <span class="hljs-operator">=</span> (username, expirationTime) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//example of seeting up expiration time</span>
    <span class="hljs-comment">//2 hours to expire in seconds</span>
    <span class="hljs-comment">//const maxAge = 2 * 60 * 60</span>

    <span class="hljs-comment">//generate token for the user</span>
    const token <span class="hljs-operator">=</span> jwt.sign(
        { username },
        process.env.TOKEN_KEY,
        {
            expiresIn: expirationTime <span class="hljs-comment">//2h in seconds</span>
        }
    )

    <span class="hljs-keyword">return</span> token
}
</code></pre><h2 id="heading-api">API</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658716091014/8VeQ4Ftt5.png" alt="image.png" /></p>
<p>This is the most important part of the project. If you don't know routing, HTTP request and response methods or your way around middleware in Express I'd recommend you check some quick tutorials to understand the concepts before digging in but here's a very small and incomplete summary:  </p>
<ul>
<li><p>Routing: by creating different <a target="_blank" href="https://stackoverflow.com/a/59678852/14356309">endpoints (or routes? - see link for differences)</a> we allow the user to go/call those specific endpoints with parameters and different HTTP requests to get the data they want.</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods">HTTP methods</a> are conventions that indicate the desired actions we request and respond with.</p>
</li>
<li><p><a target="_blank" href="https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-middleware/">Middleware</a> is the middle layer that goes between requests and/or responses, say you want to modify or add some data to the request of the user before it reaches the desired endpoint? That's what middleware does.<br />In our case we verify that the user is logged in and that it's an admin before sending it to our updateuser route.</p>
</li>
</ul>
<h3 id="heading-testroutejs">testroute.js</h3>
<p>This is just a test route to make sure everything works in our server:</p>
<pre><code>const express <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
const routerTest <span class="hljs-operator">=</span> express.Router();

routerTest.route(<span class="hljs-string">"/test"</span>).get((req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> res.<span class="hljs-built_in">send</span>(<span class="hljs-string">"GET endpoint from api/testroute"</span>));

module.exports <span class="hljs-operator">=</span> {
    routerTest,
}
</code></pre><p>Inside index.js we import it and then define the route:</p>
<pre><code><span class="hljs-comment">//import the route</span>
const { routerTest } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./api/testroute'</span>);

....

<span class="hljs-comment">//router test to make sure you know how to use middleware and imports/exports</span>
<span class="hljs-comment">//call example: http://localhost:5000/api/test</span>
app.use(<span class="hljs-string">'/api'</span>, routerTest);
</code></pre><p>This is the response we get from calling that route</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658716430573/hglXv8WVK.png" alt="image.png" class="image--center mx-auto" /></p>
<h3 id="heading-apiauth">API/auth</h3>
<p>Let's jump into our auth folder and see how it works.<br />This is router.js:</p>
<pre><code>const express <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
const router <span class="hljs-operator">=</span> express.Router();
const { login } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"./routes/login"</span>);
const { register } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"./routes/register"</span>);
const { updateUserToAdmin } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"./routes/update"</span>);
const { deleteUser } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"./routes/delete"</span>);

<span class="hljs-comment">//get middleware</span>
const verifyAccessToken <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../middleware/token"</span>);
const checkAdmin <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../middleware/checkAdmin"</span>);

router.route(<span class="hljs-string">"/register"</span>).post(register);
<span class="hljs-comment">//we can have the same route with different request types</span>
router.route(<span class="hljs-string">"/register"</span>).get((req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> res.<span class="hljs-built_in">send</span>(<span class="hljs-string">"Hello World!"</span>));

<span class="hljs-comment">//call example: http://localhost:5000/api/auth/login</span>
router.route(<span class="hljs-string">"/login"</span>).post(login);

router.route(<span class="hljs-string">"/deleteuser"</span>).delete(deleteUser);

<span class="hljs-comment">//load middleware</span>
<span class="hljs-comment">//make sure the user is logged</span>
router.use(verifyAccessToken);
<span class="hljs-comment">//make sure the logged user is an admin</span>
router.use(checkAdmin);
<span class="hljs-comment">//if the previous middleware doesn't throw an error then we update the user</span>
<span class="hljs-comment">//call example: http://localhost:5000/api/auth/updateuser/62c8ed790c6812f9ddcc1100</span>
router.route(<span class="hljs-string">"/updateuser/:id"</span>).put(updateUserToAdmin);

module.exports <span class="hljs-operator">=</span> router;
</code></pre><p>For now let's just focus on the register route.</p>
<h4 id="heading-apiauthroutesregister">API/auth/routes/register</h4>
<pre><code>const authService <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../../../services/authService"</span>);

exports.register <span class="hljs-operator">=</span> async (req, res, next) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    console.log(<span class="hljs-string">"inside register"</span>);

    const { username, password } <span class="hljs-operator">=</span> req.body;
    console.log(<span class="hljs-string">"req body is "</span>, req.body);

    <span class="hljs-comment">//check if the username already exists</span>
    const oldUser <span class="hljs-operator">=</span> await authService.getUserByUsername(username);

    console.log({ oldUser });
    <span class="hljs-keyword">if</span> (oldUser) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">409</span>).<span class="hljs-built_in">send</span>(<span class="hljs-string">"user already exists"</span>);
    }

    <span class="hljs-comment">//simple rule for the password</span>
    <span class="hljs-keyword">if</span> (password.<span class="hljs-built_in">length</span> <span class="hljs-operator">&lt;</span> <span class="hljs-number">6</span>) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ message: <span class="hljs-string">"password less than 6 characters"</span> });
    }

    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">//define variables with destructuring</span>
        <span class="hljs-comment">//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment</span>
        const { newUser, token, maxAge } <span class="hljs-operator">=</span> await authService.registerUser(
            username,
            password
        );
        <span class="hljs-comment">//send our cookie with the token</span>
        res.cookie(<span class="hljs-string">"jwt"</span>, token, {
            httpOnly: <span class="hljs-literal">true</span>,
            maxAge: maxAge <span class="hljs-operator">*</span> <span class="hljs-number">1000</span>, <span class="hljs-comment">//convert 2h to ms; maxAge uses miliseconds</span>
        });

        <span class="hljs-comment">//response status and display the created user</span>
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">201</span>).json({
            message: <span class="hljs-string">"User created successfully"</span>,
            newUser,
        });
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-comment">//if there are any errors we will get a message back</span>
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({
            message: <span class="hljs-string">"User not created"</span>,
            <span class="hljs-function"><span class="hljs-keyword">error</span>: <span class="hljs-title">err</span>.<span class="hljs-title">message</span>,
        })</span>;
    }
};
</code></pre><p>Check how we are using our function from the services folder through authService.registerUser().  </p>
<p>Let's use Postman with raw data as JSON to make the following call on 
<code>http://localhost:5000/api/auth/register</code> endpoint.</p>
<p>It should look like this: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658770605809/g6ZEbSFBB.png" alt="image.png" class="image--center mx-auto" /></p>
<p>And if we check our MongoDB we should see the user we just created here: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658770664552/B6zAT7Hy8.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Let's make a second user as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658770738805/o5Ho9j-SU.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Notice that once we create a user we get a cookie stored in postman, if you click on "Cookies" button you should see something like: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658770799795/l5i-Fcp1Y.png" alt="image.png" class="image--center mx-auto" /></p>
<p>This is our JSON Web Token (JWT):</p>
<pre><code><span class="hljs-attribute">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9</span>.eyJ<span class="hljs-number">1</span>c<span class="hljs-number">2</span>VybmFtZSI<span class="hljs-number">6</span>InRlc<span class="hljs-number">3</span>QtdXNlcjEiLCJpYXQiOjE<span class="hljs-number">2</span>NTg<span class="hljs-number">3</span>NzA<span class="hljs-number">2</span>OTIsImV<span class="hljs-number">4</span>cCI<span class="hljs-number">6</span>MTY<span class="hljs-number">1</span>ODc<span class="hljs-number">3</span>Nzg<span class="hljs-number">5</span>Mn<span class="hljs-number">0</span>.dPkQroBqkkdi<span class="hljs-number">2</span>g_<span class="hljs-number">2</span>MwNCm<span class="hljs-number">1</span>N<span class="hljs-number">16</span>fcchtMBcbbkRxRDCIc
</code></pre><p>If we go to <a target="_blank" href="https://jwt.io/">jwt.io</a> and paste the token this is what we will see:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658770998822/taZvZbjZ6.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Once we paste our signature (TOKEN_KEY from our .env file) you should see how the site changes as well: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658771062473/lt6koeDiq.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Finally I'd like to mention that I left a lot of console.logs around for you to see how everything works and why it's doing what, so feel free to add your own logs or at least check the console when calling different endpoints: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658771414984/3P2BJmvU-.png" alt="image.png" class="image--center mx-auto" /></p>
<h4 id="heading-apiauthroutesdelete">API/auth/routes/delete</h4>
<p>We have made our users but let's see a very simple way to delete one of them. Note that I'm not using <a target="_blank" href="https://en.wikipedia.org/wiki/Query_string">query parameters</a> (we will do something more complicated with the update endpoint) but instead I'm sending the id through the request body. </p>
<p>The delete route is as follows:</p>
<pre><code>const authService <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'../../../services/authService'</span>)

exports.deleteUser <span class="hljs-operator">=</span> async (req, res, next) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    const { id } <span class="hljs-operator">=</span> req.body;
    <span class="hljs-comment">//if there's no id then we can't do anything</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>id) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ message: <span class="hljs-string">"missing id"</span> });
    }

    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">//this service returns the deleted user if it exists</span>
        const user <span class="hljs-operator">=</span> await authService.getUserByIdAndDelete(id)
        <span class="hljs-comment">//if user doesn't exist then we can't do anything</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>user) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).json({
                message: <span class="hljs-string">"Could not delete user"</span>,
                <span class="hljs-function"><span class="hljs-keyword">error</span>: "<span class="hljs-title">User</span> <span class="hljs-title">not</span> <span class="hljs-title">found</span>",
            })</span>;
        }
        <span class="hljs-comment">//return success if the user is deleted</span>
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
            message: <span class="hljs-string">"User deleted successfully"</span>,
            user,
        });
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">409</span>).json({
            message: <span class="hljs-string">"User not deleted"</span>,
            <span class="hljs-function"><span class="hljs-keyword">error</span>: <span class="hljs-title">err</span>.<span class="hljs-title">message</span>,
        })</span>;
    }
}
</code></pre><p>Let's try it by hitting this endpoint with a delete method: </p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//localhost:5000/api/auth/deleteuser</span>
</code></pre><p>Note that we need to get the ObjectId from our users, which you can find in MongoDB:</p>
<pre><code>62ded50470566254e90bb059
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658771874797/1ASIAPPwc.png" alt="image.png" class="image--center mx-auto" /></p>
<p>And this is the call we do in postman: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658771924613/-rI77dKSb.png" alt="image.png" /></p>
<p>If we hit it again we can see that the error message is handled correctly, same if we type the user id wrong:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658771965240/wMkXJ_ORZ.png" alt="image.png" class="image--center mx-auto" /></p>
<h4 id="heading-apiauthrouteslogin">API/auth/routes/login</h4>
<p>Let's look at our login endpoint, it also gives us a cookie with a newly made token so we stay logged in, this is the login.js file: </p>
<pre><code>const authService <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../../../services/authService"</span>);

exports.login <span class="hljs-operator">=</span> async (req, res, next) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    const { username, password } <span class="hljs-operator">=</span> req.body;
    console.log(<span class="hljs-string">"login req body is "</span>, req.body);
    <span class="hljs-comment">//simple checker for username and password</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>username <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-operator">!</span>password) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ message: <span class="hljs-string">"username or password is missing"</span> });
    }

    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">//get the data from our auth service</span>
        const { user, validPassword, token, maxAge } <span class="hljs-operator">=</span> await authService.loginUser(username, password)
        <span class="hljs-comment">//check if the user exists</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>user) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({
                message: <span class="hljs-string">"Login not successful"</span>,
                <span class="hljs-function"><span class="hljs-keyword">error</span>: "<span class="hljs-title">User</span> <span class="hljs-title">not</span> <span class="hljs-title">found</span>",
            })</span>;
        }
        <span class="hljs-comment">//return error if the password is incorrect</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>validPassword) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({
                message: <span class="hljs-string">"Login not successful"</span>,
                <span class="hljs-function"><span class="hljs-keyword">error</span>: "<span class="hljs-title">Password</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">incorrect</span>",
            })</span>;
        }
        <span class="hljs-comment">//send our cookie with the token</span>
        res.cookie(<span class="hljs-string">"jwt"</span>, token, {
            httpOnly: <span class="hljs-literal">true</span>,
            maxAge: maxAge <span class="hljs-operator">*</span> <span class="hljs-number">1000</span>, <span class="hljs-comment">//convert 2h to ms; maxAge uses miliseconds</span>
        });

        <span class="hljs-comment">//if everything is good return the user</span>
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
            message: <span class="hljs-string">"Login successful"</span>,
            user,
        });

    } <span class="hljs-keyword">catch</span> (err) {
        res.status(<span class="hljs-number">401</span>).json({
            message: <span class="hljs-string">"Login not successful"</span>,
            <span class="hljs-function"><span class="hljs-keyword">error</span>: <span class="hljs-title">err</span>.<span class="hljs-title">message</span>,
        })</span>;
    }
};
</code></pre><p>This is what we get if we call our endpoint: </p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//localhost:5000/api/auth/login</span>
</code></pre><p>as long as the user exists in the database.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658773739872/uYKAfpzow.png" alt="image.png" class="image--center mx-auto" /></p>
<p>We get our token through our authService and afterwards we send it to the user:</p>
<pre><code>        <span class="hljs-comment">//send our cookie with the token</span>
        res.cookie(<span class="hljs-string">"jwt"</span>, token, {
            httpOnly: <span class="hljs-literal">true</span>,
            maxAge: maxAge <span class="hljs-operator">*</span> <span class="hljs-number">1000</span>, <span class="hljs-comment">//convert 2h to ms; maxAge uses miliseconds</span>
        });
</code></pre><p>Inside authService on L52 you can see the following: </p>
<pre><code>    <span class="hljs-comment">//set up the jwt token</span>
    const token <span class="hljs-operator">=</span> utils.getToken(username, maxAge)
</code></pre><p>we generate the token thanks to the function in services/utils/token.js </p>
<pre><code>    <span class="hljs-comment">//generate token for the user</span>
    const token <span class="hljs-operator">=</span> jwt.sign(
        { username },
        process.env.TOKEN_KEY,
        {
            expiresIn: expirationTime <span class="hljs-comment">//2h in seconds</span>
        }
    )
</code></pre><p>If you check the console of our server (the node app we are running) you can see the generated token, I recommend adding more logs at every bit of code that you are curious about although there are better ways to debug it:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658774092452/ZMIGfW-Y3.png" alt="image.png" class="image--center mx-auto" /></p>
<h3 id="heading-apisession-explorer">API/Session-explorer</h3>
<p>Now, before we go to our last endpoint updateuser let's understand a bit better how tokens and the communication with the server works, as well as middleware.</p>
<h4 id="heading-apisession-explorerrouter">api/session-explorer/router</h4>
<pre><code>const express <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
const router <span class="hljs-operator">=</span> express.Router();
const verifyTokenMiddleware <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../middleware/token"</span>)

<span class="hljs-comment">//route to read our cookies after loggin in</span>
router.route(<span class="hljs-string">"/cookie"</span>).get((req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    console.log(<span class="hljs-string">'cookies: '</span>, req.cookies)
    res.status(<span class="hljs-number">200</span>).json({
        cookies: req.cookies
    })

});

<span class="hljs-comment">//read more on middleware here: https://expressjs.com/en/guide/using-middleware.html</span>
<span class="hljs-comment">//token endpoint to check out how verifyToken middleware works</span>
<span class="hljs-comment">//if the token isn't correct then our middleware in /middleware/token gives an error responde</span>
router.route(<span class="hljs-string">"/token"</span>).post( verifyTokenMiddleware, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">// in case you want to read everything from the request header</span>
    <span class="hljs-comment">// console.log({req})</span>
    res.status(<span class="hljs-number">200</span>).<span class="hljs-built_in">send</span>(<span class="hljs-string">"token correct: access granted!"</span>)
})


module.exports <span class="hljs-operator">=</span> router
</code></pre><p>After logging in and having our cookie let's get a request from </p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//localhost:5000/api/cookie</span>
</code></pre><p>Which should return our cookie where the JWT token is stored:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658774664855/IBOAbf9UE.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Note that we are able to get cookies thanks to the middleware cookie-parser and interact with json thanks to express.json, we declared that middleware in our index.js file:</p>
<pre><code><span class="hljs-comment">// -- MIDDLEWARE</span>
app.use(express.json());
app.use(cookieParser());
<span class="hljs-comment">// -- MIDDLEWARE</span>
</code></pre><p>So in order to access our cookies we just need to type:</p>
<pre><code><span class="hljs-selector-tag">req</span><span class="hljs-selector-class">.cookies</span>
</code></pre><h3 id="heading-middleware">Middleware</h3>
<h4 id="heading-middlewaretoken">middleware/token</h4>
<p>Before jumping to our /token endpoint let's understand the middleware we have.</p>
<p>We are using token.js to verify that the token we get is correct: </p>
<pre><code>const jwt <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"jsonwebtoken"</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();

<span class="hljs-comment">//this only works if you use cookie-parser</span>
const checkCookie <span class="hljs-operator">=</span> (req) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    console.log(<span class="hljs-string">'inside checkCookie'</span>)
    console.log(<span class="hljs-string">'all our cookies are: '</span>, req.cookies)
    <span class="hljs-comment">//we get the jwt cookie we need</span>
    <span class="hljs-keyword">return</span> req.cookies[<span class="hljs-string">'jwt'</span>]
}

<span class="hljs-comment">//middleware for verifying the JWT</span>
const verifyAccessToken <span class="hljs-operator">=</span> (req, res, next) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//define token</span>
    let token;

    <span class="hljs-comment">//authenticate through Bearer token</span>
    <span class="hljs-keyword">if</span> (req.headers.authorization <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> req.headers.authorization.startsWith(<span class="hljs-string">"Bearer "</span>)) {
        token <span class="hljs-operator">=</span> req.headers.authorization.split(<span class="hljs-string">' '</span>)[<span class="hljs-number">1</span>]
        <span class="hljs-comment">//logs so you see what's happening</span>
        console.log(<span class="hljs-string">'auth bearer token'</span>)
        console.log({ token })
    }
    <span class="hljs-keyword">else</span> {
        token <span class="hljs-operator">=</span> req.headers[<span class="hljs-string">"x-access-token"</span>] <span class="hljs-operator">|</span><span class="hljs-operator">|</span> checkCookie(req) <span class="hljs-operator">|</span><span class="hljs-operator">|</span> null
        <span class="hljs-comment">//logs</span>
        console.log(<span class="hljs-string">'our token is from x-access-token header, a cookie or null'</span>)
        console.log({ token })
    }

    <span class="hljs-comment">//if we can't get our token anywhere then the response is an error</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>token) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">403</span>).<span class="hljs-built_in">send</span>(<span class="hljs-string">"A token is required for authentication"</span>);
    }
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">//we use the JWT library to verify the token</span>
        <span class="hljs-comment">//and we need to know the token_key which we encrypted our information</span>
        const decoded <span class="hljs-operator">=</span> jwt.verify(token, process.env.TOKEN_KEY);
        <span class="hljs-comment">//log</span>
        console.log({ decoded })
        <span class="hljs-comment">//the middleware adds the user information to the request and sends it to the route</span>
        req.user <span class="hljs-operator">=</span> decoded;
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).<span class="hljs-built_in">send</span>(<span class="hljs-string">"Invalid Token"</span>);
    }
    <span class="hljs-comment">//if you have doubts check Express middleware docs: http://expressjs.com/en/guide/using-middleware.html</span>
    <span class="hljs-keyword">return</span> next();
};

module.exports <span class="hljs-operator">=</span> verifyAccessToken;
</code></pre><p>Note how we can get our token from a cookie or headers: 
<code>req.headers.authorization</code> and <code>req.headers.authorization</code>.  </p>
<p>Now while logged in (having our cookie) let's hit our /token endpoint which is using this middleware (remember to use a POST method):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658775667656/KV7hrTEJP.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Inside the token.js file we are using this function: </p>
<pre><code>const checkCookie <span class="hljs-operator">=</span> (req) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    console.log(<span class="hljs-string">'inside checkCookie'</span>)
    console.log(<span class="hljs-string">'all our cookies are: '</span>, req.cookies)
    <span class="hljs-comment">//we get the jwt cookie we need</span>
    <span class="hljs-keyword">return</span> req.cookies[<span class="hljs-string">'jwt'</span>]
}
</code></pre><p>to check if the cookie exists (or get it). Then we store the token in the variable: </p>
<pre><code>token <span class="hljs-operator">=</span> req.headers[<span class="hljs-string">"x-access-token"</span>] <span class="hljs-operator">|</span><span class="hljs-operator">|</span> checkCookie(req) <span class="hljs-operator">|</span><span class="hljs-operator">|</span> null
</code></pre><p>And afterwards verify the token through: </p>
<pre><code>        //we use the JWT library <span class="hljs-keyword">to</span> verify the token
        //<span class="hljs-keyword">and</span> we need <span class="hljs-keyword">to</span> know the token_key which we <span class="hljs-keyword">encrypted</span> our information
        const decoded = jwt.verify(token, process.env.TOKEN_KEY);
        //<span class="hljs-keyword">log</span>
        console.log({ decoded })
</code></pre><p>This is what we get on the console: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658775878002/LkpL0P7PO.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Reminds you of something? Yeah, that's the decoded payload we got from the JWT site, let's type our token there again to see the exact results: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658775983011/KWUmAAcca.png" alt="image.png" class="image--center mx-auto" /></p>
<p>remember to have your secret stored in an .env file, this is mine: </p>
<pre><code><span class="hljs-attribute">PORT</span>=<span class="hljs-number">5000</span>
<span class="hljs-attribute">TOKEN_KEY</span>=<span class="hljs-number">8</span>bf<span class="hljs-number">0698</span>c<span class="hljs-number">0908</span>f<span class="hljs-number">00</span>edf<span class="hljs-number">6</span>b<span class="hljs-number">4</span>efeb<span class="hljs-number">837</span>cd<span class="hljs-number">52</span>baef<span class="hljs-number">165</span>b<span class="hljs-number">9029</span>c<span class="hljs-number">7</span>a<span class="hljs-number">06648</span>ef<span class="hljs-number">23</span>e<span class="hljs-number">0</span>a<span class="hljs-number">0</span>fdfda<span class="hljs-number">1</span>cdd<span class="hljs-number">758</span>e<span class="hljs-number">67597480</span>f<span class="hljs-number">74424793848596</span>
</code></pre><p>The last line inside the try block is: </p>
<pre><code>        <span class="hljs-comment">//the middleware adds the user information to the request and sends it to the route</span>
        req.user <span class="hljs-operator">=</span> decoded;
</code></pre><p>Although it's not helpful for us now what the middleware is doing is add the decoded data to the request and sends that request to the next middleware (or the endpoint it has to reach).</p>
<p>Now if we delete the cookie from postman: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658776454374/-2Ks_T1HS.png" alt="image.png" class="image--center mx-auto" /></p>
<pre><code><span class="hljs-attribute">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9</span>.eyJ<span class="hljs-number">1</span>c<span class="hljs-number">2</span>VybmFtZSI<span class="hljs-number">6</span>InRlc<span class="hljs-number">3</span>QtdXNlciIsImlhdCI<span class="hljs-number">6</span>MTY<span class="hljs-number">1</span>ODc<span class="hljs-number">3</span>MzcxNywiZXhwIjoxNjU<span class="hljs-number">4</span>NzgwOTE<span class="hljs-number">3</span>fQ.-<span class="hljs-number">4</span>feclw<span class="hljs-number">9</span>asuqMf<span class="hljs-number">5</span>MQJRd<span class="hljs-number">3</span>D<span class="hljs-number">3</span>hleqBbNxlOGkxzG<span class="hljs-number">8</span>QSF<span class="hljs-number">4</span>
</code></pre><p>Then go to authorization, select "Bearer Token" and paste our cookie it should work the same: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658776550839/UjemD-bUV.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Check the console: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658776586595/1zrY0fVz7.png" alt="image.png" class="image--center mx-auto" /></p>
<p>But this is not all, if we select "No Auth" and then go to Headers and add </p>
<pre><code>x<span class="hljs-operator">-</span>access<span class="hljs-operator">-</span>token
</code></pre><p>as key and our token as value our authorization is going to work as well:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658776764311/EuYCXOVis.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Finally if we get rid of everything and we don't have a token in our cookie or our headers then we won't be able to authenticate:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658776830098/Nq2Fybm1p.png" alt="image.png" class="image--center mx-auto" /></p>
<h4 id="heading-middlewarecheckadmin">middleware/checkadmin</h4>
<p>The other file inside our middleware folder is checkAdmin.js which is a middleware that checks if the user is an admin: if the user is an admin we go to the next middleware and if it's not we return a 403 status</p>
<pre><code>const User <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'../../models/user'</span>)

const checkAdmin <span class="hljs-operator">=</span> async (req, res, next) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//we get the logged user from our token middleware</span>
    <span class="hljs-comment">//check token @ L42</span>
    console.log(<span class="hljs-string">'inside checkadmin middleware'</span>)
    console.log(<span class="hljs-string">'user from req is: '</span>, req.user)
    const loggedUsername <span class="hljs-operator">=</span> req.user.username
    <span class="hljs-comment">// console.log({loggedUsername})</span>
    const loggedUser <span class="hljs-operator">=</span> await User.findOne({ username: loggedUsername })
    <span class="hljs-comment">// console.log({loggedUser})</span>

    <span class="hljs-keyword">if</span>(loggedUser.role <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"Admin"</span>){
        <span class="hljs-comment">//if the logged user is the admin</span>
        <span class="hljs-comment">//we go to the next action (middleware)</span>
        <span class="hljs-comment">//in this case the next action is calling the /updateuser endpoint</span>
        <span class="hljs-keyword">return</span> next()
    }
    <span class="hljs-comment">//if the user isn't an admin return a 403</span>
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">403</span>).<span class="hljs-built_in">send</span>(<span class="hljs-string">"You are not an admin"</span>);
}

module.exports <span class="hljs-operator">=</span> checkAdmin
</code></pre><h3 id="heading-apiauthupdate">API/auth/update</h3>
<p>Now that we understand how middleware and tokens work let's dig into how one user can update another as long as the logged user is an admin. So a logged in admin will be able to update another user to be an admin as long as we pass the id of the user we want to update.</p>
<p>Let's see the code from update.js</p>
<pre><code>const authService <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../../../services/authService"</span>);

<span class="hljs-comment">//after loading the middleware we can finally call to update the user</span>
exports.updateUserToAdmin <span class="hljs-operator">=</span> async (req, res, next) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//get the id from the query params</span>
    const id <span class="hljs-operator">=</span> req.params.id

    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>id) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ message: <span class="hljs-string">"missing id"</span> });
    }

    <span class="hljs-keyword">try</span> {
        console.log(<span class="hljs-string">'we have passed all the middleware and we are inside updateUsertoAdmin'</span>)
        const updatedUser <span class="hljs-operator">=</span> await authService.updateUser(id)

        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
            message: <span class="hljs-string">"User updated successfully"</span>,
            updatedUser,
        });
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({
            message: <span class="hljs-string">"User not updated"</span>,
            <span class="hljs-function"><span class="hljs-keyword">error</span>: <span class="hljs-title">err</span>.<span class="hljs-title">message</span>,
        })</span>;
    }
}
</code></pre><p>It is fairly simple because all our logic is inside the authService.js:</p>
<pre><code>exports.updateUser <span class="hljs-operator">=</span> async (id) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {

    <span class="hljs-comment">//get the user</span>
    const userToUpdate <span class="hljs-operator">=</span> await User.findById(id)
    <span class="hljs-comment">//check if the user is already an admin</span>
    <span class="hljs-keyword">if</span>(userToUpdate.role <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'Admin'</span>){
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'The user is already an admin'</span>)
    }
    userToUpdate.role <span class="hljs-operator">=</span> <span class="hljs-string">"Admin"</span>
    userToUpdate.save()

    <span class="hljs-keyword">return</span> userToUpdate
}
</code></pre><p>updateUser just updates the new user we want to admin, after getting it from the database through the id.</p>
<p>And this logic is simple because we have abstracted the heavy lifting to our middleware, if you rememeber api/auth/router.js we have the following:</p>
<pre><code><span class="hljs-comment">//get middleware</span>
const verifyAccessToken <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../middleware/token"</span>);
const checkAdmin <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../middleware/checkAdmin"</span>);

...

<span class="hljs-comment">//load middleware</span>
<span class="hljs-comment">//make sure the user is logged</span>
router.use(verifyAccessToken);
<span class="hljs-comment">//make sure the logged user is an admin</span>
router.use(checkAdmin);
<span class="hljs-comment">//if the previous middleware doesn't throw an error then we update the user</span>
<span class="hljs-comment">//call example: http://localhost:5000/api/auth/updateuser/62c8ed790c6812f9ddcc1100</span>
router.route(<span class="hljs-string">"/updateuser/:id"</span>).put(updateUserToAdmin);
</code></pre><p>Note that if the middleware fails to see a logged in user (verifyAccessToken) or fails to see that the user is an admin (checkAdmin) we won't be able to reach our /updateuser/:id route and we will get back an error.</p>
<p>Now let's see how everything works, to begin with we need at least two users and one of them needs the role of "Admin". Since we register users with only username and password we will have to make our user an admin manually by editing the database directly (bad stuff!).</p>
<p>Let's create our user:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658778185696/VVdR48gkH.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Now modify the database (note we are only doing this because it's a tutorial):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658778255876/_L6JaJ8mw.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Log in with our new user who's an admin to get the token in a cookie:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658778357466/0m07bRFdP.png" alt="image.png" class="image--center mx-auto" /></p>
<p>This is our database, get the id of the test-user:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658778504220/tjRoa3WJB.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Now let's do a PUT request to our endpoint: </p>
<pre><code><span class="hljs-attribute">http</span>://localhost:<span class="hljs-number">5000</span>/api/auth/updateuser/<span class="hljs-number">62</span>ded<span class="hljs-number">42</span>c<span class="hljs-number">70566254</span>e<span class="hljs-number">90</span>bb<span class="hljs-number">056</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658778613406/p7XRv540T.png" alt="image.png" class="image--center mx-auto" /></p>
<p>If we refresh the database again we will see that both of our users are admins:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658778707018/8Hjc76bIU.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Now if we update both users back to normal and try to update: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658779047662/EAEnD51JZ.png" alt="image.png" class="image--center mx-auto" /></p>
<p>We will get an error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658779078019/KDAwZrpOW.png" alt="image.png" class="image--center mx-auto" /></p>
<p>In this case our request reached verifyAdmin middleware and it failed: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658779154499/ySLRbYT9q.png" alt="image.png" class="image--center mx-auto" /></p>
<p>You can find the exact line of code for this @ middleware/checkAdmin.js L19: </p>
<pre><code>    <span class="hljs-comment">//if the user isn't an admin return a 403</span>
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">403</span>).<span class="hljs-built_in">send</span>(<span class="hljs-string">"You are not an admin"</span>);
</code></pre><h1 id="heading-cest-fini">C'est fini</h1>
<p>You can find the whole project on my <a target="_blank" href="https://github.com/bgdnvk/nodejs-auth">Github</a>.  </p>
<p>If you want to reach out feel free to leave a comment or hit me up on <a target="_blank" href="https://twitter.com/tekbog">Twitter</a> as well as follow me there or on Hashnode.  </p>
<p>Keep in mind that I haven't used any linterns or specific style guides so you might find some inconsistencies with semicolons here and there. I wanted to make a small project on auth at first but it got out of hand, hopefully this is helpful - most of the articles I saw about NodeJS and auth weren't going into as much detail or were outdated.  </p>
<p>Thanks for reading.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction to Golang: build a mini Twitter clone]]></title><description><![CDATA[TL;DR
This article is for those who want to quickly glance over Golang and build a small project, it serves as an introduction into the language.
After going through the post you will know how to build a simple CRUD app and you will be somehow famili...]]></description><link>https://bognov.tech/introduction-to-golang-build-a-mini-twitter-clone</link><guid isPermaLink="true">https://bognov.tech/introduction-to-golang-build-a-mini-twitter-clone</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[backend]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Thu, 30 Jun 2022 02:08:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656552451373/RCbVxIHPT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-tldr">TL;DR</h1>
<p>This article is for those who want to quickly glance over Golang and build a small project, it serves as an introduction into the language.</p>
<p>After going through the post you will know how to build a simple CRUD app and you will be somehow familiar with Go syntax to start your own project.</p>
<p>If you have feedback you can reach me out on Twitter <a target="_blank" href="https://twitter.com/tekbog">@tekbog</a> or leave a comment here.</p>
<p>The repo for this project can be found <a target="_blank" href="https://github.com/bgdnvk/mini-twitter-clone">HERE</a>.</p>
<p>If you are unfamiliar with API/backend development I have starting series with both <a target="_blank" href="https://bognov.tech/series/mern-stack">Node</a> and <a target="_blank" href="https://bognov.tech/series/spring-boot">Spring Boot</a> you can check.</p>
<h1 id="heading-why-golang">Why Golang?</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656552531384/dXq6mAQvC.png" alt="image.png" class="image--center mx-auto" /></p>
<p>If you want to build loosely coupled micro services that are low on memory and scalable Go is probably one of the best choices, if not the best, considering the fact that <a target="_blank" href="https://github.com/kubernetes/kubernetes">Kubernetes</a>, <a target="_blank" href="https://github.com/docker">Docker</a> and <a target="_blank" href="https://github.com/hashicorp/terraform">Terraform</a>.  </p>
<p>Additionally many other companies use it such as <a target="_blank" href="https://eng.uber.com/go-geofence-highest-query-per-second-service/">Uber</a> and of course the tech giant <a target="_blank" href="https://go.dev/solutions/google/">Google</a> is using it heavily internally.</p>
<p>Overall Go excels in the back end with Goroutines and Channels. It offers quick development with a minimalist C-like language.</p>
<h1 id="heading-go-syntax">Go Syntax</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656552612011/4tVkG1g4D.png" alt="image.png" class="image--center mx-auto" /></p>
<p>You can use this page as the <a target="_blank" href="https://devhints.io/go">Go syntax cheat sheet</a> or start the <a target="_blank" href="https://go.dev/tour/welcome/1">Go tour</a> from the official site.</p>
<h2 id="heading-concurrency">Concurrency</h2>
<p>I'm not going to go into concurrency, however <a target="_blank" href="https://www.golangprograms.com/go-language/concurrency.html">here</a>'s a good enough tutorial to get you started.<br />To paraphrase a bit:  </p>
<blockquote>
<p><strong>Goroutine </strong>is a lightweight thread.  </p>
<p><strong>Channel </strong>allows to send data between Goroutines.</p>
</blockquote>
<p>Now keep in mind that while looking for Go docs the last release as of today <strong><a target="_blank" href="https://go.dev/blog/go1.18">1.18 has introduced Generics</a></strong> so some of the old tutorials might be outdated.</p>
<p>Let's get through some basics to get you started.</p>
<h2 id="heading-imports-and-exports">Imports and exports</h2>
<p>In every new file you will need to declare its package right at the start such as:
<code>package services</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656468732456/0tRSwyUcI.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Then in order to use export (or expose) a function you need to start it with a capital letter. In the example above you can see that the function <code>GetFeedTweets</code> starts with a capital letter, this means I'm making it "public".<br />Afterwards just import the package like: <code>import ("project-folder-name/package")</code> and you will be use the function by invoking the package name followed by the dot and the function like: <code>package.FunctionName</code>.  </p>
<p>Note that when working with Structs you have to make the fields start with capital letter if you want to expose them. Otherwise you will end <a target="_blank" href="https://twitter.com/tekbog/status/1539787225692602373">like me</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656469197291/1DnQAPtJU.png" alt="image.png" /></p>
<h2 id="heading-golang-is-case-sensitive">Golang is case sensitive</h2>
<p><strong>REMEMBER THIS OR YOU WILL SUFFER</strong></p>
<h2 id="heading-pointers">Pointers</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656470773044/LO-XsoIDD.png" alt="image.png" class="image--center mx-auto" /></p>
<p>I won't be covering pointers in detail as it's a lengthy topic, however <a target="_blank" href="https://medium.com/@annapeterson89/whats-the-point-of-golang-pointers-everything-you-need-to-know-ac5e40581d4d#:~:text=%E2%80%9C%20Pointers%20are%20used%20for%20efficiency,we%20want%20to%20mutate%20it%20.%E2%80%9D">here's an article</a> that should make a good introduction.</p>
<p>The <a target="_blank" href="https://go.dev/tour/moretypes/1">Go tour</a> also offers a quick introduction.</p>
<p>To sum it up (badly, please read up on it):</p>
<pre><code><span class="hljs-comment">//declare int variable that equals to 42</span>
<span class="hljs-keyword">var</span> i <span class="hljs-operator">=</span> <span class="hljs-number">42</span>
<span class="hljs-comment">//make p an int pointer</span>
<span class="hljs-keyword">var</span> p <span class="hljs-operator">*</span><span class="hljs-keyword">int</span>
<span class="hljs-comment">//assign the i memory address to p</span>
p <span class="hljs-operator">=</span> <span class="hljs-operator">&amp;</span>i

<span class="hljs-comment">//p is just a pointer holding memory</span>
<span class="hljs-comment">//will print 0xc0000b8000</span>
fmt.Println(p)

<span class="hljs-comment">//p* points to the memory address it's holding</span>
<span class="hljs-comment">//will print 42</span>
fmt.Println(<span class="hljs-operator">*</span>p)
</code></pre><p>You will see functions getting parameters like <code>func FuncName (p *pointerType)</code> just use p as you normally would.</p>
<h2 id="heading-variadic-functions">Variadic functions:</h2>
<p>If you come from the JavaScript world you will know how useful this is as it works the same as the spread operator, <a target="_blank" href="https://www.geeksforgeeks.org/variadic-functions-in-go/?ref=lbp">here's a quick tutorial</a>.</p>
<p>Here's a quick example from <a target="_blank" href="https://stackoverflow.com/a/17556146/14356309">StackOverflow</a>:</p>
<pre><code>package main
<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-title">func</span> <span class="hljs-title">my_func</span>( <span class="hljs-title">args</span> ...<span class="hljs-title"><span class="hljs-keyword">int</span></span>) <span class="hljs-title"><span class="hljs-keyword">int</span></span> {
   <span class="hljs-title">sum</span> :<span class="hljs-operator">=</span> 0
  <span class="hljs-comment">//the underscore in golang is called the "blank identifier"</span>
   <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">_</span></span>, <span class="hljs-title">v</span> :<span class="hljs-operator">=</span> <span class="hljs-title">range</span> <span class="hljs-title">args</span> {
      <span class="hljs-title">sum</span> <span class="hljs-operator">=</span> <span class="hljs-title">sum</span> <span class="hljs-operator">+</span> <span class="hljs-title">v</span>
   }

   <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">sum</span>;
}

func main() {
    arr :<span class="hljs-operator">=</span> []<span class="hljs-keyword">int</span>{<span class="hljs-number">2</span>,<span class="hljs-number">4</span>}
    sum :<span class="hljs-operator">=</span> my_func(arr...)
    <span class="hljs-comment">//prints: Sum is  6</span>
    fmt.Println(<span class="hljs-string">"Sum is "</span>, sum)
}
</code></pre><p>However it's easier to understand how it works with strings:</p>
<pre><code><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"strings"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">joinString</span><span class="hljs-params">(element ...<span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> strings.Join(element, <span class="hljs-string">","</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {

    <span class="hljs-comment">//will print "join,this"</span>
    fmt.Println(joinString(<span class="hljs-string">"join"</span>, <span class="hljs-string">"this"</span>))
    <span class="hljs-comment">//will print "a,a,a"</span>
    fmt.Println(joinString(<span class="hljs-string">"a"</span>, <span class="hljs-string">"a"</span>, <span class="hljs-string">"a"</span>))

}
</code></pre><h2 id="heading-make">Make</h2>
<p>The quickest way to <em>make </em> a slice, which is a dynamic array, just do </p>
<pre><code>a := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">int</span>, <span class="hljs-number">5</span>)
</code></pre><p>Here's the page from the <a target="_blank" href="https://go.dev/tour/moretypes/13">Go tour</a></p>
<h2 id="heading-range">Range</h2>
<p>Golang doesn't have a forEach function however it uses range instead so if you want to loop through all the elements of an array or slice just do:</p>
<pre><code><span class="hljs-keyword">for</span> index, element :<span class="hljs-operator">=</span> range yourSlice{
        fmt.Println(index)
        fmt.Println(element)
}
</code></pre><p>You can find more examples in this site with <a target="_blank" href="https://gobyexample.com/range">golang code examples</a>.</p>
<h2 id="heading-maps">Maps</h2>
<p>Maps, hash tables or dictionaries - in Golang they are used as follows:</p>
<pre><code>    m :<span class="hljs-operator">=</span> map[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">int</span>{
        <span class="hljs-string">"first-key"</span>: <span class="hljs-number">5</span>,
        <span class="hljs-string">"second-key"</span>:  <span class="hljs-number">10</span>,
    }
    fmt.Println(m) 

    <span class="hljs-keyword">for</span> key, value :<span class="hljs-operator">=</span> range m { <span class="hljs-comment">// Order not specified</span>
        fmt.Println(key, value)
    }
</code></pre><p><a target="_blank" href="https://gobyexample.com/maps">Here</a>'s a quick summary about maps.</p>
<h2 id="heading-methods">Methods:</h2>
<p>Golang doesn't have classes however it has methods. It sounds counter intuitive but it works great, if you have worked with OOP before just think of Structs as classes/objects. You define a function for them and then use that function on the Struct with a dot call, here's an example.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
    Id   <span class="hljs-keyword">int</span>
    Name <span class="hljs-keyword">string</span>
}

<span class="hljs-comment">//method to set user's name</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(u *User)</span> <span class="hljs-title">setName</span><span class="hljs-params">(newName <span class="hljs-keyword">string</span>)</span></span> {
    (*u).Name = newName
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {

    <span class="hljs-comment">//initialize a new user</span>
    newUser := User{
        Id:   <span class="hljs-number">0</span>,
        Name: <span class="hljs-string">"First Name"</span>,
    }
    <span class="hljs-comment">//User's ID:  0</span>
    fmt.Println(<span class="hljs-string">"User's ID: "</span>, newUser.Id)
    <span class="hljs-comment">//User's Name:  First Name</span>
    fmt.Println(<span class="hljs-string">"User's Name: "</span>, newUser.Name)

    <span class="hljs-comment">// make a pointer to the newUser</span>
    pointerNewUser := &amp;newUser

    <span class="hljs-comment">// call your method</span>
    pointerNewUser.setName(<span class="hljs-string">"Name From Pointer"</span>)
    <span class="hljs-comment">//User's Name:  First Name</span>
    fmt.Println(<span class="hljs-string">"Same User's Id: "</span>, pointerNewUser.Id)
    <span class="hljs-comment">//User's new name: Name From Pointer</span>
    fmt.Println(<span class="hljs-string">"User's new name:"</span>, pointerNewUser.Name)
}
</code></pre><h2 id="heading-print">Print</h2>
<p>When you want to print something to the console remember to use the proper verbs:</p>
<pre><code>%v    the <span class="hljs-keyword">value</span> <span class="hljs-keyword">in</span> a <span class="hljs-keyword">default</span> <span class="hljs-keyword">format</span> <span class="hljs-keyword">when</span> printing structs, the plus flag (%+v) adds field names
%#v    a Go-syntax representation <span class="hljs-keyword">of</span> the <span class="hljs-keyword">value</span>
%T    a Go-syntax representation <span class="hljs-keyword">of</span> the <span class="hljs-keyword">type</span> <span class="hljs-keyword">of</span> the <span class="hljs-keyword">value</span>
%%    a literal percent sign; consumes <span class="hljs-keyword">no</span> <span class="hljs-keyword">value</span>
</code></pre><p> That's from the <a target="_blank" href="https://pkg.go.dev/fmt">official documentation</a>.</p>
<p>For example a normal expression would be:</p>
<pre><code>fmt.Printf(<span class="hljs-string">"checking user: %v\n"</span>, user)
</code></pre><h2 id="heading-typeof-reflection">TypeOf: Reflection</h2>
<p>If you want to examine types during runtime then you need to use the reflect package:</p>
<pre><code><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"reflect"</span>
)

<span class="hljs-keyword">type</span> user <span class="hljs-keyword">struct</span> {
    Id   <span class="hljs-keyword">int</span>
    Name <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> blog <span class="hljs-keyword">struct</span> {
    User_id <span class="hljs-keyword">int</span>
    Data    <span class="hljs-keyword">string</span>
    Date    <span class="hljs-keyword">string</span>
}

<span class="hljs-comment">//this is a generic function since I'm using the keyword "any"</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">checkTypeAndValue</span><span class="hljs-params">(x any)</span></span> {
    userType := reflect.TypeOf(x)
    userValue := reflect.ValueOf(x)
    fmt.Println(<span class="hljs-string">"Type "</span>, userType)
    fmt.Println(<span class="hljs-string">"Value "</span>, userValue)

}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    newUser := user{
        Id:   <span class="hljs-number">1</span>,
        Name: <span class="hljs-string">"myUser"</span>,
    }
    checkTypeAndValue(newUser)

    newBlog := blog{
        User_id: <span class="hljs-number">1</span>,
        Data:    <span class="hljs-string">"this is my first blog"</span>,
        Date:    <span class="hljs-string">"01-01-1990"</span>,
    }
    checkTypeAndValue(newBlog)

}
</code></pre><h2 id="heading-blank-identifier">Blank identifier</h2>
<p>You might find blank identifiers in loops or when you import a package, like:</p>
<pre><code>  <span class="hljs-comment">//the underscore in golang is called the "blank identifier"</span>
   <span class="hljs-keyword">for</span> <span class="hljs-keyword">_</span>, v :<span class="hljs-operator">=</span> range args {
      sum <span class="hljs-operator">=</span> sum <span class="hljs-operator">+</span> v
   }
</code></pre><p>You can find a good explanation from <a target="_blank" href="https://go.dev/doc/effective_go#blank">Effective Go</a> about it. However to put it simple: the compiler complains if you aren't using a variable, so if you need to store something but never use it then use the underscore.</p>
<h2 id="heading-generics">Generics</h2>
<p>Finally here! The type of jokes no longer work:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656552719138/b1Ra2TXFP.png" alt="image.png" class="image--center mx-auto" /></p>
<p>With 1.18 Golang has introduced generics, so be careful when you look at old tutorials.  </p>
<p>I'd recommend you to read on Generics if you haven't heard the term before but the gist of it is that you can use one function for many types of data, just like I did in the example of TypeOf: Reflection, there's a generic function there that accepts <strong>any</strong> type of data: </p>
<pre><code><span class="hljs-comment">//this is a generic function since I'm using the keyword "any"</span>
func checkTypeAndValue(x any) {
    userType :<span class="hljs-operator">=</span> reflect.TypeOf(x)
    userValue :<span class="hljs-operator">=</span> reflect.ValueOf(x)
    fmt.Println(<span class="hljs-string">"Type "</span>, userType)
    fmt.Println(<span class="hljs-string">"Value "</span>, userValue)

}
</code></pre><p>This <a target="_blank" href="https://www.freecodecamp.org/news/generics-in-golang/">FreeCodeCamp</a> article makes it quick to understand. And you can also refer to the <a target="_blank" href="https://go.dev/doc/tutorial/generics">official Golang docs</a>.</p>
<h1 id="heading-the-project-mini-twitter-backend">The project: mini Twitter backend</h1>
<h2 id="heading-notes-before-you-start">Notes before you start</h2>
<p>Keep in mind this project was made mainly to show off Golang a bit, you can copy the architecture but the project is missing proper <a target="_blank" href="https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping">ORM</a>, there's no authentication or authorization in place, I'm completely disregarding middleware and there are no tests.  </p>
<p>I will talk about all this issues in its own sections but it's important that you are aware that this is not ready for production. </p>
<p>If I had to start from scratch or remake the project I'd add libraries such as <a target="_blank" href="https://github.com/jmoiron/sqlx">sqlx</a> and <a target="_blank" href="https://github.com/go-gorm/gorm">Gorm</a>. As well as improve the API and other changes that I go through below.</p>
<p>Additionally I'd like to address the routing library I'm using: <a target="_blank" href="https://github.com/gofiber/fiber">Fiber</a>. Note that it's version 2, however a lot of tutorials and blog posts are showing and talking about v1, a bit has changed since then so when looking for additional information make sure the import is <code>github.com/gofiber/fiber/v2</code>.</p>
<p>Also, you should definitely have a configuration file and an .env in your project to hide your data. </p>
<p>There's also a disclaimer in the <a target="_blank" href="https://github.com/bgdnvk/mini-twitter-clone#readme">README</a>:</p>
<blockquote>
<p>Disclaimer</p>
<p>This is an introductory project to look at Golang a bit.
This project is not production ready and it has bad practices like the way pagination works or how we interact with the database. </p>
<p>Through the codebase you will find different "prints" that are used to debug the project, feel free to play with them.
What's missing for production ready?</p>
<p>You should add a proper logger, configuration, middleware, a different way to handle the data, perhaps an ORM, and a better way to handle the pagination, as well as a better API.</p>
<p>Note that you can make yourself vulnerable to SQL ingections if you copy and paste the code. This has been made for learning purposes.</p>
</blockquote>
<h2 id="heading-database">Database</h2>
<p>You should probably have <a target="_blank" href="https://hub.docker.com/_/mysql">Docker</a> running MySQL (or any other SQL database). If not you can always install MySQL on your system and use something like <a target="_blank" href="https://www.mysql.com/products/workbench/">MySQL Workbench</a> to work with it.</p>
<h3 id="heading-database-design">Database design</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656481862578/yQBkZ5PgS.png" alt="image.png" /></p>
<p>I'm using <a target="_blank" href="https://www.quickdatabasediagrams.com/">QDBD</a> for the diagram.</p>
<p>The database itself is fairly simple, you have the users that tweet tweets and a table of followers to keep the data of who follows who. The followers table is mainly to implement the feed/timeline for our users.</p>
<h3 id="heading-create-database">Create Database</h3>
<p>In the scripts folder you will find the main script to run to start your MySQL database:</p>
<pre><code><span class="hljs-keyword">use</span> twitterdb;

<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> tweets;
<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-keyword">users</span>;
<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> followers;

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">users</span> (
  user_id <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT,
  <span class="hljs-keyword">user</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  passhash <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">40</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  email <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  first_name <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  last_name <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  dob <span class="hljs-built_in">DATE</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (user_id)
);

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> tweets (
  tweet_id <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT,
  user_id <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  tweet <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">140</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  date_tweet DATETIME <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (tweet_id),
  <span class="hljs-keyword">FOREIGN</span> <span class="hljs-keyword">KEY</span> user_id(user_id) <span class="hljs-keyword">REFERENCES</span> <span class="hljs-keyword">users</span>(user_id) 
  <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">CASCADE</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">CASCADE</span>
);

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> followers (
  id_user <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">REFERENCES</span> <span class="hljs-keyword">users</span> (user_id),
  id_follower <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">REFERENCES</span> <span class="hljs-keyword">users</span> (user_id),
  PRIMARY <span class="hljs-keyword">KEY</span> (id_user, id_follower)
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-keyword">users</span> (<span class="hljs-keyword">user</span>, passhash, email, first_name, last_name, dob) <span class="hljs-keyword">VALUES</span>
(<span class="hljs-string">"foo"</span>, <span class="hljs-string">"asdsad1"</span>, <span class="hljs-string">"test@gmail.com"</span>, <span class="hljs-string">"bob"</span>, <span class="hljs-string">"bobbinson"</span>, <span class="hljs-string">"2006-01-01"</span>),
(<span class="hljs-string">"foo2"</span>, <span class="hljs-string">"asdsad2"</span>, <span class="hljs-string">"test2@gmail.com"</span>, <span class="hljs-string">"bob2"</span>, <span class="hljs-string">"bobbinson2"</span>, <span class="hljs-string">"1992-01-01"</span>),
(<span class="hljs-string">"foo3"</span>, <span class="hljs-string">"asdsad3"</span>, <span class="hljs-string">"test3@gmail.com"</span>, <span class="hljs-string">"bob3"</span>, <span class="hljs-string">"bobbinson3"</span>, <span class="hljs-string">"1993-01-01"</span>),
(<span class="hljs-string">"foo4"</span>, <span class="hljs-string">"asdsad4"</span>, <span class="hljs-string">"test4@gmail.com"</span>, <span class="hljs-string">"bob4"</span>, <span class="hljs-string">"bobbinson4"</span>, <span class="hljs-string">"1994-01-01"</span>),
(<span class="hljs-string">"foo5"</span>, <span class="hljs-string">"asdsad5"</span>, <span class="hljs-string">"test5@gmail.com"</span>, <span class="hljs-string">"bob5"</span>, <span class="hljs-string">"bobbinson5"</span>, <span class="hljs-string">"1995-01-01"</span>),
(<span class="hljs-string">"foo6"</span>, <span class="hljs-string">"asdsad6"</span>, <span class="hljs-string">"test6@gmail.com"</span>, <span class="hljs-string">"bob6"</span>, <span class="hljs-string">"bobbinson6"</span>, <span class="hljs-string">"1996-01-01"</span>),
(<span class="hljs-string">"foo7"</span>, <span class="hljs-string">"asdsad7"</span>, <span class="hljs-string">"test7@gmail.com"</span>, <span class="hljs-string">"bob7"</span>, <span class="hljs-string">"bobbinson7"</span>, <span class="hljs-string">"1925-01-01"</span>),
(<span class="hljs-string">"foo8"</span>, <span class="hljs-string">"asdsad8"</span>, <span class="hljs-string">"test8@gmail.com"</span>, <span class="hljs-string">"bob8"</span>, <span class="hljs-string">"bobbinson8"</span>, <span class="hljs-string">"1980-01-01"</span>),
(<span class="hljs-string">"foo9"</span>, <span class="hljs-string">"asdsad9"</span>, <span class="hljs-string">"test9@gmail.com"</span>, <span class="hljs-string">"bob9"</span>, <span class="hljs-string">"bobbinson9"</span>, <span class="hljs-string">"1980-01-01"</span>),
(<span class="hljs-string">"foo10"</span>, <span class="hljs-string">"asdsad10"</span>, <span class="hljs-string">"test10@gmail.com"</span>, <span class="hljs-string">"bob10"</span>, <span class="hljs-string">"bobbinson10"</span>, <span class="hljs-string">"1970-01-01"</span>);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> tweets(user_id, tweet, date_tweet) <span class="hljs-keyword">VALUES</span>
(<span class="hljs-number">1</span>, <span class="hljs-string">"test tweet"</span>, <span class="hljs-string">"2001-01-01 22:00:00"</span>),
(<span class="hljs-number">2</span>, <span class="hljs-string">"test tweet2"</span>, <span class="hljs-string">"2002-01-01 22:00:00"</span>),
(<span class="hljs-number">3</span>, <span class="hljs-string">"test tweet3"</span>, <span class="hljs-string">"2003-01-01 22:00:00"</span>),
(<span class="hljs-number">4</span>, <span class="hljs-string">"test tweet4"</span>, <span class="hljs-string">"2004-01-01 22:00:00"</span>),
(<span class="hljs-number">5</span>, <span class="hljs-string">"test tweet5"</span>, <span class="hljs-string">"2005-01-01 22:00:00"</span>);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> followers(id_user, id_follower) <span class="hljs-keyword">VALUES</span>
(<span class="hljs-number">5</span>,<span class="hljs-number">1</span>),
(<span class="hljs-number">4</span>,<span class="hljs-number">1</span>),
(<span class="hljs-number">3</span>,<span class="hljs-number">1</span>),
(<span class="hljs-number">2</span>,<span class="hljs-number">1</span>),
(<span class="hljs-number">6</span>,<span class="hljs-number">1</span>),
(<span class="hljs-number">2</span>,<span class="hljs-number">5</span>),
(<span class="hljs-number">4</span>,<span class="hljs-number">5</span>);
</code></pre><p>The other files are examples of queries that we will be using later.</p>
<h2 id="heading-project-architecture">Project Architecture</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656546490437/vnWxBjlbq.png" alt="image.png" /></p>
<p>If you are familiar with building software this should be familiar if not, first let me tell you what's missing and afterwards we will go through every folder.</p>
<p>The project is missing folders like config, middleware, logger and testing. And if you would organize the controller better you'd have a routes folder where you organize the API better.</p>
<h2 id="heading-quick-note-on-imports">Quick note on imports</h2>
<p>In this project you might get confused by imports such as:</p>
<pre><code><span class="hljs-keyword">import</span> (
    <span class="hljs-string">"goexample/database"</span>
    <span class="hljs-string">"goexample/models"</span>
    <span class="hljs-string">"goexample/services/utils"</span>
)
</code></pre><p>The goexample here is the name of the project, I just renamed my repo afterwards so it would make sense, so instead of having "mini-twitter-clone/database" we use "goexample/database" to import the database package.<br />With any other new projects just use the name of the folder.</p>
<h2 id="heading-api">API</h2>
<p>You store your endpoints/routes in controller.go:</p>
<pre><code>package api

<span class="hljs-keyword">import</span> (
    "goexample/services"

    "github.com/gofiber/fiber/v2"
)

func SetupRoutes(app *fiber.App) {

    api := app.<span class="hljs-keyword">Group</span>("/api")

    //<span class="hljs-keyword">get</span> <span class="hljs-keyword">all</span> unordened users
    api.<span class="hljs-keyword">Get</span>("/users", services.GetUsers)
    //<span class="hljs-keyword">get</span> <span class="hljs-keyword">all</span> users ordered <span class="hljs-keyword">by</span> age <span class="hljs-keyword">ASC</span>
    api.<span class="hljs-keyword">Get</span>("/users/age", services.GetUsersByAgeAsc)

    //<span class="hljs-keyword">get</span> <span class="hljs-keyword">all</span> unordened tweets <span class="hljs-keyword">from</span> db
    api.<span class="hljs-keyword">Get</span>("/tweets", services.GetTweets)

    //http://localhost:<span class="hljs-number">3000</span>/api/feed/<span class="hljs-number">1</span>
    //<span class="hljs-keyword">get</span> MOST RECENT feed/timeline <span class="hljs-keyword">for</span> the <span class="hljs-keyword">user</span>
    api.<span class="hljs-keyword">Get</span>("/feed/:id", services.GetFeedTweets)
    //pagination
    api.<span class="hljs-keyword">Get</span>("/feed/:id/:limit/:offset", services.GetFeedTweetsPaginated)
    //can try https://github.com/gofiber/fiber/issues/<span class="hljs-number">193</span>#issuecomment<span class="hljs-number">-591976894</span>
    //a whole presentation <span class="hljs-keyword">on</span> why you shouldn<span class="hljs-string">'t do what I did:
    //https://use-the-index-luke.com/no-offset

}</span>
</code></pre><p>I'm using the Fiber library, which is similar to Express, here we have several endpoints that we call with a Get request and once the server gets a request its response is to call the functions that I have exposed from the services package - that's where our business logic is.</p>
<p><strong>NB: pagination isn't properly implemented.</strong>  </p>
<p>This is just a quick example, this endpoint has security issues just like others but you should understand how the library and Golang works through the example.</p>
<p>Note that in the /feed/:id the id parameter pertains to the user we want to get the feed for.</p>
<h3 id="heading-start-the-project">Start the project</h3>
<p>You can start the project by doing
<code>go run .</code>
inside the folder.<br />Your terminal should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547397790/zr2MQc7eU.png" alt="image.png" /></p>
<p>Let's visit the different endpoints to see the responses, I'm going to use a normal browse but you should check <a target="_blank" href="https://www.postman.com/">Postman</a> if you are not familiar with debugging the backend.</p>
<p>Let's run the endpoints from the controller:</p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//127.0.0.1:3000/api/users</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547627951/SNvlI9-Od.png" alt="image.png" /></p>
<p>I left a lot of prints so if you check your terminal with every call you should see stuff like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547694916/a4iv6o79v.png" alt="image.png" /></p>
<p>Next is a call where we order users by age:</p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//127.0.0.1:3000/api/users/age</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547733559/lBoD6UZ0O.png" alt="image.png" /></p>
<p>When we ask for tweets we get all of them:</p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//127.0.0.1:3000/api/tweets</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547797655/74sC-x3oC.png" alt="image.png" /></p>
<p>And now we get the feed or timeline for the user with the id 1:</p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//127.0.0.1:3000/api/feed/1</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547879923/-3pmsWt0p.png" alt="image.png" /></p>
<p>Remember that pagination isn't production ready but the core concepts are the same:</p>
<pre><code><span class="hljs-attribute">http</span>://<span class="hljs-number">127.0.0.1:3000</span>/api/feed/<span class="hljs-number">1</span>/<span class="hljs-number">2</span>/<span class="hljs-number">1</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656547958522/a8KyOayEB.png" alt="image.png" /></p>
<p>All the calls work thanks to the business logic we have in the services package and the functions we have exposed.</p>
<h2 id="heading-services">Services</h2>
<p>Inside the services package we have the functions that are called when someone or something hits one of the endpoints. Remember that we expose the functions by using a capital letter in the package.</p>
<p>Let's look at timeline_tweets.go which contains two functions for two different endpoints in the controller.go file:</p>
<pre><code>
package services

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"goexample/database"</span>
    <span class="hljs-string">"goexample/models"</span>
    <span class="hljs-string">"goexample/services/utils"</span>
    <span class="hljs-string">"log"</span>

    <span class="hljs-string">"github.com/gofiber/fiber/v2"</span>
)

<span class="hljs-title">func</span> <span class="hljs-title">GetFeedTweets</span>(<span class="hljs-title">c</span> <span class="hljs-operator">*</span><span class="hljs-title">fiber</span>.<span class="hljs-title">Ctx</span>) <span class="hljs-title"><span class="hljs-keyword">error</span></span> {

    <span class="hljs-comment">//you shouldn't do this by the way, but it's just a demo</span>
    <span class="hljs-comment">// dbQuery := fmt.Sprintf("SELECT users.user_id, users.user, users.first_name, users.last_name, tweets.tweet, tweets.date_tweet FROM users INNER JOIN tweets ON users.user_id = tweets.user_id INNER JOIN followers ON users.user_id = followers.id_user WHERE followers.id_follower = %s ORDER BY tweets.date_tweet DESC;", c.Params("id"))</span>
    <span class="hljs-comment">// rows, err := database.DB.Query(dbQuery)</span>

    <span class="hljs-comment">//avoid the SQL injection by rewriting it like</span>
    <span class="hljs-title">dbQuery</span> :<span class="hljs-operator">=</span> <span class="hljs-string">"SELECT users.user_id, users.user, users.first_name, users.last_name, tweets.tweet, tweets.date_tweet FROM users INNER JOIN tweets ON users.user_id = tweets.user_id INNER JOIN followers ON users.user_id = followers.id_user WHERE followers.id_follower = ? ORDER BY tweets.date_tweet DESC;"</span>
    <span class="hljs-title">rows</span>, <span class="hljs-title">err</span> :<span class="hljs-operator">=</span> <span class="hljs-title">database</span>.<span class="hljs-title">DB</span>.<span class="hljs-title">Query</span>(<span class="hljs-title">dbQuery</span>, <span class="hljs-title">c</span>.<span class="hljs-title">Params</span>(<span class="hljs-string">"id"</span>))

    <span class="hljs-comment">//check for errors</span>
    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-title">nil</span> {
        <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">utils</span>.<span class="hljs-title">DefaultErrorHandler</span>(<span class="hljs-title">c</span>, <span class="hljs-title">err</span>)
    }
    <span class="hljs-comment">//close db connection</span>
    <span class="hljs-title">defer</span> <span class="hljs-title">rows</span>.<span class="hljs-title">Close</span>()

    <span class="hljs-comment">//create a slice of tweets</span>
    <span class="hljs-title"><span class="hljs-keyword">var</span></span> <span class="hljs-title">timelineTweets</span> []<span class="hljs-title">models</span>.<span class="hljs-title">TimelineTweet</span>
    <span class="hljs-comment">//loop through the result set</span>
    <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">rows</span>.<span class="hljs-title">Next</span>() {
        <span class="hljs-title">timelineTweet</span> :<span class="hljs-operator">=</span> <span class="hljs-title">models</span>.<span class="hljs-title">TimelineTweet</span>{}
        <span class="hljs-title">err</span> :<span class="hljs-operator">=</span> <span class="hljs-title">rows</span>.<span class="hljs-title">Scan</span>(<span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">User_id</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">User</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">First_name</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">Last_name</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">Tweet</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">Date_tweet</span>)
        <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-title">nil</span> {
            <span class="hljs-title">log</span>.<span class="hljs-title">Fatal</span>(<span class="hljs-title">err</span>)
        }
        <span class="hljs-title">timelineTweets</span> <span class="hljs-operator">=</span> <span class="hljs-title">append</span>(<span class="hljs-title">timelineTweets</span>, <span class="hljs-title">timelineTweet</span>)
    }
    <span class="hljs-title">fmt</span>.<span class="hljs-title">Print</span>(<span class="hljs-title">timelineTweets</span>)

    <span class="hljs-title">utils</span>.<span class="hljs-title">ResponseHelperJSON</span>(<span class="hljs-title">c</span>, <span class="hljs-title">timelineTweets</span>, <span class="hljs-string">"timeline"</span>, <span class="hljs-string">"No timeline found"</span>)

    <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">err</span>
}

<span class="hljs-title">func</span> <span class="hljs-title">GetFeedTweetsPaginated</span>(<span class="hljs-title">c</span> <span class="hljs-operator">*</span><span class="hljs-title">fiber</span>.<span class="hljs-title">Ctx</span>) <span class="hljs-title"><span class="hljs-keyword">error</span></span> {

    <span class="hljs-comment">// dbQuery := fmt.Sprintf("SELECT users.user_id, users.user, users.first_name, users.last_name, tweets.tweet, tweets.date_tweet FROM users INNER JOIN tweets ON users.user_id = tweets.user_id INNER JOIN followers ON users.user_id = followers.id_user WHERE followers.id_follower = %s ORDER BY tweets.date_tweet DESC LIMIT %s OFFSET %s;", c.Params("id"), c.Params("limit"), c.Params("offset"))</span>
    <span class="hljs-comment">// avoid a SQL injection by rewriting it like</span>
    <span class="hljs-title">dbQuery</span> :<span class="hljs-operator">=</span> <span class="hljs-string">"SELECT users.user_id, users.user, users.first_name, users.last_name, tweets.tweet, tweets.date_tweet FROM users INNER JOIN tweets ON users.user_id = tweets.user_id INNER JOIN followers ON users.user_id = followers.id_user WHERE followers.id_follower = ? ORDER BY tweets.date_tweet DESC LIMIT ? OFFSET ?;"</span>

    <span class="hljs-title">rows</span>, <span class="hljs-title">err</span> :<span class="hljs-operator">=</span> <span class="hljs-title">database</span>.<span class="hljs-title">DB</span>.<span class="hljs-title">Query</span>(<span class="hljs-title">dbQuery</span>, <span class="hljs-title">c</span>.<span class="hljs-title">Params</span>(<span class="hljs-string">"id"</span>), <span class="hljs-title">c</span>.<span class="hljs-title">Params</span>(<span class="hljs-string">"limit"</span>), <span class="hljs-title">c</span>.<span class="hljs-title">Params</span>(<span class="hljs-string">"offset"</span>))
    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-title">nil</span> {
        <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">utils</span>.<span class="hljs-title">DefaultErrorHandler</span>(<span class="hljs-title">c</span>, <span class="hljs-title">err</span>)
    }

    <span class="hljs-title">defer</span> <span class="hljs-title">rows</span>.<span class="hljs-title">Close</span>()

    <span class="hljs-title"><span class="hljs-keyword">var</span></span> <span class="hljs-title">timelineTweets</span> []<span class="hljs-title">models</span>.<span class="hljs-title">TimelineTweet</span>
    <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">rows</span>.<span class="hljs-title">Next</span>() {
        <span class="hljs-title">timelineTweet</span> :<span class="hljs-operator">=</span> <span class="hljs-title">models</span>.<span class="hljs-title">TimelineTweet</span>{}
        <span class="hljs-title">err</span> :<span class="hljs-operator">=</span> <span class="hljs-title">rows</span>.<span class="hljs-title">Scan</span>(<span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">User_id</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">User</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">First_name</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">Last_name</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">Tweet</span>, <span class="hljs-operator">&amp;</span><span class="hljs-title">timelineTweet</span>.<span class="hljs-title">Date_tweet</span>)
        <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-title">nil</span> {
            <span class="hljs-title">log</span>.<span class="hljs-title">Fatal</span>(<span class="hljs-title">err</span>)
        }
        <span class="hljs-title">timelineTweets</span> <span class="hljs-operator">=</span> <span class="hljs-title">append</span>(<span class="hljs-title">timelineTweets</span>, <span class="hljs-title">timelineTweet</span>)
    }
    <span class="hljs-comment">//<span class="hljs-doctag">TODO:</span> implement a response with pages and all that pagination jazz</span>
    <span class="hljs-title">utils</span>.<span class="hljs-title">ResponseHelperJSON</span>(<span class="hljs-title">c</span>, <span class="hljs-title">timelineTweets</span>, <span class="hljs-string">"timeline"</span>, <span class="hljs-string">"No timeline found"</span>)

    <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">err</span>
}
</code></pre><p>The first that you can notice is how we pass the context to GetFeedTweets and afterwards we use the variable 'c' to use that context as the <a target="_blank" href="https://docs.gofiber.io/api/ctx">Fiber library says</a>.</p>
<p>Afterwards we use the exposed variable DB from the package database to open the DB, read the data and close it afterwards.</p>
<p>In order to store and scan the data properly we use a struct from our models package.</p>
<p>Afterwards you will see several functions from the utils package. Those functions are mainly helpers so you can check out how Golang does loops and certain other things.</p>
<p>The two other files inside our services package are very similar, our work here is get the data from the database, scan it through our array of structs and send it back to the user in JSON format. As well as we run some functions from the utils package.</p>
<h3 id="heading-utils">Utils</h3>
<p>This package contains helper functions, perhaps the most interesting being inside user_helper as it has functions that interact with data from slices, <strong>however be careful</strong>, they are not as well implemented as you might think.</p>
<p>Let's look at the most helpful one, response_helper.go:</p>
<pre><code>package utils

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"github.com/gofiber/fiber/v2"</span>
)

<span class="hljs-comment">//response JSON for services after you loop and scan</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ResponseHelperJSON</span><span class="hljs-params">(<span class="hljs-built_in">c</span> *fiber.Ctx, data any, dataType string, dataError string)</span></span> {
    <span class="hljs-keyword">if</span> data != <span class="hljs-literal">nil</span> {
        <span class="hljs-built_in">c</span>.<span class="hljs-type">Status</span>(<span class="hljs-number">200</span>).<span class="hljs-type">JSON</span>(&amp;fiber.<span class="hljs-type">Map</span>{
            <span class="hljs-string">"success"</span>: <span class="hljs-literal">true</span>,
            dataType:  data,
        })
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">c</span>.<span class="hljs-type">Status</span>(<span class="hljs-number">404</span>).<span class="hljs-type">JSON</span>(&amp;fiber.<span class="hljs-type">Map</span>{
            <span class="hljs-string">"success"</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-string">"error"</span>:   dataError,
        })
    }
}
</code></pre><p>Note that this functions contains a generic type of data as I'm using the keyword any and I'm interacting with the context given from Fiber through the variable 'c'.</p>
<h2 id="heading-models">Models</h2>
<p>The models folder contains the different structs we use as entities to interact with our database as shown in the services folder.</p>
<p>Here's an example, note that even that if you want to expose the entire struct everything has to start with capital letter:</p>
<pre><code>package models

<span class="hljs-keyword">type</span> UserWithAge struct{
    Id         <span class="hljs-type">int</span>   `<span class="hljs-type">json</span>:"id"`
    <span class="hljs-keyword">User</span>       string `<span class="hljs-type">json</span>:"user"`
    Passhash   string `<span class="hljs-type">json</span>:"passhash"`
    Email      string `<span class="hljs-type">json</span>:"email"`
    First_name string `<span class="hljs-type">json</span>:"first_name"`
    Last_name  string `<span class="hljs-type">json</span>:"last_name"`
    Age        <span class="hljs-type">int</span>    `<span class="hljs-type">json</span>:"age"`
}
</code></pre><h2 id="heading-database">Database</h2>
<p>The database package is very straightforward and remember to use a config file and an .env to store your sensitive data.</p>
<pre><code>package database

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"database/sql"</span>
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"log"</span>
)

<span class="hljs-title"><span class="hljs-keyword">var</span></span> <span class="hljs-title">DB</span> <span class="hljs-operator">*</span><span class="hljs-title">sql</span>.<span class="hljs-title">DB</span>

<span class="hljs-title">func</span> <span class="hljs-title">Connect</span>() <span class="hljs-title"><span class="hljs-keyword">error</span></span>{
    <span class="hljs-title"><span class="hljs-keyword">var</span></span> <span class="hljs-title">err</span> <span class="hljs-title"><span class="hljs-keyword">error</span></span>
    <span class="hljs-comment">//use a config file for this</span>
    <span class="hljs-title">DB</span>, <span class="hljs-title">err</span> <span class="hljs-operator">=</span> <span class="hljs-title">sql</span>.<span class="hljs-title">Open</span>(<span class="hljs-string">"mysql"</span>, <span class="hljs-string">"root:password@tcp(127.0.0.1:3306)/twitterdb"</span>)

    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-title">nil</span> {
        <span class="hljs-title">log</span>.<span class="hljs-title">Fatal</span>(<span class="hljs-title">err</span>)
        <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">err</span>
    }

    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> <span class="hljs-operator">=</span> <span class="hljs-title">DB</span>.<span class="hljs-title">Ping</span>(); err <span class="hljs-operator">!</span><span class="hljs-operator">=</span> nil {
        log.Fatal(err)
        <span class="hljs-keyword">return</span> err
    }

    fmt.Println(<span class="hljs-string">"Connected to database"</span>)

    <span class="hljs-keyword">return</span> nil

}
</code></pre><h2 id="heading-maingo">Main.go</h2>
<p>Finally, this is where we start our server:</p>
<pre><code>package main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"github.com/gofiber/fiber/v2"</span>
    <span class="hljs-string">"goexample/database"</span>
    <span class="hljs-string">"log"</span>

    <span class="hljs-string">"goexample/api"</span>

    <span class="hljs-title"><span class="hljs-keyword">_</span></span> <span class="hljs-string">"github.com/go-sql-driver/mysql"</span>
)

<span class="hljs-title">func</span> <span class="hljs-title">main</span>() {

    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">err</span> :<span class="hljs-operator">=</span> <span class="hljs-title">database</span>.<span class="hljs-title">Connect</span>(); err <span class="hljs-operator">!</span><span class="hljs-operator">=</span> nil {
        log.Fatal(err)
    }

    app :<span class="hljs-operator">=</span> fiber.New()
    api.SetupRoutes(app)


    log.Fatal(app.Listen(<span class="hljs-string">":3000"</span>))

}
</code></pre><h1 id="heading-bonus-ukrainian-meme">Bonus Ukrainian meme</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656553993404/_Qbqn3-5h.png" alt="image.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Software Engineering OOP principles and good practices to avoid spaghetti code]]></title><description><![CDATA[Introduction
This post goes through basic concepts that every developer should know or at least be familiar with in some way or the other, it's an entry point to good practices. Most people already do all this without thinking, perhaps the post will ...]]></description><link>https://bognov.tech/software-engineering-oop-principles-and-good-practices-to-avoid-spaghetti-code</link><guid isPermaLink="true">https://bognov.tech/software-engineering-oop-principles-and-good-practices-to-avoid-spaghetti-code</guid><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Wed, 27 Apr 2022 22:56:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651099049711/eipRjJkiX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>This post goes through basic concepts that every developer should know or at least be familiar with in some way or the other, it's an entry point to good practices. Most people already do all this without thinking, perhaps the post will just server to illustrate certain actions or thoughts.<br />However and as we all know there's never a clear answer when it comes to software engineering, it boils down to two magical words: "<strong><em>it depends</em></strong>".  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651099831914/UFv3yDAKk.png" alt="image.png" /></p>
<p>Feel free to correct me or provide feedback, you can find me on twitter <a target="_blank" href="https://twitter.com/tekbog">@tekbog</a></p>
<h1 id="heading-oop-what-a-beauty">OOP: what a beauty</h1>
<p>You look outside and it's a beautiful day, you definitely can miss this weather so you decide to stay home and code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650998301658/Hsee4A5Yd.png" alt="image.png" /></p>
<p>After making a beautiful hello world program you feel good and empowered to try something more advanced, and you wonder, how should you organize or even where to start. So you ask the kind souls at StackOverflow, at which some reply and mention OOP before your thread gets deleted because code monkeys decide to fight over <a target="_blank" href="https://en.wikipedia.org/wiki/Object-oriented_programming">Objected Oriented Programming</a> VS <a target="_blank" href="https://en.wikipedia.org/wiki/Functional_programming">Functional Programming</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650998523457/V28XVyM-8.png" alt="image.png" /></p>
<p>So you start looking at OOP and it makes a lot of sense! You have everything organized in objects that call other objects and are related to one another. It seems secure and it can be as complex as you wish, yet simple to understand. What a concept!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650998795101/Vv4m1h94Q.png" alt="image.png" /></p>
<p><strong>BUT YOU ARE WRONG</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650998816705/5kmsw0c7m.png" alt="image.png" /></p>
<p>However with good practices and proper object modeling we can avoid having such a mess.</p>
<h2 id="heading-concepts">Concepts</h2>
<p>Objects are made through classes, what does this mean? 
Classes are blueprints for whatever you want to make. You use that blueprint to create (or instantiate) the object that will run in memory.
The initialised object will have:</p>
<ul>
<li><strong>state </strong>(characteristics)</li>
<li><strong>behaviour </strong>(what can it do or what can it be done to it)</li>
</ul>
<p><em>NB: in languages like C++ you need to take care of the memory usage, however a lot of languages have garbage collection implemented nowadays so you don't have to worry about when your objects disappear from memory.</em></p>
<p>So, to make things clearer, you have a design called <em>class</em> then you use that design to create a new object of that class with which you will be able to interact and use. The interactions are defined (just like instructions) inside the class through state and behaviour. The class defines what you can do with the object and how other objects will be able to interact with said object once it's created.</p>
<p>Both the state and behaviour are modified through:</p>
<ul>
<li>attributes: parameters that define the <strong>state </strong>of the object</li>
<li>methods: functions that define the <strong>behaviour </strong>of the object</li>
</ul>
<p>The strengths of OOP are as follow</p>
<h3 id="heading-encapsulation">Encapsulation</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651000234646/8wHpPieAb.png" alt="image.png" />
You want to have the data/variables and its behaviour closed in one single unit. Inside you define its behaviour through functions (methods) that you can make public or private to keep the object as hidden and pure as possible.</p>
<h3 id="heading-abstraction">Abstraction</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651002103813/pVGWYqL0v.png" alt="image.png" /></p>
<p>External agents don't need to know what's going on inside a specific object, they just need to know how to use it if needed. With abstraction you hide the internal implementation.<br />To explain the concept for example take a random controller, you need to know HOW it works but you don't need to know WHY it works.</p>
<p>If this sounds too similar to encapsulation you can think of it as: abstraction is the theory while encapsulation is the implementation.<br />Additionally you can read this <a target="_blank" href="https://www.guru99.com/java-data-abstraction.html">article</a>. The picture is from <a target="_blank" href="https://github.com/shiddiqeuy/Java-Abstraction">this</a> repo.</p>
<h3 id="heading-inheritance">Inheritance</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651002795834/9c7Orim4J.png" alt="image.png" />
or something a bit more complex
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651004691640/k4UQjh6qw.png" alt="image.png" /></p>
<p>Inheritance provides security and a cleaner -more defined- architecture by basing one object on another, either through inheritance or sub-classes. To use inheritance you can either define an interface and then <em>implement</em> it on a new object or you can use an existing class and <em>extend</em> it to make a sub-class, with the original class called a super-class.<br />You have <strong>interfaces</strong>, <strong>classes </strong>and then there's something in between called <strong>abstract classes</strong> which are just like ordinary classes but unfinished so you can't instantiate them but you can extend them and finish building them.</p>
<h3 id="heading-polymorphism">Polymorphism</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651004887669/Cd-mvp32P.png" alt="image.png" /><br />Poly stands for many;<br />Morph stands for form.<br />The main concept of polymorphism is the ability to have many forms.<br />For example an interface can have many implementations. In order to apply polymorphism you just need a core to pull from and <em>morph </em>the original object with many <em>(poly)</em> changes.</p>
<h4 id="heading-polymorphism-vs-inheritance">Polymorphism vs Inheritance</h4>
<p>Things get a bit confusing with polymorphism and inheritance but think about how a class can <em>inherit</em> properties from a superclass while an interface can be <em>implemented</em> in many different ways making itself polymorphic. Henceforth classes work mostly through inheritance while interfaces work through polymorphism and inheritance.  </p>
<h4 id="heading-method-overriding">Method Overriding</h4>
<p>Also known as <a target="_blank" href="https://www.javatpoint.com/method-overriding-in-java">Dynamic Polymorphism</a> and Run Time Polymorphism.<br />It consists of allowing the subclass to change (override) the method (function) of the superclass. If you have a super class with the method (function) that says run and prints 'superclass runs' you can change the same method in the subclass to print 'subclass runs'.</p>
<h4 id="heading-method-overloading">Method Overloading</h4>
<p>Also known as Static Polymorphism and Compile Time Polymorphism.<br />You define two different methods that are called the same but behave differently with different parameters and at compile time the program decides which method to use.  </p>
<p><a target="_blank" href="https://stackoverflow.com/questions/20783266/what-is-the-difference-between-dynamic-and-static-polymorphism-in-java">Here's a StackOverflow answer</a> that goes into both method overriding and overloading with a code example.</p>
<h4 id="heading-duck-typing">Duck Typing</h4>
<p>The principle of <a target="_blank" href="https://en.wikipedia.org/wiki/Duck_typing">duck typing</a> is related to method overloading and compile-time polymorphism, although mostly known and used in Python.<br />The saying goes as "if it walks like a duck and quacks like a duck.. it is a duck". We can apply this logic to our objects, we don't care what they are per se but we care what they do and how their functions work. Therefore you can overload a function (through polymorphism) to do whatever you want, so in this scenario if you have a bird object that does everything a duck is capable of then you call that object a duck.  </p>
<p>However in languages like Java or C# duck typing doesn't work as we are usually very concerned as to what type of objects we are working with.</p>
<h2 id="heading-inheritance-relationships">Inheritance Relationships</h2>
<p>There are two key relationships in OOP:</p>
<ul>
<li>IS A  </li>
</ul>
<p>IS-A stands for "the object I'm referring to IS An object of another type I'm extending from" in this case if we have a subclass Dog that extends from the Animal class the relationship would be: Dog class IS-A Animal class.<br />This example is based on classes but you could also have an interface called Animal and a class called Dog that implements it, also a IS-A relationship.  </p>
<ul>
<li>HAS A  </li>
</ul>
<p>This relationship is more about usage, it means that an object is using another object without a need to extend or implement it.<br />For example our Dog object could have a Toy object and interact with it. Here Dog HAS-A relationship with Toy.</p>
<h2 id="heading-solid-principles">SOLID Principles</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651013529614/ITv55-W3f.png" alt="image.png" />
Those were dark times, the dot-com bubble made developers aggressive and savage, nobody followed any rules and the bugs reigned untouchable as software engineers were fighting amongst themselves, blaming each other and not writing tests. 
In order to stop this violence and establish the order back in the workplace a prophet called Robert C. Martin came with 5 <em>solid</em> principles to put an end to this madness of developers fighting each other due to unreadable and unmaintainable code.  </p>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/SOLID">SOLID</a> principles are five main ideas to make your code understandable, flexible and maintainable.</p>
<h3 id="heading-single-responsibility-principle">Single-responsibility principle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651013591529/YNce1noDQ.png" alt="image.png" />
<a target="_blank" href="https://en.wikipedia.org/wiki/Single-responsibility_principle">SRP</a> is summed up nicely in: "every class/function/module should have only one responsibility and encapsulate that part". And so microservices were born!<br />To put an example, if you have a class or a function that has many inputs, conditionals and it's fairly long you probably need to <a target="_blank" href="https://refactoring.guru/extract-method">refactor</a> that ASAP. </p>
<h3 id="heading-openclosed-principle">Open–closed principle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651014094525/_SOIpSoTl.png" alt="image.png" /></p>
<blockquote>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle">Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification</a>  </p>
</blockquote>
<p>This means that you should be able to always extend a class with new functionality without having to change how it works. It's a key to maintainable code and it's easily achievable with interfaces, you can keep expanding it without the need to change the original interface.</p>
<h3 id="heading-liskov-substitution-principle">Liskov substitution principle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651015570749/FIWjAGyHJ.png" alt="image.png" />
<a target="_blank" href="https://en.wikipedia.org/wiki/Liskov_substitution_principle">LSP</a> is a bit confusing but basically the Liskov principle says that the subclass should be substitutable for the superclass. This will prevent you from making the wrong decisions when it comes to inheritance and polymorphism, it's easy to extend a class but make sure it's the correct order and implementation.</p>
<p>It's much easier to understand through code, check <a target="_blank" href="https://stackoverflow.com/a/44913313/14356309">this answer from StackOverflow</a>. </p>
<h3 id="heading-interface-segregation-principle">Interface segregation principle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651020791150/gQ7bkqNdD.png" alt="image.png" /></p>
<blockquote>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Interface_segregation_principle">ISP</a> is intended to keep a system decoupled and thus easier to refactor, change, and redeploy. No code should be forced to depend on methods it does not use.  </p>
</blockquote>
<p>ISP wants you to split the large interfaces and keep it simple, stupid (KISS). The official definition is as follows:  </p>
<blockquote>
<p>Clients should not be forced to depend upon interfaces that they do not use.  </p>
</blockquote>
<p>You don't want a bloated interface that has methods for multiple responsibilities. Split it.</p>
<h3 id="heading-dependency-inversion-principle">Dependency inversion principle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651021226948/5osvHcc5n.png" alt="image.png" /><br /><a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">DIP</a> is summed as follows: </p>
<ul>
<li>High-level modules should not import anything from low-level modules. Both should depend on abstractions (e.g., interfaces).  </li>
<li>Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.  </li>
</ul>
<p>It might sound simple but people tend to overlook this principle, however by following the open-closed principle and LSP you will be able to achieve the level of abstraction needed to separate both low and high level components so they never depend on each other.<br />If your components are designed to be closed for modification but open for extension (open/closed principle) and you can replace with your implementations your interface (LSP) then you are following DIP. Separate the concern for design through layers of abstraction.</p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/">FreeCodeCamp</a> has a nice definition while talking about Dependency Injection (which is a way to follow the dependency inversion principle):  </p>
<blockquote>
<p>According to the principles, a class should concentrate on fulfilling its responsibilities and not on creating objects that it requires to fulfill those responsibilities.</p>
</blockquote>
<h2 id="heading-association-composition-and-aggregation">Association: Composition and Aggregation</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651024288439/rDo2FJ0ys.png" alt="image.png" />
Both composition and aggregation are part of <a target="_blank" href="https://www.guru99.com/association-aggregation-composition-difference.html#uml-composition">association, here are some UML diagrams</a>, which is a way of saying two objects are related (by association). However composition and aggregation <a target="_blank" href="https://stackoverflow.com/a/31600062/14356309">differ</a>.  </p>
<p><strong>Composition</strong> is when a sum of parts build the object, so you need each other, following a two-way association. If you get rid of the composition its parts get deleted.<br /><a target="_blank" href="https://www.ibm.com/docs/en/rsm/7.5.0?topic=diagrams-composition-association-relationships">IBM</a> offers a nice explanation:</p>
<blockquote>
<p>A composition association relationship specifies that the lifetime of the part classifier is dependent on the lifetime of the whole classifier.</p>
</blockquote>
<p><strong>Aggregation</strong> is a more lax composition where objects don't depend on each other for the aggregation to exist. You can have two different objects that work together to build an aggregation but if the aggregation disappears the objects remain, as they are fully separate entities.<br /><a target="_blank" href="https://www.guru99.com/association-aggregation-composition-difference.html#uml-association">99guru</a> defines the aggregation relationship really well:</p>
<blockquote>
<p>an object of one class can own or access the objects of another class.  </p>
</blockquote>
<p>People tend to mix a bit the terms, more than often you will hear composition but in reality they are talking about aggregation. So just keep in mind when someone mentions composition they might be talking about a lax composition, meaning aggregation. Sometimes it doesn't matter but it might be relevant if you are designing complex systems.</p>
<h3 id="heading-composition-over-inheritance">Composition over Inheritance</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651088946747/KUeorTosv.png" alt="image.png" /></p>
<p>If our code base deviates from the SOLID principles (or any other reason) instead of having a tightly coupled structure based on inheritance you might want to use composition instead.<br />Composition is usually just a way of saying that classes might use other classes to build complex interactions instead of relying as heavily on inheritance, this leads to HAS-A relationships (or PART-OF). The term is loosely used and sometimes people confuse aggregation with composition. When someone is talking about <a target="_blank" href="https://en.wikipedia.org/wiki/Composition_over_inheritance">composition over inheritance</a> they can mean composition or aggregation, either way what they want to achieve is:</p>
<ul>
<li>Stronger encapsulation: inheritance needs a link with its subclasses which might weaken encapsulation.  </li>
<li>Easier testing: if you have separate objects without inheritance you can access and test them easier as they are fully separate units.</li>
<li>Better refactoring: swapping things around is easier when you don't have a whole family of objects depending on it. By adding interfaces and making different classes work with each other you add flexibility which is almost always good.  </li>
</ul>
<p>It's especially strong if you bring <a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> into the matter, which is a form of <a target="_blank" href="https://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a>.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651086764148/UMbkt1fj3.png" alt="image.png" /></p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/">FreeCodeCamp</a> has a nice little tutorial about DI.</p>
<h2 id="heading-replace-conditional-with-polymorphism">Replace Conditional with Polymorphism</h2>
<p>Another benefit and strong point for OOP is how you can use Polymorphism to replace Conditionals. For example if you have a class with a lot of if-else or switch statements you can refactor it with classes through polymorphism. Afterwards just use whatever class you need.<br /><a target="_blank" href="https://refactoring.guru/replace-conditional-with-polymorphism">Refactor Guru</a> offers a nice example.</p>
<h1 id="heading-engineering-principles">Engineering Principles</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651089346425/9oj2cbqoY.png" alt="image.png" />
Once again <a target="_blank" href="https://xkcd.com/">xkcd</a> points out our reality, however by applying certain principles we can get a bit better at organizing the pattern of lights.</p>
<h2 id="heading-measure-twice-and-cut-once">Measure twice and cut once</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651090260129/JjfU7Q47Z.png" alt="image.png" />
The point here is to think ahead. This depends entirely on what you are doing, for example if you are planning to make a platform but don't know how the schema database is going to look then use NOSQL over SQL.</p>
<h2 id="heading-dont-repeat-yourself-dry">Don’t Repeat Yourself (DRY)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651090568672/o8JivO_CQ.png" alt="image.png" />
<a target="_blank" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"><strong>DRY</strong></a> is a key to be a good programmer. A good way to know when you are repeating yourself is to adhere to the <a target="_blank" href="https://dev.to/jpswade/rule-of-three-1b9d">Rule of Three</a>. If you are using the same code three times you need to refactor!</p>
<h2 id="heading-keep-it-simple-stupid-kiss">Keep It Simple Stupid (KISS)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651092097664/f85NGw3P7.png" alt="image.png" /></p>
<p>Software engineers have a lot of tools at our disposal which makes us incredible prone to over-engineer everything instead of following <a target="_blank" href="https://en.wikipedia.org/wiki/KISS_principle"><strong>KISS</strong></a>. Keep things simple and avoid complexity, just make sure you can extend your code when you need to.  </p>
<p><a target="_blank" href="https://youtu.be/y8OnoxKotPQ">This video about microservices from KRAZAM</a> sums it up or take a look at <a target="_blank" href="https://youtu.be/Sxxw3qtb3_g">the one from fireship</a> if you are familiar with web development. Although over-engineering also apply to YAGNI rule.</p>
<h2 id="heading-you-arent-gonna-need-it-yagni">You Aren’t Gonna Need It (YAGNI)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651093121322/3DjVfkutR.png" alt="image.png" />
<a target="_blank" href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it">YAGNI</a> is about focusing on the problem at hand while (just like KISS) minimizing complexity. Focus on keeping things simple yet open to added complexity later on, use the open/closed principle.</p>
<h2 id="heading-avoid-premature-optimization">Avoid Premature Optimization</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651093491446/bx2-Wc7YT.png" alt="image.png" /></p>
<blockquote>
<p><a target="_blank" href="https://wiki.c2.com/?PrematureOptimization">premature optimization is the root of all evil</a>  </p>
</blockquote>
<p>While we need to keep in mind optimization to avoid performance issues most likely you don't have to optimize that function and make it less readable.</p>
<h2 id="heading-principle-of-least-astonishment">Principle Of Least Astonishment</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651093754834/qcVPUa1Bu.png" alt="image.png" />
<a target="_blank" href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment"><strong>POLA</strong></a> is about being boring. Make sure to not surprise the users or yourself both the code and the UX have to be consistent and predictable.</p>
<h2 id="heading-law-of-demeter">Law of Demeter</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651094731595/LZ843bu3q.png" alt="image.png" /></p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Law_of_Demeter"><strong>LOD</strong></a> or principle of least knowledge is summed up in 3 points:  </p>
<ul>
<li>Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.  </li>
<li>Each unit should only talk to its friends; don't talk to strangers.  </li>
<li>Only talk to your immediate friends.  </li>
</ul>
<p>Read more <a target="_blank" href="http://mi.codes/programming-principles-the-law-of-demeter-lod/">here</a>.</p>
<p>This introduces the concepts of <strong>coupling</strong> and <strong>cohesion</strong>.  </p>
<ul>
<li>Decoupling: try to reduce the number of connections between different classes.  </li>
<li>Cohesion: the associated classes must be in one module/package/directory.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651094582588/T68ehSRRZ.png" alt="image.png" /></p>
<h1 id="heading-oop-modeling">OOP Modeling</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651095017871/ryKB0A6si.png" alt="image.png" />
You know the good principles, so time to write code! But wait, first you should model your ideas for a simpler implementation. Software engineers use <a target="_blank" href="https://en.wikipedia.org/wiki/Unified_Modeling_Language">UML</a> to design their systems.<br />I will have another blog post on the topic, what follows is a very small introduction with resources.  </p>
<h2 id="heading-uml-basics">UML basics</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651096913247/YoCenTIiT.png" alt="image.png" /></p>
<p>The point of a UML diagram is to put together classes, abstract classes and interfaces together (amongst other things) so you can visualize how your software is going to work and start implementing the correct OOP hierarchies.<br />You can find a small introduction from <a target="_blank" href="https://www.tutorialspoint.com/object_oriented_analysis_design/ooad_uml_basic_notation.htm">TutorialsPoint here</a>. And if you want to watch a video <a target="_blank" href="https://youtu.be/WnMQ8HlmeXc">FreeCodeCamp</a> is your answer.  </p>
<p>One of the most basic things you should be familiar with are the UML arrows:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651070889892/XZSyWtSMS.png" alt="image.png" /></p>
<h2 id="heading-design-patterns">Design Patterns</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651097790323/cet772R_a.png" alt="image.png" /></p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Software_design_pattern"><strong>Design patterns</strong></a> are solutions to common architecture problems. If you have ever heard about Factory Method or Singleton those are creational design patterns, there are three types: <strong>Creational</strong>, <strong>Structural</strong> and  <strong>Behavioral</strong>.
<a target="_blank" href="https://refactoring.guru/design-patterns">Refactoring Guru</a> is one of the best at explaining them.</p>
<p>Additionally I highly recommend this <a target="_blank" href="https://www.youtube.com/watch?v=v9ejT8FO-7I&amp;list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc">video series from 
Christopher Okhravi</a> if you are unfamiliar with the matter.</p>
]]></content:encoded></item><item><title><![CDATA[MERN Stack: test Node.js and Express with Jest]]></title><description><![CDATA[Introduction
We will be using the code from the 2nd part of this series.
You can find the code in this Github repository, note that you are on the testing branch.
hmu @tekbog if you find any bugs or want to annoy me.
About testing and QA

People stil...]]></description><link>https://bognov.tech/mern-stack-test-nodejs-and-express-with-jest</link><guid isPermaLink="true">https://bognov.tech/mern-stack-test-nodejs-and-express-with-jest</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Fri, 08 Apr 2022 01:26:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649380352573/b_04bNLGJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p><a target="_blank" href="https://bognov.tech/mern-stack-use-mongodb-with-nodejs-and-express-through-a-restful-api">We will be using the code from the 2nd part of this series.</a></p>
<p>You can find the code in this <a target="_blank" href="https://github.com/bgdnvk/MERN-stack-2/tree/testing">Github repository</a>, note that you are on the <em>testing</em> branch.</p>
<p>hmu <a target="_blank" href="https://twitter.com/tekbog">@tekbog</a> if you find any bugs or want to annoy me.</p>
<h1 id="heading-about-testing-and-qa">About testing and QA</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649361358546/XmZ3pUiUj.png" alt="image.png" /></p>
<p>People still fight over definition and how it should be done, however <a target="_blank" href="https://www.ibm.com/topics/software-testing">this article from IBM</a> might give you some insight if you are unfamiliar with software testing.</p>
<p>To <strong>largely</strong> simplify testing we can define some concepts:</p>
<ul>
<li>Unit tests: as the definition implies we will test simple units of code, one function at a time. </li>
<li>Integration tests or I&amp;T: is when you test several functions or different pieces of code that work together</li>
<li>End to End testing: as the name implies you fully test your whole application, often as an emulated user</li>
<li>Test Driven Development: write the test for the function you want, then write the function</li>
</ul>
<p>A lot of different tools exist for almost any language, in JavaScript the most famous ones are <a target="_blank" href="https://bognov.tech/full-stack-development-in-2022-trends-frameworks-and-languages#heading-testing-do-people-actually">Jest, Mocha and Cypress for E2E</a>. However the overall most famous E2E tool might be <a target="_blank" href="https://www.selenium.dev/">Selenium</a>.</p>
<h1 id="heading-git">Git</h1>
<p>I'm not going to go into detail here, if you unfamiliar with Git and want to learn more about check out this <a target="_blank" href="https://www.atlassian.com/git/tutorials/using-branches/git-checkout">tutorial from Atlassian</a>. 
Start at the beginning if you are confused. A few key points for newbies:</p>
<ul>
<li>Git is a version control tool</li>
<li>Github is the <em>hub</em> that hosts Git projects, it's owned by others and there are other companies such as Bitbucket and Gitlab that do the same.</li>
</ul>
<p>I'm using my old project so I'm going to make a new branch with</p>
<pre><code><span class="hljs-attribute">git</span> checkout -b testing main
</code></pre><p>and stay here as this will be the branch for this article.</p>
<h1 id="heading-jest-or-mocha">Jest (or Mocha)</h1>
<p>We will be using <a target="_blank" href="https://jestjs.io/">Jest</a> since we want to focus on React, however if you are working with Node.js and Mongoose <a target="_blank" href="https://mongoosejs.com/docs/jest.html">it's discouraged even in the official Mongoose docs</a> so feel free to use an alternative like <a target="_blank" href="https://mochajs.org/">Mocha</a>. We will use Jest as our application isn't complex enough to run into problems and we will focus on React in the future.  </p>
<p>Let's install Jest</p>
<pre><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev jest
</code></pre><p>Afterwards inside <code>package.json</code> modify the test script</p>
<pre><code><span class="hljs-string">"test"</span>: <span class="hljs-string">"jest --verbose"</span>
</code></pre><p>You should have this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649360552459/9ebuWy5lS.png" alt="image.png" /></p>
<h3 id="heading-start-testing">Start testing</h3>
<p>Now that we have Jest installed let's make some dummy tests to see how it works.</p>
<p><em>NB: I will be using normal import/export as ES6 module exports might give you some issues.</em></p>
<p>Let's make a helper file inside utils folder that will contain our function we want to test <code>test_helper.js</code>:</p>
<pre><code><span class="hljs-comment">//return the sum of two numbers</span>
const sumFunction <span class="hljs-operator">=</span> (a,b) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-keyword">return</span> a<span class="hljs-operator">+</span>b
}

module.exports <span class="hljs-operator">=</span> {
    sumFunction
}
</code></pre><p>Next we will make a folder called tests and inside a file called dummy.test.js where we will test the function above:</p>
<pre><code>const { sumFunction } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../utils/test_helper"</span>)
<span class="hljs-comment">//tests take a description and a function</span>
test(<span class="hljs-string">'test sumFunction, expected to pass'</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    const a <span class="hljs-operator">=</span> <span class="hljs-number">5</span>
    const b <span class="hljs-operator">=</span> <span class="hljs-number">6</span>
    const result <span class="hljs-operator">=</span> sumFunction(a, b)
    <span class="hljs-comment">//through expect we indicate the expected result of the test</span>
    <span class="hljs-comment">//the .toBe method expects a specific value you pass</span>
    <span class="hljs-comment">//https://jestjs.io/docs/expect#tobevalue</span>
    expect(result).toBe(<span class="hljs-number">11</span>)
})
test(<span class="hljs-string">'test sumFunction, expected to fail'</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    const a <span class="hljs-operator">=</span> <span class="hljs-number">5</span>
    const b <span class="hljs-operator">=</span> <span class="hljs-number">6</span>
    const result <span class="hljs-operator">=</span> sumFunction(a, b)

    expect(result).toBe(<span class="hljs-number">12</span>)
})
</code></pre><p>Note that .test is needed so Jest knows to read your tests from this file.
Now let's do</p>
<pre><code>npm run <span class="hljs-built_in">test</span>
</code></pre><p>This should be the result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649365476196/mlhvacqEp.png" alt="image.png" /></p>
<p>Check out many of the Expect methods Jest has <a target="_blank" href="https://jestjs.io/docs/expect">here</a></p>
<h1 id="heading-testing-a-restful-api">Testing a RESTful API</h1>
<p>We will be using ES6 modules so we need to make some changes in our package.json as follows:</p>
<pre><code><span class="hljs-string">"test"</span>: <span class="hljs-string">"node --experimental-vm-modules node_modules/jest/bin/jest.js --verbose --runInBand --forceExit"</span>
</code></pre><p><a target="_blank" href="https://jestjs.io/docs/ecmascript-modules">Jest gives you more information here.</a></p>
<p>We will be using <a target="_blank" href="https://www.npmjs.com/package/supertest">Supertest</a>, so let's install it</p>
<pre><code><span class="hljs-built_in">npm</span> install supertest
</code></pre><p>Now let's make a file inside tests called <code>api.test.js</code> where we will be importing everything we need to make our tests:</p>
<pre><code><span class="hljs-keyword">import</span> supertest <span class="hljs-keyword">from</span> <span class="hljs-string">'supertest'</span>
<span class="hljs-keyword">import</span> { app } <span class="hljs-keyword">from</span> <span class="hljs-string">'../app.js'</span>
<span class="hljs-comment">//use the supertest object as our API</span>
<span class="hljs-keyword">const</span> api = supertest(app)

<span class="hljs-keyword">import</span> { Item } <span class="hljs-keyword">from</span> <span class="hljs-string">'../models/item'</span>
</code></pre><p>Then remember to run our server with <code>npm start dev</code> so it restarts every time we make changes and open a new window terminal so we can type our Jest commands.</p>
<h2 id="heading-get-test">GET test</h2>
<p>Since we are getting our data from a server we will need to use async functions, keep that in mind.</p>
<p>This is a test for our GET call expecting a 200 status:</p>
<pre><code>test(<span class="hljs-string">'GET call'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    await api
        .get(<span class="hljs-string">'/api/items'</span>)
        .expect(<span class="hljs-number">200</span>)
})
</code></pre><p>You can run this test through this command</p>
<pre><code>run npm test <span class="hljs-operator">-</span><span class="hljs-operator">-</span> <span class="hljs-operator">-</span>t <span class="hljs-string">"GET call"</span>
</code></pre><p>That's how you run individual tests.  </p>
<p>In order to make the test a bit more complete we will also add a method to expect JSON data:</p>
<pre><code>test(<span class="hljs-string">'GET call'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    await api
        .get(<span class="hljs-string">'/api/items'</span>)
        .expect(<span class="hljs-number">200</span>)
        .expect(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-operator">/</span>application\<span class="hljs-operator">/</span>json<span class="hljs-operator">/</span>)
})
</code></pre><p>Your <code>api.test.js</code> file should look like this by now</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">supertest</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'supertest'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> { <span class="hljs-title">app</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'../app.js'</span>
<span class="hljs-comment">//use the supertest object as our API</span>
<span class="hljs-title">const</span> <span class="hljs-title">api</span> <span class="hljs-operator">=</span> <span class="hljs-title">supertest</span>(<span class="hljs-title">app</span>)

<span class="hljs-comment">//run npm test -- -t "GET call"</span>
<span class="hljs-comment">//test GET or READ call on localhost:3001/api/items endpoint</span>
<span class="hljs-title">test</span>(<span class="hljs-string">'GET call'</span>, <span class="hljs-title">async</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-title">await</span> <span class="hljs-title">api</span>
        .<span class="hljs-title">get</span>(<span class="hljs-string">'/api/items'</span>)
        .<span class="hljs-title">expect</span>(200)
        .<span class="hljs-title">expect</span>(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-operator">/</span><span class="hljs-title">application</span>\<span class="hljs-operator">/</span><span class="hljs-title">json</span><span class="hljs-operator">/</span>)
})
</code></pre><h2 id="heading-post-test">POST test</h2>
<p>In order to interact with the database properly we will use our Mongoose model</p>
<pre><code><span class="hljs-keyword">import</span> { Item } <span class="hljs-keyword">from</span> <span class="hljs-string">'../models/item'</span>
</code></pre><p>Afterwards we will proceed to make a POST call</p>
<pre><code>test(<span class="hljs-string">'POST call'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//build a new item</span>
    const newItem <span class="hljs-operator">=</span> {
        description:<span class="hljs-string">"sent from Jest!"</span>,
        likes: <span class="hljs-number">10</span>
    }
    <span class="hljs-comment">//we send the item object to the DB through the API</span>
    <span class="hljs-comment">//we expect a successful result</span>
    await api
        .post(<span class="hljs-string">'/api/items'</span>)
        .<span class="hljs-built_in">send</span>(newItem)
        .expect(<span class="hljs-number">201</span>)
    <span class="hljs-comment">//get all the items in our DB</span>
    const items <span class="hljs-operator">=</span> await Item.find({})
    <span class="hljs-comment">//let's check that the last item added was indeed newItem object</span>
    <span class="hljs-comment">//it should contain the description "sent from Jest!"</span>
    expect(items[items.<span class="hljs-built_in">length</span>-<span class="hljs-number">1</span>].description).toBe(<span class="hljs-string">"sent from Jest!"</span>)
})
</code></pre><h2 id="heading-get-item-by-id">GET item by id</h2>
<p>In this test we are going to check if the GET route by specific id works as expected.</p>
<pre><code>test(<span class="hljs-string">'GET one'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//get all the items</span>
    const items <span class="hljs-operator">=</span> await Item.find({})
    <span class="hljs-comment">//get the the first item parsed to JSON</span>
    const firstItem <span class="hljs-operator">=</span> items[<span class="hljs-number">0</span>].toJSON()
    <span class="hljs-comment">//get the result expecting success and JSON data</span>
    const resItem <span class="hljs-operator">=</span> await
        api.get(`<span class="hljs-operator">/</span>api<span class="hljs-operator">/</span>items<span class="hljs-operator">/</span>${firstItem.id}`)
        .expect(<span class="hljs-number">200</span>)
        .expect(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-operator">/</span>application\<span class="hljs-operator">/</span>json<span class="hljs-operator">/</span>)
    <span class="hljs-comment">//check if the item has the same id and the route works as expected</span>
    expect(resItem.body.id).toEqual(firstItem.id)
})
</code></pre><h2 id="heading-check-all-items-have-an-id">Check all items have an id</h2>
<p>Let's add one more simple test</p>
<pre><code>    test(<span class="hljs-string">'check all items have ids'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        <span class="hljs-comment">//get all the items</span>
        const items <span class="hljs-operator">=</span> await api.get(<span class="hljs-string">'/api/items'</span>)
        <span class="hljs-comment">//check that every item in our DB has the id property</span>
        <span class="hljs-keyword">for</span>(const item of items.body){
            expect(item.id).toBeDefined()
        }
    })
</code></pre><h2 id="heading-refactoring-get-calls">Refactoring GET calls</h2>
<p>Let's use <a target="_blank" href="https://jestjs.io/docs/api#describename-fn">describe</a> to put our three GET calls together as follows:</p>
<pre><code>describe(<span class="hljs-string">'GET calls'</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//run npm test -- -t "GET call"</span>
    <span class="hljs-comment">//test GET or READ call on localhost:3001/api/items endpoint</span>
    test(<span class="hljs-string">'GET call'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        await api
            .get(<span class="hljs-string">'/api/items'</span>)
            .expect(<span class="hljs-number">200</span>)
            .expect(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-operator">/</span>application\<span class="hljs-operator">/</span>json<span class="hljs-operator">/</span>)
    })
    <span class="hljs-comment">//npm test -- -t "GET one"</span>
    <span class="hljs-comment">//GET item by id</span>
    test(<span class="hljs-string">'GET one'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        <span class="hljs-comment">//get all the items</span>
        const items <span class="hljs-operator">=</span> await Item.find({})
        <span class="hljs-comment">//get the the first item parsed to JSON</span>
        const firstItem <span class="hljs-operator">=</span> items[<span class="hljs-number">0</span>].toJSON()
        <span class="hljs-comment">//get the result expecting success and JSON data</span>
        const resItem <span class="hljs-operator">=</span> await
            api.get(`<span class="hljs-operator">/</span>api<span class="hljs-operator">/</span>items<span class="hljs-operator">/</span>${firstItem.id}`)
            .expect(<span class="hljs-number">200</span>)
            .expect(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-operator">/</span>application\<span class="hljs-operator">/</span>json<span class="hljs-operator">/</span>)
        <span class="hljs-comment">//check if the item has the same id and the route works as expected</span>
        expect(resItem.body.id).toEqual(firstItem.id)
    })
    test(<span class="hljs-string">'check all items have ids'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        <span class="hljs-comment">//get all the items</span>
        const items <span class="hljs-operator">=</span> await api.get(<span class="hljs-string">'/api/items'</span>)
        <span class="hljs-comment">//check that every item in our DB has the id property</span>
        <span class="hljs-keyword">for</span>(const item of items.body){
            expect(item.id).toBeDefined()
        }
    })
})
</code></pre><p>Afterwards we can use this cmd to call this block of tests</p>
<pre><code>npm test <span class="hljs-operator">-</span><span class="hljs-operator">-</span> <span class="hljs-operator">-</span>t <span class="hljs-string">"GET calls"</span>
</code></pre><p>If everything is successful we will get this in the console:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649376311674/cFVqbAhDh.png" alt="image.png" /></p>
<h2 id="heading-delete">DELETE</h2>
<p>Let's check that we can delete an item and all its data is gone</p>
<pre><code>test(<span class="hljs-string">'DELETE item'</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//get items and parse the one you want to delete to JSON</span>
    const itemsAtStart <span class="hljs-operator">=</span> await Item.find({})
    const itemToDelete <span class="hljs-operator">=</span> itemsAtStart[<span class="hljs-number">0</span>].toJSON()
    <span class="hljs-comment">//delete the item by id</span>
    await api
        .delete(`<span class="hljs-operator">/</span>api<span class="hljs-operator">/</span>items<span class="hljs-operator">/</span>${itemToDelete.id}`)
        .expect(<span class="hljs-number">204</span>)
    <span class="hljs-comment">//get all items from the database again</span>
    const itemsNow <span class="hljs-operator">=</span> await Item.find({})
    <span class="hljs-comment">//check if the number of current items is one less than before</span>
    expect(itemsNow).toHaveLength(itemsAtStart.<span class="hljs-built_in">length</span>-<span class="hljs-number">1</span>)
    <span class="hljs-comment">//get an array of all the descriptions inside the DB</span>
    <span class="hljs-comment">//could get any other info like the id</span>
    const itemsDescriptions <span class="hljs-operator">=</span> itemsNow.map(i <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> i.toJSON().description)
    <span class="hljs-comment">//expect the description from the deleted item to not be there</span>
    expect(itemsDescriptions).not.toContain(itemToDelete.description)
})
</code></pre><h2 id="heading-beforeeach">beforeEach</h2>
<p>If you want to run any code before tests start you need to use <a target="_blank" href="https://jestjs.io/docs/api#beforeeachfn-timeout">beforEach</a>. In our case we want our database to reset every time we start testing so let's make some data to insert inside a file called <code>test_helper.js</code> </p>
<pre><code><span class="hljs-string">const</span> <span class="hljs-string">initialItems</span> <span class="hljs-string">=</span> [
    {
        <span class="hljs-attr">description:</span> <span class="hljs-string">"first item"</span>,
        <span class="hljs-attr">likes:</span> <span class="hljs-number">5</span>
    },
    {
        <span class="hljs-attr">description:</span> <span class="hljs-string">"second item"</span>,
        <span class="hljs-attr">likes:</span> <span class="hljs-number">7</span>
    },
    {
        <span class="hljs-attr">description:</span> <span class="hljs-string">"third item"</span>,
        <span class="hljs-attr">likes:</span> <span class="hljs-number">10</span>
    }
]

<span class="hljs-string">export</span> {
    <span class="hljs-string">initialItems</span>
}
</code></pre><p>then import that data and use it to reset our database every time we start testing. We delete everything and then insert our initial data again:</p>
<pre><code>beforeEach(async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    await Item.deleteMany({})
    await Item.insertMany(initialItems)
})
</code></pre><h2 id="heading-afterall">afterAll</h2>
<p>If you want to run something after all our tests are done then use afterAll</p>
<pre><code>afterAll(() <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> mongoose.connection.close())
</code></pre><p>In our case we just close the connection to the database.</p>
]]></content:encoded></item><item><title><![CDATA[MERN Stack: use MongoDB with Node.js and Express through a RESTful API]]></title><description><![CDATA[Intro
You will learn how to make a full RESTful API that connects with a real database. The endpoints contain all the CRUD operations and you will apply modern techniques like ES6 export modules and async/await functions, as well as the relevant libr...]]></description><link>https://bognov.tech/mern-stack-use-mongodb-with-nodejs-and-express-through-a-restful-api</link><guid isPermaLink="true">https://bognov.tech/mern-stack-use-mongodb-with-nodejs-and-express-through-a-restful-api</guid><category><![CDATA[MongoDB]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Tue, 05 Apr 2022 04:51:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649133525038/xCaZcgYaJ.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-intro">Intro</h1>
<p>You will learn how to make a full RESTful API that connects with a real database. The endpoints contain all the CRUD operations and you will apply modern techniques like ES6 export modules and async/await functions, as well as the relevant libraries to make building the project a breeze.</p>
<p><a target="_blank" href="https://github.com/bgdnvk/MERN-stack-2">Here's the repository for the project</a> and you can find me on <a target="_blank" href="https://twitter.com/tekbog">Twitter @tekbog</a>.</p>
<p><a target="_blank" href="https://bognov.tech/mern-stack-how-to-build-a-restful-api-with-nodejs-and-express">Additionally you can find the first chapter of the series that connects to an in-memory database here.</a></p>
<h1 id="heading-setup">Setup</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649133616818/Ep2fVXTi-.png" alt="image.png" />
Do </p>
<pre><code>npm <span class="hljs-keyword">init</span>
</code></pre><p>The install all the dependencies</p>
<pre><code><span class="hljs-built_in">npm</span> install express nodemon dotenv cors express-<span class="hljs-keyword">async</span>-errors mongoose
</code></pre><p>Afterwards modify the package.json by adding</p>
<pre><code><span class="hljs-string">"type"</span>:<span class="hljs-string">"module"</span>,
</code></pre><p>right after</p>
<pre><code><span class="hljs-string">"main"</span>: <span class="hljs-string">"index.js"</span>,
</code></pre><p>this will allow us to use ES6 exports.</p>
<p>Once that's done we will modify the "scripts" part. You run those scripts by typing </p>
<pre><code><span class="hljs-built_in">npm</span> run name_of_script
</code></pre><p>We will add:</p>
<pre><code>    <span class="hljs-string">"start"</span>: <span class="hljs-string">"node index.js"</span>,
    <span class="hljs-string">"dev"</span>: <span class="hljs-string">"nodemon index.js"</span>,
</code></pre><p>That way whenever you type </p>
<pre><code><span class="hljs-built_in">npm</span> run dev
</code></pre><p>it will be equal to</p>
<pre><code>nodemon <span class="hljs-keyword">index</span>.js
</code></pre><p><a target="_blank" href="https://www.npmjs.com/package/nodemon">Nodemon</a> is a tool that restarts the server every time a line of code is modified. It's only used for development purposes.</p>
<p>Your package.json should look like this now:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649123633515/wgxYnUR8Y.png" alt="image.png" /></p>
<h2 id="heading-project-structure">Project Structure</h2>
<p>The project structure is going to look as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649123825527/HeHjy5kjs.png" alt="image.png" /></p>
<p>Controllers folder will contain our endpoints and the way we interact with them.<br />Models folder will have the model of our database, we will use that model in our controller items.js.<br />Utils is generally a folder for anything non-specific but you don't want floating around in the project, in our case it will contain a configuration file.<br />App.js is the server itself where we will be importing from controllers and models.<br />Index.js is the main point that starts everything, we will import our server/app there.  </p>
<p>Then there's package.json that contains all the dependencies and information about the project.</p>
<h3 id="heading-gitignore-andampandamp-env">.gitignore &amp;&amp; .env</h3>
<p>.gitignore is there if you are using Git, make sure to ignore your node_modules folder as it should only be installed locally or on the server. We will also be ignoring our .env file through .gitignore since it will contain information we can't expose.<br />.env is there so you can use the dotenv library and use all the keys and passwords without exposing anything outside. If you aren't pushing your code anywhere then feel free to ignore process.env variables and write them as consts in your code.</p>
<h2 id="heading-mongodb-atlas">MongoDB Atlas</h2>
<p>We will be working with a real database and its free tier. If you are unfamiliar with it then have a quick look at their guide <a target="_blank" href="https://www.mongodb.com/basics/mongodb-atlas-tutorial">here</a>.<br />However the TL;DR is: get your mongodb URI and put it into the .env file like this</p>
<pre><code><span class="hljs-attr">MONGODB_URI</span>=mongodb+srv://YOUR_USER:YOUR_PASSWORD@cluster0.pekyz.mongodb.net/YOUR_DATABASE?retryWrites=<span class="hljs-literal">true</span>&amp;w=majority
<span class="hljs-attr">PORT</span>=<span class="hljs-number">3001</span>
</code></pre><p>Note that you have to use the information of your account but don't confuse your own login with your database account.</p>
<h1 id="heading-mongoose-schema">Mongoose Schema</h1>
<p>Let's start with the models folder. Inside we will put the <a target="_blank" href="https://en.wikipedia.org/wiki/Database_schema">schema</a> of our data. Object databases don't need schemas however it's always good practice to have one. If you don't want to dig into databases right now just know that here you are defining a model of the data your database will be storing.<br />The easiest way to interact with MongoDB is the <a target="_blank" href="https://mongoosejs.com/">mongoose library</a>.</p>
<p>item.js</p>
<pre><code><span class="hljs-comment">//in order to communicate with mongoDB we will use mongoose</span>
<span class="hljs-comment">//it simplifies the process</span>
<span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">"mongoose"</span>
<span class="hljs-comment">//we define the schema of the database</span>
<span class="hljs-comment">//description field is a string and likes is a number</span>
<span class="hljs-keyword">const</span> itemSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
    <span class="hljs-attr">description</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">likes</span>: <span class="hljs-built_in">Number</span>
})
<span class="hljs-comment">//we modify the schema and pass it to JSON</span>
<span class="hljs-comment">//mongoDB adds two fields we don't necessarily want</span>
<span class="hljs-comment">//_id is the id the objects get randomly assigned</span>
<span class="hljs-comment">//we transform _id into a string variable called .id and delete _id</span>
<span class="hljs-comment">//we also delete __v</span>
<span class="hljs-comment">//try the data without deleting __v</span>
itemSchema.set(<span class="hljs-string">'toJSON'</span>, {
    <span class="hljs-attr">transform</span>: <span class="hljs-function">(<span class="hljs-params"><span class="hljs-built_in">document</span>, returnedObject</span>) =&gt;</span> {
        returnedObject.id = returnedObject._id.toString()
        <span class="hljs-keyword">delete</span> returnedObject._id
        <span class="hljs-keyword">delete</span> returnedObject.__v
    }
})
<span class="hljs-comment">//mongoose needs you to define a 'model' with your schema</span>
<span class="hljs-comment">//then use that model to operate with different functions</span>
<span class="hljs-keyword">const</span> Item = mongoose.model(<span class="hljs-string">'Item'</span>, itemSchema)

<span class="hljs-keyword">export</span> { Item }
</code></pre><h1 id="heading-endpoints-with-async-functions">Endpoints with async functions</h1>
<p>The controllers folder could also be named API as it serves the routes/endpoints for our server. Once we have the user requesting HTTPS methods on those endpoints we will direct those requests to the database through our Mongoose model as you will see in the code.<br />It works as follows: the user interacts with the frontend, we receive an event through it that triggers our server's backend through the api we have designed, the api then interacts with the database through the different models. The database sends back the information to the server and the server sends it back to the frontend.  </p>
<pre><code><span class="hljs-keyword">user</span> -&gt; frontend sends an event -&gt; <span class="hljs-keyword">server</span> receives the event through a HTTP <span class="hljs-keyword">method</span> (<span class="hljs-keyword">GET</span>, POST, <span class="hljs-keyword">UPDATE</span>, <span class="hljs-keyword">DELETE</span>) -&gt; <span class="hljs-keyword">server</span> calls the <span class="hljs-keyword">database</span> through the model
</code></pre><p>Then depending if the interaction with the database is successful we send information back to the user</p>
<pre><code>DB <span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span> server <span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span> frontend <span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span> user
</code></pre><p>Here we will be using the <a target="_blank" href="https://expressjs.com/en/guide/routing.html">Router object from Express</a> as it simplifies development.  We will then use the mongoose schema to interact with the database. Everything is done with <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function">async/await</a> functions instead of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promises</a>, if you are unfamiliar with them the main thing is: those functions wait for the data so everything works properly.</p>
<p><em>NB: You will find the concept <a target="_blank" href="https://expressjs.com/en/guide/using-middleware.html">Middleware</a> everywhere in the backend, it just means a function that modifies the data object and usually passes it to the next point.</em></p>
<p>items.js</p>
<pre><code><span class="hljs-keyword">import</span> { Router } from <span class="hljs-string">"express"</span>
<span class="hljs-keyword">import</span> { Item } from <span class="hljs-string">"../models/item.js"</span>
<span class="hljs-comment">//define our router object</span>
<span class="hljs-keyword">const</span> itemsRouter = Router()
<span class="hljs-comment">//GET or READ endpoint</span>
<span class="hljs-comment">//it's an async function that waits for the data thanks to await</span>
<span class="hljs-comment">//we get the data from the database by using our mongoose model</span>
<span class="hljs-comment">//one of the methods at the moongoose model is .find where you can get whatever you want</span>
<span class="hljs-comment">//find is empty so we get all the data</span>
<span class="hljs-comment">//afterwards we return a successful status and the JSON data</span>
itemsRouter.<span class="hljs-keyword">get</span>(<span class="hljs-string">'/'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> items = <span class="hljs-keyword">await</span> Item.find({})
    res.status(<span class="hljs-number">200</span>).json(items).end()
})
<span class="hljs-comment">//in order to use a paramater we need to put ":id"</span>
<span class="hljs-comment">//then we can use the value of that "id" through req.params.id</span>
<span class="hljs-comment">//req stands for request, res stands for response</span>
itemsRouter.<span class="hljs-keyword">get</span>(<span class="hljs-string">'/:id'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> item = <span class="hljs-keyword">await</span> Item.findById(req.params.id)
    <span class="hljs-comment">//check if the object exists and deliver the relevant status</span>
    <span class="hljs-keyword">if</span>(item){
        res.status(<span class="hljs-number">200</span>).json(item).end()
    } <span class="hljs-keyword">else</span>{
        res.status(<span class="hljs-number">404</span>).end()
    }
})
<span class="hljs-comment">//POST or CREATE ednpoint</span>
<span class="hljs-comment">//we get the data sent to the server through req.body</span>
itemsRouter.post(<span class="hljs-string">'/'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> body = req.body
    <span class="hljs-comment">//if the request is missing the description field deliver a 404</span>
    <span class="hljs-keyword">if</span>(!body.description) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).end()
    <span class="hljs-comment">//make the object we are going to insert into the database</span>
    <span class="hljs-comment">//we get the content from body</span>
    <span class="hljs-comment">//the id is self generated so we don't have to make one</span>
    <span class="hljs-comment">//if the likes doesn't exist we will put 0</span>
    <span class="hljs-keyword">const</span> itemObj = <span class="hljs-keyword">new</span> Item({
        description: body.description,
        likes: body.likes || <span class="hljs-number">0</span>
    })
    <span class="hljs-comment">//save the new object into our database and return a CREATED status</span>
    <span class="hljs-keyword">const</span> savedItem = <span class="hljs-keyword">await</span> itemObj.save()
    res.status(<span class="hljs-number">201</span>).json(savedItem).end()
})
<span class="hljs-comment">//DELETE endpoint</span>
<span class="hljs-comment">//we search for the object through the id and delete it from our DB</span>
itemsRouter.delete(<span class="hljs-string">'/:id'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">await</span> Item.findByIdAndRemove(req.params.id)
    res.status(<span class="hljs-number">204</span>).end()
})
<span class="hljs-comment">//PUT or UPDATE endpoint</span>
itemsRouter.put(<span class="hljs-string">'/:id'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> body = req.body
    <span class="hljs-comment">//we make a new object just like with POST</span>
    <span class="hljs-keyword">const</span> itemObj = {
        description: body.description,
        likes: body.likes
    }
    <span class="hljs-comment">//findAndUpdate requires the id and then the object you are inserting</span>
    <span class="hljs-keyword">const</span> updatedItem = <span class="hljs-keyword">await</span> Item.findByIdAndUpdate(req.params.id, itemObj)
    res.status(<span class="hljs-number">201</span>).json(updatedItem).end()
})

<span class="hljs-keyword">export</span> { itemsRouter }
</code></pre><h1 id="heading-utils">Utils</h1>
<p>This is just good practice to hide sensitive information in your .env file.</p>
<p>config.js</p>
<pre><code><span class="hljs-comment">//we need this library to use our .env file</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'dotenv/config'</span>
<span class="hljs-comment">//get the variables from the .env file</span>
<span class="hljs-keyword">const</span> PORT = process.env.PORT
<span class="hljs-keyword">const</span> MONGODB_URI = process.env.MONGODB_URI

<span class="hljs-keyword">export</span> {
    PORT,
    MONGODB_URI
}
</code></pre><h1 id="heading-server">Server</h1>
<p>Here's is where will unite everything and establish a connection to our database. We use mongoose to connect to MongoDB Atlas through an async function. Note that we are using a express-async-errors library so we never had to catch the errors, however in this particular case you can see how to deal with a try/catch block in case the connection to the database fails.<br />After the database connection we use middleware to make our server work, first one allows the server to <a target="_blank" href="https://expressjs.com/en/api.html#express.json">parse everything as JSON</a> and second is our Router object that has all our endpoints. If we were to put this on the internet you'd also need to use CORS.  </p>
<p>app.js</p>
<pre><code><span class="hljs-comment">//example on how to import the whole object called config</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> config <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/config.js'</span>
<span class="hljs-comment">//get the express object and assign it to app</span>
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">const</span> app = express()
<span class="hljs-comment">//express router</span>
<span class="hljs-keyword">import</span> { itemsRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">'./controllers/items.js'</span>
<span class="hljs-comment">//mongoose is needed to connect to the database</span>
<span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">'mongoose'</span>
<span class="hljs-comment">//async function so we can connect to the database</span>
<span class="hljs-comment">//throws an error if the connection fails</span>
<span class="hljs-keyword">const</span> connectToDB = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> mongoose.connect(config.MONGODB_URI)
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`connected to the database`</span>)
    } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`error connecting to the db: <span class="hljs-subst">${e}</span>`</span>)
    }
}
<span class="hljs-comment">//run the function so we are connected to the database</span>
connectToDB()
<span class="hljs-comment">//------------- middleware -------------//</span>
<span class="hljs-comment">//allow the server read json data</span>
app.use(express.json())
<span class="hljs-comment">//define the endpoint: localhost:3001/api/items for the router</span>
app.use(<span class="hljs-string">'/api/items'</span>, itemsRouter)

<span class="hljs-keyword">export</span> { app }
</code></pre><p>Then we import everything into index.js which is our entry point.</p>
<pre><code>//<span class="hljs-keyword">import</span> the app <span class="hljs-keyword">object</span>
<span class="hljs-keyword">import</span> { app } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.js'</span>
//<span class="hljs-keyword">get</span> the port <span class="hljs-keyword">from</span> .env
<span class="hljs-keyword">import</span> { PORT } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/config.js'</span>
//run the <span class="hljs-keyword">server</span> <span class="hljs-keyword">on</span> the app <span class="hljs-keyword">object</span> <span class="hljs-keyword">with</span> the defined port
app.<span class="hljs-keyword">listen</span>(PORT, () =&gt; {
    console.log(`<span class="hljs-keyword">server</span> running <span class="hljs-keyword">on</span> port ${PORT}`)
})
</code></pre>]]></content:encoded></item><item><title><![CDATA[MERN stack: how to build a RESTful API with Node.js and Express]]></title><description><![CDATA[MERN stack introduction

MERN stack stands for MongoDB, Express, React and Node. It's widely popular due to the fact that you can use JavaScript on the backend and frontend, or TypeScript. It's also fast as scalable, with millions of developers writi...]]></description><link>https://bognov.tech/mern-stack-how-to-build-a-restful-api-with-nodejs-and-express</link><guid isPermaLink="true">https://bognov.tech/mern-stack-how-to-build-a-restful-api-with-nodejs-and-express</guid><category><![CDATA[MERN Stack]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Sun, 03 Apr 2022 21:11:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649018637678/yf3hYy6gP.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-mern-stack-introduction">MERN stack introduction</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648954444439/EQTKghtH7.png" alt="image.png" />
MERN stack stands for MongoDB, Express, React and Node. It's widely popular due to the fact that you can use JavaScript on the backend and frontend, or TypeScript. It's also fast as scalable, with millions of developers writing code and contributing to the documentation and the ecosystem.</p>
<p>There are variations where instead of React for the frontend you will find Angular, Vue, or even Svelte nowadays, although this last one is still not as popular. Additionally you also have Next.js, Nuxt.js, Remix.js, etc. You can do everything with JavaScript or TypeScript nowadays.</p>
<p>This is the first article of the MERN stack series that will progress in complexity. At the end of it you will be able to create a full stack web app and deploy it anywhere with Docker. But now we will focus on building the simplest RESTful API with Node and Express.</p>
<p><em>NB: There's an 'older' stack, called <a target="_blank" href="https://en.wikipedia.org/wiki/LAMP_(software_bundle">LAMP</a>) that consists of Linux, Apache, MySQL, PHP/Perl/Python, depending on your focus you might want to check it out</em></p>
<p><a target="_blank" href="https://bognov.tech/mern-stack-2-connect-to-mongodb-with-nodejs-and-express">You can find the next chapters of this series here: RESTful API with Node.JS, Express and MongoDB.</a></p>
<h1 id="heading-concepts-and-memes">Concepts and memes</h1>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Node.js">Node.JS</a> is a runtime environment for JavaScript, it basically allows you to ruin everything with JavaScript anywhere.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649018707425/_kIdBfVeE.png" alt="image.png" /></p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Express.js">Express or Express.js</a> is the most famous backend framework for Node.js. It allows you to build web applications and APIs.</p>
<p>Once you have your project you can put Express.js on top of Node.js in a machine and it will act as a server for requests, you can also connect it to a database and it will server you as an intermediary between user events and the information you want to show.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649018754742/396GM2m5f.png" alt="image.png" /></p>
<h1 id="heading-write-code-not-docs-our-first-server">Write code, not docs - our first server</h1>
<p>No, you should totally write documentation but let's start this tutorial.</p>
<p>The first thing we need to do is go to our directory and 
<code>npm init</code> this will start the package.json, you can just press yes to everything. We will have all the dependencies stored in this file. Instead of <a target="_blank" href="https://www.npmjs.com/">npm</a> you could also check out another package manager called <a target="_blank" href="https://yarnpkg.com/">Yarn</a>.</p>
<p>Once that's done follow with 
<code>npm install express</code>  and make a index.js file, that's where our code is going to be. 
If you are using git or any sort of version control remember to ignore the node_modules folder. That's where all your dependencies are, you shouldn't be touching that folder at all.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648955301700/AWyk_GZjv.png" alt="image.png" /></p>
<p>Let's write our first server, put this into index.js:</p>
<pre><code><span class="hljs-comment">//we import the express dependency</span>
const express <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>)
<span class="hljs-comment">//assign express to a variable so it's easiet to work with</span>
const app <span class="hljs-operator">=</span> express()
<span class="hljs-comment">//this is our first route</span>
<span class="hljs-comment">//we want to get http://localhost:3001/</span>
<span class="hljs-comment">//the app already knows that we are on localhost</span>
<span class="hljs-comment">//we just need to indicate that's the entry point with '/'</span>
<span class="hljs-comment">//req stands for request and res for response</span>
app.get(<span class="hljs-string">'/'</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//we reply to the get endpoint by sending a text back</span>
    res.<span class="hljs-built_in">send</span>(<span class="hljs-string">'hello world!'</span>)
})
<span class="hljs-comment">//define the port where our app is gonna run</span>
const PORT <span class="hljs-operator">=</span> <span class="hljs-number">3001</span>
<span class="hljs-comment">//make the server listen to that port</span>
app.listen(PORT, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//the console.log is for your CLI</span>
    <span class="hljs-comment">//so you know the server has started</span>
    console.log(`server running on localhost with port ${PORT}`)
})
</code></pre><p>Once you have it you can run your server through CLI by typing <code>node index.js</code> in your terminal (remember you have to be in the folder where index.js is). We are using our Node runtime to execute the code in our index.js file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648956926254/2QQom6BWW.png" alt="image.png" />
<em>NB: Every time you make a change in your code you need to restart your server, you exit it with CTRL+C from the terminal and every time you want to run it again you need to type 'node index.js'. 
In order to get around this you could install <a target="_blank" href="https://www.npmjs.com/package/nodemon">nodemon</a></em></p>
<p>Afterwards in your browser go to <code>http://localhost:3001/</code>
You should see the following:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648956866243/bfYaUT-55.png" alt="image.png" /></p>
<h1 id="heading-restful-api">RESTful API</h1>
<p>There are several discrepancies between the theory and the practice of building a RESTful API, as well as different definitions, here we will go with a CRUD example. Which stands for Create, Read, Update and Delete. We will build endpoints for all these operations.</p>
<p>Before starting make sure you have this middleware on top of your file</p>
<pre><code><span class="hljs-comment">//middleware so the server can parse json data</span>
app.use(express.json())
</code></pre><p>and also make a "database" like this:</p>
<pre><code>let infoDB = [
    {
        id: <span class="hljs-number">1</span>,
        <span class="hljs-keyword">info</span>: "example of information",
        <span class="hljs-type">date</span>: "2022-04-03T20:00:22.158Z"
    },
    {
        id: <span class="hljs-number">2</span>,
        <span class="hljs-keyword">info</span>: "example of information2, put anything here",
        <span class="hljs-type">date</span>: "2022-03-03T20:00:22.158Z"
    }
]
</code></pre><p>This is how the top of your file should look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649016699860/EyZXDqzLp.png" alt="image.png" /></p>
<p>Additionally I will be using <a target="_blank" href="https://www.postman.com/">Postman</a> to make calls to my endpoints, it's free and simplifies the process of development, however there are many alternatives.</p>
<h2 id="heading-get-or-read">GET or Read</h2>
<p>The code is very straightforward, we make a call to /api/info and get a response with all the data back in JSON format.</p>
<pre><code><span class="hljs-comment">//an endpoint to return all our infor back</span>
app.get(<span class="hljs-string">'/api/info'</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//we send the information back in JSON format</span>
    <span class="hljs-comment">//along with a 200 status which means it's successful</span>
    res.status(<span class="hljs-number">200</span>).json(infoDB)
})
</code></pre><p>The call to Postman should return:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019491643/RBznULp9_.png" alt="image.png" /></p>
<p>We will also add a way to get a specific item from the database through the id but you can check it out later, first get familiar with the rest of the code.</p>
<pre><code><span class="hljs-comment">//and endpoint to return an object with a specific id</span>
app.get(<span class="hljs-string">'/api/info/:id'</span>, (req, res ) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>{
    <span class="hljs-comment">//we parse the request id since it's a string</span>
    const id <span class="hljs-operator">=</span> Number(req.params.id)
    <span class="hljs-comment">//find the object the user wants in our database</span>
    const infoObject <span class="hljs-operator">=</span> infoDB.find(info <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> info.id <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> id)
    <span class="hljs-comment">//return with the needed status and the object if you find it</span>
    infoObject
        ? res.status(<span class="hljs-number">200</span>).json(infoObject).end()
        : res.status(<span class="hljs-number">404</span>).json({
            <span class="hljs-function"><span class="hljs-keyword">error</span>: `<span class="hljs-title">an</span> <span class="hljs-title">object</span> <span class="hljs-title">doesn</span>'<span class="hljs-title">t</span> <span class="hljs-title">exist</span> <span class="hljs-title">with</span> <span class="hljs-title">the</span> <span class="hljs-title">id</span> <span class="hljs-title">$</span></span>{id} in our database`
        }).end()
})
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019507961/9u_Y5CSV8.png" alt="image.png" /></p>
<h2 id="heading-post-or-create">POST or Create</h2>
<p>In order to make this endpoint we will need an additional helper function to generate ids for our data:</p>
<pre><code><span class="hljs-comment">//a helper function to generate an id</span>
<span class="hljs-comment">//if you want to make it simpler just return infoDB.length + 1</span>
const generateId <span class="hljs-operator">=</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    const maxId <span class="hljs-operator">=</span> infoDB.<span class="hljs-built_in">length</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>
        ? Math.<span class="hljs-built_in">max</span>(...infoDB.map(i <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> i.id))
        : <span class="hljs-number">0</span>
    <span class="hljs-keyword">return</span> maxId <span class="hljs-operator">+</span> <span class="hljs-number">1</span>
}
</code></pre><p>If you are unfamiliar with the methods what you do here is first make an array of items with the ids through <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a> then we use the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator</a> (the three dots) to spread the array and pass it to <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max">Math.max</a> which will return the maximum item.</p>
<p>Afterwards we use a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">ternary operator</a> to assign either the maximum id or 0.</p>
<p>Here's the Express endpoint for a POST method:</p>
<pre><code><span class="hljs-comment">//an endpoint to add a note</span>
app.post(<span class="hljs-string">'/api/info'</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//without the middleware express.json() on L6 we wouldn't be able to read this data</span>
    <span class="hljs-comment">//extract the body from the request</span>
    const body <span class="hljs-operator">=</span> req.body
    <span class="hljs-comment">//check if the body doesn't contain any info</span>
    <span class="hljs-keyword">if</span>(<span class="hljs-operator">!</span>body.info) {
        <span class="hljs-comment">//return an error status and a json response</span>
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-function"><span class="hljs-keyword">error</span>: '<span class="hljs-title">you</span> <span class="hljs-title">need</span> <span class="hljs-title">to</span> <span class="hljs-title"><span class="hljs-keyword">type</span></span> <span class="hljs-title">the</span> <span class="hljs-title">information</span>'
        })
    }
    <span class="hljs-comment">//we make an object from the request to add it to our database</span>
    <span class="hljs-comment">//in order to generate the id and the date we use helper functions</span>
    <span class="hljs-comment">//read more about how to use Date: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date</span>
    <span class="hljs-title">const</span> <span class="hljs-title">infoObject</span> = </span>{
        id: generateId(),
        info: body.info,
        date: <span class="hljs-keyword">new</span> Date()
    }
    <span class="hljs-comment">//we modify our database by adding our object to it</span>
    <span class="hljs-comment">//first we copy the data (so we don't modify existing data), add our object and finally store everything back</span>
    <span class="hljs-comment">//feel free to read about ACID: Atomicity, Consistency, Isolation, and Durability</span>
    infoDB <span class="hljs-operator">=</span> infoDB.concat(infoObject)
    <span class="hljs-comment">//we send a response with the stored object</span>
    <span class="hljs-comment">//and a status of 201 which means created</span>
    res.status(<span class="hljs-number">201</span>).json(infoObject)
})
</code></pre><p>In order to make a call to our post endpoint and send the data it needs we use Postman as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019617639/mVnVzD3tr.png" alt="image.png" /></p>
<p>Make sure to select all the parameters in the picture: body -&gt; raw and JSON format.
After clicking the SEND button you should get back this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019673143/l1yVDCvx-.png" alt="image.png" /></p>
<h2 id="heading-delete">DELETE</h2>
<pre><code><span class="hljs-comment">//an endpoint to delete information from our db</span>
<span class="hljs-comment">//the ":id" at the end means we will be using that as a parameter</span>
<span class="hljs-comment">//we get the id from params.id in the request</span>
app.delete(<span class="hljs-string">'/api/info/:id'</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//parse the data as a number since req.params.id is a string</span>
    const id <span class="hljs-operator">=</span> Number(req.params.id)
    <span class="hljs-comment">//filer back all the data that doesn't contain the requested id</span>
    infoDB <span class="hljs-operator">=</span> infoDB.filter(i <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> i.id <span class="hljs-operator">!</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> id)
    <span class="hljs-comment">//return a code with no content and close the operation</span>
    res.status(<span class="hljs-number">204</span>).end()
})
</code></pre><p>If we want to delete the information object with the id 3 this is our call on Postman:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019770003/GLyBgBIZE.png" alt="image.png" /></p>
<h2 id="heading-put-or-update">PUT or Update</h2>
<p>We will be using a helper function to obtain the object we want to modify and its id:</p>
<pre><code><span class="hljs-comment">//helper function for the update operation</span>
<span class="hljs-comment">//we get the id of the object we want to modify</span>
<span class="hljs-comment">//then return the object to modify and its index in infoDB</span>
const getInfoObjectAndIndex <span class="hljs-operator">=</span> (id) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//declare our variables</span>
    let infoToModify <span class="hljs-operator">=</span> {}
    let indexOfInfo <span class="hljs-operator">=</span> <span class="hljs-number">0</span>
    <span class="hljs-comment">//find the object through the id and assign our values</span>
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> infoDB.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        <span class="hljs-keyword">if</span>(id <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> infoDB[i].id) {
            infoToModify <span class="hljs-operator">=</span> infoDB[i]
            indexOfInfo <span class="hljs-operator">=</span> i
        } 
    }
    <span class="hljs-comment">//return our values in form of an array</span>
    <span class="hljs-comment">//so we can use destructuring to assign our variables</span>
    <span class="hljs-keyword">return</span> [infoToModify, indexOfInfo]
}
</code></pre><p>The actual endpoint call is as follows:</p>
<pre><code><span class="hljs-comment">//an endpoint to update info</span>
app.put(<span class="hljs-string">'/api/info/:id'</span>, (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">//get the data from the body</span>
    const body <span class="hljs-operator">=</span> req.body
    <span class="hljs-comment">//if we don't get the information for our object throw an error</span>
    <span class="hljs-keyword">if</span>(<span class="hljs-operator">!</span>body.info) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({
        <span class="hljs-function"><span class="hljs-keyword">error</span>: '<span class="hljs-title">the</span> <span class="hljs-title">content</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">missing</span>'
    })
    <span class="hljs-comment">//check what you are getting(feel free to add console logs everywhere)</span>
    <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">body</span>)
    <span class="hljs-comment">//parse the date into a number</span>
    <span class="hljs-title">const</span> <span class="hljs-title">id</span> = <span class="hljs-title">Number</span>(<span class="hljs-params">req.params.id</span>)
    <span class="hljs-comment">//we use destructuring assignment here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment</span>
    <span class="hljs-title">const</span> [<span class="hljs-title">infoToModify</span>, <span class="hljs-title">indexOfInfo</span>] = <span class="hljs-title">getInfoObjectAndIndex</span>(<span class="hljs-params">id</span>)
    <span class="hljs-comment">//a console log to show the object we got</span>
    <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">infoToModify</span>)
    <span class="hljs-comment">//we make a new object with the new values</span>
    <span class="hljs-title">const</span> <span class="hljs-title">modifiedInfo</span> = </span>{
        id: infoToModify.id,
        info: body.info,
        date: infoToModify.date
    }
    <span class="hljs-comment">//insert (or overwrite) our object into the database</span>
    infoDB[indexOfInfo] <span class="hljs-operator">=</span> modifiedInfo
    <span class="hljs-comment">//send a success status</span>
    res.status(<span class="hljs-number">200</span>).json(modifiedInfo).end()
})
</code></pre><p>In order to update our data through Postman the call should be:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019856208/hE3N_6Gjc.png" alt="image.png" />
(that's the data you get after you press SEND, check through a GET call that you have all your data in the database)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649019917517/_LZOmX87P.png" alt="image.png" /></p>
<h1 id="heading-github-and-disclaimer">GitHub and disclaimer</h1>
<p>You can find the source code on my <a target="_blank" href="https://github.com/bgdnvk/MERN-stack-1">Github</a> here you have the <a target="_blank" href="https://github.com/bgdnvk/MERN-stack-1/blob/main/index.js">index.js</a> alone.</p>
<p>Note that this is the first chapter in a series of guides, here I haven't followed the best practices and this guide was solely made for learning purposes. If you are developing a proper product remember to use the <a target="_blank" href="https://expressjs.com/en/advanced/best-practice-security.html">best security practices</a>.</p>
<p>To get in direct touch with me you can hit me up on Twitter <a target="_blank" href="https://twitter.com/tekbog">@tekbog</a></p>
]]></content:encoded></item><item><title><![CDATA[Build a RESTful API using Spring Boot and store the data with MySQL]]></title><description><![CDATA[Introduction
This guide is on how to build a full RESTful API with Spring Boot so you can make CRUD operations on MySQL database.
You can find the code to the full project on my GitHub.
If you are unfamiliar with Spring Boot I have better introductor...]]></description><link>https://bognov.tech/build-a-restful-api-using-spring-boot-and-store-the-data-with-mysql</link><guid isPermaLink="true">https://bognov.tech/build-a-restful-api-using-spring-boot-and-store-the-data-with-mysql</guid><category><![CDATA[Java]]></category><category><![CDATA[APIs]]></category><category><![CDATA[backend]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[Spring]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Wed, 23 Feb 2022 01:10:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645577694416/uKRnNrfaf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>This guide is on how to build a full RESTful API with Spring Boot so you can make CRUD operations on MySQL database.</p>
<p>You can find the code to the full project on my <a target="_blank" href="https://github.com/bgdnvk/restful-tutorial-mysql">GitHub</a>.</p>
<p>If you are unfamiliar with Spring Boot I have better introductory articles:</p>
<ul>
<li><a target="_blank" href="https://bognov.tech/starting-with-spring-boot-how-to-make-a-restful-get-endpoint">Make a single GET endpoint</a></li>
<li><a target="_blank" href="https://bognov.tech/how-to-make-apis-with-spring-boot-read-from-a-mysql-database">APIs with Spring Boot</a></li>
</ul>
<p>For any questions you can reach me on Twitter <a target="_blank" href="https://twitter.com/tekbog">@tekbog</a></p>
<h1 id="heading-architecture">Architecture</h1>
<p>The project will have two layers:</p>
<ul>
<li>Business (where the logic is): Service and Controller</li>
<li>Data access layer: Repository and Entity</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645575647005/Acg84VEEw.png" alt="image.png" /></p>
<p>Additionally you would have a "view" layer to display the data properly using a front-end framework or JSP but this tutorial will only cover how to handle the API. If you are unfamiliar with some of these terms search for "MVC" and "3 tier" architectures.</p>
<h1 id="heading-connect-to-the-database">Connect to the database</h1>
<p>Before starting to code anything make sure your database is working and it's connected to your project. If everything is running then proceed to modify <code>resources/application.properties</code> file:</p>
<pre><code><span class="hljs-comment">#autotable creation</span>
<span class="hljs-attr">spring.jpa.hibernate.ddl-auto</span>=update
<span class="hljs-comment">#db connected</span>
<span class="hljs-attr">spring.datasource.url</span>=jdbc:mysql://localhost:<span class="hljs-number">3306</span>/db_restful_example_spring
<span class="hljs-attr">spring.datasource.username</span>=root
<span class="hljs-attr">spring.datasource.password</span>=password
</code></pre><h1 id="heading-entity-and-lombok">Entity and Lombok</h1>
<p>The very first thing is to know the data we are going to store in our database, in this case it will be as follows:</p>
<ul>
<li>id (Long)</li>
<li>data (String)</li>
<li>email (String)</li>
<li>name (String)</li>
</ul>
<p>Once that's clear we will proceed to make an Entity Class:</p>
<pre><code><span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">lombok</span><span class="hljs-selector-class">.AllArgsConstructor</span>;
<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">lombok</span><span class="hljs-selector-class">.Data</span>;
<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">lombok</span><span class="hljs-selector-class">.NoArgsConstructor</span>;
<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">lombok</span><span class="hljs-selector-class">.NonNull</span>;

<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">javax</span><span class="hljs-selector-class">.persistence</span>.*;

<span class="hljs-comment">//we define this is an entity</span>
@<span class="hljs-selector-tag">Entity</span>
<span class="hljs-comment">//using lombok</span>
<span class="hljs-comment">//generates all the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects)</span>
<span class="hljs-comment">// and beans: getters for all fields, setters for all non-final fields, and appropriate toString, equals and hashCode</span>
<span class="hljs-comment">//https://projectlombok.org/features/Data</span>
@<span class="hljs-selector-tag">Data</span>
<span class="hljs-comment">//generate constructors</span>
<span class="hljs-comment">// https://projectlombok.org/features/constructor</span>
@<span class="hljs-selector-tag">NoArgsConstructor</span>
@<span class="hljs-selector-tag">AllArgsConstructor</span>
<span class="hljs-selector-tag">public</span> <span class="hljs-selector-tag">class</span> <span class="hljs-selector-tag">DataExample</span> {
    <span class="hljs-comment">//all entity objects need an id</span>
    <span class="hljs-comment">//in this case every time new data added to the object</span>
    <span class="hljs-comment">//we get a new id</span>
    <span class="hljs-variable">@Id</span>
    <span class="hljs-variable">@GeneratedValue</span>(strategy = GenerationType.AUTO)
    <span class="hljs-variable">@Column</span>(name = <span class="hljs-string">"data_id"</span>, nullable = false)
    private Long dataId;

    <span class="hljs-comment">//make sure the email is not null</span>
    <span class="hljs-comment">//https://projectlombok.org/features/NonNull</span>
    <span class="hljs-variable">@NonNull</span>
    private String email;
    <span class="hljs-selector-tag">private</span> <span class="hljs-selector-tag">String</span> <span class="hljs-selector-tag">name</span>;
    <span class="hljs-selector-tag">private</span> <span class="hljs-selector-tag">String</span> <span class="hljs-selector-tag">data</span>;

}
</code></pre><p>We use <a target="_blank" href="https://projectlombok.org/">Lombok</a> to generate all the boilerplate code as explained above.</p>
<p>If you start the app you will generate the following table:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645135288065/-C5vf9Dq1.png" alt="imagen.png" /></p>
<h1 id="heading-set-up-the-repository">Set up the Repository</h1>
<p>The Repository annotation allows us to access and modify the data however we want, and it also gives us a lot of<a target="_blank" href="https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html">implemented methods thanks to JPA</a>. Additionally we can also use <a target="_blank" href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation">keywords to make methods we want</a> without writing JPQL or additional queries.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">restfultutorialmysql</span>.<span class="hljs-title">entity</span>.<span class="hljs-title">DataExample</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">data</span>.<span class="hljs-title">jpa</span>.<span class="hljs-title">repository</span>.<span class="hljs-title">JpaRepository</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">stereotype</span>.<span class="hljs-title">Repository</span>;

<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">util</span>.<span class="hljs-title">List</span>;

<span class="hljs-comment">//this is the implementation of the DAO interface</span>
<span class="hljs-comment">//data access object which lets you access and modify data</span>
<span class="hljs-comment">//the parameters are &lt;TypeOfData, TypeOfId&gt;</span>
@Repository
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DataExampleRepository</span> <span class="hljs-title">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">DataExample</span>, <span class="hljs-title">Long</span>&gt; </span>{

    <span class="hljs-comment">//this are JPA additional methods</span>
    <span class="hljs-comment">//follow the docs to know how to create them</span>
    <span class="hljs-comment">//https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation</span>
    <span class="hljs-comment">//uncomment this and try to implement them in the Service yourself</span>

<span class="hljs-comment">//    //get data by email</span>
<span class="hljs-comment">//    List&lt;DataExample&gt; findDataExampleByEmail(String email);</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">//    //get data by name</span>
<span class="hljs-comment">//    List&lt;DataExample&gt; findDataExampleByName(String name);</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">//    //get data by id</span>
<span class="hljs-comment">//    List&lt;DataExample&gt; findDataExampleByDataId(Long id);</span>
}
</code></pre><h1 id="heading-service">Service</h1>
<p>Following good practice first I will set up the interface and afterwards implement all the methods.</p>
<p>The interface:</p>
<pre><code><span class="hljs-keyword">import</span> com.example.restfultutorialmysql.entity.DataExample;

<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DataExampleService</span> </span>{
    <span class="hljs-comment">//GET</span>
    <span class="hljs-function">List&lt;DataExample&gt; <span class="hljs-title">getAllData</span><span class="hljs-params">()</span></span>;

    <span class="hljs-comment">//POST</span>
    <span class="hljs-function">DataExample <span class="hljs-title">saveData</span><span class="hljs-params">(DataExample dataExample)</span></span>;

    <span class="hljs-comment">//PUT</span>
    <span class="hljs-function">DataExample <span class="hljs-title">updateDate</span><span class="hljs-params">(DataExample dataExample)</span></span>;

    <span class="hljs-comment">//DELETE</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">deleteDataById</span><span class="hljs-params">(Long id)</span></span>;

}
</code></pre><p>The implementation:</p>
<pre><code><span class="hljs-keyword">import</span> com.example.restfultutorialmysql.entity.DataExample;
<span class="hljs-keyword">import</span> com.example.restfultutorialmysql.repository.DataExampleRepository;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-comment">//we define this cass as a service</span>
<span class="hljs-comment">//so we can use it as a bean in our Controller</span>
<span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataExampleServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DataExampleService</span></span>{

    <span class="hljs-comment">//bean injection</span>
    <span class="hljs-comment">//https://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it</span>
    <span class="hljs-comment">//the link above is to clarify if you get any kind of warning with @Autowired</span>
    <span class="hljs-comment">//we get the repository that will interact</span>
    <span class="hljs-comment">//with the database through our entity objects</span>
    <span class="hljs-meta">@Autowired</span>
    DataExampleRepository dataExampleRepository;

    <span class="hljs-comment">//implement all the CRUD methods</span>
    <span class="hljs-comment">//READ</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;DataExample&gt; <span class="hljs-title">getAllData</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> dataExampleRepository.findAll();
    }
    <span class="hljs-comment">//CREATE</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> DataExample <span class="hljs-title">saveData</span><span class="hljs-params">(DataExample dataExample)</span> </span>{
        <span class="hljs-keyword">return</span> dataExampleRepository.save(dataExample);
    }
    <span class="hljs-comment">//UPDATE</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> DataExample <span class="hljs-title">updateDate</span><span class="hljs-params">(DataExample dataExample)</span> </span>{
        <span class="hljs-keyword">return</span> dataExampleRepository.save(dataExample);
    }
    <span class="hljs-comment">//DELETE</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteDataById</span><span class="hljs-params">(Long id)</span> </span>{
        dataExampleRepository.deleteById(id);
    }
}
</code></pre><p>Note that we have implemented the CRUD operations: create, read, update and delete.</p>
<h1 id="heading-controller-setting-up-our-endpoints">Controller: setting up our endpoints</h1>
<p>Now that we have all good practices in place it's time to make our endpoints.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">restfultutorialmysql</span>.<span class="hljs-title">entity</span>.<span class="hljs-title">DataExample</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">restfultutorialmysql</span>.<span class="hljs-title">service</span>.<span class="hljs-title">DataExampleServiceImpl</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">beans</span>.<span class="hljs-title">factory</span>.<span class="hljs-title">annotation</span>.<span class="hljs-title">Autowired</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">http</span>.<span class="hljs-title">HttpStatus</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">http</span>.<span class="hljs-title">ResponseEntity</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">validation</span>.<span class="hljs-title">annotation</span>.<span class="hljs-title">Validated</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">web</span>.<span class="hljs-title">bind</span>.<span class="hljs-title">annotation</span>.<span class="hljs-operator">*</span>;

<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">util</span>.<span class="hljs-title">List</span>;

<span class="hljs-comment">//@RestController annotation will make this class the controller</span>
<span class="hljs-comment">//meaning that it's listening to htttp://localhost:8080 calls</span>
<span class="hljs-comment">//and replying with whatever endpoints you have made</span>
@RestController
<span class="hljs-comment">//if you want to add the api version, which is good practice</span>
<span class="hljs-comment">//add this annotation</span>
<span class="hljs-comment">//localhost:8080/api/v1</span>
<span class="hljs-comment">//@RequestMapping("api/v1")</span>
<span class="hljs-keyword">public</span> class Controller {

    <span class="hljs-comment">//we inject the service bean</span>
    <span class="hljs-comment">//and use it to handle the data</span>
    <span class="hljs-comment">//after every call to the endpoint we will do dataExampleService.method(methodParam);</span>
    @Autowired
    DataExampleServiceImpl dataExampleService;

    <span class="hljs-comment">//get all the data from the database using the service</span>
    <span class="hljs-comment">//once the call is successful respond with an OK status</span>
    @GetMapping(<span class="hljs-string">"/data"</span>)
    <span class="hljs-keyword">public</span> ResponseEntity<span class="hljs-operator">&lt;</span>List<span class="hljs-operator">&lt;</span>DataExample<span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span> getData(){
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResponseEntity<span class="hljs-operator">&lt;</span>List<span class="hljs-operator">&lt;</span>DataExample<span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span>(dataExampleService.getAllData(), HttpStatus.OK);
    }
    <span class="hljs-comment">//you can also just get all the data</span>
    <span class="hljs-comment">//without making a ResponseEntity object</span>
<span class="hljs-comment">//    @GetMapping("/data")</span>
<span class="hljs-comment">//    public List&lt;RandomData&gt; getData(){</span>
<span class="hljs-comment">//        return dataService.getRandomData();</span>
<span class="hljs-comment">//    }</span>

    <span class="hljs-comment">//save the data you send and return CREATED</span>
    <span class="hljs-comment">//valid docs: https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/Validate.html</span>
    <span class="hljs-comment">//difference with @Validated: https://stackoverflow.com/questions/36173332/difference-between-valid-and-validated-in-spring</span>
    <span class="hljs-comment">//ReQuestBody means you are expected to introduce data into your request</span>
    @PostMapping(<span class="hljs-string">"/data"</span>)
    <span class="hljs-keyword">public</span> ResponseEntity<span class="hljs-operator">&lt;</span>DataExample<span class="hljs-operator">&gt;</span> saveDate(@Validated @RequestBody DataExample dataExample){
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResponseEntity<span class="hljs-operator">&lt;</span><span class="hljs-operator">&gt;</span>(dataExampleService.saveData(dataExample), HttpStatus.CREATED);
    }

    <span class="hljs-comment">//update the data</span>
    @PutMapping(<span class="hljs-string">"/data"</span>)
    <span class="hljs-keyword">public</span> ResponseEntity<span class="hljs-operator">&lt;</span>DataExample<span class="hljs-operator">&gt;</span> updateData(@RequestBody DataExample dataExample){
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResponseEntity<span class="hljs-operator">&lt;</span><span class="hljs-operator">&gt;</span>(dataExampleService.updateDate(dataExample), HttpStatus.OK);
    }

    <span class="hljs-comment">//delete the data</span>
    <span class="hljs-comment">//PathVariable means you are expected to pass a parameter/variable</span>
    <span class="hljs-comment">//{id} translates into the Long id that you interact with afterwards</span>
    @DeleteMapping(<span class="hljs-string">"/data/{id}"</span>)
    <span class="hljs-keyword">public</span> ResponseEntity<span class="hljs-operator">&lt;</span>HttpStatus<span class="hljs-operator">&gt;</span> deleteData(@PathVariable Long id){
        dataExampleService.deleteDataById(id);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResponseEntity<span class="hljs-operator">&lt;</span><span class="hljs-operator">&gt;</span>(HttpStatus.NO_CONTENT);
    }

}
</code></pre><h1 id="heading-testing-our-app">Testing our app</h1>
<p>We will be using Postman for this purpose.</p>
<h2 id="heading-post">POST</h2>
<p>First we will test the POST method:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645488928648/NAnznKw4S.png" alt="image.png" /></p>
<p>Make sure you send the data as raw-&gt;JSON</p>
<pre><code>{
    <span class="hljs-attr">"email"</span>: <span class="hljs-string">"email3@email.com"</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"name example3"</span>,
    <span class="hljs-attr">"data"</span>: <span class="hljs-string">"this is an example of data3"</span>
}
</code></pre><p>As you can after we send the data we get it back with an assigned ID and a 201 OK status code.</p>
<p>The {{url}} is just a local variable that means:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645488952152/Ny_phFtH0.png" alt="image.png" /></p>
<p>You can define local variables while working with Postman, in our case is <code>http://localhost:8080</code> make sure you are using the correct port, if you want to make a call on postman without defining variables just write <code>http://localhost:8080/data</code></p>
<p>We have inserted data into our database, let's see if it's stored correctly:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645549483026/tynEUvHbM.png" alt="image.png" /></p>
<h2 id="heading-get">GET</h2>
<p>And now let's test the GET method:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645489325851/NspoKJSer.png" alt="image.png" /></p>
<p>The returned status is 200, so everything works as expected.</p>
<h2 id="heading-put">PUT</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645570903898/R2ayOI61l.png" alt="image.png" /></p>
<h2 id="heading-delete">DELETE</h2>
<p>Finally we test the delete method by deleting one of the items in our database:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645571063640/qTR0zodMA.png" alt="image.png" />
Check afterwards that it got deleted:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645571082527/_cjvRnJht.png" alt="image.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Full Stack development in 2022: trends, frameworks and languages.]]></title><description><![CDATA[Self-update or be deprecated
The tech industry is continuously evolving, changing, new tools are made every day and new frameworks are created or mass adopted. The point of this post is to glimpse at what's going on, check the current trends and wher...]]></description><link>https://bognov.tech/full-stack-development-in-2022-trends-frameworks-and-languages</link><guid isPermaLink="true">https://bognov.tech/full-stack-development-in-2022-trends-frameworks-and-languages</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Python]]></category><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Flutter]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Sun, 20 Feb 2022 00:39:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645315291066/0La8044_2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-self-update-or-be-deprecated">Self-update or be deprecated</h1>
<p>The tech industry is continuously evolving, changing, new tools are made every day and new frameworks are created or mass adopted. The point of this post is to glimpse at what's going on, check the current trends and where the industry is headed.</p>
<h1 id="heading-languages">Languages</h1>
<p>If you ever want to know what language is the most popular a good and don't know where to look the best place might be <a target="_blank" href="https://www.tiobe.com/tiobe-index/">TIOBE</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645307897259/fLo7CthA7N.png" alt="imagen.png" /></p>
<p>Python currently being king but closely followed by C and Java. Let me give a quick explanation on why those languages are the most used.</p>
<h2 id="heading-python">Python</h2>
<p>One of the selling points of Python is just how easy the syntax is and how it almost reads as pseudocode.   </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645369062253/FmQ2Z4spx.png" alt="image.png" />
Python has libraries for all your needs and despite being criticized as slow it's widely used everywhere. 
Most projects related to data science or machine learning will rely on Python, not to mention it has three of the most popular web frameworks right now: <a target="_blank" href="https://github.com/django/django">Django</a>, <a target="_blank" href="https://flask.palletsprojects.com/en/2.0.x/">Flask</a> and <a target="_blank" href="https://github.com/tiangolo/fastapi">FastAPI</a>.</p>
<p>It's the perfect language for beginners but at the same time it's widely adopted everywhere, if you don't know where to start learn Python but good looking trying to figure out the best environment:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645309138574/RSIZCU2fr.png" alt="imagen.png" /></p>
<p><a target="_blank" href="https://xkcd.com/1987/">There's always a relevant xkcd</a></p>
<h2 id="heading-c">C</h2>
<p>C isn't as trendy or flashy but it's everywhere and does everything. Operating systems, embedded programming, etc. Both <a target="_blank" href="https://github.com/git/git">Git</a> and <a target="_blank" href="https://github.com/torvalds/linux">Linux</a> are written mostly in C.</p>
<p><a target="_blank" href="https://youtu.be/CYvJPra7Ebk">If it's good enough for Linus then it's good enough for the rest of us.</a></p>
<h2 id="heading-java">Java</h2>
<p>Java, owned by Oracle, is enterprise king. Google, Netflix, Amazon, etc use Java in one way or another. </p>
<p>Most Apache projects are also written in Java - if you are curious to why, here's a <a target="_blank" href="https://news.ycombinator.com/item?id=9249913">HN reply</a>.</p>
<p>Learn Java, learn <a target="_blank" href="https://spring.io/">Spring</a> and you will never be out of a job. Check out some of the articles and tutorials on this blog about Java and Spring if you don't know where to start. The first post is: How to <a target="_blank" href="https://bognov.tech/starting-with-spring-boot-how-to-make-a-restful-get-endpoint">Make your first API.</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645310628891/xzMYlXhcx.png" alt="imagen.png" /></p>
<h2 id="heading-php">PHP</h2>
<p>Before JavaScript there was PHP, after JavaScript there's still PHP.  </p>
<p>This language went through a lot of iterations over the years to improve the developer's experience. Nowadays it's mainly used as a backend language on the web. It has two of the biggest frameworks: <a target="_blank" href="https://laravel.com/">Laravel</a> and <a target="_blank" href="https://symfony.com/">Symfony</a>.   </p>
<p>However PHP's main use comes from <a target="_blank" href="https://wordpress.org/">WordPress</a>. If you haven't heard or used WordPress, you should have a look. We don't know the exact statistics but everyone keeps saying that it powers over 33% of the web. Why? <a target="_blank" href="https://bognov.tech/how-to-install-wordpress-with-plesk-on-digitalocean">It's fast to set up</a>, design and have an e-commerce site ready or anything you'd want, there are millions of plugins and it's fairly easy to use for no-coders.<br />The perfect CMS, you can have a site with a blog in less than a day and focus on SEO (marketing loves WordPress for how easy it makes positioning) or whatever the business needs.  </p>
<p>If you ever hear that PHP is dead or dying, well, just look at the amount of jobs there are.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645362528737/MlQDPHTMd.png" alt="image.png" /></p>
<h1 id="heading-javascript">JavaScript</h1>
<p>Not long ago <a target="_blank" href="https://2021.stateofjs.com/en-US/">The State of JS 2021</a> was released. It doesn't take a very large pool of votes but it's widely known in the dev community and worth looking into. It's probably one of the most important surveys to consider if you have anything to do with JavaScript. Most tools/frameworks work with TypeScript as well, if you were in doubt.</p>
<h2 id="heading-front-end-frameworks">Front-end Frameworks</h2>
<p>The big three are there as always there: React, Angular and Vue:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645311426706/vdvs8XBiH.png" alt="imagen.png" /></p>
<p>Last year <a target="_blank" href="https://svelte.dev/">Svelte</a> made a lot of noise and it's slowly being adopted, the docs have improved a lot and after trying it for a bit I consider myself a fan as well for its ease of use.<br />However it's not the only new kid on the block, I've seen a lot of praise for both <a target="_blank" href="https://www.solidjs.com/">SolidJS</a> and <a target="_blank" href="https://alpinejs.dev/">AlpineJS</a>. </p>
<h2 id="heading-back-end-frameworks">Back-end Frameworks</h2>
<p>The results aren't going to surprise anyone, if you are a backend developer you have to know Express:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645312134123/k86FJF5iT.png" alt="imagen.png" /></p>
<p>Although the amount of new tools we got this past year has been impressive:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645312199337/kQDD-GuEw.png" alt="imagen.png" /></p>
<p>From what I've seen I believe <a target="_blank" href="https://remix.run/">Remix</a> is the one receiving the most hype right now but <a target="_blank" href="https://astro.build/">Astro</a> and <a target="_blank" href="https://kit.svelte.dev/">SvelteKit</a> could be here to stay.</p>
<h2 id="heading-testing-do-people-actually">Testing? Do people actually..?</h2>
<p>Yes, TDD is a thing.<br />Jest or Mocha at the top. The usual.   </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645312648863/yA9u52HDI.png" alt="imagen.png" /></p>
<h2 id="heading-bloated-apps-for-mobile-and-desktop">Bloated apps for mobile and desktop</h2>
<p>Don't freak out if you open your Discord desktop app and you can inspect its source code as if it was an ordinary website. Everything is JavaScript now, well, TypeScript actually.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645312730862/U51evV8OY.png" alt="imagen.png" /></p>
<p><a target="_blank" href="https://www.electronjs.org/">Electron</a> and <a target="_blank" href="https://reactnative.dev/">React Native</a> shouldn't surprise anyone, with Cordova and Ionic following close.</p>
<p>It will be fun to see how <a target="_blank" href="https://tauri.studio/">Tauri</a> can compete or find its market considering <a target="_blank" href="https://medium.com/flutter/announcing-flutter-for-windows-6979d0d01fed">Flutter is here</a>.</p>
<h2 id="heading-build-tools">Build Tools</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645313030393/1Yo0-7WvK.png" alt="imagen.png" /></p>
<p>Nothing out of the ordinary, however I expect <a target="_blank" href="https://vitejs.dev/">Vite</a> to be widely adopted by next year.</p>
<h2 id="heading-libraries">Libraries</h2>
<p>Here we have Axios, Lodash, Moment, Redux, etc. Nothing out of the ordinary.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645313272660/YXKqt0u-N.png" alt="imagen.png" /></p>
<p>Out of the list you should know <a target="_blank" href="https://redux.js.org/">Redux</a> and <a target="_blank" href="https://tailwindcss.com/">Tailwindcss</a>.</p>
<h1 id="heading-google-shenanigans">Google shenanigans</h1>
<p>Google has been hard at work this last couple of years when it comes to their tools, and I'm not talking about <a target="_blank" href="https://github.com/kubernetes/kubernetes">Kubernetes</a> here or the awful state of the search engine.</p>
<h2 id="heading-go">Go</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645313643322/N8lyVFfJd.png" alt="imagen.png" />
If you are a backend developer you probably have noticed the increased adoption of the <a target="_blank" href="https://go.dev/">Go language</a>. Considering that K8s is written in Go and the amount of companies that have started to use it I'd keep an eye on the language and its ecosystem.</p>
<h2 id="heading-flutter">Flutter</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645314161818/3QTd2GxYX.png" alt="imagen.png" />
Google has decided Facebook (Meta) is too cool with their React Native and <a target="_blank" href="https://medium.com/flutter/announcing-flutter-for-windows-6979d0d01fed">who doesn't want to get rid of Electron</a>? Enter <a target="_blank" href="https://flutter.dev/">Flutter</a>. 
They might be getting a bit too ambitious here but working with Flutter and Dart is a breeze. </p>
<p>I've directed a multi-platform project this past year using Flutter + Firebase. It's fairly easy to setup and make an MVP, I recommend it highly for a fast paced project where the client doesn't want a pixel-perfect design, perfect for startups. </p>
<p>For anything else? Well, as always, <strong>it depends</strong>. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645315192940/np9-fehbq.png" alt="imagen.png" /></p>
<h1 id="heading-what-else-is-out-there">What else is out there?</h1>
<p>Terraform, serverless architecture, Rust, micro frontends and everything involved in Web 3.0: blockchain, crypto, NFTs, all that jazz.</p>
<h1 id="heading-cest-fini">C'est fini</h1>
<p><a target="_blank" href="https://joancornella.net/en/">The cover art is from Joan Cornellà</a>.  </p>
<p>If you think I'm wrong we can argue on Twitter: <a target="_blank" href="https://twitter.com/tekbog">hmu @tekbog</a>.  </p>
<p>Disclaimer: I haven't talked about C#, C++, Ruby, Swift, R, etc because they are out of my area of expertise.  </p>
]]></content:encoded></item><item><title><![CDATA[How to make APIs with Spring Boot: read from a MySQL database]]></title><description><![CDATA[Before we start coding
TL;DR

Make a database
Connect database to our project
Use GET calls to read from SQL database with Spring Boot
Source code on Github
Architecture:


For any questions you can ask me on Twitter @ tekbog
Set up the database (and...]]></description><link>https://bognov.tech/how-to-make-apis-with-spring-boot-read-from-a-mysql-database</link><guid isPermaLink="true">https://bognov.tech/how-to-make-apis-with-spring-boot-read-from-a-mysql-database</guid><category><![CDATA[Java]]></category><category><![CDATA[Springboot]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[APIs]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Sun, 30 Jan 2022 04:23:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643516107911/3aYOTp_KF.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-before-we-start-coding">Before we start coding</h1>
<h3 id="heading-tldr">TL;DR</h3>
<ol>
<li>Make a database</li>
<li>Connect database to our project</li>
<li>Use GET calls to read from SQL database with Spring Boot</li>
<li>Source code on <a target="_blank" href="https://github.com/bgdnvk/sqldbexample">Github</a></li>
<li>Architecture:</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643512825318/lEWeqxy7J.png" alt="image.png" /></p>
<p>For any questions you can ask me on <a target="_blank" href="https://twitter.com/tekbog">Twitter @ tekbog</a></p>
<h2 id="heading-set-up-the-database-and-make-sure-its-running">Set up the database (and make sure it's running)</h2>
<p>In my case I'm gonna use MySQL Workbench to create a database called "mydb" and then add a table called "my_table"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643511954084/DnG9L_fc8.png" alt="image.png" /></p>
<p>Once that's done run this query to put some data in your database:</p>
<pre><code><span class="hljs-keyword">USE</span> mydb;

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> my_table 
(
    <span class="hljs-keyword">id</span> <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT PRIMARY <span class="hljs-keyword">KEY</span>,
    <span class="hljs-keyword">name</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    email <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> my_table (<span class="hljs-keyword">name</span>, email) <span class="hljs-keyword">VALUES</span> (<span class="hljs-string">"random_name"</span>, <span class="hljs-string">"random@random.com"</span>);
<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> my_table (<span class="hljs-keyword">name</span>, email) <span class="hljs-keyword">VALUES</span> (<span class="hljs-string">"random_name1"</span>, <span class="hljs-string">"random1@random.com"</span>);
<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> my_table (<span class="hljs-keyword">name</span>, email) <span class="hljs-keyword">VALUES</span> (<span class="hljs-string">"random_name2"</span>, <span class="hljs-string">"random2@random.com"</span>);
</code></pre><h2 id="heading-starting-with-spring-boot">Starting with Spring Boot</h2>
<p>Connect your database to the Spring Boot app by changing </p>
<pre><code><span class="hljs-selector-tag">application</span><span class="hljs-selector-class">.properties</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643512941776/M6XX1L1GH.png" alt="image.png" /></p>
<p>The port is default, make sure it's the same. You can check the port number when you start the Spring Boot app. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643513347958/g8lBIHwUX.png" alt="image.png" />
The username and password pertain to your MySQL database.</p>
<pre><code>spring.datasource.url=jdbc:mysql:<span class="hljs-comment">//localhost:3306/mydb</span>
spring.datasource.username=root
spring.datasource.password=password
</code></pre><p>And the dependencies are:</p>
<pre><code>    <span class="hljs-operator">&lt;</span>dependencies<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>dependency<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>groupId<span class="hljs-operator">&gt;</span>org.springframework.boot&lt;<span class="hljs-operator">/</span>groupId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>artifactId<span class="hljs-operator">&gt;</span>spring<span class="hljs-operator">-</span>boot<span class="hljs-operator">-</span>starter<span class="hljs-operator">-</span>data<span class="hljs-operator">-</span>jpa<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>artifactId<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>dependency<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>groupId<span class="hljs-operator">&gt;</span>org.springframework.boot&lt;<span class="hljs-operator">/</span>groupId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>artifactId<span class="hljs-operator">&gt;</span>spring<span class="hljs-operator">-</span>boot<span class="hljs-operator">-</span>starter<span class="hljs-operator">-</span>jdbc<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>artifactId<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>dependency<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>groupId<span class="hljs-operator">&gt;</span>org.springframework.boot&lt;<span class="hljs-operator">/</span>groupId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>artifactId<span class="hljs-operator">&gt;</span>spring<span class="hljs-operator">-</span>boot<span class="hljs-operator">-</span>starter<span class="hljs-operator">-</span>web<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>artifactId<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">&gt;</span>

        <span class="hljs-operator">&lt;</span>dependency<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>groupId<span class="hljs-operator">&gt;</span>mysql<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>groupId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>artifactId<span class="hljs-operator">&gt;</span>mysql<span class="hljs-operator">-</span>connector<span class="hljs-operator">-</span>java<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>artifactId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>scope<span class="hljs-operator">&gt;</span>runtime<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>scope<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">&gt;</span>

        <span class="hljs-operator">&lt;</span>dependency<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>groupId<span class="hljs-operator">&gt;</span>org.projectlombok&lt;<span class="hljs-operator">/</span>groupId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>artifactId<span class="hljs-operator">&gt;</span>lombok<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>artifactId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>optional<span class="hljs-operator">&gt;</span><span class="hljs-literal">true</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>optional<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">&gt;</span>

        <span class="hljs-operator">&lt;</span>dependency<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>groupId<span class="hljs-operator">&gt;</span>org.springframework.boot&lt;<span class="hljs-operator">/</span>groupId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>artifactId<span class="hljs-operator">&gt;</span>spring<span class="hljs-operator">-</span>boot<span class="hljs-operator">-</span>starter<span class="hljs-operator">-</span>test<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>artifactId<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>scope<span class="hljs-operator">&gt;</span>test<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>scope<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">&gt;</span>

    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dependencies<span class="hljs-operator">&gt;</span>
</code></pre><p>You can use <a target="_blank" href="https://start.spring.io/">Spring Initializr</a> as well to set up your project, it's highly recommended.</p>
<h2 id="heading-postman">Postman</h2>
<p>In order to make calls to the server I'm going to be using <a target="_blank" href="https://www.postman.com/">Postman</a>
Although there are many alternatives.</p>
<h1 id="heading-architecture-and-code">Architecture and code</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643513256644/OGcFKSGAZ.png" alt="image.png" />
The "folders" are called packages, once you create them: inside you can make classes, interfaces, etc.</p>
<h2 id="heading-entity">Entity</h2>
<p>UserData class makes it possible to interact with the database</p>
<pre><code><span class="hljs-selector-tag">package</span> <span class="hljs-selector-tag">com</span><span class="hljs-selector-class">.example</span><span class="hljs-selector-class">.sqldbexample</span><span class="hljs-selector-class">.entity</span>;


<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">lombok</span><span class="hljs-selector-class">.Getter</span>;

<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">javax</span><span class="hljs-selector-class">.persistence</span>.*;

<span class="hljs-comment">//lombok getter so we don't have to write getters</span>
@<span class="hljs-selector-tag">Getter</span>
<span class="hljs-comment">//The entity interacts with the database</span>
@<span class="hljs-selector-tag">Entity</span>
@<span class="hljs-selector-tag">Table</span>(name = <span class="hljs-string">"my_table"</span>)
<span class="hljs-selector-tag">public</span> <span class="hljs-selector-tag">class</span> <span class="hljs-selector-tag">UserData</span> {
    <span class="hljs-comment">//an id is always needed to index the data</span>
    <span class="hljs-comment">//the annotation GeneratedValue allows the data to be generated automatically</span>
    <span class="hljs-comment">//and we add the name of the columns where the data goes</span>
    <span class="hljs-variable">@Id</span>
    <span class="hljs-variable">@GeneratedValue</span>(strategy = GenerationType.AUTO)
    <span class="hljs-variable">@Column</span>(name = <span class="hljs-string">"id"</span>, nullable = false)
    private Long id;

    <span class="hljs-variable">@Column</span>(name = <span class="hljs-string">"name"</span>)
    private String name;

    <span class="hljs-variable">@Column</span>(name = <span class="hljs-string">"email"</span>)
    private String email;
}
</code></pre><p>To begin we import <a target="_blank" href="https://projectlombok.org/features/GetterSetter">Lombok</a> so we don't have to write the getters for the class. Afterwards we define the class as Entity and map the Java objects to the database we are accessing.
The most confused annotation could be GeneratedValue: we always need an id and in this case we made our id to be generated automatically. Spring annotations have the following syntax:</p>
<pre><code><span class="hljs-meta">@AnnotationName(parameter=<span class="hljs-meta-string">"parameter value"</span>)</span>
</code></pre><h2 id="heading-repository">Repository</h2>
<p>The Repository interface is a <a target="_blank" href="https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/dao.html">DAO (data access object)</a> bean that simplifies our interaction with SQL thanks to JPA, the interface takes 2 parameters: the type of object and the type of id, after which it will allow you to use its extended methods:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643514703251/Li5KUFAKW.png" alt="image.png" /></p>
<p>In our case we want to interact with the entity object we have created called UserData and the id is Long type.</p>
<p>Note that Repository annotation also indicates that this is a type of bean we can use anywhere in our project.</p>
<pre><code>package com.example.sqldbexample.repository;

<span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">sqldbexample</span>.<span class="hljs-title">entity</span>.<span class="hljs-title">UserData</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">data</span>.<span class="hljs-title">jpa</span>.<span class="hljs-title">repository</span>.<span class="hljs-title">JpaRepository</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">stereotype</span>.<span class="hljs-title">Repository</span>;

<span class="hljs-comment">//repository to interact with the entity</span>
<span class="hljs-comment">//we use the JpaRepository because of all its methods</span>
@Repository
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserDataRepository</span> <span class="hljs-title">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">UserData</span>, <span class="hljs-title">Long</span>&gt; </span>{
}
</code></pre><h2 id="heading-service">Service</h2>
<p>UserDataService interface is gonna allow us to use the repository we have just created to get the data we want</p>
<pre><code>package com.example.sqldbexample.service;

<span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">sqldbexample</span>.<span class="hljs-title">entity</span>.<span class="hljs-title">UserData</span>;

<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">util</span>.<span class="hljs-title">List</span>;

<span class="hljs-comment">//interface to handle the entity UserData</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserDataService</span> </span>{
    List<span class="hljs-operator">&lt;</span>UserData<span class="hljs-operator">&gt;</span> getUserData();
}
</code></pre><p>Now the implementation is as follows:</p>
<pre><code>package com.example.sqldbexample.service;

<span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">sqldbexample</span>.<span class="hljs-title">entity</span>.<span class="hljs-title">UserData</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">example</span>.<span class="hljs-title">sqldbexample</span>.<span class="hljs-title">repository</span>.<span class="hljs-title">UserDataRepository</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">beans</span>.<span class="hljs-title">factory</span>.<span class="hljs-title">annotation</span>.<span class="hljs-title">Autowired</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">springframework</span>.<span class="hljs-title">stereotype</span>.<span class="hljs-title">Service</span>;

<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">util</span>.<span class="hljs-title">List</span>;

@Service
<span class="hljs-keyword">public</span> class UserDataServiceImpl implements UserDataService{

    <span class="hljs-comment">//get the repository bean</span>
    @Autowired
    UserDataRepository userDataRepository;

    <span class="hljs-comment">//we use the repository bean to get access to all the methods</span>
    <span class="hljs-comment">//like findAll</span>
    @Override
    <span class="hljs-keyword">public</span> List<span class="hljs-operator">&lt;</span>UserData<span class="hljs-operator">&gt;</span> getUserData() {
        <span class="hljs-keyword">return</span> userDataRepository.findAll();
    }
}
</code></pre><p>Thanks to the <a target="_blank" href="https://spring.io/projects/spring-data-jpa">JPA</a> repository we get access to all its methods without having to implement any of them, it just works with our MySQL database. So in order to get all the users from the table we use .findAll() method.</p>
<h2 id="heading-api">API</h2>
<p><a target="_blank" href="https://bognov.tech/starting-with-spring-boot-how-to-make-a-restful-get-endpoint">You can read my previous article if you are unfamiliar with the Controller</a></p>
<pre><code><span class="hljs-comment">//@RestController annotation will make this class the controller</span>
<span class="hljs-comment">//meaning that it's listening to htttp://localhost:8080 calls</span>
<span class="hljs-comment">//and replying with whatever endpoints you have made</span>
<span class="hljs-variable">@RestController</span>
<span class="hljs-comment">//localhost:8080/api/v1</span>
<span class="hljs-variable">@RequestMapping</span>(<span class="hljs-string">"api/v1"</span>)
public class Controller {

    <span class="hljs-variable">@Autowired</span>
    private UserDataService userDataService;

    <span class="hljs-variable">@GetMapping</span>(<span class="hljs-string">"/getdata"</span>)
    public List&lt;UserData&gt; getData(){
        <span class="hljs-selector-tag">return</span> <span class="hljs-selector-tag">userDataService</span><span class="hljs-selector-class">.getUserData</span>();
    }
}
</code></pre><p>The main difference is the fact that we add RequestMapping so everything goes to <code>api/v1</code> path after <code>localhost:port/</code>. Putting the version of your API is good practice.</p>
<p>To sum it up we use the UserDataService bean (service), the Autowired annotation allows us to get the bean through <a target="_blank" href="https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html">Inversion of Control (Spring magic)</a> and use that interface's implementation without calling it ourselves.</p>
<h2 id="heading-test-that-everything-works">Test that everything works</h2>
<p>Start the server, make sure your database is running and then using Postman call <code>localhost:8080/api/v1/getdata</code></p>
<p>you should get this back:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643515521035/u4D0vpDOU.png" alt="image.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Starting with Spring Boot: how to make a RESTful GET endpoint]]></title><description><![CDATA[Disregard the Java hate wagon
Java is often hated for various reasons one of them is being too verbose.

However it's a great language that's continuously evolving and it's an absolute king of enterprise software, for the good or the bad. One of its ...]]></description><link>https://bognov.tech/starting-with-spring-boot-how-to-make-a-restful-get-endpoint</link><guid isPermaLink="true">https://bognov.tech/starting-with-spring-boot-how-to-make-a-restful-get-endpoint</guid><category><![CDATA[Spring]]></category><category><![CDATA[Springboot]]></category><category><![CDATA[Java]]></category><category><![CDATA[backend]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Fri, 21 Jan 2022 12:31:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1642767712124/BW3Zet_oq.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-disregard-the-java-hate-wagon">Disregard the Java hate wagon</h2>
<p>Java is often hated for various reasons one of them is being too verbose.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642725472805/kasGXhAxt.png" alt="image.png" /></p>
<p>However it's a great language that's continuously evolving and it's an absolute king of enterprise software, for the good or the bad. One of its main strengths is the <a target="_blank" href="https://spring.io/">Spring Framework</a>, and for anyone who wants to make a project quickly Spring Boot is the fastest and easiest way to make your backend with Java. Spring is a tested framework that has evolved through the years, just like Java, it's secure and you can find any bugs you will encounter on <a target="_blank" href="https://stackoverflow.com/questions/tagged/spring-boot">StackOverflow</a> with ease.</p>
<p>Under the hood Spring is very complex and let's you trivialize a lot of needed implementations thanks to its <strong>inversion of control</strong> and <strong>dependency injection</strong>, you use all the power of the framework through annotations. </p>
<h2 id="heading-start-the-project">Start the project</h2>
<p>Start the project with <a target="_blank" href="https://start.spring.io/">Spring Initializr</a> if your IDE doesn't have it built-in just download it (generate) from the site and include the dependency of Spring Web as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642726188752/Y7vagEKRk.png" alt="image.png" /></p>
<h2 id="heading-restcontroller">RestController</h2>
<p>After you have started your project all you need to do is make a new class anywhere and just add the <code>@RestController</code>  this will instantly tell Sping that this class will have RESTful endpoints:</p>
<pre><code><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Controller</span> </span>{
}
</code></pre><p>RestController annotation will make this class the controller meaning that it's listening to <code>htttp://localhost:8080</code> calls and replying with whatever endpoints you have made.</p>
<p>For clarification: </p>
<ul>
<li>8080 is the default port but you can change it in <code>application.properties</code></li>
<li>all the Spring annotations start with @</li>
</ul>
<h2 id="heading-getmapping">GetMapping</h2>
<p>This GetMapping annotation makes the <code>htttp://localhost:8080/api</code> endpoint, after the call it will return or do whatever you put in the api() method. The name of the method is irrelevant, and it can also be void. </p>
<p>If you want your endpoint to be something other than <code>/api</code> just write the name you want.</p>
<pre><code><span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/api"</span>)</span>
<span class="hljs-keyword">public</span> String api(){
    <span class="hljs-keyword">return</span> <span class="hljs-string">"call to /api"</span>;
}
</code></pre><p>When you type in the browser the URL you will see the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642766831488/dNeLtWDhsX.png" alt="image.png" /></p>
<h2 id="heading-requestparam">RequestParam</h2>
<p>If you want to extract a query parameter in your get method then you need to add the RequestParam as the following:</p>
<pre><code><span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/call"</span>)</span>
<span class="hljs-keyword">public</span> String call(<span class="hljs-meta">@RequestParam(value = <span class="hljs-meta-string">"val"</span>)</span> String <span class="hljs-keyword">val</span>){
    <span class="hljs-keyword">return</span> <span class="hljs-string">"the val is "</span>+<span class="hljs-keyword">val</span>;
}
</code></pre><p>This is an example of a call:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642767189948/KOVVqdiNc.png" alt="image.png" /></p>
<p>The enpoint <code>htttp://localhost:8080/call</code> will read the parameter you pass in the browser, for example</p>
<pre><code><span class="hljs-attribute">http</span>:<span class="hljs-comment">//localhost:8080/call?val=myparam</span>
</code></pre><h2 id="heading-controller-class-code-andamp-tldr">Controller class code &amp; TL;DR</h2>
<pre><code><span class="hljs-comment">//@RestController annotation will make this class the controller</span>
<span class="hljs-comment">//meaning that it's listening to htttp://localhost:8080 calls</span>
<span class="hljs-comment">//and replying with whatever endpoints you have made</span>
<span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Controller</span> </span>{

    <span class="hljs-comment">//@GetMapping annotation makes the htttp://localhost:8080/api endpoint</span>
    <span class="hljs-comment">//it will return or do whatever you put in the api() method</span>
    <span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/api"</span>)</span>
    <span class="hljs-keyword">public</span> String api(){
        <span class="hljs-keyword">return</span> <span class="hljs-string">"call to /api"</span>;
    }

    <span class="hljs-comment">//the enpoint is htttp://localhost:8080/call</span>
    <span class="hljs-comment">//it also reads the parameters you pass in the browser</span>
    <span class="hljs-comment">//for example http://localhost:8080/call?val=myvalue</span>
    <span class="hljs-comment">//it can read the parameters because of the @RequestParam annotation</span>
    <span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/call"</span>)</span>
    <span class="hljs-keyword">public</span> String call(<span class="hljs-meta">@RequestParam(value = <span class="hljs-meta-string">"val"</span>)</span> String <span class="hljs-keyword">val</span>){
        <span class="hljs-keyword">return</span> <span class="hljs-string">"the val is "</span>+<span class="hljs-keyword">val</span>;
    }

}
</code></pre><p>Official Spring documentation:</p>
<ul>
<li><a target="_blank" href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html">RequestParam</a></li>
<li><a target="_blank" href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/GetMapping.html">GetMapping</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[JavaScript Arrays 101 tips and tricks ft. LeetCode]]></title><description><![CDATA[What is LeetCode?
 LeetCode  defines itself as

LeetCode is the best platform to help you enhance your skills, expand your knowledge and prepare for technical interviews.

Is it truly the best? That's debatable (I will explain in another article) how...]]></description><link>https://bognov.tech/javascript-arrays-101-tips-and-tricks-ft-leetcode</link><guid isPermaLink="true">https://bognov.tech/javascript-arrays-101-tips-and-tricks-ft-leetcode</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Competitive programming]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Mon, 29 Nov 2021 06:41:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638167862589/s0lVjRja3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-what-is-leetcode">What is LeetCode?</h1>
<p> <a target="_blank" href="https://leetcode.com/">LeetCode</a>  defines itself as</p>
<blockquote>
<p>LeetCode is the best platform to help you enhance your skills, expand your knowledge and prepare for technical interviews.</p>
</blockquote>
<p>Is it truly the best? That's debatable (I will explain in another article) however it's very useful and it's been a standard for interviews - especially from FAANG companies (or MAANG now) - since the tech boom and the need to filter candidates. 
I personally like it because I generally enjoy challenging programming problems but most people use the platform just to prepare for interviews.</p>
<h1 id="heading-javascript-arrayshttpsgithubcombgdnvkleetcode-arrays-101"><a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101">JavaScript Arrays</a></h1>
<p>LeetCode has something called "Explore Cards" so I decided to dive into Arrays
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638157836291/D8Alm_MZy.png" alt="image.png" /></p>
<p>Next you will find all the problems and its solutions with comments.<br /><a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101">The full repository is here.</a> And you can find me on <a target="_blank" href="https://twitter.com/tekbog">Twitter @tekbog</a></p>
<h3 id="heading-max-consecutive-oneshttpsleetcodecomproblemsmax-consecutive-ones"><a target="_blank" href="https://leetcode.com/problems/max-consecutive-ones/">Max Consecutive Ones</a></h3>
<p>Given a binary array nums, return the maximum number of consecutive 1's in the array.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165166569/e0UQUTwNm.png" alt="image.png" /></p>
<p> <a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Max%20Consecutive%20Ones.js">Solution:</a> </p>
<pre><code><span class="hljs-keyword">var</span> findMaxConsecutiveOnes <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
     <span class="hljs-comment">//initialize a variable to keep track of the max consecutive ones</span>
    <span class="hljs-keyword">var</span> contmax <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">var</span> cont <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        <span class="hljs-comment">// console.log("i is: "+nums[i]);</span>
        <span class="hljs-keyword">if</span>(nums[i]){
            <span class="hljs-comment">//simple counter, if there's something in the array then add 1 to the counter</span>
            cont<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
            <span class="hljs-comment">// console.log("cont is "+cont);</span>
        } <span class="hljs-keyword">else</span> {
            console.log(<span class="hljs-string">"it's a zero "</span> <span class="hljs-operator">+</span>i)
            console.log(<span class="hljs-string">"cont is "</span><span class="hljs-operator">+</span>cont)
            <span class="hljs-comment">//check if the current consecutive ones is greater than the max consecutive ones we have already</span>
            contmax <span class="hljs-operator">=</span> Math.<span class="hljs-built_in">max</span>(cont, contmax);
            cont <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        }
    }
    <span class="hljs-comment">// console.log("contmax is "+contmax)</span>
    <span class="hljs-comment">// this is a ternary operator</span>
    <span class="hljs-comment">//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator</span>
    <span class="hljs-comment">// check which counter is higher and return it in case the last counter is higher</span>
    <span class="hljs-keyword">return</span> cont <span class="hljs-operator">&gt;</span> contmax ? cont: contmax;
};
</code></pre><h3 id="heading-find-numbers-with-even-number-of-digitshttpsleetcodecomproblemsfind-numbers-with-even-number-of-digits"><a target="_blank" href="https://leetcode.com/problems/find-numbers-with-even-number-of-digits/">Find Numbers with Even Number of Digits</a></h3>
<p>Given an array nums of integers, return how many of them contain an even number of digits.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165244970/fEVGg3p3M.png" alt="image.png" /></p>
<p> <a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Find%20Numbers%20with%20Even%20Number%20of%20Digits.js">Solution: </a> </p>
<pre><code> <span class="hljs-keyword">var</span> findNumbers <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
     <span class="hljs-comment">//log for debugging</span>
    console.log(...nums)
    <span class="hljs-comment">//initialize a variable to keep track of the even numbers of digits</span>
    let count <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-comment">//iterate through the array</span>
    <span class="hljs-keyword">for</span> (let num of nums){
        console.log(num.toString().split(<span class="hljs-string">''</span>))
        <span class="hljs-comment">//convert the number to a string to use string methods</span>
        <span class="hljs-comment">//we can clearly see the number of digits in every number now</span>
        let innerNum <span class="hljs-operator">=</span> num.toString().split(<span class="hljs-string">''</span>)
        <span class="hljs-keyword">if</span> (innerNum.<span class="hljs-built_in">length</span> <span class="hljs-operator">%</span> <span class="hljs-number">2</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>){
            <span class="hljs-comment">//if the number of digits is even, add one to the count</span>
            count<span class="hljs-operator">+</span><span class="hljs-operator">+</span>
        }
    }
    <span class="hljs-keyword">return</span> count;
};
</code></pre><h3 id="heading-squares-of-a-sorted-arrayhttpsleetcodecomproblemssquares-of-a-sorted-array"><a target="_blank" href="https://leetcode.com/problems/squares-of-a-sorted-array/">Squares of a Sorted Array</a></h3>
<p>Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165274665/h-XiZZu-l.png" alt="image.png" /></p>
<p> <a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Squares%20of%20a%20Sorted%20Array.js">Solution:</a> </p>
<pre><code> <span class="hljs-keyword">var</span> sortedSquares <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-comment">//create a new array to store the squares</span>
    let arr <span class="hljs-operator">=</span> [];
    <span class="hljs-comment">//push the squares of the numbers into the array</span>
    <span class="hljs-keyword">for</span> (let i of nums){
        arr.<span class="hljs-built_in">push</span>(i<span class="hljs-operator">*</span>i)
    }
    console.log(arr)
    <span class="hljs-comment">//sort the array in non-decreasing order</span>
    arr.sort((a,b) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> a<span class="hljs-operator">-</span>b)
    console.log(arr)
    <span class="hljs-keyword">return</span> arr
};
</code></pre><h3 id="heading-duplicate-zeroshttpsleetcodecomproblemsduplicate-zeros"><a target="_blank" href="https://leetcode.com/problems/duplicate-zeros/">Duplicate Zeros</a></h3>
<p>Given a fixed-length integer array arr, duplicate each occurrence of zero, shifting the remaining elements to the right.</p>
<p>Note that elements beyond the length of the original array are not written. Do the above modifications to the input array in place and do not return anything.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165347271/vfc_jTWi_.png" alt="image.png" /></p>
<p> <a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Duplicate%20Zeros.js">Solution:</a> </p>
<pre><code><span class="hljs-keyword">var</span> duplicateZeros <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">arr</span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i<span class="hljs-operator">=</span><span class="hljs-number">0</span>; i<span class="hljs-operator">&lt;</span>arr.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        <span class="hljs-keyword">if</span> (arr[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
            <span class="hljs-comment">//use the method splice to insert a new zero after the current zero</span>
            arr.splice(i, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
            <span class="hljs-comment">//get rid of the last element since we just inserted a new zero so there's less space in the array</span>
            arr.<span class="hljs-built_in">pop</span>();
            <span class="hljs-comment">//increment i to skip over the new zero we just inserted</span>
            i<span class="hljs-operator">+</span><span class="hljs-operator">=</span><span class="hljs-number">1</span>
        }
    }
};
</code></pre><h3 id="heading-merge-sorted-arrayhttpsgithubcombgdnvkleetcode-arrays-101blobmainmerge20sorted20arrayjs"><a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Merge%20Sorted%20Array.js">Merge Sorted Array</a></h3>
<p>You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively.</p>
<p>Merge nums1 and nums2 into a single array sorted in non-decreasing order.</p>
<p>The final sorted array should not be returned by the function, but instead be stored inside the array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165468831/oqY4lIRoO.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Merge%20Sorted%20Array.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> merge <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums1, m, nums2, n</span>) </span>{
    <span class="hljs-comment">// console.log(nums1.slice(0,m))</span>
    <span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> n; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        console.log(nums1[m])
        <span class="hljs-comment">//since we know that from 'm' the array will be free we can start inserting elements there</span>
        nums1[m] <span class="hljs-operator">=</span> nums2[i]
        console.log(nums1[m])
        <span class="hljs-comment">//incremenet the index 'm' so we can insert the next element properly</span>
        m<span class="hljs-operator">+</span><span class="hljs-operator">+</span>
    }
    <span class="hljs-comment">//remember to sort the array in a non-decreasing order</span>
    nums1.sort((a,b) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> a <span class="hljs-operator">-</span> b);
    console.log(nums1)
};
</code></pre><h3 id="heading-remove-elementhttpsleetcodecomproblemsremove-element"><a target="_blank" href="https://leetcode.com/problems/remove-element/">Remove Element</a></h3>
<p>Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The relative order of the elements may be changed.</p>
<p>Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.</p>
<p>Return k after placing the final result in the first k slots of nums.</p>
<p>Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165593219/or9MrxDuz.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Remove%20Element.js">Solution:</a></p>
<pre><code>const removeElement <span class="hljs-operator">=</span> (nums, val) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
      <span class="hljs-keyword">if</span> (nums[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> val) {
        <span class="hljs-comment">// use the method splice to remove the element that's equal to val</span>
        nums.splice(i, <span class="hljs-number">1</span>);
        <span class="hljs-comment">// decrement i by 1 to account for the splice</span>
        i<span class="hljs-operator">-</span><span class="hljs-operator">-</span>;
      }
    }
    <span class="hljs-comment">//since we removed elements from the array we just return the length of the array</span>
    <span class="hljs-keyword">return</span> nums.<span class="hljs-built_in">length</span>;
  };
</code></pre><h3 id="heading-remove-duplicates-from-sorted-arrayhttpsleetcodecomproblemsremove-duplicates-from-sorted-array"><a target="_blank" href="https://leetcode.com/problems/remove-duplicates-from-sorted-array/">Remove Duplicates from Sorted Array</a></h3>
<p>Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements should be kept the same.</p>
<p>Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.</p>
<p>Return k after placing the final result in the first k slots of nums.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165715220/zffyOFRey.png" alt="image.png" /></p>
<p><a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Remove%20Duplicates%20from%20Sorted%20Array.js">Solution:</a></p>
<pre><code><span class="hljs-keyword">var</span> removeDuplicates <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-comment">// nums = [...new Set(nums)]</span>
    <span class="hljs-comment">// return nums.length</span>
    <span class="hljs-comment">// doesn't work cuz it has to be in place</span>
    <span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        <span class="hljs-comment">//remove the next element if it's the same as the current element</span>
        <span class="hljs-keyword">if</span> (nums[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> nums[i <span class="hljs-operator">+</span> <span class="hljs-number">1</span>]) {
            <span class="hljs-comment">//use the method splice to remove the element</span>
            nums.splice(i, <span class="hljs-number">1</span>)
            <span class="hljs-comment">//decrement i to account for the splice</span>
            i<span class="hljs-operator">-</span><span class="hljs-operator">-</span>
        }
    }
};
</code></pre><h3 id="heading-check-if-n-and-its-double-existhttpsleetcodecomproblemscheck-if-n-and-its-double-exist"><a target="_blank" href="https://leetcode.com/problems/check-if-n-and-its-double-exist/">Check If N and Its Double Exist</a></h3>
<p>Given an array arr of integers, check if there exists two integers N and M such that N is the double of M ( i.e. N = 2 * M).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165836366/HAlMXukPI.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Check%20If%20N%20and%20Its%20Double%20Exist.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> checkIfExist <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">arr</span>) </span>{
    <span class="hljs-comment">//make a flag to check if there is a double</span>
    <span class="hljs-comment">//update it if it exists</span>
    let res <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    console.log(`arr <span class="hljs-keyword">is</span> ${arr}`);
    <span class="hljs-comment">//use forEach to iterate through all the elements in the array</span>
    arr.forEach( (e, i) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        <span class="hljs-comment">//check if the double of e exists in the array with indexOf</span>
        <span class="hljs-keyword">if</span>(arr.indexOf(e<span class="hljs-operator">*</span><span class="hljs-number">2</span>) <span class="hljs-operator">!</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">-1</span>){
            <span class="hljs-comment">//check we are not iterating over the same element</span>
            <span class="hljs-keyword">if</span>(arr.lastIndexOf(e<span class="hljs-operator">*</span><span class="hljs-number">2</span>) <span class="hljs-operator">!</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> arr.indexOf(arr[i])){
                res <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>
            }
            }
        }
    )
    <span class="hljs-keyword">return</span> res
};
</code></pre><h3 id="heading-valid-mountain-arrayhttpsleetcodecomproblemsvalid-mountain-array"><a target="_blank" href="https://leetcode.com/problems/valid-mountain-array/">Valid Mountain Array</a></h3>
<p>Given an array of integers arr, return true if and only if it is a valid mountain array.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638165938571/eherID97E.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Valid%20Mountain%20Array.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> validMountainArray <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">arr</span>) </span>{
     <span class="hljs-comment">//get the max of the array to know the "top" of the mountain</span>
    let max <span class="hljs-operator">=</span> Math.<span class="hljs-built_in">max</span>(...arr);
    <span class="hljs-comment">//get its index as well</span>
    let maxIndex <span class="hljs-operator">=</span> arr.indexOf(max);
    <span class="hljs-comment">//debugging 101</span>
    console.log(`max <span class="hljs-keyword">is</span> ${max}`);
    console.log(`maxIndex <span class="hljs-keyword">is</span> ${maxIndex}`);
    <span class="hljs-comment">//check for edge cases</span>
    <span class="hljs-keyword">if</span>(maxIndex <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span> <span class="hljs-operator">|</span><span class="hljs-operator">|</span> maxIndex <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> arr.<span class="hljs-built_in">length</span>-<span class="hljs-number">1</span>){
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }
    <span class="hljs-comment">//iterate through the first half of the "mountain"</span>
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> maxIndex; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        console.log(<span class="hljs-string">'first half'</span>);
        console.log(`<span class="hljs-keyword">is</span> <span class="hljs-keyword">is</span> ${i} i<span class="hljs-operator">+</span><span class="hljs-number">1</span> <span class="hljs-keyword">is</span> ${i<span class="hljs-operator">+</span><span class="hljs-number">1</span>}`);
        <span class="hljs-comment">//if the mountain isn't strictly increasing, return false</span>
        <span class="hljs-keyword">if</span>(arr[i] <span class="hljs-operator">&gt;</span> arr[i<span class="hljs-operator">+</span><span class="hljs-number">1</span>] <span class="hljs-operator">|</span><span class="hljs-operator">|</span> arr[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> arr[i<span class="hljs-operator">+</span><span class="hljs-number">1</span>]){
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }
    }
    <span class="hljs-comment">//iterate through the second half of the "mountain"</span>
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> maxIndex; i <span class="hljs-operator">&lt;</span> arr.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        console.log(<span class="hljs-string">'second half'</span>);
        console.log(`<span class="hljs-keyword">is</span> <span class="hljs-keyword">is</span> ${i} i<span class="hljs-operator">+</span><span class="hljs-number">1</span> <span class="hljs-keyword">is</span> ${i<span class="hljs-operator">+</span><span class="hljs-number">1</span>}`);
        <span class="hljs-comment">//if the mountain isn't strictly decreasing, return false</span>
        <span class="hljs-keyword">if</span>(arr[i] <span class="hljs-operator">&lt;</span> arr[i<span class="hljs-operator">+</span><span class="hljs-number">1</span>] <span class="hljs-operator">|</span><span class="hljs-operator">|</span> arr[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> arr[i<span class="hljs-operator">+</span><span class="hljs-number">1</span>]){
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }
    }
    <span class="hljs-comment">//return true if the mountain is valid</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
};
</code></pre><h3 id="heading-replace-elements-with-greatest-element-on-right-sidehttpsleetcodecomproblemsreplace-elements-with-greatest-element-on-right-side"><a target="_blank" href="https://leetcode.com/problems/replace-elements-with-greatest-element-on-right-side/">Replace Elements with Greatest Element on Right Side</a></h3>
<p>Given an array arr, replace every element in that array with the greatest element among the elements to its right, and replace the last element with -1.</p>
<p>After doing so, return the array.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166059954/wJt7ynnzM.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Replace%20Elements%20with%20Greatest%20Element%20on%20Right%20Side.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> replaceElements <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">arr</span>) </span>{
     console.log(arr);
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> arr.<span class="hljs-built_in">length</span>-<span class="hljs-number">1</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        <span class="hljs-comment">//assign max as the next element to check</span>
        let max <span class="hljs-operator">=</span> arr[i<span class="hljs-operator">+</span><span class="hljs-number">1</span>];
        <span class="hljs-comment">//iterate through the right side of the array</span>
        <span class="hljs-keyword">for</span>(let j <span class="hljs-operator">=</span> i<span class="hljs-operator">+</span><span class="hljs-number">1</span>; j<span class="hljs-operator">&lt;</span>arr.<span class="hljs-built_in">length</span>; j<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
            <span class="hljs-comment">//check if there's an element that's greater than the current max</span>
            <span class="hljs-keyword">if</span>(arr[j] <span class="hljs-operator">&gt;</span> max){
                max <span class="hljs-operator">=</span> arr[j];
            }
        }
        <span class="hljs-comment">//put the max element as you finish the array</span>
        arr[i] <span class="hljs-operator">=</span> max;
    }
    <span class="hljs-comment">//put the last element as -1 since the problem asks for it</span>
    arr[arr.<span class="hljs-built_in">length</span>-<span class="hljs-number">1</span>] <span class="hljs-operator">=</span> <span class="hljs-number">-1</span>;
    <span class="hljs-keyword">return</span> arr;
};
</code></pre><h3 id="heading-remove-duplicates-from-sorted-arrayhttpsleetcodecomproblemsremove-duplicates-from-sorted-array"><a target="_blank" href="https://leetcode.com/problems/remove-duplicates-from-sorted-array/">Remove Duplicates from Sorted Array</a></h3>
<p>Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements should be kept the same.</p>
<p>Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.</p>
<p>Return k after placing the final result in the first k slots of nums.</p>
<p>Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166190740/y2mkWYFOb.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Remove%20Duplicates%20from%20Sorted%20Array.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> removeDuplicates <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-comment">// nums = [...new Set(nums)]</span>
    <span class="hljs-comment">// return nums.length</span>
    <span class="hljs-comment">// doesn't work cuz it has to be in place</span>
    <span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        <span class="hljs-comment">//remove the next element if it's the same as the current element</span>
        <span class="hljs-keyword">if</span> (nums[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> nums[i <span class="hljs-operator">+</span> <span class="hljs-number">1</span>]) {
            <span class="hljs-comment">//use the method splice to remove the element</span>
            nums.splice(i, <span class="hljs-number">1</span>)
            <span class="hljs-comment">//decrement i to account for the splice</span>
            i<span class="hljs-operator">-</span><span class="hljs-operator">-</span>
        }
    }  
};
</code></pre><p>###<a target="_blank" href="https://leetcode.com/problems/move-zeroes/">Move Zeroes</a>
Given an integer array nums, move all 0's to the end of it while maintaining the relative order of the non-zero elements.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166313101/kNo8RTS14.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Move%20Zeroes.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> moveZeroes <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
     console.log(nums);
     <span class="hljs-comment">//edge case in case arr is empty</span>
     <span class="hljs-keyword">if</span> (nums.<span class="hljs-built_in">length</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>
     <span class="hljs-comment">//make two pointers</span>
     let positiveEleTracker <span class="hljs-operator">=</span> <span class="hljs-number">0</span>, j <span class="hljs-operator">=</span> <span class="hljs-number">0</span>
     <span class="hljs-comment">//loop through array finding positive elements and filling the zeroes</span>
     <span class="hljs-keyword">while</span> (j <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>) {
         <span class="hljs-keyword">if</span> (nums[j] <span class="hljs-operator">!</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
             <span class="hljs-comment">//once we find a positive element swap it and keep count of positive elements</span>
             nums[positiveEleTracker] <span class="hljs-operator">=</span> nums[j]
             positiveEleTracker<span class="hljs-operator">+</span><span class="hljs-operator">+</span>
         }
         <span class="hljs-comment">//keep iterating through array</span>
         j<span class="hljs-operator">+</span><span class="hljs-operator">+</span>
     }
     console.log(nums);
     <span class="hljs-comment">//use the positiveEleTracker to fill the rest of the array with zeroes</span>
     <span class="hljs-comment">//fill the rest of the array with zeroes</span>
     <span class="hljs-keyword">while</span> (positiveEleTracker <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>) {
         nums[positiveEleTracker] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>
         positiveEleTracker<span class="hljs-operator">+</span><span class="hljs-operator">+</span>
     }
     console.log(nums);
 }
</code></pre><h3 id="heading-sort-array-by-parityhttpsleetcodecomproblemssort-array-by-parity"><a target="_blank" href="https://leetcode.com/problems/sort-array-by-parity/">Sort Array By Parity</a></h3>
<p>Given an integer array nums, move all the even integers at the beginning of the array followed by all the odd integers.</p>
<p>Return any array that satisfies this condition.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166415692/NsRP9sCM1.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Sort%20Array%20By%20Parity.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> sortArrayByParity <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
     <span class="hljs-comment">//edge case if arr length is 0</span>
    <span class="hljs-keyword">if</span>(nums.<span class="hljs-built_in">length</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> nums;
    <span class="hljs-comment">//keep track where the even index is</span>
    let evenIndex <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span><span class="hljs-number">0</span>; i<span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        <span class="hljs-comment">//if even</span>
        <span class="hljs-keyword">if</span>(nums[i] <span class="hljs-operator">%</span> <span class="hljs-number">2</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>){
            console.log(nums[i]);
            <span class="hljs-comment">//saving the val that's gonna get rewriten</span>
            <span class="hljs-comment">//this is the odd value</span>
            let oddTempVal <span class="hljs-operator">=</span> nums[evenIndex];
            console.log(<span class="hljs-string">"temp is "</span><span class="hljs-operator">+</span>oddTempVal);
            <span class="hljs-comment">//if the value is even it should go at the beginning</span>
            <span class="hljs-comment">//there are no strict rules so any even value will do</span>
            nums[evenIndex] <span class="hljs-operator">=</span> nums[i];
            <span class="hljs-comment">//keep track of the even index</span>
            evenIndex<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
            <span class="hljs-comment">// place the odd value where the even value was</span>
            nums[i] <span class="hljs-operator">=</span> oddTempVal;
        }
    }
    console.log(nums);
    <span class="hljs-keyword">return</span> nums;
};
</code></pre><h3 id="heading-remove-elementhttpsleetcodecomproblemsremove-element"><a target="_blank" href="https://leetcode.com/problems/remove-element/">Remove Element</a></h3>
<p>Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The relative order of the elements may be changed.</p>
<p>Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.</p>
<p>Return k after placing the final result in the first k slots of nums.</p>
<p>Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166574328/MEHXw0Yke.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Remove%20Element.js">Solution:</a></p>
<pre><code>const removeElement <span class="hljs-operator">=</span> (nums, val) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
      <span class="hljs-keyword">if</span> (nums[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> val) {
        <span class="hljs-comment">// use the method splice to remove the element that's equal to val</span>
        nums.splice(i, <span class="hljs-number">1</span>);
        <span class="hljs-comment">// decrement i by 1 to account for the splice</span>
        i<span class="hljs-operator">-</span><span class="hljs-operator">-</span>;
      }
    }
    <span class="hljs-comment">//since we removed elements from the array we just return the length of the array</span>
    <span class="hljs-keyword">return</span> nums.<span class="hljs-built_in">length</span>;
  };
</code></pre><h3 id="heading-height-checkerhttpsleetcodecomproblemsheight-checker"><a target="_blank" href="https://leetcode.com/problems/height-checker/">Height Checker</a></h3>
<p>A school is trying to take an annual photo of all the students. The students are asked to stand in a single file line in non-decreasing order by height. Let this ordering be represented by the integer array expected where expected[i] is the expected height of the ith student in line.</p>
<p>You are given an integer array heights representing the current order that the students are standing in. Each heights[i] is the height of the ith student in line (0-indexed).</p>
<p>Return the number of indices where heights[i] != expected[i].</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166670621/Ua4guUUyX.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Height%20Checker.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> heightChecker <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">heights</span>) </span>{

    <span class="hljs-comment">//first copy the array using the spread operator</span>
    <span class="hljs-comment">//then sort the array to check the differences</span>
    const sorted <span class="hljs-operator">=</span> [...heights].sort((a,b) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> a <span class="hljs-operator">-</span> b)

    console.log(heights);
    console.log(sorted);
    <span class="hljs-comment">//counter for the different elements</span>
    let diffCount <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i<span class="hljs-operator">&lt;</span>heights.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        <span class="hljs-keyword">if</span>(heights[i] <span class="hljs-operator">!</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> sorted[i]){
            console.log(<span class="hljs-string">"diff"</span>);
            diffCount<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
        }
    }
    console.log(diffCount);
    <span class="hljs-keyword">return</span> diffCount;
};
</code></pre><h3 id="heading-third-maximum-numberhttpsleetcodecomproblemsthird-maximum-number"><a target="_blank" href="https://leetcode.com/problems/third-maximum-number/">Third Maximum Number</a></h3>
<p>Given an integer array nums, return the third distinct maximum number in this array. If the third maximum does not exist, return the maximum number.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166771816/cvUIPVqn0.png" alt="image.png" />
<a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Third%20Maximum%20Number.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> thirdMax <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-comment">//make a copy of the array without dupes</span>
    const nonDupArr <span class="hljs-operator">=</span> [...new Set(nums)];
    <span class="hljs-comment">//order the array from largest to smallest</span>
    nonDupArr.sort((a,b) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> b<span class="hljs-operator">-</span>a);
    console.log(nonDupArr);
    <span class="hljs-comment">//get the third max number after sorting</span>
    const thirdNum <span class="hljs-operator">=</span> nonDupArr[<span class="hljs-number">2</span>];
    <span class="hljs-comment">//if the array is less than 3 return the maximum number</span>
    <span class="hljs-comment">//if it's greater than 3 return the third maximum</span>
    <span class="hljs-keyword">return</span> nonDupArr.<span class="hljs-built_in">length</span> <span class="hljs-operator">&lt;</span> <span class="hljs-number">3</span> ? Math.<span class="hljs-built_in">max</span>(...nonDupArr) : thirdNum;
};
</code></pre><h3 id="heading-find-all-numbers-disappeared-in-an-arrayhttpsleetcodecomproblemsfind-all-numbers-disappeared-in-an-array"><a target="_blank" href="https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/">Find All Numbers Disappeared in an Array</a></h3>
<p>Given an array nums of n integers where nums[i] is in the range [1, n], return an array of all the integers in the range [1, n] that do not appear in nums.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166872799/TbDOqDMfn.png" alt="image.png" /></p>
<p><a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Find%20All%20Numbers%20Disappeared%20in%20an%20Array.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> findDisappearedNumbers <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
     <span class="hljs-comment">//get the max range meaning it goes from [1,max]</span>
    const maxRange <span class="hljs-operator">=</span> nums.<span class="hljs-built_in">length</span>;
    console.log(maxRange);
    <span class="hljs-comment">//array to store the missing numbers</span>
    let res <span class="hljs-operator">=</span> [];
    <span class="hljs-comment">//iterate from 1 to the range we need</span>
    <span class="hljs-keyword">for</span>(let i <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; i <span class="hljs-operator">&lt;</span><span class="hljs-operator">=</span> maxRange; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
        <span class="hljs-comment">//if the number is not in the array, push it to the array</span>
        let found <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
        <span class="hljs-comment">//iterate through the array to see if the number is in the array</span>
        <span class="hljs-keyword">for</span>(let j <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; j <span class="hljs-operator">&lt;</span> nums.<span class="hljs-built_in">length</span>; j<span class="hljs-operator">+</span><span class="hljs-operator">+</span>){
            <span class="hljs-keyword">if</span> (i <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> nums[j]){
                <span class="hljs-comment">//if the number is in the array, set found to true</span>
                found <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
            }
        }
        <span class="hljs-comment">//only push the numbers that are not found</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>found){
            res.<span class="hljs-built_in">push</span>(i);
        }
    }
    console.log(res);
    <span class="hljs-keyword">return</span> res;
};
</code></pre><h3 id="heading-squares-of-a-sorted-arrayhttpsleetcodecomproblemssquares-of-a-sorted-array"><a target="_blank" href="https://leetcode.com/problems/squares-of-a-sorted-array/">Squares of a Sorted Array</a></h3>
<p>Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638166967014/9jKspMO0Q.png" alt="image.png" /></p>
<p><a target="_blank" href="https://github.com/bgdnvk/leetcode-arrays-101/blob/main/Squares%20of%20a%20Sorted%20Array.js">Solution:</a></p>
<pre><code> <span class="hljs-keyword">var</span> sortedSquares <span class="hljs-operator">=</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-comment">//create a new array to store the squares</span>
    let arr <span class="hljs-operator">=</span> [];
    <span class="hljs-comment">//push the squares of the numbers into the array</span>
    <span class="hljs-keyword">for</span> (let i of nums){
        arr.<span class="hljs-built_in">push</span>(i<span class="hljs-operator">*</span>i)
    }
    console.log(arr)
    <span class="hljs-comment">//sort the array in non-decreasing order</span>
    arr.sort((a,b) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> a<span class="hljs-operator">-</span>b)
    console.log(arr)
    <span class="hljs-keyword">return</span> arr
};
</code></pre>]]></content:encoded></item><item><title><![CDATA[WordPress hosting comparison]]></title><description><![CDATA[Is WordPress good?
What happens when you have an idea or side project and don't know where to start? Easy: Wordpress.
WordPress is quick, cheap and easy to use. 
It is SEO friendly and you can build anything you want in a matter of hours. It is also ...]]></description><link>https://bognov.tech/wordpress-hosting-comparison</link><guid isPermaLink="true">https://bognov.tech/wordpress-hosting-comparison</guid><category><![CDATA[WordPress]]></category><category><![CDATA[hosting]]></category><category><![CDATA[DigitalOcean]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Mon, 15 Nov 2021 18:44:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1637001429174/yQxWlR2lB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-is-wordpress-good">Is WordPress good?</h1>
<p>What happens when you have an idea or side project and don't know where to start? Easy: Wordpress.</p>
<p>WordPress is quick, cheap and easy to use. </p>
<p>It is SEO friendly and you can build anything you want in a matter of hours. It is also probably the best CMS right now and if you are working with non-tech literate people, they can do anything they want through plugins - although this is a double-edged sword.</p>
<h1 id="heading-hosting-solutions">Hosting solutions</h1>
<p>However, the issue is always how/where to host your project - whether to go with shared hosting, dedicated server or VPS. There is also the cost to consider - after all this is a minor side project. I didn't want to spend any valuable time dealing with servers and just wanted to build something as quick as possible.</p>
<p>If the website would have been for a client, and they wanted Wordpress, I would have chosen Kinsta or Pantheon. I have used both in the past and I highly recommend them. The majority of my time was dealing with Kinsta, and while they both have amazing support (especially Kinsta), they were out of my budget.</p>
<h3 id="heading-list-of-cheap-hosting-services-for-wordpress">List of cheap hosting services for WordPress:</h3>
<ol>
<li><a target="_blank" href="https://www.awardspace.com/wordpress-hosting/">AwardsSpace</a> </li>
<li><a target="_blank" href="https://www.namecheap.com/wordpress/">NameCheap - EasyWP</a> </li>
<li><a target="_blank" href="https://x10hosting.com/">x10Premium</a> </li>
<li>Ionos (2022 update: STAY AWAY FROM IONOS)</li>
<li><a target="_blank" href="https://www.bluehost.com/wordpress/wordpress-hosting#pricing-cards">Bluehost</a></li>
<li><a target="_blank" href="https://www.dreamhost.com/wordpress/shared-wp-hosting/">Dreamhost</a></li>
</ol>
<h3 id="heading-popular-hosting-services-that-arent-dirt-cheap">Popular hosting services that aren't dirt cheap:</h3>
<ol>
<li><a target="_blank" href="https://wpengine.com/plans/">WPEngine</a></li>
<li><a target="_blank" href="https://tfwph.com/the-fastest-wordpress-hosting-price-comparison/#">TFWPH</a></li>
<li><a target="_blank" href="https://getflywheel.com/">FlyWheel</a></li>
</ol>
<p>I ended up going with <strong>NameCheap - EasyWP</strong>, I buy my domains there and it's been a good experience so far. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636069882388/n5EjW2hp0.png" alt="imagen.png" /></p>
<p>2022 edit: I had some issues with them but the service is worth checking out, from what I understand they have improved quite a bit.</p>
<h3 id="heading-so-whats-the-best-and-cheap-hosting-for-wordrpess">So what's the best and cheap hosting for Wordrpess?</h3>
<p>After my horrible experience I ended up looking into something a bit more complicated to set up, but still quite simple.</p>
<p><strong> <a target="_blank" href="https://bognov.tech/how-to-install-wordpress-with-plesk-on-digitalocean">DigitalOcean with Plesk</a></strong> 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636070419607/p-l9FKAHp.png" alt="imagen.png" /></p>
<p>DigitalOcean with Plesk allows you to get a free Plesk license with 3 email accounts. The installation is really simple, you can follow my guide on how to install WordPress with Plesk on DigitalOcean  <a target="_blank" href="https://bognov.tech/how-to-install-wordpress-with-plesk-on-digitalocean">here</a>, the price is almost unbeatable for the amount of features you get.</p>
<p> <a target="_blank" href="https://baitgaming.com">This is the end result: BaitGaming</a>, the site still needs optimization everywhere and I need to set up cache. But it's the v1.0.0 and we are up and running in record time, the rest of the team can start building online presence and in the near future I will rework the site.
It is most likely going to be Next.JS with Wordpress as headless CMS.</p>
<p>To get in touch with me the quickest way is <a target="_blank" href="https://twitter.com/tekbog">@tekbog</a> and if you are looking for more WordPress content <a target="_blank" href="https://twitter.com/natmiletic">@natmiletic</a> is a good and reliable source and so is <a target="_blank" href="https://twitter.com/edanbenatar">@edanbenatar</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to install WordPress with Plesk on DigitalOcean]]></title><description><![CDATA[This is one of the cheapest and quickest solutions to have a website up and running that contains a blog with backups and your own email. 
The WordPress site is hosted on DigitalOcean's virtual machine (droplet) that goes for as low as 5$/month. 
Dig...]]></description><link>https://bognov.tech/how-to-install-wordpress-with-plesk-on-digitalocean</link><guid isPermaLink="true">https://bognov.tech/how-to-install-wordpress-with-plesk-on-digitalocean</guid><category><![CDATA[DigitalOcean]]></category><category><![CDATA[WordPress]]></category><category><![CDATA[Devops]]></category><category><![CDATA[hosting]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Bogdan N.]]></dc:creator><pubDate>Sat, 13 Nov 2021 06:58:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636782680345/ING8xBV9c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is one of the <strong>cheapest </strong>and <strong>quickest </strong>solutions to have a website up and running that contains a blog with backups and your own email. 
The WordPress site is hosted on DigitalOcean's virtual machine (droplet) that goes for as low as 5$/month. </p>
<p>DigitalOcean compared to GCP, AWS, Azure, etc, offers a one click deployment with minimal configuration that allows you to host several WordPress sites (or CMS of your choice) through Plesk. This allows you to have personalized email accounts using your domain without additional cost. It's perfect for small businesses, MVPs or early projects. </p>
<p>To start you need a <a target="_blank" href="https://m.do.co/c/1e4904d4946c">DigitalOcean</a> account. From the referral link you get 100$ for 60 days. </p>
<p>The guide is as follows:</p>
<ol>
<li>Install Plesk on DigitalOcean</li>
<li>Set up Plesk and install your WordPress site</li>
<li>Set up SSL for WordPress</li>
<li>Set up the webmail on Plesk</li>
<li>Set up backups or snapshots for your DigitalOcean droplet</li>
</ol>
<p>If you get lost and need technical support I can ignore you on <a target="_blank" href="https://twitter.com/tekbog">Twitter @tekbog</a> </p>
<h1 id="heading-install-plesk-on-digitalocean">Install Plesk on DigitalOcean</h1>
<p>What we are going to do is go to marketplace, search for  <a target="_blank" href="https://marketplace.digitalocean.com/apps/plesk">Plesk </a> and click on Create Plesk Droplet:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636778240717/7AtrCtF1E.png" alt="image.png" /></p>
<p>After we select our machine (remember to save the password, I personally use  <a target="_blank" href="https://keepassxc.org/">KeePassXC</a> ).</p>
<h1 id="heading-set-up-plesk-and-install-wordpress">Set up Plesk and install WordPress</h1>
<p>We go into our droplet and copy the ip, which will lead us to this page:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772116594/0Y-qwhx-b.png" alt="image.png" /></p>
<p>Don't be too quick!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772136222/7csGSzVsB.png" alt="image.png" /></p>
<p>We will need to make an username and password, I'd recommend using a password manager like KeePassXC.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772203078/5zFAZugHS.png" alt="image.png" /></p>
<p>Plesk ready to use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772219358/VtWT20wxz.png" alt="image.png" /></p>
<p>Click on add a new domain, if you don't have one just select temporary domain and go to the install WordPress step:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772235249/Nakuo3MPy.png" alt="image.png" /></p>
<p>Once you have added your domain you will have to configure your DNS, just follow the link: 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772291454/4-7-s6K7a.png" alt="image.png" /></p>
<p>In my case I had to follow  <a target="_blank" href="https://docs.plesk.com/en-US/obsidian/administrator-guide/72225/#namecheap">NameCheap</a> 's instructions but you can pick your registrar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772350199/BTlKe4baK.png" alt="image.png" /></p>
<p>What we want to do next is go to WordPress and install the site:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772408304/H0p_wWgzk.png" alt="image.png" /></p>
<p>It will ask for your admin's username and password:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772538045/D7T2NBKwK.png" alt="image.png" /></p>
<p> after you set that up it will install WordPress:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772504987/PUcrMZLkV.png" alt="image.png" /></p>
<h1 id="heading-set-up-ssl-for-our-wordpress-site">Set up SSL for our WordPress site</h1>
<p>The first thing you will notice when you have your site ready is that it lacks a security certificate 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772627047/D7Kc5pVik.png" alt="image.png" /></p>
<p>Web servers work through HTTP however in order to add security and encryption we add an SSL certificate (the 'S' in HTTPS stands for secure, so when you see https it just means the data is encrypted and secure). 
Just click on the "no certificate button" and "get SSL/TLS certificate":</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772849010/k6LXAzITI.png" alt="image.png" /></p>
<p>You will see this page:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636772881226/ZmlS_vBjU.png" alt="image.png" /></p>
<p>Feel free to buy one if you want, however a Let's Encrypt certificate is more than enough, click on install.</p>
<p>We want to secure everything since we will be using the webmail as well: 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636773002573/nuv8FC17x.png" alt="image.png" /></p>
<p>In order to validate our domain we will need to add a TXT record in our DNS:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636773195282/E_ODQ7zvF.png" alt="image.png" /></p>
<p>Plesk does this automatically.</p>
<p>While this is going on your server (droplet) might suffer a bit, just be patient:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636773823560/nZJ0pow4Y.png" alt="image.png" /></p>
<p>Once you are done you will see that your site contains https:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636773904469/YLDzhQeJvOh.png" alt="image.png" /></p>
<h1 id="heading-set-up-the-webmail-on-plesk">Set up the webmail on Plesk</h1>
<p>Our encryption is ready for our site, let's set up our email. Digital Ocean's default Plesk license allows 3 emails. Go to Mail and click on Create Email Address:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636774035702/kNFngX_OP.png" alt="image.png" /></p>
<p>The next thing is to input the data, however I'd recommend on deactivating "Can be used to log in to Plesk" for security reasons:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636774236685/d5IZwpNba.png" alt="image.png" /></p>
<p>In order to use our email we can open it through this button:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636774325556/xLI6M2Q3J.png" alt="image.png" />
or just go to: https://webmail.your-domain.com</p>
<p>However due to security policies our outgoing mail is ending in spam, to fix this what we need to do is enable DKIM, go to mail, mail settings and click on your account, you will see the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636775647897/r-zwltM2O.png" alt="image.png" /></p>
<p>Check the DKIM box, click on apply and then OK:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636775678297/n9Pzx1jrO.png" alt="image.png" /></p>
<p>And in order to get rid of the </p>
<blockquote>
<p>You cannot send emails from Plesk because outbound connections on TCP port 25 is blocked. Check the firewall settings or contact your hosting provider. If you are sure that the ports are already open, Plesk can recheck them. Start the recheck</p>
</blockquote>
<p>Just click on start Recheck, if you are not sure if it has worked go to your DNS settings and check for a DKIM record. 
I've had problems with this issue before, <a target="_blank" href="https://support.plesk.com/hc/en-us/articles/213934285-Unable-to-receive-or-send-e-mails-port-25-is-blocked">there's even a support article from Plesk here</a> however you shouldn't worry about doing anything with the firewall. 
Another possible issue related to DKIM records can also be found  <a target="_blank" href="https://support.plesk.com/hc/en-us/articles/115004142193-Emails-go-to-Spam-DKIM-record-is-corrupted">here</a>. The solutions is literally to turn it off and on, like always.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636780144878/4V4VbV6mg.png" alt="image.png" /></p>
<p><strong>It's very important to double check that our email works properly before launching our site or starting a marketing campaign, make sure it doesn't land in spam!</strong></p>
<h1 id="heading-set-up-backups-for-your-digitalocean-droplet">Set up backups for your DigitalOcean droplet</h1>
<p>DO <strong>NOT </strong>FORGET BACKUPS!</p>
<p>You can also use <a target="_blank" href="https://docs.plesk.com/en-US/obsidian/administrator-guide/backing-up-and-restoration.59256/">Plesk </a> for backups but we are going to just snapshot our entire VM.</p>
<p>Go to droplets, click on your droplet and then click on backups:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636780641749/TYj-9NcNO.png" alt="image.png" /></p>
<p>This costs an additional $1, however you can also just do Snapshots on your own, which is what I do for new projects that haven't exactly started yet:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636780734533/vnyHyS-yN.png" alt="image.png" />
Once you have created your snapshot all you have to do is restore when things go wrong:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636780778982/KDeat2IOL.png" alt="image.png" /></p>
]]></content:encoded></item></channel></rss>