<?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[kolynz]]></title><description><![CDATA[kolynz]]></description><link>https://articles.collinsbenda.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1697971643691/gwjtj1uFh.png</url><title>kolynz</title><link>https://articles.collinsbenda.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 21:12:11 GMT</lastBuildDate><atom:link href="https://articles.collinsbenda.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Big O notations]]></title><description><![CDATA[Have you ever poured your heart and soul into writing what you believed to be the pinnacle of code excellence, only to have your confidence shattered by your colleague having much better code? Then, during the code review, the senior trashes you and ...]]></description><link>https://articles.collinsbenda.com/big-o-notations</link><guid isPermaLink="true">https://articles.collinsbenda.com/big-o-notations</guid><category><![CDATA[DSA]]></category><category><![CDATA[#dsainjavascript]]></category><dc:creator><![CDATA[Atuhaire Collins Benda]]></dc:creator><pubDate>Sun, 17 Nov 2024 06:47:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731863163005/1a6c7a13-9769-44ac-827f-5cc4e1e1072f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever poured your heart and soul into writing what you believed to be the pinnacle of code excellence, only to have your confidence shattered by your colleague having much better code? Then, during the code review, the senior trashes you and your colleague's code in favor of a much more straightforward and effortlessly effective one. Hmmm, so how do I determine whether my code is great or subpar? Imagine having a system or metric to categorize how shaky my code is, similar to how earthquakes are quantified or contrasted with the Richter scale. Something that could classify the 'shittiness' of my code and provide a standardized measure of its quality?</p>
<p>In our pursuit of an objective measure of code quality, I encountered the term "Big O Notation." It initially seemed a bit abstract and theoretical, but its importance cannot be overstated. Big O Notation provides a systematic and universally accepted way to measure and compare the efficiency of algorithms. It's like a compass that guides you toward writing code that not only works but works efficiently, even when faced with vast amounts of data.</p>
<p>So why should you care about Big O notation? Let me break it down for you in a way that'll make you want to high-five your computer screen!</p>
<p><strong>Time-Saving :</strong> Imagine you're at a big tech company tasked you with writing an algorithm. Knowing Big O helps you create algorithms that work faster and more efficiently. Picture this: you shave off a whole hour of processing time! That's like gaining an extra episode in your Netflix binge-watching marathon. Who doesn't want that?</p>
<p><strong>Code Lingo:</strong> Big O gives you a secret language to chat about code performance with your team members. No more vague "it's kinda slow" talk. You'll be tossing around phrases like <code>O(1),</code> <code>O(log n)</code>, and <code>O(n^2)</code> like a coding maestro. It's like having a secret handshake in the world of devs.</p>
<p><strong>Trade-off Tango:</strong> Sometimes we face tough decisions while we code. Should I go for the flashy, super-speedy code that gobbles up memory like a hungry hippo, or opt for the lean, memory-efficient one that takes a bit longer to finish? Big O helps you weigh these choices with confidence. It's like picking between a turbocharged sports car and a fuel-efficient hybrid but for your code. And most of all helps me understand the different things I can factor into my decisions</p>
<p><strong>Code CSI:</strong> Ever had a piece of code go rogue, slowing down your app or causing it to crash? Big O is your trusty detective tool. It helps you spot the misbehaving culprits in your code lineup. Think of it as your code CSI kit, ready to uncover performance bottlenecks faster than Sherlock Holmes or Jake Peralta.</p>
<p><strong>Interview Hero:</strong> Job interviews in tech often throw Big O questions your way. Think of it as your secret weapon. Nail those questions, and you're one step closer to landing your dream job in a swanky tech company. It's like having a cheat code for leveling up in the world of coding careers.</p>
<h3 id="heading-lets-talk-timing-what-makes-code-better">Let's Talk Timing: What Makes Code "Better"?</h3>
<p>When we say we want "better" code, what exactly do we mean? Is it all about speed, making our code run faster than Usain Bolt? Or perhaps it's about being more frugal with memory, like a financial guru managing their budget. And let's not forget about readability – the art of crafting code that's as clear as a crystal-clear mountain stream.</p>
<p>But here's where things get a bit tricky. If we use time as our sole metric for measuring code quality, we run into a snag. Time can be a slippery character, measured differently depending on various factors like the computer's processing power, the phase of the moon (okay, maybe not that last one).</p>
<p><strong>For instance</strong>, think about rendering a high-definition image. On your speedy gaming rig, it might take a mere blink of an eye, but on Aunt Mildred's vintage computer, it could feel like an eternity. So, if we rely solely on time measurements, we might miss the bigger picture.</p>
<h3 id="heading-enter-the-world-of-operations">Enter the World of Operations</h3>
<p>So, if not time, then what? Well, here's where we bring some math into the mix (don't worry, it's not rocket science). Instead of counting seconds, let's count something that remains constant no matter what computer you're on – the number of <strong>simple operations</strong> the computer has to perform.</p>
<p>But hold on, what's an operation, you ask? Great question!</p>
<p>An operation is a fundamental action the computer performs. These can be as simple as adding two numbers, comparing values, or moving data around in memory. The beauty of operations is that they're like LEGO blocks – you can use them to build complex structures, and the number of operations needed to perform a task remains consistent across different machines.</p>
<p><strong>For example</strong>, let's say you're sorting a list of names alphabetically. Each time you compare two names to decide which one comes first, that's an operation. If you have a list of 10 names, you might need a handful of operations. If you have a list of 10,000 names, you'll need a lot more operations. if 'n' here represents the number of items you need to sort then increasing n increases the number of operations.</p>
<p>So, when we talk about better code, we're often talking about code that does the same task with fewer operations. In other words, it's like finding the shortest route from point A to point B, where each operation is a step – the fewer steps, the faster you get there! And that, my friends, is the magic of measuring code quality by counting operations. It levels the playing field, allowing us to evaluate code based on its efficiency and performance, regardless of the computer it runs on. 🚀</p>
<p>We'll explore two functions designed to perform the same task: calculating the sum of all numbers from 1 to 'n'. However, these functions take different paths to reach the same destination. One uses a traditional loop, while the other employs a mathematical formula. Our goal is to compare these two approaches based on their operational efficiency, shedding light on how the choice of coding techniques can significantly impact code performance. let's start by taking a closer look at the number of operations in both functions, including the operations within the loop:</p>
<p><strong>Function 1:</strong> <code>addUpToSecond</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addUpToSecond</span>(<span class="hljs-params">n</span>) </span>{
  <span class="hljs-keyword">return</span> n * (n + <span class="hljs-number">1</span>) / <span class="hljs-number">2</span>; <span class="hljs-comment">// 3 operations (multiplication, addition, division)</span>
}
</code></pre>
<p>For <code>addUpToSecond(5)</code>, calculates the sum directly using a mathematical formula.</p>
<p>So, for <code>addUpToSecond(5)</code>, there are a total of 3 operations(multiplication, addition, and division) regardless of the size of n.</p>
<p>That means that if I pass in 1000 or 100000 it will still take the same number of operations.</p>
<p><strong>Function 2:</strong> <code>addUpToFirst</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addUpToFirst</span>(<span class="hljs-params">n</span>) </span>{
  <span class="hljs-keyword">var</span> total = <span class="hljs-number">0</span>; <span class="hljs-comment">// 1 operation</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt;= n; i++) {
    total += i; <span class="hljs-comment">// 4 operations (addition, assignment of i, comparison, increment of i)</span>
  }
  <span class="hljs-keyword">return</span> total; <span class="hljs-comment">// 1 operation</span>
}
</code></pre>
<p>For <code>addUpToFirst(5)</code>, the number of operations is as follows:</p>
<ul>
<li><p>Initializing <code>total</code> is the first operation and it occurs once when the program is run Now if we enter the loop:</p>
</li>
<li><p>We know that <code>total += i;</code> is shorthand for <code>total = total + i;</code> . Meaning there are two operations happening addition and assignment. But notice this is happening in a loop so it is repeated <code>n</code> times. So now we have <code>n</code> additions and <code>n</code> assignments. So if <code>n=5</code> , the loop will do repeat 5 times so there will be 5 additions and 5 subtractions.</p>
<p>  Let’s look at the line <code>for (var i = 0; i &lt;= n; i++)</code> where the loop is created</p>
</li>
<li><p><code>var i = 0</code>: operation for assigning 0 to <code>i</code> that happens only once the loop has started.</p>
</li>
<li><p><code>i &lt;= n</code> : Comparison of <code>i</code> and <code>n</code> which happens on every iteration of the loop meaning it occurs n times</p>
</li>
<li><p><code>i++</code> : This is shorthand for <code>i=i+1</code> which has two operations (addition and assignment) that occur on every iteration. Meaning they happen <code>n</code> times. (<em>So if n is a billion it happens a billion times</em>)</p>
</li>
</ul>
<p><img src="https://res.cloudinary.com/kolynz-b/image/upload/v1695613255/portfolio/blog/DSA/addUpto.png" alt class="image--center mx-auto" /></p>
<p>To get the total number of operations for <code>addUpToFirst(n)</code>, we would use <code>5n+2</code>.but regardless of the exact number the number of operations grows roughly proportionally with n.</p>
<p>The total number of operations for <code>addUpToFirst(5)</code> is <code>(5x5) + 2</code> = 27 operations.</p>
<p>Now if we compare the two functions:</p>
<ul>
<li><p><code>addUpToFirst</code> for <code>n = 5</code> requires 27 operations.</p>
</li>
<li><p><code>addUpToSecond</code> for <code>n = 5</code> requires 3 operations.</p>
</li>
</ul>
<p>As you can see, <code>addUpToSecond</code> is significantly more efficient in terms of the number of operations, especially as 'n' increases. This emphasizes the efficiency gained by using a mathematical formula instead of a loop, making <code>addUpToSecond</code> it faster and more efficient than <code>addUpToFirst</code>.</p>
<h3 id="heading-visualizing-code-efficiency-a-closer-look-at-execution-time"><strong>Visualizing Code Efficiency: A Closer Look at Execution Time</strong></h3>
<p>To get a detailed understanding of how two functions perform in terms of execution time, we'll utilize a helpful tool (<a target="_blank" href="https://rithmschool.github.io/function-timer-demo/">https://rithmschool.github.io/function-timer-demo/</a>). However, there's a slight twist here – we'll start with a small 'n' value and gradually increase it to find the optimal results for each function. we'll notice a fascinating trend in the visualization.</p>
<p><strong>Trend 1: Function 1 (</strong><code>addUpToSecond</code>)</p>
<p>For Function 1, which utilizes a loop to calculate the sum, we'll observe the following trend:</p>
<ul>
<li><p>Initially, as 'n' starts with a small value (e.g., 10), the execution time is relatively short (measured in microseconds).</p>
</li>
<li><p>However, as we increment 'n' to 100, 1000, and beyond, the execution time steadily increases.</p>
</li>
<li><p>This increase in execution time follows a linear pattern, roughly proportional to 'n'. In the visualization, you'll see a linear slope where execution time gradually rises as 'n' grows.</p>
</li>
<li><p>The key takeaway is that for Function 1, the time it takes to complete the task increases linearly with the size of 'n'. This behavior is consistent with a linear time complexity, often represented as O(n).</p>
</li>
</ul>
<p><strong>Trend 2: Function 2 (</strong><code>addUpToFirst</code>)</p>
<p>For Function 2, which relies on a mathematical formula, we'll observe a different trend:</p>
<ul>
<li><p>Similar to Function 1, the execution time starts at a low level when 'n' is small.</p>
</li>
<li><p>However, as 'n' increases, the execution time remains remarkably stable and minimal. It does not exhibit the same linear growth seen in Function 1.</p>
</li>
<li><p>In the visualization, you'll notice a nearly flat line, indicating that the execution time is not significantly affected by changes in 'n'.</p>
</li>
<li><p>This behavior aligns with a constant time complexity, often represented as O(1), where the execution time remains constant, regardless of the input size.</p>
</li>
</ul>
<p>In summary, the trend reveals that Function 1's execution time increases linearly with 'n', while Function 2's execution time remains nearly constant, regardless of the value of 'n'. This visualization vividly illustrates the concept of code efficiency and how the choice of coding techniques can significantly impact the time required to complete a task, especially as the problem size ('n') grows. From this, we can establish that efficiency depends on time and space.</p>
<h3 id="heading-so-what-is-big-0">So what is Big 0</h3>
<p><strong>Big O notation</strong> is a mathematical notation used in computer science and mathematics to describe the <em>upper bound or worst-case scenario</em> of the time complexity or space complexity of an algorithm or function. It provides a way to analyze and compare algorithms based on their efficiency and how they scale with input size. (<em>Think of special notation that helps us describe how fast or slow a computer program is and how it handles bigger and bigger tasks</em>)</p>
<p>In Big O notation, an algorithm's performance is expressed using a function, typically denoted as <code>O(f(n)),</code> where "f(n)" represents the relationship between the input size (often denoted as 'n') and the number of basic operations performed by the algorithm. This function describes how the algorithm's runtime or space usage grows as the input size increases. So <code>f(n)</code> can be linear (<code>f(n) = n</code>), quadratic (<code>f(n) = n^2</code>), constant (<code>f(n) =1</code>), or something entirely different</p>
<p>The most common Big O notations include:</p>
<ol>
<li><p><strong>O(1)</strong> (Constant Time): The algorithm's runtime or space usage remains constant regardless of the input size. It indicates highly efficient algorithms that execute in a fixed amount of time or require a fixed amount of memory. (<em>This is like having a magic spell that instantly finds the word, no matter how big the book is. It's super fast and always takes the same amount of time, whether it's a small book or a huge library.</em>)</p>
</li>
<li><p><strong>O(log n)</strong> (Logarithmic Time): The algorithm's runtime or space usage grows logarithmically with the input size. These algorithms become more efficient as the input size increases. (<em>Think of this as a clever guessing game. As the book gets bigger, you need a few more guesses, but it's still pretty fast, and the more you guess, the faster you get at it.</em>)</p>
</li>
<li><p><strong>O(n)</strong> (Linear Time): The algorithm's runtime or space usage scales linearly with the input size. For every additional element in the input, the algorithm performs a constant amount of work. (<em>This is like reading the book page by page. If the book doubles in size, it takes twice as long. It's simple but can get slow for really big books.</em>)</p>
</li>
<li><p><strong>O(n log n)</strong> (Logarithmic Time): The algorithm's runtime or space usage grows in proportion to 'n' multiplied by the logarithm of 'n.' Algorithms with this complexity are often efficient and are commonly seen in sorting and searching algorithms. (<em>Imagine reading the book, making some notes, and then finding what you need. It takes a bit longer than just reading but is still pretty efficient.</em>)</p>
</li>
<li><p><strong>O(n^2)</strong> (Quadratic Time): The algorithm's runtime or space usage grows quadratically with the input size. It indicates algorithms that perform nested iterations over the input. (<em>This is like checking every word on every page one by one. As the book gets bigger, it takes much more time, and it can be slow for large books.</em>)</p>
</li>
<li><p><strong>O(2^n)</strong> (Exponential Time): The algorithm's runtime or space usage grows exponentially with the input size. These algorithms become impractical for large input sizes due to their rapid increase in resource requirements. (<em>This is extremely slow. It's like making a copy of the entire book for every word you want to find. For big books, it's painfully slow</em>)</p>
</li>
<li><p><strong>O(n!)</strong> (Factorial Time): The algorithm's runtime or space usage grows factorially with the input size. These algorithms are highly inefficient and are typically used for small, specialized cases. (<em>This is the slowest. It's like writing out every possible combination of words and checking them all. Even for moderately-sized books, it can take forever.</em>)</p>
</li>
</ol>
<p><img src="https://media.geeksforgeeks.org/wp-content/cdn-uploads/mypic.png" alt /></p>
<p><a target="_blank" href="https://www.geeksforgeeks.org/analysis-algorithms-big-o-analysis/">image from geeks for geeks</a></p>
<p>Big O notation provides a standard way to analyze and compare algorithms, enabling developers to make informed decisions about algorithm selection and optimization to ensure efficient and scalable software. It focuses on the worst-case scenario, helping to predict how an algorithm will perform when faced with the largest possible input.</p>
<p>If we go back to the examples discussed earlier</p>
<ul>
<li><p>The time complexity of <code>sumUsingLoop</code> is O(n). This means that as the input size 'n' increases, the number of operations also increases linearly. If 'n' doubles, the number of operations roughly doubles as well.</p>
</li>
<li><p>The time complexity of <code>sumUsingFormula</code> is O(1), which is constant time. Regardless of how large 'n' becomes, the number of operations remains the same. It's highly efficient and doesn't depend on the input size. <strong>Contrast:</strong></p>
</li>
<li><p>When comparing the two functions, you can see that <code>sumUsingFormula</code> is far more efficient in terms of time complexity. Its execution time remains constant, making it the preferred choice for large values of 'n.'</p>
</li>
<li><p>In contrast, <code>sumUsingLoop</code> has a linear time complexity. As 'n' grows, the number of operations increases proportionally. This means it might not be the best choice for large datasets or inputs because it can become slower as 'n' gets larger.</p>
</li>
<li><p>Big O notation precisely describes this difference in efficiency. It tells us that <code>sumUsingFormula</code> is O(1), indicating constant time, while <code>sumUsingLoop</code> is O(n), indicating linear time. So, this allows us to understand and compare the efficiency of algorithms or code. It helps us make informed decisions about which approach to use based on the problem's size and the resources available. In this case, it's clear that <code>sumUsingFormula</code> is the more efficient option for summing numbers from 1 to 'n' for larger values of 'n.'</p>
</li>
</ul>
<h3 id="heading-understanding-big-o-simplification">Understanding Big O Simplification</h3>
<p>You might be wondering how we simplified O(5n + 2) into <code>O(n)</code> .Let's break down how we simplify the Big O notation to O(n).</p>
<p>In Big O notation, we're interested in understanding how the number of operations or the execution time grows concerning the size of the input (usually denoted as 'n'). When simplifying, we focus on the term that has the most significant impact as 'n' becomes large, and we ignore constants and lower-order terms.</p>
<p>In the expression O(5n + 2), we have two terms: 5n and 2.</p>
<p>Here's why we simplify it to O(n):</p>
<ol>
<li><p><strong>Focus on the Dominant Term</strong>: In this case, the term 5n dominates because its growth rate is directly proportional to 'n.' As 'n' increases, the number of operations increases linearly with 'n' due to the 5n term.</p>
</li>
<li><p><strong>Ignore Constants</strong>: Big O notation doesn't concern itself with constants because they don't affect the overall growth rate concerning 'n.' The "+ 2" term represents a constant (2) that doesn't change as 'n' varies.</p>
</li>
<li><p><strong>Ignore Lower-Order Terms</strong>: Big O notation focuses on the most significant term that contributes to the growth rate. In this case, 5n is the dominant term, and it's a linear term.</p>
</li>
<li><ol>
<li><strong>Arithmetic operations are constant</strong>: In most cases, basic arithmetic operations like addition, subtraction, multiplication, and division are considered constant time operations. They take the same amount of time regardless of the values involved.</li>
</ol>
</li>
<li><p><strong>Variable assignment is constant</strong>: Assigning a value to a variable typically takes constant time. It doesn't matter how large or small the value being assigned is; the time it takes remains constant.</p>
</li>
<li><p><strong>Accessing elements in an array (by index) or object (by key) is constant</strong>: This statement highlights the concept of constant-time access to elements in data structures like arrays and objects. It doesn't matter how big the array or object is; accessing an element by its index or key takes roughly the same amount of time.</p>
</li>
<li><p><strong>In a loop, the complexity is the length of the loop times the complexity of whatever happens inside the loop</strong>: This is a crucial principle in analyzing algorithms with loops. The time complexity of a loop is determined by multiplying the number of iterations (the length of the loop) by the complexity of the operations inside the loop. This helps in understanding how loops impact overall algorithm efficiency.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Big O Notation</td><td>Simplification</td><td>Explanation</td></tr>
</thead>
<tbody>
<tr>
<td>O(2n)</td><td>O(n)</td><td>Constant factors are dropped; it's still linear growth with 'n'.</td></tr>
<tr>
<td>O(3n^2)</td><td>O(n^2)</td><td>Constant factors are dropped; it's still quadratic growth with 'n'.</td></tr>
<tr>
<td>O(n + 1000)</td><td>O(n)</td><td>Constants are dropped; they don't significantly impact growth with 'n'.</td></tr>
<tr>
<td>O(5n^2 + 3n + 1)</td><td>O(n^2)</td><td>Keep the most dominant term (quadratic); lower-order terms are dropped.</td></tr>
<tr>
<td>O(log n + n)</td><td>O(n)</td><td>Linear growth (n) dominates logarithmic growth (log n).</td></tr>
<tr>
<td>O(2^log n)</td><td>O(2^log n)</td><td>No simplification; exponential time complexity remains.</td></tr>
<tr>
<td>O(n^3 + n^2 + n)</td><td>O(n^3)</td><td>Keep the most dominant term (cubic); lower-order terms are dropped.</td></tr>
<tr>
<td>O(2^n * n!)</td><td>O(2^n * n!)</td><td>No simplification; exponential and factorial complexities remain.</td></tr>
<tr>
<td>O(n log n + n^2)</td><td>O(n^2)</td><td>Quadratic growth (n^2) dominates n log n growth.</td></tr>
</tbody>
</table>
</div><p>These principles provide a foundation for understanding how various operations and code structures contribute to an algorithm's time complexity. They are essential when breaking down and analyzing the performance of algorithms and code.</p>
<p>It's worth noting that while these principles are generally true, there can be exceptions and variations depending on the specific programming language, hardware, and optimizations applied. However, they provide a good starting point for reasoning about algorithmic efficiency.</p>
<p>So, when we simplify O(5n + 2) to O(n), we're essentially saying that as 'n' becomes large, the number of operations grows linearly with 'n,' and the constant term 2 doesn't significantly impact the overall growth rate concerning 'n'. If you want to learn more about simplifying big expressions read this <a target="_blank" href="https://medium.com/swlh/lets-simplify-big-o-9aed90d11f34">https://medium.com/swlh/lets-simplify-big-o-9aed90d11f34</a></p>
<p>In Big O notation, we aim to express the upper bound or worst-case scenario of an algorithm's growth rate as a function of 'n' while simplifying the expression by focusing on the most dominant term, ignoring constants, and ignoring lower-order terms. This simplification helps us compare and analyze algorithms more effectively.</p>
<p>Let’s look at a few more algorithms in the <a target="_blank" href="https://rithmschool.github.io/function-timer-demo/">https://rithmschool.github.io/function-timer-demo/</a> tool and try to get their big O notation. So for the <code>countUpAnddown</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">countUpAndDown</span>(<span class="hljs-params">n</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Going up!"</span>);
<span class="hljs-comment">//loop one </span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; n; i++) {
    <span class="hljs-built_in">console</span>.log(i);
  }
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"At the top!\nGoing down..."</span>);
  <span class="hljs-comment">// loop two</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = n - <span class="hljs-number">1</span>; j &gt;= <span class="hljs-number">0</span>; j--) {
    <span class="hljs-built_in">console</span>.log(j);
  }
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Back down. Bye!"</span>);
}
</code></pre>
<p>It's understandable to think that because there are two loops in the <code>countUpAndDown</code> function, both with time complexities of O(n), the overall time complexity is 2n. However, when analyzing the time complexity of consecutive loops, we don't simply add their complexities together.</p>
<p>In this case, you have two separate loops, each with its own iteration over 'n.' When determining the overall time complexity, you take the highest time complexity because the loops run sequentially, not concurrently.</p>
<p>So, in this function:</p>
<ul>
<li><p>The first loop has a time complexity of O(n).</p>
</li>
<li><p>The second loop also has a time complexity of O(n).</p>
</li>
</ul>
<p>But since they run one after the other, you consider the highest time complexity, which is O(n). This represents the overall time complexity of the function. Therefore, the time complexity of <code>countUpAndDown</code> is O(n), not 2n.</p>
<p>For <code>printAllPairs</code></p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printAllPairs</span>(<span class="hljs-params">n</span>) </span>{
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; n; i++) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = <span class="hljs-number">0</span>; j &lt; n; j++) {
      <span class="hljs-built_in">console</span>.log(i, j);
    }
  }
}
</code></pre>
<p>For the nested loops in the <code>printAllPairs</code> function, where you have two loops iterating from 0 to 'n,' the time complexity can be analyzed as follows:</p>
<ul>
<li>The outer loop runs 'n' times, and for each iteration of the outer loop, the inner loop also runs 'n' times. This means that for each of the 'n' iterations of the outer loop, the inner loop performs 'n' iterations.</li>
</ul>
<p>To determine the overall time complexity, you can multiply the number of iterations of the outer loop by the number of iterations of the inner loop:</p>
<ul>
<li>'n' iterations of the outer loop <em>'n' iterations of the inner loop = n</em> n = n^2</li>
</ul>
<p>So, the time complexity of the <code>printAllPairs</code> function with nested loops is O(n^2), which is quadratic time complexity. This indicates that the number of operations grows quadratically with the size of 'n,' and it can become significantly slower as 'n' increases.</p>
<h2 id="heading-space-complexity">Space Complexity</h2>
<p>So far we have been focusing on time complexity: how can we analyze the runtime of an algorithm as the size of the inputs increases? So good news is we can still use big O notation to analyze space complexity: how much additional memory do we need to allocate in order to run the code in our algorithm</p>
<p>let’s talk about the inputs, so we shall ignore the size of n since it obviously increases with the n. we shall focus on auxiliary space complexity which refers to space required by the algorithm, not including the space taken by the inputs.</p>
<p><strong>A few rules of thumb</strong></p>
<ul>
<li><p>Most primitives(Booleans, numbers, undefined, null) are constant space.</p>
</li>
<li><p>Strings require O(n) space (where n is the string length)</p>
</li>
<li><p>Reference types are generally O( <em>n</em>), where n is the length (for arrays) or the number of keys (for objects)</p>
</li>
</ul>
<p>Let’s look at a few examples:</p>
<p><strong>Example 1:</strong> <code>sum</code> function</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">let</span> total = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; arr.length; i++) {
    total += arr[i];
  }
  <span class="hljs-keyword">return</span> total;
}
</code></pre>
<p>In this example:</p>
<ul>
<li><p>The function <code>sum</code> takes an array <code>arr</code> as input.</p>
</li>
<li><p>A single variable <code>total</code> is created, which is constant space (O(1)) because it doesn't depend on the size of the input.</p>
</li>
<li><p>The loop uses an iterator <code>i</code>, which is also constant space (O(1)).</p>
</li>
<li><p>Now since the <code>total</code> is already in memory we don't consider <code>total += arr[i];</code></p>
</li>
<li><p>The space complexity is primarily determined by the input array <code>arr</code>. As the array's size increases, the space required to store it increases proportionally. Therefore, the space complexity of this function is O(n), where 'n' is the length of the input array.</p>
</li>
</ul>
<p><strong>Example 2:</strong> <code>double</code> function</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">double</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">let</span> newArr = [];
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; arr.length; i++) {
    newArr.push(<span class="hljs-number">2</span> * arr[i]);
  }
  <span class="hljs-keyword">return</span> newArr;
}
</code></pre>
<p>In this example:</p>
<ul>
<li><p>The function <code>double</code> takes an array <code>arr</code> as input.</p>
</li>
<li><p>A new array <code>newArr</code> is created, which is directly related to the size of the input array. As <code>arr</code> grows, so does <code>newArr</code>. Therefore, the space complexity for <code>newArr</code> is O(n), where 'n' is the length of the input array.</p>
</li>
<li><p>The loop uses an iterator, <code>i</code> which is constant space (O(1)).</p>
</li>
</ul>
<p>So, for the <code>double</code> function, the primary contributor to space complexity is the new array, <code>newArr</code> making it O(n).</p>
<h4 id="heading-lastly-lets-talk-about-logarithms">Lastly let’s talk about logarithms</h4>
<p>We've explored some of the familiar complexities in Big O notation, such as O(1) for constant time, O(n) for linear time, and O(n^2) for quadratic time. However, as we delve deeper into algorithm analysis, we encounter more intricate mathematical expressions, and one that frequently arises is the logarithm.</p>
<p>Logarithmic time complexity is a desirable characteristic of algorithms because it means that the algorithm's performance improves as the input size increases. Certain searching algorithms, such as binary search, have logarithmic time complexity because they repeatedly divide the search space in half. Efficient sorting algorithms, such as quicksort, merge sort, and heapsort, involve logarithms because they divide the input into smaller and smaller pieces until they are sorted. Recursion sometimes involves logarithmic space complexity because each recursive call adds a new layer to the call stack, which has a logarithmic relationship to the input size.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://cs.slides.com/colt_steele/big-o-notation#/41/0/3">Colt Steele Slides</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Dive into Nest JS: The Ultimate Crash Course for The Impatient]]></title><description><![CDATA[A few years ago, I faced a constant struggle: joining new Node.js teams always meant dealing with a unique setup, often inconsistent and complex. This, as you might guess from reading my previous blog post about Node.js setups, could be incredibly ti...]]></description><link>https://articles.collinsbenda.com/dive-into-nest-js-the-ultimate-crash-course-for-the-impatient</link><guid isPermaLink="true">https://articles.collinsbenda.com/dive-into-nest-js-the-ultimate-crash-course-for-the-impatient</guid><category><![CDATA[nestjs]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[backend]]></category><category><![CDATA[crash course]]></category><dc:creator><![CDATA[Atuhaire Collins Benda]]></dc:creator><pubDate>Mon, 04 Mar 2024 14:07:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731863712035/65c8d47c-b4ca-4553-bd34-99ce492640da.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few years ago, I faced a constant struggle: joining new Node.js teams always meant dealing with a unique setup, often inconsistent and complex. This, as you might guess from reading my previous blog post about Node.js setups, could be incredibly time-consuming and frustrating. Onboarding new team members was just as complicated, with everyone learning unfamiliar configurations.</p>
<p>In search of a better solution, I went on a quest for a "batteries-included" framework akin to Django in Python, Laravel in PHP, or .NET in C#. I wanted something that:</p>
<p><strong>Enforced best practices:</strong> Consistent structures and patterns would save time, prevent errors, and improve code maintainability.</p>
<p><strong>Supported TypeScript out of the box:</strong> For a more robust and scalable development experience.</p>
<p><strong>Handled authentication out of the box:</strong> Eliminate the need to build authentication logic from scratch, saving development time and improving security.</p>
<p>My search led me to <a target="_blank" href="https://nestjs.com/">NestJS</a>, and it instantly transformed my Node.js development experience. This blog will be your ultimate deep dive into NestJS, exploring its features, components, benefits, and why it's the perfect choice for building robust and scalable Node.js applications. Now that we've established the pain points of inconsistent setups and the desire for a structured framework, let's dive deeper into NestJS itself.</p>
<h1 id="heading-what-is-nestjs"><strong>What is NestJS?</strong></h1>
<p>NestJS is a JavaScript application framework designed specifically for building efficient and scalable server-side applications using Node.js. It embraces modern development practices, offering several key features:</p>
<p><strong>Progressive JavaScript:</strong> the ability to gradually adopt modern JavaScript features while still maintaining compatibility with older.</p>
<p><strong>TypeScript Support:</strong> Embraces the benefits of TypeScript for type safety and advanced features, while still allowing pure JavaScript development for flexibility.</p>
<p><strong>Paradigm Blend:</strong> NestJS incorporates elements from various programming paradigms like Object-Oriented Programming (OOP), Functional Programming (FP), and Functional Reactive Programming (FRP), providing flexibility and diverse tools for different situations.</p>
<p><strong>Opinionated Approach:</strong> NestJS guides developers towards best practices by promoting specific patterns and structures, leading to cleaner, more maintainable code. This "opinionated" approach draws inspiration from frameworks in the <a target="_blank" href="http://ASP.NET">ASP.NET</a> and Java worlds.</p>
<p><strong>Express Integration:</strong> NestJS leverages the popular Express framework under the hood, allowing you to utilize familiar Express concepts like middleware and routing within the NestJS structure.</p>
<p><strong>Batteries Included:</strong> NestJS boasts a rich ecosystem with numerous features "out of the box," including support for web sockets, microservices architecture, and extensive testing capabilities. This reduces the need for extensive third-party library integrations.</p>
<p>NestJS provides a robust foundation for building modern and scalable Node.js applications, promoting best practices through its structure and offering a comprehensive feature set without sacrificing developer flexibility. By combining powerful features with familiar paradigms, NestJS empowers developers to focus on business logic and deliver exceptional applications.</p>
<h2 id="heading-why-embrace-nestjs-for-your-next-project">Why Embrace NestJS for Your Next Project?</h2>
<p>NestJS stands out as a compelling choice for building robust and scalable Node.js applications, offering several key advantages:</p>
<p><strong>1. Enforcing Best Practices:</strong></p>
<p>NestJS promotes well-established design patterns, guiding developers towards a structured and organized codebase. This approach simplifies the process of creating maintainable, scalable, and extensible systems, reducing the risk of technical debt in the long run.</p>
<p><strong>2. Suitable Abstractions:</strong></p>
<p>NestJS provides appropriate abstractions that effectively shield developers from low-level complexities. This simplifies development and allows them to focus on core business logic without getting bogged down in the intricacies of underlying technologies.</p>
<p><strong>3. Opinionated Approach:</strong></p>
<p>NestJS isn't afraid to take a stance on best practices. It encourages consistent patterns and structures across projects, leading to code that's easier to understand, maintain, and collaborate on. This "opinionated" approach, while valuing flexibility, ultimately fosters consistency and coherence within a project and across different teams. This translates to <strong>shorter onboarding times</strong> and <strong>reduced training overhead</strong>, especially for those with experience in similar frameworks like Spring Boot, thanks to shared concepts. This is particularly valuable for startups where time is often a critical resource.</p>
<p><strong>4. Enhanced Reusability:</strong></p>
<p>NestJS promotes code reusability at multiple levels:</p>
<p><strong>Code-Level Reusability:</strong> The framework offers reusable components and modules, reducing redundancy and streamlining development.</p>
<p><strong>Experience and Knowledge Reusability:</strong> By borrowing concepts from established frameworks like <a target="_blank" href="http://ASP.NET">ASP.NET</a>, Angular, and Spring, NestJS leverages existing knowledge and experience, shortening the learning curve for developers familiar with these platforms.</p>
<p><strong>In essence, NestJS empowers developers to:</strong></p>
<p><strong>Focus on innovation:</strong> Simplified development and enforced best practices free up valuable time and cognitive resources to focus on delivering innovative solutions and features.</p>
<p><strong>Build maintainable systems:</strong> The structured approach fosters code that's easier to understand, modify, and scale, ensuring long-term project health.</p>
<p><strong>Leverage existing knowledge:</strong> Familiarity with similar frameworks translates into quicker adoption and utilization of NestJS, accelerating development and reducing onboarding times.</p>
<p>By combining these benefits, NestJS presents a compelling choice for developers seeking a structured, efficient, and scalable foundation for their next Node.js application.</p>
<h2 id="heading-getting-started-with-nestjs-setup-and-installation">Getting Started with NestJS: Setup and Installation</h2>
<h3 id="heading-prerequisites"><strong>Prerequisites:</strong></h3>
<p>Before diving into NestJS, ensure you have the following installed on your system:</p>
<ul>
<li><strong>Node.js:</strong> NestJS is built upon Node.js, so you'll need a recent version installed. Download and install it from the official website.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/JINE4D0Syqw">https://youtu.be/JINE4D0Syqw</a></div>
<p> </p>
<ul>
<li><p><strong>ES6 Features</strong>: like classes</p>
</li>
<li><p>Backend basics</p>
</li>
</ul>
<h3 id="heading-getting-started"><strong>Getting Started:</strong></h3>
<p><strong>1. Install Nest CLI:</strong></p>
<p>Once you have Node.js running, you can install the <strong>Nest CLI (Command Line Interface)</strong> globally using npm:</p>
<pre><code class="lang-bash">npm install -g @nestjs/cli
</code></pre>
<p>This command installs the Nest CLI tools globally, allowing you to easily create and manage NestJS projects from your terminal.</p>
<p><strong>2. Create a New Nest Project:</strong></p>
<p>With the Nest CLI installed, you can create a new NestJS project using the following command:</p>
<pre><code class="lang-bash">nest new &lt;project_name&gt;
</code></pre>
<p>Replace <code>&lt;project_name&gt;</code> with your desired project name (e.g., <code>my-awesome-app</code>).</p>
<p>This command will create a new directory named <code>&lt;project_name&gt;</code> with the basic NestJS project structure, including essential files and folders for your application.</p>
<p><strong>Next Steps:</strong></p>
<p>After creating the project, navigate to the project directory using <code>cd &lt;project_name&gt;</code>:</p>
<p>You can then install dependencies and run the application using the following commands:</p>
<pre><code class="lang-bash">
npm install
npm run start
</code></pre>
<p>These commands will install the required dependencies and start your NestJS application in development mode. You can then access your application in your browser, typically at <a target="_blank" href="http://localhost:3000"><code>http://localhost:3000</code></a>.</p>
<h2 id="heading-mastering-the-nestjs-cli-essential-commands">Mastering the NestJS CLI: Essential Commands</h2>
<p>The NestJS CLI is a powerful tool that streamlines project creation, development, and management. Here's a breakdown of some key commands you'll use frequently:</p>
<p><strong>1.</strong><code>nest new &lt;project_name&gt;</code><strong>:</strong></p>
<p><strong>Purpose:</strong> Scaffolds a new NestJS project with the specified name, providing the fundamental directory structure and essential files to kick-start your application.</p>
<p><strong>2.</strong><code>nest start</code><strong>:</strong></p>
<p><strong>Purpose:</strong> Starts the development server, transpiling your TypeScript code into JavaScript for execution.</p>
<p><code>--watch</code><strong>flag:</strong> Enables automatic transpilation whenever you make changes to your code, ensuring your application reflects the latest updates without manual intervention.</p>
<p><strong>3.</strong><code>nest generate &lt;element&gt;</code><strong>:</strong></p>
<p><strong>Purpose:</strong> Generates various building blocks of your NestJS application, including :</p>
<p><strong>Modules</strong>: Organize your application logic and functionality.</p>
<p><strong>Controllers</strong>: Handle incoming API requests and responses.</p>
<p><strong>Pipes</strong>: Transform and validate data before it reaches your controllers.</p>
<p><strong>Guards</strong>: Implement authorization logic to control access to specific application parts.</p>
<p><strong>Providers</strong>: Create services and utility functions used throughout your application.</p>
<p>Services: Encapsulate reusable business logic and interact with external resources like databases.</p>
<p><strong>Test file inclusion:</strong> Importantly, this command also generates a corresponding test file for the specified element, promoting good testing practices from the outset.</p>
<p>With these fundamental CLI commands, you'll be well-equipped to navigate the development process and build robust NestJS applications efficiently. If you want to see more of these check out the official docs.</p>
<h2 id="heading-nestjs-project-structure-files-and-scripts-explained">NestJS Project Structure: Files and Scripts Explained</h2>
<p>NestJS offers a well-organized project structure to streamline development and maintainability. This section delves into essential files and scripts within our newly created NestJS project:</p>
<p><strong>1.</strong><code>package.json</code><strong>Scripts:</strong></p>
<p><img src="https://cdn.sanity.io/images/dvgwl1ti/production/8d50aab0d3ea936627057812dc3564d19b575910-890x585.png?rect=6,0,878,585&amp;w=600&amp;h=400&amp;fit=fillmax" alt="NestJS package.json scripts" /></p>
<p><code>npm run build</code><strong>:</strong> Transpiles your TypeScript code into JavaScript for production use. The generated code resides in the <code>dist</code> folder, ready for deployment to your server.</p>
<p><code>npm run format</code><strong>:</strong> Leverages the <code>prettier</code> library to format your code consistently, enforcing a uniform style guide across your project. This promotes code readability and improves team collaboration. Ideally, you'd run this before committing changes or pushing code.</p>
<p><code>npm run start</code><strong>:</strong> Starts the NestJS web server using the transpiled code in the <code>dist</code> folder. This command is typically used on the server where your application runs.</p>
<p><code>npm run start:dev</code><strong>:</strong> Similar to <code>npm run start</code>, but includes the <code>--watch</code> flag. This enables a file watcher that automatically rebuilds your code and restarts the server whenever you make changes, streamlining the development workflow.</p>
<p><strong>2. Application Files:</strong></p>
<p><code>src</code><strong>Folder:</strong> Holds all of your application's source code, categorized into different files.</p>
<p><strong>3. Core Application Files:</strong></p>
<p>nestJS App src folder</p>
<p><img src="https://cdn.sanity.io/images/dvgwl1ti/production/a5e676af1eaa99f5fd27a40d35bdc20d59cda045-383x183.png?rect=55,0,275,183&amp;w=600&amp;h=400&amp;fit=fillmax" alt="nestJS App src folder" /></p>
<p>I'll make an effort to provide a brief explanation of the files in your src folder. When we get to the nest's construction blocks, we'll dig deeper;</p>
<p><code>main.ts</code><strong>:</strong> The entry point of your application. When you run <code>nest start</code>, it executes this file, finding and instantiating the root module (<code>AppModule</code>) to create the application instance. It also sets up global middleware and starts the Express server on the specified port (3000 by default). This file contains the bootstrapping logic, keeping it separate from application-specific concerns, making it easier to modify or test in isolation following the Encapsulation &amp; Single Responsibility Principle (SRP).</p>
<p><code>app.controller.ts</code><strong>:</strong> A basic controller providing an endpoint at <a target="_blank" href="http://localhost:3000"><code>http://localhost:3000</code></a>. The controller focuses on handling requests and responses, delegating business logic to the injected <code>AppService</code> (see below). <strong>Inversion of Control</strong>(IoC) helps manage dependencies, improving testability and flexibility.</p>
<p><code>app.controller.spec.ts</code><strong>:</strong> The corresponding test suite for the <code>AppController</code>. These test suites are automatically generated when you create elements using <code>nest generate</code>, providing a starting point for writing unit tests.</p>
<p><code>app.service.ts</code><strong>:</strong> A simple injectable provider that returns a "hello world" message. In real-world scenarios, service classes handle the bulk of your application's business logic.</p>
<p><code>app.module.ts</code><strong>:</strong> The root module, acts as the dependency injection container explicitly managing dependencies and their lifecycles. It registers all your controllers and providers for the application to use. This <code>AppModule</code> is typically maintained and other modules are imported into it. This improves code testability and makes the system more flexible to change.</p>
<p><strong>4. NestJS-Specific Files:</strong></p>
<p><code>nest-cli.json</code><strong>:</strong> Configures the Nest CLI, allowing customization of project generation settings or default CLI behaviors (e.g., default file naming conventions).</p>
<p><code>tsconfig.json</code><strong>:</strong> The base TypeScript configuration file, controlling the compilation behavior of your TypeScript code.</p>
<p>**<a target="_blank" href="http://tsconfig.build"><code>tsconfig.build</code></a><code>.json</code>: ** Occasionally, this file may exist to provide specific configuration for the TypeScript compiler used in the build process.</p>
<p><code>public</code><strong>:</strong> May contain static assets to be served directly by the web server.</p>
<p><strong>3. Testing-Related Files:</strong></p>
<p><code>test/*</code><strong>:</strong> You might have a dedicated <code>test</code> folder containing different types of tests:</p>
<p><code>.e2e-spec.ts</code><strong>:</strong> End-to-end tests that simulate real user interactions with your application through the browser.</p>
<p><strong>Other integration test files:</strong> These might focus on testing how different components of your application interact with each other.</p>
<p><strong>4. Other Files:</strong></p>
<p><code>.eslint.js*</code><strong>:</strong> allows you to define configuration rules for your project using various formats. This format offers a concise and readable way to specify your desired coding style and enforce best practices. You can go ahead and add linters to the project to enforce your team code styles</p>
<p><strong>Note:</strong> This is not exhaustive. As your project grows, you might introduce new file types or folders to organize things like:</p>
<h2 id="heading-nestjs-module-structure-feature-based-organization">NestJS Module Structure: Feature-Based Organization</h2>
<p>NestJS adopts a <strong>per-feature module approach</strong>, similar to Angular and Django. This means that all the elements needed to implement a single feature (like CRUD operations for a database model) are grouped within a dedicated folder and bundled into a corresponding module.</p>
<p><strong>Comparison with Traditional Layered Structure:</strong></p>
<p>Traditional approaches, often seen in <a target="_blank" href="http://ASP.NET">ASP.NET</a>, Java, and elsewhere, organize classes by their type (e.g., controllers, services, models) in separate folders. Here's an example:</p>
<pre><code class="lang-bash">Controllers/
|--- TodoController.cs
Services/
|--- TodoService.cs
Models/
|--- TodoEntity.cs
</code></pre>
<p><strong>NestJS Approach:</strong></p>
<p>In NestJS, the structure looks different, grouping elements by feature:</p>
<pre><code class="lang-bash">todo/
|--- todo.controller.ts
|--- todo.entity.ts
|--- todo.module.ts
|--- todo.service.ts
</code></pre>
<p><strong>Benefits of Per-Feature Modules:</strong></p>
<p><strong>Improved Discoverability:</strong> Grouping related code by feature makes it easier to find and understand specific functionalities within your application.</p>
<p><strong>Enhanced Reusability:</strong> Entire modules, representing complete features, can be easily moved around, integrated into other projects, or packaged as libraries.</p>
<p><strong>Clear Delegation:</strong> Feature modules facilitate assigning ownership and development responsibilities to individual teams or members.</p>
<p>This approach makes it rather painless to pick up and move large portions of functionality to new codebases or into packageable libraries, and also makes it easy to split up code responsibilities among teams or team members.</p>
<h2 id="heading-core-building-blocks-of-nestjs">Core Building Blocks of NestJS</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/f0qzBkAQ3mk">https://youtu.be/f0qzBkAQ3mk</a></div>
<p> </p>
<p>As highlighted by NestJS's founder, the framework offers several key building blocks that empower developers to efficiently construct robust and scalable applications. Here's a breakdown of these essential elements:</p>
<h4 id="heading-modules"><strong>Modules</strong></h4>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/qZfO4EopfPA">https://youtu.be/qZfO4EopfPA</a></div>
<p> </p>
<p>Modules are where all of the controllers and providers are registered, along with all of the imported sub-modules which contain their own controllers and providers. Modules hook up the dependency injection containers and enable the resolving of required dependencies for controllers and providers. In NestJS, modules are created by decorating a class with the <code>@Module</code> decorator. A simple example of a Module class would look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//sample.module.ts</span>
<span class="hljs-meta">@Module</span>({
    imports: [DatabaseModule],
    controllers: [TodoController],
    providers: [TodoService],
    <span class="hljs-built_in">exports</span>: [TodoService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> TodoModule  {}
</code></pre>
<p>The <code>@Module</code> decorator takes in a metadata object with four properties: • <code>imports</code>: Importing other <code>@Module</code> classes allows for using other sub-modules and creating the hierarchy of functionality. For instance, the <code>AppModule</code> will be importing the <code>TodoModule</code>, enabling the <code>TodoModule</code> functionality to be enabled at the root of the application. This is also how third-party modules such as <code>@nestjs/typeorm</code>, <code>@nestjs/config</code>, and others are wired into your application. • <code>controllers</code>: The controller's array contains the <code>@Controller</code> classes that are registered to this module. By defining them in this array, they are made accessible via HTTP requests. • <code>providers</code>: The provider's array contains all <code>@Injectable</code> classes such as data services, instance factories, pipes, guards, middleware, and interceptors. • <code>exports</code>: This array allows for making providers and imports registered to this module available for use outside of the current module. For example, a <code>TodoService</code> registered to a <code>TodoModule</code> is only available for classes inside the <code>TodoModule</code>. Once <code>TodoService</code> is added to the exports array, it is now available to outside modules. (<em>This is the main difference between nest and angular</em>)</p>
<h4 id="heading-controllers"><strong>Controllers</strong></h4>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/QTA8emDmH-s">https://youtu.be/QTA8emDmH-s</a></div>
<p> </p>
<p>Controllers are responsible for handling incoming requests and returning responses to the client. Controllers can group related request-handling logic into a single class. For example, a <code>TodoController</code> class might handle all incoming requests related to users, including showing, creating, updating, and deleting to-dos. They are responsible for interpreting input, passing the request details to services, and then formatting the service results in a way that can be exposed as responses. In the case of NestJS, “Controller” specifically refers to a class that handles HTTP requests. In NestJS, controllers are decorated with the <code>@Controller</code> decorator. By passing a string into the <code>@Controller</code> argument, we define a base route path for all of the routes inside the controller. The routes inside this class are notated with HTTP method decorators and path designations. It is best practice to keep controllers relatively “thin” and avoid putting significant business logic, data logic, or otherwise processing logic in your controller route methods: that work belongs in a provider service. By keeping the controller’s responsibility clearly defined as input and output transformation, it becomes easier to write, read, design, and test your code. A simple example of a Controller class would look like:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//sample.controller.ts</span>
<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'api/app'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  AppController  {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  appService:  AppService</span>)  {}

    <span class="hljs-meta">@Get</span>(<span class="hljs-string">'health'</span>)
    getHealth():  HealthCheck  {
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.appService.getHealth();
    }
}
</code></pre>
<p>Providers</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/ECEkU5WreVU">https://youtu.be/ECEkU5WreVU</a></div>
<p> </p>
<p>Providers is a blanket term in NestJS that encompasses service classes, repositories, factories, utility classes, and anything of that nature. This also includes important NestJS elements like middleware and guards. These are marked with the <code>@Injectable()</code> decorator. A provider is an instruction to the dependency injection system on how to obtain a value for dependency it can be a simple injectable class or a factory, third-party library.</p>
<h4 id="heading-services"><strong>Services</strong></h4>
<p>Services contain the core business logic of your application, handling complex operations, interacting with databases or other external resources, and generally orchestrating application logic.</p>
<h4 id="heading-others"><strong>Others</strong></h4>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/x1W3FJ1RJlM">https://youtu.be/x1W3FJ1RJlM</a></div>
<p> </p>
<p><strong>Interceptors</strong></p>
<p>These inspect, enhance, or transform HTTP requests from the client to the applications or transform responses on their way back to the client.</p>
<p><strong>Guards</strong></p>
<p>These control the request behavior. So when a request is sent before it can proceed each guard checks if the request should be allowed to proceed for instance extract the json-web-token.</p>
<p><strong>Pipes</strong></p>
<p>Pipes in NestJS transform request parameters at a method level. While you can create your own, the <code>@nestjs/common</code> package comes with very helpful pipes that cover the most common use cases. • <code>ValidationPipe</code>: provides request validation using the class-validator library. • <code>ParseIntPipe</code>: parses the route parameter to a number type. • <code>ParseBoolPipe</code>: parses the route parameter to a boolean type. • <code>ParseArrayPipe</code>: parses the route parameter to an array of a given type. • <code>ParseUUIDPipe</code>: parses the route parameter to a UUID of a provided version. • <code>DefaultValuePipe</code>: allows for a default value if no value is supplied in the route.</p>
<h2 id="heading-building-a-nestjs-todo-list-api">Building a NestJS Todo List API</h2>
<p>Let's create a simple Todo List API in NestJS to solidify our understanding of its core concepts. Here's a step-by-step approach:</p>
<p><strong>1. Project Setup:</strong></p>
<p><strong>Prerequisites:</strong> Ensure you have Node.js and npm (or yarn) installed on your system.</p>
<p><strong>Create Project:</strong> Open your terminal and run:</p>
<pre><code class="lang-bash">nest new todo-api
</code></pre>
<p>This creates a new NestJS project named <code>todo-api</code></p>
<h3 id="heading-creating-todo-directory-and-files">Creating <code>Todo</code> directory and files</h3>
<p>To start building our custom <code>Todo</code> module, let’s first create the empty files we will need. While the NestJS CLI has some excellent generation tools that we can use (which we will review later!), for this exercise we will create them by hand to demonstrate how these files all work together. Inside of your application directory, make the following directory and files:</p>
<pre><code class="lang-bash">mkdir src/todo/
touch src/todo/todo.controller.ts
touch src/todo/todo.interface.ts
touch src/todo/todo.module.ts
touch src/todo/todo.service.ts
</code></pre>
<p>Optionally you can use the Nest CLI. The Nest CLI simplifies this process quite a bit and we can accomplish the same module setup with the following commands:</p>
<pre><code class="lang-bash">nest generate module todo
nest generate controller todo
nest generate service todo
<span class="hljs-built_in">cd</span> todo &amp;&amp; nest generate interface todo
</code></pre>
<p><strong>Create the Todo interface</strong></p>
<p>Inside of the <code>todo/todo.interface.ts</code> file, we will define the shape of the To-do JSON object. Note that interfaces are different from classes in that interfaces are “abstract” - there is no JavaScript code output and they are purely used for the TypeScript compiler and IntelliSense tooling - while classes are actual instantiations in memory. To create an interface, use the TypeScript keyword <code>interface</code>. Our To-do class will have three properties:<br />• an optional id (optional new To-do requests will auto-assign the id)<br />• a label string<br />• a complete Boolean flag We will add these to the interface as such:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.interface.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span>  Todo  {
    id?:  <span class="hljs-built_in">number</span>;
    label:  <span class="hljs-built_in">string</span>;
    complete:  <span class="hljs-built_in">boolean</span>;
}
</code></pre>
<p>Create the <code>TodoService</code> data service</p>
<p>Following the prescribed NestJS architecture pattern, we will create a <code>TodoService</code> class that handles the data logic for maintaining our To-dos. Inside of the <code>todo.service.ts</code> file, we will define an exported TypeScript class, <code>TodoService</code>, and decorate it with the <code>@Injectable</code> decorator.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.service.ts</span>
<span class="hljs-keyword">import</span>  {  Injectable  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoService  {
}
</code></pre>
<p>We will be using an in-memory array as our storage mechanism. This will not persist and will be cleared out every time the development server is restarted, but it will serve as a simple mechanism to start your NestJS journey. To create this array, we will define and instantiate a storage class-level variable. Once added, your <code>todo.service.ts</code> class should look as such:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// todo.service.ts</span>
<span class="hljs-keyword">import</span>  { Injectable }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  { Todo }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> TodoService  {
    <span class="hljs-keyword">private</span> storage: Todo[] = [];
}
</code></pre>
<p><strong>Note</strong>: that NestJS providers are singletons by default and any injection of the <code>TodoService</code> will share the same in-memory array</p>
<p><strong>Create the</strong><code>TodoController</code><strong>REST API Controller</strong></p>
<p>We now need a Controller to handle our HTTP requests. To do so, we create and export a <code>TodoController</code> class that is decorated with the NestJS <code>@Controller</code> decorator with the base route path of “todo”.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {  Controller  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
}
</code></pre>
<p>To leverage the <code>TodoService</code> we created, we will use NestJS’ dependency injection through constructor injection. Using TypeScript’s constructor assignment feature, we can easily set the provider as a <code>private</code>, <code>readonly</code> class-level instance property.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {  Controller  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  todoService:  TodoService</span>)  {}
}
</code></pre>
<p>NestJS will analyze the parameters in the constructor, find the types in the dependency injection container, and resolve them. We will now be able to use the <code>TodoService</code> in-controller methods via <code>this.todoService</code>. To validate our module, we will set up a single <code>GET</code> route that returns an empty array (note the added import). Routes are enabled using HTTP method decorators: <code>@Get</code>, <code>@Post</code>, <code>@Put</code>, <code>@Patch</code>, and <code>@Delete</code>. Just like the parameter passed to <code>@Controller</code>, the value passed to the method decorator defines the path of the route. In the case of this GET request, we will leave it as undefined, ultimately resolving to the base route path of <code>/todo</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {  Controller,  Get  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;
<span class="hljs-keyword">import</span>  {  Todo  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  todoService:  TodoService</span>)  {}

    <span class="hljs-meta">@Get</span>()
    findAll():  Todo[]  {
        <span class="hljs-keyword">return</span>  [];
    }
}
</code></pre>
<p><strong>Create the</strong><code>TodoModule</code><strong>module</strong></p>
<p>With our Controller and Provider classes created, we now need to create a class and decorate it with the <code>@Module</code> decorator to register them to the NestJS application. To do so, we’ll create a <code>TodoModule</code> class and decorate it with the <code>@Module</code> decorator.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// todo.module.ts</span>
<span class="hljs-keyword">import</span>  {  Module  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-meta">@Module</span>({})
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoModule  {}
</code></pre>
<p>Now we can add the <code>TodoService</code> as a Provider to this module to make it available for injection.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// todo.module.ts</span>
<span class="hljs-keyword">import</span>  {  Module  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Module</span>({
    providers:  [TodoService],
})
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoModule  {}
</code></pre>
<p>With the <code>TodoService</code> now registered, we can register the <code>TodoController</code> which will resolve the service as a dependency.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.module.ts</span>
<span class="hljs-keyword">import</span>  {  Module  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  TodoController  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.controller'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Module</span>({
    controllers:  [TodoController],
    providers:  [TodoService],
})
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoModule  {}
</code></pre>
<p>Import <code>TodoModule</code> into <code>AppModule</code></p>
<p>We now have a contained module of functionality, from the HTTP request to the data storage. However, the root module <code>AppModule</code> we saw in the previous chapters has no reference to <code>TodoModule</code>. As we know, our entry point <code>main.ts</code> creates the <code>INestApplication</code> from the <code>AppModule</code>, so without this reference, our <code>TodoModule</code> logic is unavailable. To create this link between <code>AppModule</code> and <code>TodoModule</code>, open the <code>app.module.ts</code> file. In this <code>@Module</code> decorator, add <code>TodoModule</code> to the imports array.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// app.module.ts</span>
<span class="hljs-keyword">import</span>  {  Module  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  AppController  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./app.controller'</span>;
<span class="hljs-keyword">import</span>  {  AppService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./app.service'</span>;
<span class="hljs-keyword">import</span>  {  TodoModule  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo/todo.module'</span>;

<span class="hljs-meta">@Module</span>({
    imports:  [TodoModule],
    controllers:  [AppController],
    providers:  [AppService],
})
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  AppModule  {}
</code></pre>
<p>If the development server is not still running, start it by running <code>npm run start:dev</code>. In the console output, you should see Nest wiring up the <code>TodoModule</code> and creating the <code>TodoController</code> route:</p>
<p>With your server still running, open the Postman application. Make a new request to the <code>TodoController</code> route at <a target="_blank" href="http://localhost:3000/todo">http://localhost:3000/todo</a>. The controller will return a JSON response of an empty array, which we return in the <code>findAll()</code> method. We are now resolving HTTP requests to our <code>TodoController</code> and are ready to start adding the CRUD actions to the controller and service.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {
Controller,
Get,
} <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;
<span class="hljs-keyword">import</span>  {  Todo  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  todoService:  TodoService</span>)  {}

    <span class="hljs-meta">@Get</span>()
    findAll():  Todo[]  {
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.findAll();
    }
}
</code></pre>
<p>Ensure that the development server is still running in your command-line tool. Open Postman and make a GET request to <a target="_blank" href="http://localhost:3000/todo"><code>http://localhost:3000/todo</code></a>. In response, we’ll get an empty array (again).</p>
<h4 id="heading-create"><code>create()</code></h4>
<p><strong>Add the POST route</strong></p>
<p>With the data service method in place, we now need to enable an HTTP endpoint in our controller to call it. To do this, we will create a @Post route on the <code>TodoController</code>. Following REST standards, we’ll configure this route to be <code>POST/todo</code>. With <code>@Post</code>, <code>@Put</code>, and <code>@Patch</code> routes, the HTTP content body is used to transfer data objects, such as JSON, XML, or text. In this example, we will be sending a JSON object of a <code>Todo</code> item. For NestJS to parse and interpret the content body, the decorator <code>@Body</code> should be applied to the route method parameter. NestJS will apply <code>JSON.parse()</code> to the content and provide you a JSON object to work with. Since we expect this payload to match our <code>Todo</code> interface, we will type it as such.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {
Body,
Controller,
Get,
Post,
} <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  Todo  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
    <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  todoService:  TodoService</span>)  {}

    <span class="hljs-meta">@Post</span>()
    create(<span class="hljs-meta">@Body</span>()  todo:  Todo):  <span class="hljs-built_in">void</span>  {
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.create(todo);
    }

    <span class="hljs-meta">@Get</span>()
    findAll():  Todo[]  {
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.findAll();
    }
}
</code></pre>
<p>We can now send a POST request to <a target="_blank" href="http://localhost:3000/todo"><code>http://localhost:3000/todo</code></a> with a JSON payload to add it to the storage array. In Postman, do the following to set up your POST request:</p>
<p>1. Create a new request tab.</p>
<p>2. Change the GET value in the HTTP method dropdown to POST.</p>
<p>3. Enter the <a target="_blank" href="http://localhost:3000/todo"><code>http://localhost:3000/todo</code></a> value in the URL.</p>
<p>4. In the <code>Body</code> tab, select <code>raw</code>. In the dropdown to the right of <code>binary</code>, select “<code>JSON(application/json)</code>”.</p>
<p>In the text-area, supply the following body:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"label"</span>:  <span class="hljs-string">"Create  an  awesome  API"</span>,
    <span class="hljs-attr">"complete"</span>:  <span class="hljs-literal">false</span>
}
</code></pre>
<p>Send the request. Our response will be empty but with a status of <code>201</code> Created. We can now make a GET request to <a target="_blank" href="http://localhost:3000/todo"><code>http://localhost:3000/todo</code></a> again to see our new To-do item in our array with a set id of 1.</p>
<h4 id="heading-quick-aside-adding-the-nestjs-logger">Quick aside: Adding the NestJS Logger</h4>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/OdSaI_S7uwM">https://youtu.be/OdSaI_S7uwM</a></div>
<p> </p>
<p>You may have noticed that there was no indication in our command-line console that the request was processed. While this is likely ideal in most scenarios, it would be very helpful for us to see that we are hitting the routes that we expect. NestJS provides a <code>Logger</code> implementation that makes it easy to add logging to your application. It is best practice to use this <code>Logger</code> class over the <code>console log</code> methods because the log messages are formatted cohesively, and the Logger allows you to swap out functionality or disable logging completely at a global level with a simple configuration in your <code>main.ts</code> file. To add logging to our controller, create a new instance of a Logger as a class-level variable on the <code>TodoController</code>. We will add a log statement to each of our methods as well.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {
Body,
Controller,
Get,
Logger,
Post,
} <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  Todo  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
    <span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  logger  =  <span class="hljs-keyword">new</span>  Logger(TodoController.name);

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span>  <span class="hljs-keyword">readonly</span>  todoService:  TodoService</span>)  {}

    <span class="hljs-meta">@Post</span>()
    create(<span class="hljs-meta">@Body</span>()  todo:  Todo):  <span class="hljs-built_in">void</span>  {
        <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Handling create() request...'</span>);
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.create(todo);
    }

    <span class="hljs-meta">@Get</span>()
    findAll():  Todo[]  {
        <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Handling findAll() request...'</span>);
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.findAll();
    }
}
</code></pre>
<p>Now when we make a request to either method, we will see items in our console such as:</p>
<pre><code class="lang-bash">[TodoController]  Handling  create()  request...
[TodoController]  Handling  findAll()  request...
</code></pre>
<h4 id="heading-findone"><code>findOne()</code></h4>
<h4 id="heading-add-the-get-route">Add the GET route</h4>
<p>We will now need to update the <code>TodoController</code> accordingly to enable this service method through an HTTP request. In <code>todo.controller.ts</code>, we will add a new <code>@Get</code> method, but this time we will take in a route parameter in the <code>@Get</code> decorator. Route parameters are variables inside of a given path. Routers use pattern matching to interpret and parse these paths and pluck out the variables in the provided route pattern. To access this variable in your NestJS route method, the <code>@Param</code> decorator is applied to the method argument, supplying the name of the route parameter. In our API, we want to supply the To-do object’s id as a route parameter, so we use the route pattern of <code>:id</code> to indicate a parameter variable with an id, and then use the <code>@Param('id')</code> decorator to hook the value into the method argument.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {
Body,
Controller,
Get,
Logger,
Param,
Post,
} <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  Todo  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
    <span class="hljs-comment">// ...</span>

    <span class="hljs-meta">@Get</span>(<span class="hljs-string">':id'</span>)
    findOne(<span class="hljs-meta">@Param</span>(<span class="hljs-string">'id'</span>)  id:  <span class="hljs-built_in">number</span>):  Todo  {
        <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Handling findOne() request with id='</span>  +  id  +  <span class="hljs-string">'...'</span>);
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.findOne(id);
    }
}
</code></pre>
<p>Since the storage array was cleared when we restarted our development server, we will do the following to test:</p>
<p>Send the POST request outlined in the create() section to create a new To-do item.</p>
<p>Send a GET request to <a target="_blank" href="http://localhost:3000/todo">http://localhost:3000/todo</a> to see all the items in storage, including your new To-do.</p>
<p>Send a GET request to <a target="_blank" href="http://localhost:3000/todo/1">http://localhost:3000/todo/1</a>, our new route, to retrieve the To-do item directly. <strong><em>Uh oh, the response is empty!</em></strong> Our command-line console says we hit the route with expected ID <code>([TodoController] Handling findOne() request with id=1...)</code> . So, what happened? It is important to understand that by default, <code>@Param</code> values are strings. While we gave it the type of number, recall that TypeScript types are abstract and have no impact on the actual executing code; this is to say that the executing code had no way of knowing it should have parsed the route parameter id to a number. This is where the <code>@Pipe</code> decorator comes in.</p>
<p>To fix our <code>findOne()</code> endpoint, we need to add the <code>ParseIntPipe</code> to our <code>@Param</code> pipe.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//todo.controller.ts</span>
<span class="hljs-keyword">import</span>  {
Body,
Controller,
Get,
Logger,
Param,
ParseIntPipe,
Post,
} <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span>  {  Todo  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.interface'</span>;
<span class="hljs-keyword">import</span>  {  TodoService  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./todo.service'</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'todo'</span>)
<span class="hljs-keyword">export</span>  <span class="hljs-keyword">class</span>  TodoController  {
<span class="hljs-comment">// ...</span>
    <span class="hljs-meta">@Get</span>(<span class="hljs-string">':id'</span>)
    findOne(<span class="hljs-meta">@Param</span>(<span class="hljs-string">'id'</span>,  ParseIntPipe)  id:  <span class="hljs-built_in">number</span>):  Todo  {
        <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Handling findOne() request with id='</span>  +  id  +  <span class="hljs-string">'...'</span>);
        <span class="hljs-keyword">return</span>  <span class="hljs-built_in">this</span>.todoService.findOne(id);
    }
}
</code></pre>
<p>This will parse the value to a number and now our <code>.find()</code> method in our data service will find an exact equality against the Todo item we POST. Since the storage array was cleared when we restarted our development server, we will do the following to test:</p>
<p>Send the POST request outlined in the <code>create()</code> section to create a new Todo item.</p>
<p>Send a GET request to <a target="_blank" href="http://localhost:3000/todo"><code>http://localhost:3000/todo</code></a> to see all the items in storage, including your new Todo.</p>
<p>Send a GET request to <a target="_blank" href="http://localhost:3000/todo/1"><code>http://localhost:3000/todo/1</code></a>, our new route, to retrieve the To-do item directly. With this pipe in place, we’re now able to retrieve the To-do item.</p>
<h3 id="heading-integrating-user-interface">Integrating User Interface</h3>
<p>To test with this user interface, start up your development web server with <code>npm run start:dev</code>. In the user interface, try to create a new To-do item by typing in the “What’s next?” input and hitting enter. <em>Uh oh, nothing happened!</em></p>
<h4 id="heading-enable-cors">Enable CORS</h4>
<p>If you check out your browser console, you’ll see some errors about a missing <code>Access-Control-Allow-Origin</code> header. These errors are due to cross-origin reference sharing (CORS) restrictions that prevent web applications from making XHR requests to other domains. These restrictions are a security feature browsers have put in place using what are known as pre-flight requests and API response headers. Pre-flight requests are OPTION HTTP requests that are executed before the actual XHR request. Your browser automatically injects this request and if the restrictions specified in the response headers are met by the request parameters, then the actual request will continue as expected. By default, these restrictions prevent requests from any other origin; in our case, our server at <a target="_blank" href="http://localhost">localhost</a> is preventing XHR requests from <a target="_blank" href="http://stackblitz.com">stackblitz.com</a>. NestJS makes opening these CORS restrictions simple. In your <code>main.ts</code> file, call <code>app.enableCors();</code> in the <code>bootstrap()</code> method. This will add headers to your controller route responses that enable cross-domain requests.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.ts</span>

<span class="hljs-keyword">import</span>  {  NestFactory  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'@nestjs/core'</span>;
<span class="hljs-keyword">import</span>  {  AppModule  }  <span class="hljs-keyword">from</span>  <span class="hljs-string">'./app.module'</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bootstrap</span>(<span class="hljs-params"></span>)  </span>{
    <span class="hljs-keyword">const</span> app = <span class="hljs-keyword">await</span> NestFactory.create(AppModule);
    app.enableCors();
    <span class="hljs-keyword">await</span>  app.listen(<span class="hljs-number">3000</span>);
}
bootstrap();
</code></pre>
<h1 id="heading-resources"><strong>Resources</strong></h1>
<p><a target="_blank" href="https://www.youtube.com/watch?v=f0qzBkAQ3mk">Building a platform: NestJS from the ground up | Kamil Mysliwiec | JS Poland 2018</a><br /><a target="_blank" href="https://wanago.io/2020/05/11/nestjs-api-controllers-routing-module/">Wanago Blog</a><br /><a target="_blank" href="https://www.codewithvlad.com/ebooks/">Code with Vlad's book</a><br /><a target="_blank" href="https://www.radiansys.com/blog/nestjs">Radiansys blog</a></p>
]]></content:encoded></item></channel></rss>