<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://truongtx.me/feed.xml" rel="self" type="application/atom+xml" /><link href="https://truongtx.me/" rel="alternate" type="text/html" /><updated>2026-02-11T23:43:24+00:00</updated><id>https://truongtx.me/feed.xml</id><title type="html">TruongTX Blog</title><subtitle>My personal blog</subtitle><author><name>TruongTX</name><email>me@truongtx.me</email></author><entry><title type="html">Merge Sort and the Interview</title><link href="https://truongtx.me/2024/11/30/merge-sort-and-the-interview" rel="alternate" type="text/html" title="Merge Sort and the Interview" /><published>2024-11-30T00:00:00+00:00</published><updated>2024-11-30T00:00:00+00:00</updated><id>https://truongtx.me/2024/11/30/merge-sort-and-the-interview</id><content type="html" xml:base="https://truongtx.me/2024/11/30/merge-sort-and-the-interview"><![CDATA[<blockquote>
  <p>It’s not just about Sorting!</p>
</blockquote>

<h1 id="1-merge-sort">1. Merge Sort</h1>

<p>Merge Sort is one of the most commonly taught sorting algorithm (beside Quick Sort)
in any Computer Science and Information Technology courses. I will start by briefly reviewing the
fundamental knowledge of Merge Sort. The basic idea behind Merge sort is a divide-and-conquer
strategy, where you break the array into smaller halves, sort each half and then merge them back
together. The recursive process continues until each half contains only 1 item (already sorted).</p>

<p><img src="/files/2024-10-24-merge-sort-interview/merge-sort.png" alt="Merge Sort Explain" /></p>

<p>There are 2 variants of Merge sort implementation, using <code class="language-plaintext highlighter-rouge">for</code> and <code class="language-plaintext highlighter-rouge">while</code> loop. You can check my
other post about Merge Sort <a href="/2018/05/23/merge-sort-summary">here</a>, which contains
the <code class="language-plaintext highlighter-rouge">for</code> version from the algorithm course on Coursera. For the purpose of
interview questions, I’ll demonstrate using the <code class="language-plaintext highlighter-rouge">while</code> version in this post.</p>

<p>As mentioned above, there are 2 essential steps in Merge Sort, the Divide step and the Merge step.
Let’s begin with the Divide step</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// WARNING: This is not working code and not the most efficient way to do</span>
<span class="kd">const</span> <span class="nx">mergeSort</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// base case</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="nx">arr</span><span class="p">;</span>

  <span class="kd">const</span> <span class="nx">mid</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span>
  <span class="kd">const</span> <span class="nx">firstHalf</span> <span class="o">=</span> <span class="nx">mergeSort</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">mid</span><span class="p">));</span>
  <span class="kd">const</span> <span class="nx">secondHalf</span> <span class="o">=</span> <span class="nx">mergeSort</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">mid</span><span class="p">,</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span>
  <span class="k">return</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">firstHalf</span><span class="p">,</span> <span class="nx">secondHalf</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>and here is how you merge 2 halves (2 sorted arrays)</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// WARNING: This is not working code and not the most efficient way to do</span>
<span class="kd">const</span> <span class="nx">merge</span>  <span class="o">=</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">,</span> <span class="nx">arr2</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="p">[];</span>
  <span class="k">while</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span> <span class="o">&amp;&amp;</span> <span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">item1</span> <span class="o">=</span> <span class="nx">arr1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="kd">const</span> <span class="nx">item2</span> <span class="o">=</span> <span class="nx">arr2</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">item1</span> <span class="o">&lt;</span> <span class="nx">item2</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item1</span><span class="p">);</span>
      <span class="nx">arr1</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
      <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item2</span><span class="p">);</span>
      <span class="nx">arr2</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(...</span><span class="nx">arr1</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(...</span><span class="nx">arr2</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">res</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<!-- more -->

<p>It’s time for you to practice some easy Leetcode questions related to Merge Sort before reading the
next part.</p>
<ul>
  <li><a href="https://leetcode.com/problems/merge-sorted-array/description/">Merge Sorted Array</a></li>
  <li><a href="https://leetcode.com/problems/merge-two-sorted-lists/description/">Merge Two Sorted Lists</a>
(<a href="/2021/12/10/solution-to-merge-two-sorted-lists-problem">solution</a>)</li>
  <li><a href="https://leetcode.com/problems/squares-of-a-sorted-array/description/">Squares of a Sorted Array</a>
(<a href="/2022/10/11/solution-for-squares-of-a-sorted-array-problem">solution</a>)</li>
</ul>

<h1 id="2-the-merge-function">2. The Merge Function</h1>

<p>We will continue by examining the above <code class="language-plaintext highlighter-rouge">merge</code> function in detail. Here is another way to
visualize it. Think about it as
<strong>Pick the first item from either array based on some criteria, then repeat until no items left</strong></p>

<p><img src="/files/2024-10-24-merge-sort-interview/merge-function.png" alt="Merge Function" /></p>

<p>This time, ask yourself these questions</p>
<ul>
  <li>What if the arrays are replaced with two linked lists?</li>
  <li>What if they are replaced with two queues?</li>
  <li>How about the arrays with unknown size?</li>
  <li>How do you handle datasets that are too large to fit in memory?</li>
</ul>

<p>These scenarios often appear in interview problems. You can spot them when
you see the input involves two datasets that can be ordered, such as sorted arrays, linked lists
or queues. For more challenging questions, the interviewer might obscure these details, requiring
you to transform the input into an ordered format (usually by sorting).</p>

<p>Let’s take a look at some scenarios</p>

<h2 id="external-sorting">External Sorting</h2>

<p>Merge Sort and its variants are useful for doing External Sorting, a technique to
handle massive amounts of data that don’t fit in RAM. The most common question related to this
type is to sort a large file (containing 1 million 8-bit integers) on a computer with only
1MB of RAM. The approach remains the same: divide the file into smaller parts that fit into memory,
sort each of them individually, write the sorted parts to another file and finally merge the
files back together.</p>

<p><img src="/files/2024-10-24-merge-sort-interview/merge-file.png" alt="Merge 2 files" /></p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// pseudo code only</span>
<span class="kd">let</span> <span class="nx">val1</span> <span class="o">=</span> <span class="nx">readLine</span><span class="p">(</span><span class="nx">file1</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">val2</span> <span class="o">=</span> <span class="nx">readLine</span><span class="p">(</span><span class="nx">file2</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">val1</span> <span class="o">||</span> <span class="nx">val2</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">val1</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">writeLine</span><span class="p">(</span><span class="nx">val2</span><span class="p">,</span> <span class="nx">outFile</span><span class="p">);</span>
    <span class="nx">val2</span> <span class="o">=</span> <span class="nx">readLine</span><span class="p">(</span><span class="nx">file2</span><span class="p">);</span>
    <span class="k">continue</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">val2</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">writeLine</span><span class="p">(</span><span class="nx">val1</span><span class="p">,</span> <span class="nx">outFile</span><span class="p">);</span>
    <span class="nx">val1</span> <span class="o">=</span> <span class="nx">readLine</span><span class="p">(</span><span class="nx">file1</span><span class="p">);</span>
    <span class="k">continue</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="nx">val1</span> <span class="o">&lt;</span> <span class="nx">val2</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">writeLine</span><span class="p">(</span><span class="nx">val1</span><span class="p">,</span> <span class="nx">outFile</span><span class="p">);</span>
    <span class="nx">val1</span> <span class="o">=</span> <span class="nx">readLine</span><span class="p">(</span><span class="nx">file1</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">writeLine</span><span class="p">(</span><span class="nx">val2</span><span class="p">,</span> <span class="nx">outFile</span><span class="p">);</span>
    <span class="nx">val2</span> <span class="o">=</span> <span class="nx">readLine</span><span class="p">(</span><span class="nx">file2</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Read more <a href="/2018/05/05/solutions-to-the-sorting-with-1mb-ram-computer-problem">Solution to the Sorting with 1MB RAM computer problem</a></p>

<h2 id="intersection-and-union">Intersection and Union</h2>

<p>Another interview problem is to find the intersection
or union of two arrays. <strong>Union</strong> is an array containing elements present in either or both of the
arrays, while <strong>intersection</strong> is an array containing only items present in both arrays. In both
cases, all duplicates are removed and the order of the elements in the result may vary depending on
the implementation.</p>

<p>For problems like these, sorting the input arrays beforehand can simplify it a lot. Once sorted,
apply a modified version of the <strong>merge function</strong> to your 2 sorted arrays. For the union, maintain
two pointers starting at the beginning of both arrays, append the smaller one to the result and
advance the pointer for that array. If the two items are equal, append one of them and advance both
pointers.</p>

<p>To help you imagine it better, here’s the visualization of each iteration inside the merge function</p>

<p><img src="/files/2024-10-24-merge-sort-interview/union.png" alt="Union" /></p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// pseudo code only</span>
<span class="kd">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span> <span class="o">||</span> <span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// edge where only arr1 or arr2 has items</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{...}</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{...}</span>

  <span class="c1">// decide which array to pick item from and then move the point up</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;</span> <span class="nx">arr2</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">{</span>
    <span class="c1">// pick from arr1</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">shift</span><span class="p">());</span>
  <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;</span> <span class="nx">arr2</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">{</span>
    <span class="c1">// pick from arr2</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arr2</span><span class="p">.</span><span class="nx">shift</span><span class="p">());</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="c1">// pick from both</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">shift</span><span class="p">());</span>
    <span class="nx">arr2</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>A similar process can be adapted to compute the intersection, but only equal elements are added to
the result</p>

<p><img src="/files/2024-10-24-merge-sort-interview/intersection.png" alt="Intersection" /></p>

<p>Here are some similar questions to practice</p>
<ul>
  <li>What happens if the two input arrays contain duplicate elements?</li>
  <li><a href="https://leetcode.com/explore/featured/card/top-interview-questions-easy/127/strings/887/">Longest Common Prefix</a></li>
</ul>

<h2 id="concurrency-control">Concurrency Control</h2>

<p>The merge function is not limited to solving mathematical problems, but also applied in concurrency
control. It is widely used to combine and coordinate different data sources like processes, queues
or linked lists.</p>

<p><img src="/files/2024-10-24-merge-sort-interview/concurrency.png" alt="Concurrency Control" /></p>

<p>Consider the following interview exercises</p>

<ol>
  <li><strong>Two-Lane Bridge Problem</strong>: A bridge has two lanes, one for vehicles <strong>coming in</strong> and one for
vehicles <strong>going out</strong>. The bridge can only support one vehicle per lane at a time. Vehicles arrive
at different times, and each vehicle wants to either enter or exit the bridge.
    <ul>
      <li>If a vehicle wants to enter and another wants to exit at the same time, prioritize the vehicle
that arrived first.</li>
      <li>How would you determine the exact time each vehicle can cross the bridge, respecting the order of
arrival and the last usage of the bridge?</li>
    </ul>
  </li>
  <li><strong>Train Station Platform</strong>: A train station has a single platform and two queues: one for passengers
wanting to <strong>board</strong> the train and one for passengers wanting to <strong>disembark</strong>.
    <ul>
      <li>The train can either be used for boarding or disembarking at any given time. Passengers arrive at
different times and are either boarding or leaving.</li>
      <li>The platform can be used for boarding or disembarking, but the direction depends on who arrived
first when simultaneous arrivals happen.</li>
      <li>How would you calculate the exact time each passenger can board or disembark the train?</li>
    </ul>
  </li>
  <li><strong>Single Gate Airport Security</strong>: At an airport, there is a single security gate that allows people
to either <strong>enter</strong> or <strong>exit</strong>. People arrive at the gate at different times and want to either
board a flight or leave the airport.
    <ul>
      <li>If two people arrive at the same time with opposite directions (one entering, one exiting), the
direction in which the gate was last used will determine who goes first.</li>
      <li>How would you determine when each person passes through the gate?</li>
    </ul>
  </li>
  <li><strong>Library Entry/Exit System</strong>: A library has a single turnstile and two queues: one for people
who want to <strong>enter</strong> the library and another for those who want to <strong>exit</strong>.
    <ul>
      <li>Each person arrives at a specific time, and their direction (enter or exit) is known.</li>
      <li>If two people arrive at the same time with different directions, the decision of who goes first
depends on the turnstile’s last usage.</li>
      <li>Calculate the time each person will be allowed to pass through the turnstile.</li>
    </ul>
  </li>
  <li><strong>Parking Garage Gate</strong>: A parking garage has a single gate that vehicles can use either to
<strong>enter</strong> or to <strong>exit</strong>. Each vehicle has a specific arrival time, and its desired direction
(enter or exit) is also given.
    <ul>
      <li>If vehicles with opposite directions arrive at the same time, the gate gives priority based on its last usage.</li>
      <li>Determine when each vehicle will pass through the gate, considering these rules.</li>
    </ul>
  </li>
  <li><strong>Single Lane Toll Booth</strong>: A toll booth has a single lane, and vehicles either want to
<strong>pay tolls</strong> or <strong>leave</strong>. Vehicles arrive at the booth at different times, and their direction
(whether they want to pay or leave) is given.
    <ul>
      <li>If two vehicles arrive at the same time, one wishing to pay and the other wishing to leave, the
decision of who goes first depends on the toll booth’s last usage.</li>
      <li>Calculate the time each vehicle will cross the toll booth.</li>
    </ul>
  </li>
  <li><strong>Hospital Entry System</strong>: A hospital has a single entrance, and people arrive either to
<strong>enter</strong> the hospital or <strong>leave</strong>. Each person arrives at a given time with a desired direction
(enter or exit).
    <ul>
      <li>If people arrive at the same time, the direction the entrance was last used will determine who gets to go first.</li>
      <li>How would you compute when each person can pass through the entrance?</li>
    </ul>
  </li>
  <li><strong>Amusement Park Entrance</strong>: An amusement park has a single gate, and guests either want to
<strong>enter</strong> or <strong>exit</strong>. The entrance operates like a turnstile and can only process one guest at a
time.
    <ul>
      <li>If two guests with different directions arrive at the same time, the direction the gate was last
used (enter or exit) determines who goes first.</li>
      <li>How would you determine the exact time each guest will pass through the gate?</li>
    </ul>
  </li>
  <li><strong>Stadium Gate Entry/Exit</strong>: A stadium has a single turnstile and two queues: one for people
wanting to <strong>enter</strong> the stadium and another for those wanting to <strong>exit</strong>.
    <ul>
      <li>If two people arrive at the same time, the one with the direction corresponding to the last
operation of the turnstile will go first.</li>
      <li>How would you calculate when each person passes through the gate?</li>
    </ul>
  </li>
  <li><strong>Convention Center Turnstile</strong>: A convention center has a single turnstile that can be used for
people to either <strong>enter</strong> or <strong>exit</strong>. People arrive at the turnstile at different times, and each
person is either entering or leaving.
    <ul>
      <li>If two people arrive at the same time and their directions are different, the decision of who goes
first depends on the previous usage of the turnstile.</li>
      <li>Determine the time when each person passes through the turnstile.</li>
    </ul>
  </li>
</ol>

<p>Did you spot the pattern? The keyword of this type of challenge is to
<strong>coordinate two different queues</strong>. The above questions are just the simplified version. In
reality, they may require you to do some data transformation to form the two queues but the
idea remain unchanged. Now, it’s your turn to solve the above problems yourself. 😉</p>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="algorithm" /><summary type="html"><![CDATA[It's not just about Sorting!]]></summary></entry><entry><title type="html">Optimize a Recursive problem</title><link href="https://truongtx.me/2024/10/13/optimize-a-recursive-problem" rel="alternate" type="text/html" title="Optimize a Recursive problem" /><published>2024-10-13T00:00:00+00:00</published><updated>2024-10-13T00:00:00+00:00</updated><id>https://truongtx.me/2024/10/13/optimize-a-recursive-problem</id><content type="html" xml:base="https://truongtx.me/2024/10/13/optimize-a-recursive-problem"><![CDATA[<p>Ok, you will probably find this problem during your coding interview 😩 Many companies don’t like
giving the candidates tricky problems. Instead, they often ask you to write a recursive
function to prove that you’re a real engineer, not some random guys applying for the job because
it’s well paid 😆 After that, the next question is usually about
how to optimize that function with very large datasets and avoid the “Maximum call stack size exceeded” error</p>

<p>Here is how you can prepare yourself for that type of interview question</p>

<h1 id="1-basic-recursion">1. Basic Recursion</h1>

<p>Let’s start with this very basic recursion question</p>

<blockquote>
  <p>Given an array <code class="language-plaintext highlighter-rouge">arr</code> with <code class="language-plaintext highlighter-rouge">N</code> items, write a recursive function to calculate the sum of all items in the array</p>
</blockquote>

<p>If you think about recursion in its simplest form, it’s like a divide and conquer strategy,
where you break the problem into smaller ones, solve one of them first and then repeat with
the other remaining ones (recursive case) until there is no item left (base case). Now, let’s take
a look at the above problem, the solution can be described like this: The sum of an array is the sum
of the first element (the head of the list) and all the remaining items (the tail of the array).</p>

<blockquote>
  <p>If you have worked in any lisp-like language (Emacs Lisp for example 😂), you will
immediately see the pattern. They are the <code class="language-plaintext highlighter-rouge">car</code> and <code class="language-plaintext highlighter-rouge">cdr</code> function in Elisp.</p>
</blockquote>

<p>From that, you can easily write a basic recursive function like this (in Javascript)</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sum</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">head</span><span class="p">,</span> <span class="p">...</span><span class="nx">tail</span><span class="p">]</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">;</span>
  <span class="k">return</span> <span class="nx">head</span> <span class="o">+</span> <span class="nx">sum</span><span class="p">(</span><span class="nx">tail</span><span class="p">);</span>
<span class="p">};</span>
</code></pre></div></div>

<!-- more -->

<h2 id="an-iterative-solution">An iterative solution</h2>

<p>Of course, the easiest way is to convert the above one to a simple <code class="language-plaintext highlighter-rouge">for</code> (or <code class="language-plaintext highlighter-rouge">while</code>) loop to
avoid adding to the call stack.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sum</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">let</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">sum</span> <span class="o">+=</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="nx">sum</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Simple? Yeah that’s just what you learnt in university, but that will probably help you during
the interview.</p>

<h2 id="tail-call-optimization-and-trampoline">Tail-call optimization and Trampoline</h2>

<p>Another way you can answer the interviewer is to use Tail-call optimization. In some programming
languages, if you return the recursive call as the last expression in the function, they can optimize automatically by
avoiding creating a new call stack. Using that concept, you can rewrite the above <code class="language-plaintext highlighter-rouge">sum</code> function like this</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sum</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">acc</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">acc</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">head</span><span class="p">,</span> <span class="p">...</span><span class="nx">tail</span><span class="p">]</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">;</span>
  <span class="k">return</span> <span class="nx">sum</span><span class="p">(</span><span class="nx">tail</span><span class="p">,</span> <span class="nx">head</span> <span class="o">+</span> <span class="nx">acc</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">sum</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Does it look like <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce">Array.prototype.reduce()</a> in Javascript?</p>
</blockquote>

<p>However, a new problem arises here. The above piece of code is written in Javascript, which doesn’t support tail-call optimization</p>

<blockquote>
  <p>Actually, it’s partially supported now. However, let’s assume we are working on a non-supported language.</p>
</blockquote>

<p>There is another way you can rewrite the above one in a tail-call style without the support from the
language. Instead of returning the recursive call, you can return a function calling the recursive
function and use a wrapper function (trampoline) to execute and manage the stack.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sum</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">acc</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">acc</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">head</span><span class="p">,</span> <span class="p">...</span><span class="nx">tail</span><span class="p">]</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">;</span>
  <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">sum</span><span class="p">(</span><span class="nx">tail</span><span class="p">,</span> <span class="nx">head</span> <span class="o">+</span> <span class="nx">acc</span><span class="p">);</span> <span class="c1">// the difference is here</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">sumTrampoline</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">sum</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
  <span class="k">while</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">result</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">function</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">result</span> <span class="o">=</span> <span class="nx">result</span><span class="p">();</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">};</span>

<span class="nx">sumTrampoline</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>
</code></pre></div></div>

<h1 id="2-dynamic-programming">2. Dynamic Programming</h1>

<p>Now, let’s come to a more complicated problem</p>

<blockquote>
  <p>You are climbing a staircase. It takes <code class="language-plaintext highlighter-rouge">n</code> steps to reach the top.
Each time you can either climb <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">2</code> steps. In how many distinct ways can you climb to the top?</p>
</blockquote>

<p>This is the most common DP problem that you will see every time you enter a coding interview (beside the
Fibonacci and House Robber question). The most straight forward solution is to write a recursive
function to count the ways to step through 1 or 2 steps.</p>

<p><img src="/files/2024-09-16-optimize-a-recursive-problem/climb1.png" alt="Climb 1" /></p>

<p>For the above example, the solution can be explained like this</p>
<ul>
  <li>Start with <code class="language-plaintext highlighter-rouge">count(4)</code></li>
  <li>We can climb <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">2</code> steps each time, that means the total ways is the sum of climbing <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">2</code>
steps, or <code class="language-plaintext highlighter-rouge">count(4) = count(4-2) + count(4-1) = count(2) + count(3)</code></li>
  <li>Repeat the same problem with the smaller numbers until there is no more step to climb</li>
</ul>

<p><img src="/files/2024-09-16-optimize-a-recursive-problem/climb2.png" alt="Climb 1" /></p>

<p>From the above explanation, it’s not hard to come up with the simplest recursive implementation</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">count</span> <span class="o">=</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// base case: only 1 way to climb if 0 or 1 step</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">n</span> <span class="o">===</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">n</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>

  <span class="k">return</span> <span class="nx">count</span><span class="p">(</span><span class="nx">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="nx">count</span><span class="p">(</span><span class="nx">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">);</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">n</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">count</span><span class="p">(</span><span class="nx">n</span><span class="p">));</span> <span class="c1">// print 5</span>
</code></pre></div></div>

<h2 id="memoization">Memoization</h2>

<p>Let’s take a look at the above solution again, you may notice that both these recursive calls
<code class="language-plaintext highlighter-rouge">count(2)</code> and <code class="language-plaintext highlighter-rouge">count(3)</code> contain an overlapping problem (the blue one in the below picture) because
<code class="language-plaintext highlighter-rouge">count(3)</code> can be interpreted as <code class="language-plaintext highlighter-rouge">count(1) + count(2)</code>.</p>

<p><img src="/files/2024-09-16-optimize-a-recursive-problem/climb3.png" alt="Climb 3" /></p>

<p>With that in mind, we can store the overlapping calculation into an array and pass that array into
each recursive call.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">count</span> <span class="o">=</span> <span class="p">(</span><span class="nx">n</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// same base case</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">n</span> <span class="o">===</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">n</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>

  <span class="c1">// check if this problem has already been calculated</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">res</span><span class="p">[</span><span class="nx">n</span><span class="p">]</span> <span class="o">!==</span> <span class="kc">undefined</span><span class="p">)</span>
    <span class="k">return</span> <span class="nx">res</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span>

  <span class="nx">res</span><span class="p">[</span><span class="nx">n</span><span class="p">]</span> <span class="o">=</span> <span class="nx">count</span><span class="p">(</span><span class="nx">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">+</span> <span class="nx">count</span><span class="p">(</span><span class="nx">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</span>
  <span class="k">return</span> <span class="nx">res</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">n</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">count</span><span class="p">(</span><span class="nx">n</span><span class="p">,</span> <span class="nx">res</span><span class="p">));</span>
</code></pre></div></div>

<h2 id="tabulation">Tabulation</h2>

<p>In the above memoization solution, after executing the <code class="language-plaintext highlighter-rouge">count</code> function, the <code class="language-plaintext highlighter-rouge">res</code> array will
be built like this</p>

<p><img src="/files/2024-09-16-optimize-a-recursive-problem/climb4.png" alt="Climb 4" /></p>

<p>The pattern here is similar to Fibonacci problem, where the value of each item in the array is the
value of the previous 2 items. We can then build a solution to traverse and build the array from the
beginning</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">count</span> <span class="o">=</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>

  <span class="c1">// base case</span>
  <span class="nx">res</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="nx">res</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>

  <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span><span class="o">=</span><span class="mi">2</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;=</span><span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">res</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">res</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="nx">res</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">2</span><span class="p">];</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="nx">res</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">n</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">count</span><span class="p">(</span><span class="nx">n</span><span class="p">));</span>
</code></pre></div></div>

<p>You can also optimize it even more using only 2 variables to store <code class="language-plaintext highlighter-rouge">i-1</code> and <code class="language-plaintext highlighter-rouge">i-2</code> values.</p>

<h1 id="3-depth-first-search-and-breadth-first-search">3. Depth First Search and Breadth First Search</h1>

<p>Another type of recursion question that the interviewer usually ask is the question related to tree data structure, for example this one</p>

<p>Given a starting directory, build a JSON model representing the structure of the directory and all its nested items. Your function should output a json structure like this</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"root"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"contents"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="s2">"file.txt"</span><span class="p">,</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"root/folder1"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"contents"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"weavels.pdf"</span><span class="w">
      </span><span class="p">]</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"root/an_empty_folder"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"contents"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="s2">"test.txt"</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<ul>
  <li>Each file is represented as a string</li>
  <li>Each folder is represented as an object with a contents array for all its child <code class="language-plaintext highlighter-rouge">{ "name": "xxx", "contents": []}</code></li>
</ul>

<h2 id="depth-first-search">Depth First Search</h2>

<blockquote>
  <p>I was quite surprised that many engineers couldn’t solve this problem using the simplest recursive implementation 🫠</p>
</blockquote>

<p>At the very basic level, a software engineer should be able to write a simple recursive function like this to traverse the directory tree starting from the root node</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">getContents</span> <span class="o">=</span> <span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// implement this</span>
  <span class="k">return</span> <span class="p">[</span><span class="dl">'</span><span class="s1">child1.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">child2.txt</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">childFolder1</span><span class="dl">'</span><span class="p">];</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">isFolder</span> <span class="o">=</span> <span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// implement this</span>
  <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">buildNode</span> <span class="o">=</span> <span class="p">(</span><span class="nx">parent</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">children</span> <span class="o">=</span> <span class="nx">getContents</span><span class="p">(</span><span class="nx">parent</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
  
  <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">children</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">name</span> <span class="o">=</span> <span class="nx">children</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
    <span class="kd">const</span> <span class="nx">childNode</span> <span class="o">=</span> <span class="nx">isFolder</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">?</span>
      <span class="nx">buildNode</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="na">contents</span><span class="p">:</span> <span class="p">[]})</span> <span class="p">:</span> <span class="nx">name</span><span class="p">;</span>
    <span class="nx">parent</span><span class="p">.</span><span class="nx">contents</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">childNode</span><span class="p">);</span>
  <span class="p">}</span>
  
  <span class="k">return</span> <span class="nx">parent</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="nx">buildNode</span><span class="p">({</span><span class="na">name</span><span class="p">:</span> <span class="nx">entryPoint</span><span class="p">,</span> <span class="na">contents</span><span class="p">:</span> <span class="p">[]});</span>
</code></pre></div></div>

<h2 id="breadth-first-search">Breadth First Search</h2>

<p>After you have finished writing that, the interviewer will definitely ask a follow up question about your optimization when the input folder is a very big one with a lot of nested levels. There are many ways to solve this, but the most common way is to convert this to a Breadth First Search solution.</p>

<blockquote>
  <p>As long as you can mention that keyword, you are 50% to the success 😆</p>
</blockquote>

<p>The idea behind BFS is to visit all nodes in the current level first (closest nodes first) before visiting the next level (further ones later), in constrast to DFS, that is to traverse all the nested child of the current node before visiting the next one. BFS can help you avoid the “Maximum call stack exceeded” error in DFS for very large trees. The implementation relies on a queue and sometimes an extra array to store the visited items.</p>

<p>Here is the quick and dirty BFS solution</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">buildTree</span> <span class="o">=</span> <span class="p">(</span><span class="nx">entryPoint</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">root</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span> <span class="nx">entryPoint</span><span class="p">,</span> <span class="na">contents</span><span class="p">:</span> <span class="p">[]};</span>
  <span class="kd">const</span> <span class="nx">q</span> <span class="o">=</span> <span class="p">[</span><span class="nx">root</span><span class="p">];</span> <span class="c1">// use array for bfs queue</span>
  
  <span class="k">while</span> <span class="p">(</span><span class="nx">q</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">current</span> <span class="o">=</span> <span class="nx">q</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
    <span class="kd">const</span> <span class="nx">children</span> <span class="o">=</span> <span class="nx">getContents</span><span class="p">(</span><span class="nx">current</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
    <span class="nx">children</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">child</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">isFolder</span><span class="p">(</span><span class="nx">child</span><span class="p">))</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">childNode</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span> <span class="nx">child</span><span class="p">,</span> <span class="na">contents</span><span class="p">:</span> <span class="p">[]};</span>
        <span class="nx">q</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">childNode</span><span class="p">);</span>
        <span class="nx">current</span><span class="p">.</span><span class="nx">contents</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">childNode</span><span class="p">);</span>
      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="nx">current</span><span class="p">.</span><span class="nx">contents</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">child</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">});</span>
  <span class="p">}</span>
  
  <span class="k">return</span> <span class="nx">root</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<blockquote>
  <p>You can also use BFS for Binary tree, 2D maze and Unweighted graph problems</p>
</blockquote>

<h1 id="time-to-practice">Time to practice</h1>

<p>What I presented in this post so far are just the suggestions to the common recursive problems. They are not everything but can cover most of the interview questions related to recursion. I’ve been through several similar interviews and even the advanced problems given to Senior role are based on those 3 categories with a lot more edge cases to handle (FAANG and Big Tech interview could be different and harder).</p>

<p>You should also practice to get yourself familiar with those types of question before any interview. Here are some challenges that you could take</p>

<ul>
  <li>Factorial</li>
  <li><a href="https://leetcode.com/problems/climbing-stairs/description/">Climbing Stairs</a></li>
  <li><a href="https://leetcode.com/problems/house-robber/description/">House Robber</a></li>
  <li><a href="https://www.geeksforgeeks.org/coin-change-dp-7/">Coin Change</a></li>
  <li><a href="https://leetcode.com/problems/fibonacci-number/description/">Fibonacci</a></li>
  <li><a href="https://leetcode.com/problems/binary-tree-level-order-traversal/description/">Binary Tree Level Order Traversal</a></li>
  <li><a href="https://leetcode.com/problems/flood-fill/">Flood Fill</a></li>
  <li><a href="https://leetcode.com/problems/max-area-of-island/">Max Area of Island</a></li>
  <li><a href="https://leetcode.com/problems/01-matrix/">01 Matrix</a></li>
  <li><a href="https://leetcode.com/problems/populating-next-right-pointers-in-each-node/">Populating Next Right Pointers in Each Node</a></li>
  <li><a href="https://leetcode.com/problems/rotting-oranges/">Rotting Oranges</a></li>
  <li><a href="https://leetcode.com/problems/binary-tree-right-side-view/">Binary Tree Right Side View</a></li>
  <li><a href="https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/">Populating Next Right Pointers in Each Node II</a></li>
  <li><a href="https://leetcode.com/problems/symmetric-tree/">Symmetric Tree</a></li>
  <li><a href="https://leetcode.com/problems/find-if-path-exists-in-graph/description/">Find if Path Exists in Graph</a></li>
</ul>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="algorithm" /><summary type="html"><![CDATA[Prepare yourself for a coding interview…]]></summary></entry><entry><title type="html">A Unified Development Environment Journey - Part 2</title><link href="https://truongtx.me/2024/09/06/a-unified-development-environment-journey-part-2" rel="alternate" type="text/html" title="A Unified Development Environment Journey - Part 2" /><published>2024-09-06T00:00:00+00:00</published><updated>2024-09-06T00:00:00+00:00</updated><id>https://truongtx.me/2024/09/06/a-unified-development-environment-journey-part-2</id><content type="html" xml:base="https://truongtx.me/2024/09/06/a-unified-development-environment-journey-part-2"><![CDATA[<blockquote>
  <p>Previous post: <a href="/2024/08/26/a-unified-development-environment-journey-part-1">A Unified Development Environment Journey - Part 1</a></p>
</blockquote>

<p>I won’t mention about setting up Codespaces or Devcontainer as it’s already on their documentation
page. In this post, I’ll show you some of the problems and example workflows that I did with
Codespaces/Devcontainer.</p>

<h1 id="dev-credentials-and-environment-variables">Dev credentials and Environment variables</h1>

<p>Your organization may created some private packages that requires some layers of authentication in
order to install (the npm packages hosted on GCP for example). One possible solution is to create
an access token (or any other type of credential) and put set it in your development environment.
For Codespaces, you can simply set it on your Github configuration page. However, for Devcontainer,
it needs a bit more work. The idea is to mount the environment file from outside of the container
and then load those variables to Devcontainer</p>

<p>Create an env file on your computer, for example <code class="language-plaintext highlighter-rouge">/var/devcontainer-mount/workflow.env</code>, which
contains all the secrets that you want to inject</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">GOOGLE_APPLICATION_CREDENTIALS</span><span class="o">=</span><span class="s2">"xxx"</span>
</code></pre></div></div>

<p>Mount the folder to your Devcontainer by adding a mount volume to your <strong>devcontainer.json</strong> file.
Read more here <a href="https://code.visualstudio.com/remote/advancedcontainers/add-local-file-mount">Add another local file mount</a></p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="err">//...other</span><span class="w"> </span><span class="err">config</span><span class="w">
  </span><span class="nl">"mounts"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/var/devcontainer-mount"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"target"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/workspaces/devcontainer-mount"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"bind"</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<!-- more -->

<p>In your Devcontainer bootstrap file (usually defined under <code class="language-plaintext highlighter-rouge">updateContentCommand</code> section in your
<strong>devcontainer.json</strong> file), load those variables before executing any script</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">[[</span> <span class="nt">-e</span> <span class="s2">"/workspaces/devcontainer-mount/workflow.env"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Sourcing secret env file..."</span>
  <span class="nb">source</span> <span class="s2">"/workspaces/devcontainer-mount/workflow.env"</span>
<span class="k">fi</span>
</code></pre></div></div>

<p>You can also make these variables available by default in your VSCode Terminal or in SSH session
by adding it to your shell’s startup files. For example, if you use zsh with a Node Devcontainer,
add this to your bootstrap file</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">touch</span> /home/node/.zshenv
<span class="nb">cat</span> /workspaces/devcontainer-mount/workflow.env <span class="o">&gt;&gt;</span> /home/node/.zshenv
</code></pre></div></div>

<h1 id="git-config-not-shared-properly-with-devcontainer">Git config not shared properly with Devcontainer</h1>

<p>It’s suggested that you install <a href="https://github.com/git-ecosystem/git-credential-manager">git-credential-manager</a>
when working with Devcontainer. However, it only transfers the credential, not the configurations (git username and user email).
Codespaces set these values automatically based your Github account. For Devcontainer, you need
to do it manually.</p>

<p>Continue with the <code class="language-plaintext highlighter-rouge">workflow.env</code> file that I mentioned above, add your Git details</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">GIT_USER_NAME</span><span class="o">=</span><span class="s2">"Tony Tran"</span>
<span class="nv">GIT_USER_EMAIL</span><span class="o">=</span><span class="s2">"my.email@my-company.com"</span>
</code></pre></div></div>

<p>and then in your bootstrap file (after sourcing the env file)</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config user.name <span class="o">&gt;</span> /dev/null <span class="o">||</span> <span class="nv">gitUserNameCheck</span><span class="o">=</span><span class="nv">$?</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$gitUserNameCheck</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$GIT_USER_NAME</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Setting Git user.name"</span>
  git config <span class="nt">--global</span> user.name <span class="s2">"</span><span class="nv">$GIT_USER_NAME</span><span class="s2">"</span>
<span class="k">fi

</span>git config user.email <span class="o">&gt;</span> /dev/null <span class="o">||</span> <span class="nv">gitUserEmailCheck</span><span class="o">=</span><span class="nv">$?</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$gitUserEmailCheck</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$GIT_USER_EMAIL</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Setting Git user.email"</span>
  git config <span class="nt">--global</span> user.email <span class="s2">"</span><span class="nv">$GIT_USER_EMAIL</span><span class="s2">"</span>
<span class="k">fi</span>
</code></pre></div></div>

<h1 id="docker-in-docker-and-its-bugs">docker-in-docker and its bugs</h1>

<p>Your Devcontainer/Codespaces instance is actually a Docker container (or can be treated as another
computer). You can install any database engine into it and connect directly. However, for
simplicity, we usually just pull a docker image with the database engine already bundled. You can
also easily find other docker images for different backing services, for example Pubsub emulator.</p>

<p>Devcontainer supports running
<a href="https://github.com/devcontainers/features/tree/main/src/docker-in-docker">docker inside docker</a>.
Once you have enabled and recreated your Devcontainer, just use all the Docker commands normally
inside your Devcontainer</p>

<p>This is an example of Docker running inside Docker Devcontainer
<img src="/files/2024-04-19-a-unified-dev-environment/docker-in-docker.jpg" alt="docker-in-docker" /></p>

<p>However, I usually get these below issues when using this feature, sometimes on first rebuild of
the container or sometimes when the container is started</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/docker-issue-1.jpg" alt="docker issue 1" />
<img src="/files/2024-04-19-a-unified-dev-environment/docker-issue-2.jpg" alt="docker issue 2" /></p>

<p>I figured out the issue is that Docker service inside Devcontainer sometimes fail to start. You can
simply run this command inside Devcontainer/Codespaces to fix</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/share/docker-init.sh
</code></pre></div></div>

<blockquote>
  <p>Similar, if you use its
<a href="https://github.com/devcontainers/features/tree/main/src/sshd">sshd feature</a>, sometimes it also
fails to start. Run <code class="language-plaintext highlighter-rouge">/usr/local/share/ssh-init.sh</code> to manually start ssh service.</p>
</blockquote>

<p>It may still fail after you run the above init command in case you run it inside your iTerm via an
SSH session. In that case, simply run any Docker commands (<code class="language-plaintext highlighter-rouge">docker compose up</code> for example) inside
<strong>VSCode Terminal</strong> and then come back to your SSH window. 99% it will work in both VSCode and SSH
after that. I guess it’s because VSCode terminal has some environment variable set by default
related to Docker RPC. 🫠</p>

<h1 id="e2e-and-ui-tests">E2E and UI Tests</h1>

<p>Devcontainer acts like another computer and we connect to it via our VSCode/Jetbrains terminal
or SSH session. For UI testing with browser, you can only run in headless mode. Luckily,
Devcontainer comes with a builtin feature, providing us a minimal VNC desktop UI. It can be
connected using any VNC client or directly via WebUI. You can enable it following the instructions
<a href="https://github.com/devcontainers/features/tree/main/src/desktop-lite">here</a>.</p>

<p>After you have rebuilt your Devcontainer/Codespaces, simply install any browser or UI test
framework that you want and start them in headful mode. You can easily access that VNC desktop
via browser</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/desktop.jpg" alt="lite-desktop" /></p>

<h1 id="anything-else">Anything else?</h1>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="misc" /><summary type="html"><![CDATA[My dream about a unified development environment for everybody in the team for the last 10 years...]]></summary></entry><entry><title type="html">A Unified Development Environment Journey - Part 1</title><link href="https://truongtx.me/2024/08/26/a-unified-development-environment-journey-part-1" rel="alternate" type="text/html" title="A Unified Development Environment Journey - Part 1" /><published>2024-08-26T00:00:00+00:00</published><updated>2024-08-26T00:00:00+00:00</updated><id>https://truongtx.me/2024/08/26/a-unified-development-environment-journey-part-1</id><content type="html" xml:base="https://truongtx.me/2024/08/26/a-unified-development-environment-journey-part-1"><![CDATA[<p>I have been dreaming about a unified dev environment for everybody in the team, where there’s no
more <strong>It works on my machine</strong> issue. The dev environment should be portable, automatically
configured and can be destroyed/recreated as quickly as possible. It should also provide all the
necessary tools for the developer as well as enforce everyone in the team to follow the correct
convention consistently.</p>

<h1 id="my-first-attempt-in-university">My first attempt in university</h1>

<p>Here is my first effort when I was a student, a classic solution.</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/first-attempt.png" alt="First attempt" /></p>

<p>In this method, you would run everything normally in your computer and use a Bash/Ansible script
to install all the necessary tools as well as set up the development environment. Of course,
this is the worst (but was the best with my knowledge at that time 😆).</p>

<ul>
  <li>This setup won’t be reused for multiple engineers. Each engineer has a very different setup on
that machine. The script can mess up the other people’s computer easily.</li>
  <li>Even if it’s just for me, that also won’t work. I install and set up new applications all the
time. After a while, when I touch that project again, all the scripts were broken and I don’t even
remember how to run my app again.</li>
</ul>

<h1 id="a-better-way">A better way</h1>

<p>I began learning how to do it the professional way in my first job after graduated.
The environment is configured using a Virtualbox VM (provisioned by Vagrant), 
which reflects the real setup on the production server. The server/VM runs everything, from the
database server to the main application.</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/before-codespaces.png" alt="2014" /></p>

<!-- more -->

<p>Later on, with the increase in Docker adoption, the setup had changed to this</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/docker-workflow.png" alt="Docker" /></p>

<p>This time, of course, it was a much better setup</p>
<ul>
  <li>The VM/Containers could be created or destroyed easily.</li>
  <li>The VM/Containers reflect the real production server, which is a Linux server while my machine is
a Macbook</li>
</ul>

<p>However, there are still a lot of drawbacks with this approach. Each engineer in the team still has
their own computer with different applications, different setup. We then need to clone the repo,
install all the necessary tools (Nodejs, Homebrew, tmux,…), load the repo into our text editor,
configure the plugins (ex eslint, prettier,…) to work.</p>
<ul>
  <li>The only things that we can make sure that always behave the same is the VM or the containers
running inside Docker. Everything else, <strong>No</strong>. It really depends on what is installed on that
computer. An engineer could have multiple Nodejs versions (installed via nvm) and forget to switch
to the correct version for the project. An engineer could install a different application on that
computer, for example, the command like ls behave slighly different on Macos and Linux,…</li>
  <li>We have to configure all the IDE/Editor plugins to follow the correct convention. What will happen
if we accidentally install a different version of prettier/eslint or install a different version
of the plugin? What will happen if we misconfigure it?</li>
  <li>As a result, still the classic problem: It works on my machine.</li>
  <li>What will happen if you mess up everything and want to do a fresh setup of the project?</li>
  <li>What will happen if you want to run 2 instances of the same project, to test some configuration?</li>
  <li>How to share a same setup across all team while still maintain the customizability of each
engineer’s habit?</li>
</ul>

<blockquote>
  <p>Some people also mount the git repo into Docker to run the app directly, but the performance is
not very good so I won’t mention that solution here.</p>
</blockquote>

<h1 id="adopting-github-codespaces">Adopting Github Codespaces</h1>

<p>At Skutopia, we then adopted <strong>Codespaces</strong> as a solution to the above problems. The idea behind is to
transform <strong>Your Computer</strong> into <strong>Somebody else Computer</strong>. Codespaces is a Cloud technology, where
you can quickly spin up a new VM running your whole dev environment. Your computer acts as a UI
only.</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/codespaces.png" alt="Codespaces" /></p>

<p>Here are the benefits of running Codespaces</p>
<ul>
  <li><strong>A single unified development environment</strong> for the whole team, where you define a configuration file
describing what you want to set up for that machine, even the VSCode plugins.</li>
  <li>You can configure <strong>the exact software</strong> and the version that should be used for the whole team</li>
  <li>You can configure <strong>the exact plugins</strong> to make sure everybody in the company follow the same
convention</li>
  <li>Once created, the application will <strong>just work</strong>. You can start working immediately, using the
debugger or running a test case. Everything will be configured already.</li>
  <li>No more <strong>It works on my machine!</strong></li>
  <li>You can still <strong>customize it</strong>! Simply set a dotfiles repository to install your favorite software.
It won’t mess up your local computer. You can also override specific VSCode settings if needed,
for example your favorite key bindings, favorite editor theme, favorite shell setup, etc.</li>
  <li>And of course, fix all the problems mentioned above with previous methods</li>
</ul>

<p>However, I have never been satisfied enough with Codespaces</p>
<ul>
  <li>It’s someone else computer (I mean cloud computer), it’s laggy, even if you have a good internet.
It has been a really annoying feeling for everybody working on Codespaces</li>
  <li>It has limited disk space. The instance we can afford has just 32gb of ram and there is no way
to increase just the disk space. We have to pay for the higher machine specs. Some of our
applications consume quite a lot of disk space.</li>
  <li>Its performance is terrible. An M1 macbook with 16gb ram really outperforms a Codespaces instance
with 4 cores and 16gb ram. We all have M1+ Macbook but cannot utilize that power.</li>
  <li>It’s pricey!</li>
</ul>

<h1 id="to-devcontainer">To Devcontainer</h1>

<p>Let’s go into more details about Codespaces</p>

<p><img src="/files/2024-04-19-a-unified-dev-environment/codespaces-details.png" alt="Codespaces" /></p>

<ul>
  <li>Codespaces is a Linux VM</li>
  <li>It runs Devcontainer, which is actually a Docker container, hence you build it using a Dockerfile
    <ul>
      <li>Devcontainer is just a wrapper around normal Docker container, providing you some other utilities to make that Docker container a dev environment.</li>
      <li>Codespaces uses Devcontainer, that’s why you see we configure it using devcontainer.json file</li>
    </ul>
  </li>
  <li>Your VSCode UI doesn’t connect to that Codespaces VM. It actually interacts with that Devcontainer. The gh command abstracts everything for you, from starting the VM+container to connect to the correct one.</li>
  <li>Devcontainer is a separate technology. Codespaces just build the wrapper around it to provide the infrastructure. VSCode actually supports us running Devcontainer separately, directly on our computer using Docker.
    <ul>
      <li>You have already installed this VSCode extension when working with Codespaces. If not, simply install it from VSCode marketplace</li>
    </ul>
  </li>
</ul>

<p><img src="/files/2024-04-19-a-unified-dev-environment/devcontainer.png" alt="Devcontainer" /></p>

<p>To get the best of both worlds, fix all the existing problems with Codespaces while still maintaining the benefit of a unified development environment, we should run Devcontainer directly on our machine, not via Codespaces.</p>

<blockquote>
  <p>My blog is also configured with Devcontainer now! 😆</p>
</blockquote>

<h1 id="arent-we-going-back-to-our-initial-solution">Aren’t we going back to our initial solution?</h1>
<p>No. Here is the comparison table</p>

<table class="table">
  <thead>
    <tr>
      <th> </th>
      <th>Initial Setup</th>
      <th>Codespaces</th>
      <th>Devcontainer</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Performant</td>
      <td>✅</td>
      <td>❌</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Exactly same environment (apps, plugins, setup,…)</td>
      <td>❌</td>
      <td>✅</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Multi instances of the same app</td>
      <td>❌</td>
      <td>✅</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Easily mess up and rebuild</td>
      <td>❌</td>
      <td>✅</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Enough disk space</td>
      <td>✅</td>
      <td>❌</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Save money</td>
      <td>✅</td>
      <td>❌</td>
      <td>✅</td>
    </tr>
  </tbody>
</table>

<h1 id="next">Next</h1>

<ul>
  <li>Problems/Solutions when setting up Codespaces/Devcontainer</li>
  <li>Sample Dev workflow with Codespaces/Devcontainer</li>
</ul>

<blockquote>
  <p>My last words: Why is Jetbrains (my favorite IDE and I paid for it) losing to VSCode in this race?
I have been waiting for so long but its support still far behind compare to VSCode 🫠</p>
</blockquote>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="misc" /><summary type="html"><![CDATA[My dream about a unified development environment for everybody in the team for the last 10 years...]]></summary></entry><entry><title type="html">Who will win?</title><link href="https://truongtx.me/2024/08/26/who-will-win" rel="alternate" type="text/html" title="Who will win?" /><published>2024-08-26T00:00:00+00:00</published><updated>2024-08-26T00:00:00+00:00</updated><id>https://truongtx.me/2024/08/26/who-will-win</id><content type="html" xml:base="https://truongtx.me/2024/08/26/who-will-win"><![CDATA[<p>My friend sent me this and asked me what the value printed at the end is, which promise would win
the race.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">promise1</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="mi">10000</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{}</span> <span class="c1">// longer loop</span>
  <span class="nx">resolve</span><span class="p">(</span><span class="dl">'</span><span class="s1">promise1</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>

<span class="kd">const</span> <span class="nx">promise2</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{}</span> <span class="c1">// shorter loop</span>
  <span class="nx">resolve</span><span class="p">(</span><span class="dl">'</span><span class="s1">promise2</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>

<span class="nb">Promise</span><span class="p">.</span><span class="nx">race</span><span class="p">([</span><span class="nx">promise1</span><span class="p">,</span> <span class="nx">promise2</span><span class="p">]).</span><span class="nx">then</span><span class="p">((</span><span class="nx">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
</code></pre></div></div>

<p>Surprisingly, most of their answers are the same, with <code class="language-plaintext highlighter-rouge">promise2</code> to be printed at the end!</p>

<p>If you have been working with Nodejs long enough and understand its event loop, you can immediately
see the problem in the above code. Even though the code is inside a Promise, which should be run
<strong>concurrently</strong> (in normal mindset). However, the <code class="language-plaintext highlighter-rouge">for</code> loops contain nothing inside. They are
called blocking code in js. Since Nodejs is single-threaded, the above functions will be executed
sequentially, in the order of declaration.</p>

<!-- more -->

<p>It will behave differently only when you add some non-blocking (async) operation inside the
Promise, for example <code class="language-plaintext highlighter-rouge">setInterval</code>.</p>

<p>Turns out a lot of them also use ChatGPT to get the answer 🥸</p>

<p><img src="/files/2024-08-26-who-will-win/chatgpt.png" alt="ChatGPT" /></p>

<blockquote>
  <p>In conclusion, use these AIs to speed up and improve your workflow, but don’t completely trust
them. Always verify the answers yourself.</p>
</blockquote>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="javascript" /><summary type="html"><![CDATA[Another interview question likely?]]></summary></entry><entry><title type="html">Compose Higher Order Functions in Typescript</title><link href="https://truongtx.me/2024/06/23/compose-higher-order-functions-in-typescript" rel="alternate" type="text/html" title="Compose Higher Order Functions in Typescript" /><published>2024-06-23T00:00:00+00:00</published><updated>2024-06-23T00:00:00+00:00</updated><id>https://truongtx.me/2024/06/23/compose-higher-order-functions-in-typescript</id><content type="html" xml:base="https://truongtx.me/2024/06/23/compose-higher-order-functions-in-typescript"><![CDATA[<h1 id="initial-problem">Initial problem</h1>

<p>It’s the classic logging issue again! In the Warehouse Management system that I’m working on, the
team usually needs to add this logging pattern</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sendToteToPackingStation</span> <span class="o">=</span> <span class="p">(</span><span class="nx">warehouseId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toteId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">Result</span><span class="o">&gt;</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">'</span><span class="s1">Sending tote to packing station</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">warehouseId</span><span class="p">,</span> <span class="nx">toteId</span> <span class="p">});</span>

  <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">someLogic</span><span class="p">(...);</span>

  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">'</span><span class="s1">Send tote result</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">result</span> <span class="p">});</span>
  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The purpose is simple. It’s what you have to do for production debugging in every system. You should
write out some unique ids so you have a place to start querying your logging system.
From that point, you will then trace the related entries using a correlation id that your system
provides.</p>

<p>From time to time, when the system scaled up, there were new areas that could slow down the system.
We then added more logging logic to the system, for example, execution time logging to help build
some visualization dashboards to identify the root cause.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sendToteToPackingStation</span> <span class="o">=</span> <span class="p">(</span><span class="nx">warehouseId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toteId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">Result</span><span class="o">&gt;</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">startTime</span> <span class="o">=</span> <span class="nx">performance</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>

  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">'</span><span class="s1">Sending tote to packing station</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">warehouseId</span><span class="p">,</span> <span class="nx">toteId</span> <span class="p">});</span>
  <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">someLogic</span><span class="p">(...);</span>
  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">'</span><span class="s1">Send tote result</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">result</span> <span class="p">});</span>

  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">'</span><span class="s1">Execution time</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="na">durationMs</span><span class="p">:</span> <span class="nx">elapsedTimeMs</span><span class="p">(</span><span class="nx">startTime</span><span class="p">)</span> <span class="p">});</span>
  <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Of course, when this was repeated multiple times, we started thinking about making a higher order
function (HOF) to reuse everywhere is the system</p>

<h1 id="first-implementation">First implementation…</h1>

<p>Let’s begin with the type definition. Here are the generic types how a HOF looks like. It’s a
function that receives a function and return another function with the same signature with the
input function</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">type</span> <span class="nx">WrappedFunction</span><span class="o">&lt;</span>
  <span class="nx">FunctionArgs</span> <span class="kd">extends</span> <span class="nx">ReadonlyArray</span><span class="o">&lt;</span><span class="nx">unknown</span><span class="o">&gt;</span><span class="p">,</span>
  <span class="nx">FunctionReturn</span>
<span class="o">&gt;</span> <span class="o">=</span> <span class="p">(...</span><span class="nx">args</span><span class="p">:</span> <span class="nx">FunctionArgs</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">FunctionReturn</span><span class="p">;</span>

<span class="k">export</span> <span class="kd">type</span> <span class="nx">HigherOrderFunction</span> <span class="o">=</span> <span class="o">&lt;</span>
  <span class="nx">FunctionArgs</span> <span class="kd">extends</span> <span class="nx">ReadonlyArray</span><span class="o">&lt;</span><span class="nx">unknown</span><span class="o">&gt;</span><span class="p">,</span>
  <span class="nx">FunctionReturn</span>
<span class="o">&gt;</span><span class="p">(</span>
  <span class="nx">func</span><span class="p">:</span> <span class="nx">WrappedFunction</span><span class="o">&lt;</span><span class="nx">FunctionArgs</span><span class="p">,</span> <span class="nx">FunctionReturn</span><span class="o">&gt;</span>
<span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">WrappedFunction</span><span class="o">&lt;</span><span class="nx">FunctionArgs</span><span class="p">,</span> <span class="nx">FunctionReturn</span><span class="o">&gt;</span><span class="p">;</span>
</code></pre></div></div>

<!-- more -->

<p>And here is the first basic implementation</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">const</span> <span class="nx">withLogging</span><span class="p">:</span> <span class="nx">HigherOrderFunction</span> <span class="o">=</span>
  <span class="p">(</span><span class="nx">wrappedFunction</span><span class="p">)</span> <span class="o">=&gt;</span>
  <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">functionName</span> <span class="o">=</span> <span class="nx">wrappedFunction</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span> <span class="nx">wrappedFunction</span><span class="p">.</span><span class="kd">constructor</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
    <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">`Running function </span><span class="p">${</span><span class="nx">functionName</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="p">{</span> <span class="nx">args</span> <span class="p">});</span>
    <span class="kd">const</span> <span class="nx">startTime</span> <span class="o">=</span> <span class="nx">performance</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>

    <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">wrappedFunction</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>
    <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">`Finished </span><span class="p">${</span><span class="nx">functionName</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="p">{</span>
      <span class="nx">result</span><span class="p">,</span>
      <span class="na">durationMs</span><span class="p">:</span> <span class="nx">elapsedTimeMs</span><span class="p">(</span><span class="nx">startTime</span><span class="p">)</span>      
    <span class="p">});</span>

    <span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
  <span class="p">};</span>

<span class="kd">const</span> <span class="nx">sendToteToPackingStationFn</span> <span class="o">=</span> <span class="p">(</span><span class="nx">warehouseId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toteId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">Result</span><span class="o">&gt;</span> <span class="o">=&gt;</span> <span class="p">{...}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">sendToteToPackingStation</span> <span class="o">=</span> <span class="nx">withLogging</span><span class="p">(</span><span class="nx">sendToteToPackingStationFn</span><span class="p">);</span>
</code></pre></div></div>

<h1 id="but-it-introduced-other-problems">…but it introduced other problems</h1>

<ul>
  <li>There are some cases that we want to log only the input and the execution time because the output
object is too large and can slow down the system. We had to introduced another HOF
<code class="language-plaintext highlighter-rouge">withParamsLogging</code> just for that purpose. Finally, we ended up with a lot of overlapping HOFs like
that in our system.</li>
  <li>For function output logging, depending on the case, we have different ways of returning data.
Sometimes, it’s a normal object with a <code class="language-plaintext highlighter-rouge">status</code>/<code class="language-plaintext highlighter-rouge">outcome</code> prop. In some other cases, we have to
return an object from <a href="https://www.npmjs.com/package/neverthrow">neverthrow</a> library. It’s hard to
maintain an HOF for multiple purposes. It usually becomes too complex and contains a lot of 
<code class="language-plaintext highlighter-rouge">if/else</code> to make sure we log the right way.</li>
  <li>We cannot use just part of the logic of the HOF, for example, only log execution time of the input
function.</li>
</ul>

<h1 id="composable-small-hofs">Composable Small HOFs</h1>

<p>Inspired by <a href="https://redux.js.org/api/compose">Redux compose</a> function, it doesn’t take much time
to resolve all the above problems with a composable approach. Instead of making big and generic
HOFs, I decided to split them into smaller HOFs, each HOF is responsible for 1 and only 1 single
purpose, for example</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">withInputLogging</code> and <code class="language-plaintext highlighter-rouge">withOutputLogging</code> to log the input and output of a function</li>
  <li><code class="language-plaintext highlighter-rouge">withNeverthrowOutputLogging</code> for logic specific to logging <strong>neverthrow</strong> output object</li>
  <li><code class="language-plaintext highlighter-rouge">withExecutionTimeLogging</code></li>
  <li><code class="language-plaintext highlighter-rouge">withPubsubLogging</code> automatically sends the data to pubsub</li>
  <li><code class="language-plaintext highlighter-rouge">withUnhandledErrorLogging</code> beautifies the unhandled error and rethrows it</li>
  <li>…</li>
</ul>

<p>To combine them, implement a <code class="language-plaintext highlighter-rouge">compose</code> function like this</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">const</span> <span class="nx">compose</span> <span class="o">=</span>
  <span class="p">(...</span><span class="nx">hofs</span><span class="p">:</span> <span class="nb">Array</span><span class="o">&lt;</span><span class="nx">HigherOrderFunction</span><span class="o">&gt;</span><span class="p">):</span> <span class="nx">HigherOrderFunction</span> <span class="o">=&gt;</span>
  <span class="p">(</span><span class="nx">wrappedFunction</span><span class="p">)</span> <span class="o">=&gt;</span>
  <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">hofs</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">wrappedFunction</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="p">[</span><span class="nx">head</span><span class="p">,</span> <span class="p">...</span><span class="nx">tail</span><span class="p">]</span> <span class="o">=</span> <span class="nx">hofs</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">finalFunc</span> <span class="o">=</span> <span class="nx">tail</span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span>
      <span class="p">(</span><span class="nx">res</span><span class="p">,</span> <span class="nx">hof</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">hof</span><span class="p">(</span><span class="nx">res</span><span class="p">),</span>
      <span class="nx">head</span><span class="p">(</span><span class="nx">wrappedFunction</span><span class="p">)</span>
    <span class="p">);</span>

    <span class="k">return</span> <span class="nx">finalFunc</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>
  <span class="p">};</span>
</code></pre></div></div>

<p>and then you can decide which HOFs you want to use in each individual case</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">const</span> <span class="nx">sendToteToPackingStation</span> <span class="o">=</span> <span class="nx">compose</span><span class="p">(</span>
  <span class="nx">withInputLogging</span><span class="p">,</span>
  <span class="nx">withOutputLogging</span><span class="p">,</span>
  <span class="nx">withExecutionTimeLogging</span><span class="p">,</span>
<span class="p">)(</span><span class="nx">sendToteToPackingStationFn</span><span class="p">);</span>
</code></pre></div></div>

<h1 id="make-it-work-with-promise">Make it work with Promise</h1>

<p>You may notice that the above logging utils don’t really play nicely with Promise. To fix it, just
add a <code class="language-plaintext highlighter-rouge">finally</code> block if the return data is a Promise.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//...</span>
<span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">wrappedFunction</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="nx">isPromise</span><span class="p">(</span><span class="nx">result</span><span class="p">))</span> <span class="p">{</span>
  <span class="nx">result</span><span class="p">.</span><span class="k">finally</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">logFinishTime</span><span class="p">());</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
  <span class="nx">logFinishTime</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">//...</span>
</code></pre></div></div>

<h1 id="include-extra-information">Include extra information</h1>

<p>You may find yourself need to include some extra information to the HOFs, for example, to log a key
that you can use to correlation the business logic. In that case, simply turn that HOF to a
function that return the actual HOF (yes, it’s a function returning a function returning a
function 😅).</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">const</span> <span class="nx">withInputLogging</span> <span class="o">=</span>
  <span class="p">(</span><span class="nx">opts</span><span class="p">:</span> <span class="p">{</span> <span class="nl">action</span><span class="p">?:</span> <span class="kr">string</span> <span class="p">}</span> <span class="o">=</span> <span class="p">{}):</span> <span class="nx">HigherOrderFunction</span> <span class="o">=&gt;</span>
  <span class="p">(</span><span class="nx">wrappedFunction</span><span class="p">)</span> <span class="o">=&gt;</span>
  <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">'</span><span class="s1">Start hof</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">action</span><span class="p">,</span> <span class="nx">args</span> <span class="p">})</span>
    <span class="c1">//...</span>
  <span class="p">};</span>

<span class="c1">// or to specify the pubsub topic to publish to?</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">withPubsubLogging</span> <span class="o">=</span>
  <span class="p">(</span><span class="nx">opts</span><span class="p">:</span> <span class="p">{</span> <span class="nl">topic</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}):</span> <span class="nx">HigherOrderFunction</span> <span class="o">=&gt;</span>
  <span class="p">(</span><span class="nx">wrappedFunction</span><span class="p">)</span> <span class="o">=&gt;</span>
  <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">client</span><span class="p">.</span><span class="nx">publish</span><span class="p">(</span><span class="nx">topic</span><span class="p">,</span> <span class="p">{</span> <span class="nx">args</span> <span class="p">});</span>
    <span class="c1">//...</span>
  <span class="p">};</span>
</code></pre></div></div>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="javascript" /><summary type="html"><![CDATA[Initial problem It’s the classic logging issue again! In the Warehouse Management system that I’m working on, the team usually needs to add this logging pattern const sendToteToPackingStation = (warehouseId: string, toteId: string): Promise&lt;Result&gt; =&gt; { logger.info('Sending tote to packing station', { warehouseId, toteId }); const result = await someLogic(...); logger.info('Send tote result', { result }); return result; }; The purpose is simple. It’s what you have to do for production debugging in every system. You should write out some unique ids so you have a place to start querying your logging system. From that point, you will then trace the related entries using a correlation id that your system provides. From time to time, when the system scaled up, there were new areas that could slow down the system. We then added more logging logic to the system, for example, execution time logging to help build some visualization dashboards to identify the root cause. const sendToteToPackingStation = (warehouseId: string, toteId: string): Promise&lt;Result&gt; =&gt; { const startTime = performance.now(); logger.info('Sending tote to packing station', { warehouseId, toteId }); const result = await someLogic(...); logger.info('Send tote result', { result }); logger.info('Execution time', { durationMs: elapsedTimeMs(startTime) }); return result; }; Of course, when this was repeated multiple times, we started thinking about making a higher order function (HOF) to reuse everywhere is the system First implementation… Let’s begin with the type definition. Here are the generic types how a HOF looks like. It’s a function that receives a function and return another function with the same signature with the input function export type WrappedFunction&lt; FunctionArgs extends ReadonlyArray&lt;unknown&gt;, FunctionReturn &gt; = (...args: FunctionArgs) =&gt; FunctionReturn; export type HigherOrderFunction = &lt; FunctionArgs extends ReadonlyArray&lt;unknown&gt;, FunctionReturn &gt;( func: WrappedFunction&lt;FunctionArgs, FunctionReturn&gt; ) =&gt; WrappedFunction&lt;FunctionArgs, FunctionReturn&gt;;]]></summary></entry><entry><title type="html">Let’s build Product, not Software - Part 3</title><link href="https://truongtx.me/2023/09/12/lets-build-product-not-software-part-3" rel="alternate" type="text/html" title="Let’s build Product, not Software - Part 3" /><published>2023-09-12T00:00:00+00:00</published><updated>2023-09-12T00:00:00+00:00</updated><id>https://truongtx.me/2023/09/12/lets-build-product-not-software-part-3</id><content type="html" xml:base="https://truongtx.me/2023/09/12/lets-build-product-not-software-part-3"><![CDATA[<p><a href="/2023/09/03/lets-build-product-not-software-part-2">Let’s build Product, not Software - Part 2</a></p>

<p>In the previous post, I have shown you a real example about how to solve the problem as a
Software Engineer. This time, we gonna do it by the Product Engineer approach.</p>

<blockquote>
  <p>Make Agile great again!</p>
</blockquote>

<p>If you refer to the first post that I wrote, Building Product is about delivering user values,
collecting feedbacks and constantly adapting to the change of business. Does it sound like Agile?
Yes, in my opinion, Agile seems to be the best fit out there for Product company at a small
and medium size.</p>

<h1 id="dont-do-this">Don’t do this</h1>

<p>Let’s start with the non-Agile way by this picture-by-picture story</p>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/delivery-1.png" alt="delivery-1" /></p>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/delivery-2.png" alt="delivery-2" /></p>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/delivery-4.png" alt="delivery-4" /></p>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/delivery-3.png" alt="delivery-3" /></p>

<p>When you put this into a Software perspective, it’s pretty much the same with the
<a href="/2023/09/03/lets-build-product-not-software-part-2#a-software-engineer-approach">first example</a>
that I showed in my previous post. The way most people would choose is to implement the whole
feature, from backend to frontend before delivering to the customer. Again, do NOT do this.</p>

<!-- more -->

<h1 id="but-use-this-incremental-delivery-model">but use this Incremental Delivery model</h1>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/delivery-5.png" alt="delivery-5" /></p>

<p>How about taking 1 parcel at a time? Begin with the most valuable one and repeat until you’re done?</p>

<p>Does it feel repetitive? Yes, but it’s less risky because it’s much simpler for you to implement.
You can ship the values continuously, collecting the feedbacks from your customers. When there are
any problems, you can quickly change the route (the approach). Sometimes, you can even throw away
the unnecessary features based on the feedbacks. By starting with the most valuable ones, you also
focus on resolving 80% of the problem using 20% of the effort, gain the most revenue for
the company.</p>

<table class="table">
  <thead>
    <tr>
      <th>The Agile way</th>
      <th>The old way</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Deliver values continuously</td>
      <td>Wait until the end to see the result</td>
    </tr>
    <tr>
      <td>Keep Customers in a feedback loop</td>
      <td>Cannot give feedbacks until very late</td>
    </tr>
    <tr>
      <td>Less multi-tasking</td>
      <td>Many features at once</td>
    </tr>
    <tr>
      <td>Less big work, easier to refactor</td>
      <td>Hard to make it smaller</td>
    </tr>
    <tr>
      <td>Can throw away unnecessary features</td>
      <td>Don’t know what to throw until the end</td>
    </tr>
  </tbody>
</table>

<h1 id="start-from-user-values">Start from User Values</h1>

<p>Ok. If all the above sound so theoretical, how about taking the Integration project that I
mentioned in
<a href="/2023/09/03/lets-build-product-not-software-part-2">part 2</a>
of this series and do it the Agile way?</p>

<p>Instead of defining the tickets/milestones based on the code implementation, try re-writing the
Acceptance Criteria following this format</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- As a user (a staff, a system admin,...), I want...
- (Optional) so that I can solve (don't have to, be able to,...) ...
</code></pre></div></div>

<ul>
  <li>As a user of XXX, I want to be able to log in to Shopify from XXX so I can verify
that the credentials are correct.</li>
  <li>As a user of XXX, I want my order to be synced to XXX when it is placed on Shopify.</li>
  <li>As a user of XXX, I want my order to be updated in XXX when it is changed on Shopify.</li>
  <li>As a user of XXX, I want my fulfillment information to be reflected in XXX when I mark the order
as fulfilled on Shopify.</li>
</ul>

<h1 id="then-come-up-with-the-implementation">then come up with the implementation</h1>

<p>For instance, you have this AC from the above</p>

<blockquote>
  <p>As a user of XXX, I want my order to be synced to XXX when it is placed on Shopify.</p>
</blockquote>

<p>you will then define the steps to execute it</p>
<ul>
  <li>Set up the webhook endpoint to handle <code class="language-plaintext highlighter-rouge">OrderCreated</code> event from Shopify.</li>
  <li>Configure Shopify to send updated data to the new webhook endpoint.</li>
  <li>Implement the mapping logic to map from Shopify sales order to XXX sales order schema.</li>
  <li>Add a new API to get list of orders (very basic information).</li>
  <li>Design a <strong>simple</strong> UI so the user can verify the information.</li>
</ul>

<p>We should try to make this as simple and as achievable as possible. This ticket should not target
on building a beautiful UI. It should follows exactly the pre-defined AC and provide a very simple
UI to verify the data only. After that, there should be another ticket to enhance the UI.</p>

<h1 id="defining-user-value-rules">Defining User Value rules</h1>

<p>Here are some rules for you to follow to ensure that the project will be on the right track</p>

<ul>
  <li>Usually, you still need a scaffolding phase in the beginning.
    <ul>
      <li>Again, be agile, try to make it as small as possible. Don’t try to be perfect!</li>
    </ul>
  </li>
  <li>A User value <strong>isn’t necessarily a big and complete feature</strong>.
    <ul>
      <li>If it’s still too big, split it until it’s small enough for an <code class="language-plaintext highlighter-rouge">S</code>, <code class="language-plaintext highlighter-rouge">M</code> or maximum <code class="language-plaintext highlighter-rouge">L</code> estimate.
Never create <code class="language-plaintext highlighter-rouge">XL</code>+ ticket</li>
    </ul>
  </li>
  <li>However, a User value/ticket should be <strong>a complete flow</strong>, frontend to backend
    <ul>
      <li>That means the Users can use it</li>
    </ul>
  </li>
  <li>Be clear about the target users and decide whether this feature is necessary for that target users.</li>
  <li>A clear definition of <strong>Done</strong>
    <ul>
      <li>Done is when the feature flows all the way to Production and is shipped to the user. You don’t
have to come back anymore</li>
    </ul>
  </li>
  <li>Do <strong>NOT</strong> include future work.</li>
  <li>Prioritization: be <strong>80-20</strong>, highest value with smallest effort first.</li>
</ul>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/prioritization.png" alt="prioritization" /></p>

<h1 id="to-be-continued">To be continued</h1>

<p>More real world examples…</p>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="misc" /><summary type="html"><![CDATA[In the previous post, I have shown you a real example about how to solve the problem as a Software Engineer. This time, we gonna do it by the Product Engineer approach.]]></summary></entry><entry><title type="html">Let’s build Product, not Software - Part 2</title><link href="https://truongtx.me/2023/09/03/lets-build-product-not-software-part-2" rel="alternate" type="text/html" title="Let’s build Product, not Software - Part 2" /><published>2023-09-03T00:00:00+00:00</published><updated>2023-09-03T00:00:00+00:00</updated><id>https://truongtx.me/2023/09/03/lets-build-product-not-software-part-2</id><content type="html" xml:base="https://truongtx.me/2023/09/03/lets-build-product-not-software-part-2"><![CDATA[<blockquote>
  <p>Previous post: <a href="/2023/08/29/lets-build-product-not-software-part-1">Let’s build Product, not Software - Part 1</a></p>
</blockquote>

<p>In the first part of this series, I have walked you quickly through some differences
between Building Product and Building Software and why Building Product is important.
In this post, I’ll show you a simple example, analyze its problem and come up with
a solution following the Product Engineer mindset.</p>

<h1 id="a-software-engineer-approach">A Software Engineer approach</h1>

<p>Let’s take a look at this simple project</p>

<blockquote>
  <p>You are working for an Automation marketing platform for E-commerce merchants.
The product needs the data about the sales orders of the merchant and your task is to build a
1 way Sales Order integration feature to sync data from Shopify to your system</p>
</blockquote>

<p>After going through several discovery steps with your customers and the PO, you decide that it’s
time to make the implementation plan. You now come up with this plan</p>

<table class="table">
  <thead>
    <tr>
      <th>Milestones</th>
      <th>Details</th>
      <th>Duration</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Backend</td>
      <td>Build the backend to handle auth &amp; webhook requests from Shopify</td>
      <td>1 month</td>
    </tr>
    <tr>
      <td>Frontend</td>
      <td>Build the frontend for the users</td>
      <td>1 month</td>
    </tr>
    <tr>
      <td>Beta</td>
      <td>Release to some beta customers</td>
      <td>0.5 month</td>
    </tr>
    <tr>
      <td>Bug fixes</td>
      <td>Handle issues reported from customers</td>
      <td>0.5 month</td>
    </tr>
    <tr>
      <td>Go live</td>
      <td>Release to everybody</td>
      <td>0.5 month</td>
    </tr>
  </tbody>
</table>

<p>Sounds good? Yes, this is a perfect plan from a Software Engineer perspective, but…</p>

<!-- more -->

<p>Assume that it’s 01/10/2023 and you have finished the first Backend phase. Everything works as
expected, you bring this to the weekly project update meeting and present to all the stakeholders.
However, oposite to what you expected, they feel so disappointed. What has happened?</p>
<ul>
  <li>They have been waiting for 1 month and they still have nothing.</li>
  <li>They have to be patient for another month, for 4 other project update meeting to start using
the feature.</li>
  <li>The PO and QA have also waited for that long, sitting there without doing anything beside
preparing all the test cases</li>
</ul>

<p>Another month has passes, you now finish the beautiful frontend so everybody can start
experimenting it. The PO now realizes that the workflow is so confusing, could lead to a lot of
complaints from customers. They ask you to go back and change the main workflow. You say
that the business needs to either extend the deadline or accept that flow because it would take
a lot of time to adapt to this change. The whole team start debating because nobody is satisfied.</p>

<p>After several discussions, you have convinced the team to follow the original solution. It’s time
to release to some beta customers. What the PO worried about has happened now. The customers say
that the feature is too hard to use and they don’t really like this. It’s when the project really
go off-track</p>

<h1 id="how-about-making-smaller-milestones">How about making smaller milestones?</h1>

<p>After reading the above part of this post, you decide to do it differently. You now go back and
update the milestones like this</p>

<table class="table">
  <thead>
    <tr>
      <th>Milestones</th>
      <th>Details</th>
      <th>Duration</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Project setup</td>
      <td>Scaffolding, set up server and architecture</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Connect to Shopify</td>
      <td>Connect, authentication and sync first order</td>
      <td>2 weeks</td>
    </tr>
    <tr>
      <td>Handle Sales order requests</td>
      <td>Handle all webhook requests related to Sales orders</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Handle Product requests</td>
      <td>Handle all webhook requests related to Products</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Handle Fulfillment requests</td>
      <td>Handle all webhook requests related to Fulfilments</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Handle Customer requests</td>
      <td>Handle all webhook requests related to Customer data</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Handle Address requests</td>
      <td>Handle all webhook requests related to Billing and Shipping address</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Frontend</td>
      <td>Display the data</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Others</td>
      <td>Implement other small requirements</td>
      <td>1 week</td>
    </tr>
    <tr>
      <td>Bug fixes</td>
      <td>Handle issues reported from customers</td>
      <td>2 weeks</td>
    </tr>
    <tr>
      <td>Go live</td>
      <td>Release to everybody</td>
      <td>2 weeks</td>
    </tr>
  </tbody>
</table>

<p>Sounds better, huh? Yeah this is closer to the target. Smaller milestones make it easier to change.
However, there are still some questions you need to ask here</p>

<ul>
  <li>Do we look into this from the User perspective? What are the problems that you are trying to solve
for your customers?</li>
  <li>What does it mean when you say <code class="language-plaintext highlighter-rouge">I have finished "Handle Sales order requests" phase</code>? Does it
mean that you finished setting up the API to handle that type of webhook requests? Or do you
mean that you have completed the function to map from Shopify schema to your system schema? Does
it include the frontend? Can the user start using it?</li>
  <li>Or more precisely, the question is <code class="language-plaintext highlighter-rouge">What is your definition of Done?</code>. Do you mean it’s done when
you say it’s done? Do you need to go back and change it if the frontend doesn’t fit the data?</li>
  <li>When the project goes off-track and you are going to miss the deadline, what features can you
drop but not affecting the workflow?</li>
</ul>

<blockquote>
  <p>Are you building a Software or a Product?</p>
</blockquote>

<h1 id="to-be-continued">To be continued</h1>

<p>A Product-oriented solution will be presented in
<a href="/2023/09/12/lets-build-product-not-software-part-3">Part 3</a></p>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="misc" /><summary type="html"><![CDATA[Previous post: Let’s build Product, not Software - Part 1 In the first part of this series, I have walked you quickly through some differences between Building Product and Building Software and why Building Product is important. In this post, I’ll show you a simple example, analyze its problem and come up with a solution following the Product Engineer mindset. A Software Engineer approach Let’s take a look at this simple project You are working for an Automation marketing platform for E-commerce merchants. The product needs the data about the sales orders of the merchant and your task is to build a 1 way Sales Order integration feature to sync data from Shopify to your system After going through several discovery steps with your customers and the PO, you decide that it’s time to make the implementation plan. You now come up with this plan Milestones Details Duration Backend Build the backend to handle auth &amp; webhook requests from Shopify 1 month Frontend Build the frontend for the users 1 month Beta Release to some beta customers 0.5 month Bug fixes Handle issues reported from customers 0.5 month Go live Release to everybody 0.5 month Sounds good? Yes, this is a perfect plan from a Software Engineer perspective, but…]]></summary></entry><entry><title type="html">Let’s build Product, not Software - Part 1</title><link href="https://truongtx.me/2023/08/29/lets-build-product-not-software-part-1" rel="alternate" type="text/html" title="Let’s build Product, not Software - Part 1" /><published>2023-08-29T00:00:00+00:00</published><updated>2023-08-29T00:00:00+00:00</updated><id>https://truongtx.me/2023/08/29/lets-build-product-not-software-part-1</id><content type="html" xml:base="https://truongtx.me/2023/08/29/lets-build-product-not-software-part-1"><![CDATA[<blockquote>
  <p>This may not always be true. It really depends on the type of company that I will go
through in this post. This also sometimes sounds strange from a Software Engineering
perspective, but as we get used to, it really did help FMG (my old company) grow to the
leading player
that niche market</p>
</blockquote>

<p>Software engineers love technology, for sure. We love building
things, love applying the latest technology into our product. However, we usually forget
one important thing: The technology that doesn’t fit in the product, cannot make a profitable
business, is a useless one. That sounds obvious, right? Surprisingly, a lot of Software Engineers
that I’ve met made this mistake, especially the talented ones.</p>

<p>Let me walk you through the 2 approaches, compare the differences between them and analyze some
real examples. In latter posts, you can also find some techniques that I’ve applied in order to
help build a better Product Engineer mindset.</p>

<p><img src="/files/2023-08-17-lets-build-product-instead-of-software/img1.png" alt="img1" /></p>

<blockquote>
  <p>This is converted from a presentation that I made at work</p>
</blockquote>

<!-- more -->

<h1 id="what-is-building-product">What is Building Product?</h1>

<p>In short, Building Product could be described as</p>

<blockquote>
  <p>Delivering USER VALUES</p>
</blockquote>

<p>Building Product usually includes these 3 main steps</p>
<ul>
  <li>Identify the user problems</li>
  <li>Provide the solutions, using technology, and optionally, do it better than your opponents</li>
  <li>Constantly update and adapt to the changes of the business. If you don’t keep up with the market,
you are losing already. A good product you build today could be a crap tomorrow.</li>
</ul>

<p>In Building Product, you should NOT prioritize the technology. Yes, tech still plays an important
role but it is not the most important factor. You should always be focusing on the User Values.
Building Product is also not about Building a Perfect solution. Nothing is perfect. The business
changes every day. Spending time making one thing perfect means getting nothing done. A perfect
feature that you write today could be a shitty one tomorrow.</p>

<blockquote>
  <p>Perfect is the enemy of good</p>
</blockquote>

<h1 id="why-building-product-instead-of-software">Why Building Product instead of Software?</h1>

<p>Let’s ask these questions</p>
<ul>
  <li>Do the users care if you are using latest technology or not?</li>
  <li>Do they care if you have spent a lot of effort to develop a feature on your own or do they care
if you use a third party solution?</li>
  <li>Do they care if you have some tech debt to resolve?</li>
  <li>Do they care if you use PHP to develop? 🤣</li>
</ul>

<p>Sadly, the answer to all those questions is NO. They don’t (fucking) care. All they care are their
problems. Building Product is to deliver User Values, and that’s what matters to your customers.</p>

<p>Also, a good technology doesn’t always mean a good product if it doesn’t solve user problems.
Even a shitty technology sometimes is a suitable choice because it does the job. And then, it simply
becomes a high quality one.</p>

<p>A better product, of course, helps generating better revenue. By providing what the customers need,
you can attract new clients, retain the existing ones longer and reduce the churn rate. Once you
got the money, you can even throw away some crappy modules that you made and buy another solution.
That is really important to keep in mind and is cruelly how the business works.</p>

<blockquote>
  <p>“Start with the customer experience and work backwards to the technology. You can’t start with the technology and try to figure out where you’re gonna try to sell it” - Steve Jobs</p>
</blockquote>

<h1 id="when-to-apply">When to apply?</h1>

<p>However, you don’t always need to apply that mindset. If you are working in an outsourcing
company or in a large organization, where all the requirements are clearly defined, sometimes it’s
better to just build the software.</p>

<p>Building Product mindset is more suitable for startup or small/medium product company, where you
have to move fast, where nothing is clear and the requirements change everyday.</p>

<h1 id="to-be-continued">To be continued</h1>

<p>In the next post, I’ll show some real examples and examine the problems as well as come up with
the solution that we can use.</p>

<p>Read it here <a href="/2023/09/03/lets-build-product-not-software-part-2">Let’s build Product, not Software - Part 2</a></p>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="misc" /><summary type="html"><![CDATA[This may not always be true. It really depends on the type of company that I will go through in this post. This also sometimes sounds strange from a Software Engineering perspective, but as we get used to, it really did help FMG (my old company) grow to the leading player that niche market Software engineers love technology, for sure. We love building things, love applying the latest technology into our product. However, we usually forget one important thing: The technology that doesn’t fit in the product, cannot make a profitable business, is a useless one. That sounds obvious, right? Surprisingly, a lot of Software Engineers that I’ve met made this mistake, especially the talented ones. Let me walk you through the 2 approaches, compare the differences between them and analyze some real examples. In latter posts, you can also find some techniques that I’ve applied in order to help build a better Product Engineer mindset. This is converted from a presentation that I made at work]]></summary></entry><entry><title type="html">Tips when working with Postgres - Part 2</title><link href="https://truongtx.me/2022/10/16/tips-for-working-with-postgres-part-2" rel="alternate" type="text/html" title="Tips when working with Postgres - Part 2" /><published>2022-10-16T00:00:00+00:00</published><updated>2022-10-16T00:00:00+00:00</updated><id>https://truongtx.me/2022/10/16/tips-for-working-with-postgres-part-2</id><content type="html" xml:base="https://truongtx.me/2022/10/16/tips-for-working-with-postgres-part-2"><![CDATA[<blockquote>
  <p>Just a collection of tips to make working with Postgres (and other SQL-like databases) easier</p>
</blockquote>

<h1 id="integration-data">Integration data</h1>

<p>Usually when you build a system that integrates with other 3rd party service, you will need to store
integration information related to the entity, for example the id of the entity on the 3rd party
system or some of its configuration on that system. Imagine that you are building an e-commerce
related product, you may want to sync the Sales order information from Shopify to do the analytics
on customer behavior. The first solution you can think of is to add a column like
<em>shopify_entity_id</em> on that table.</p>

<ul>
  <li>What will happens if you introduce another integration later? Does the name <em>shopify_entity_id</em>
still make sense? You may consider renaming it to <em>external_entity_id</em>. How do you know where it
comes from? Adding another <em>source</em> column? How do you store extra 3rd party information about the
sales order? Keep adding columns like <em>external_something</em>? Do those columns actually belong to
the <em>sales_order</em> table itself?</li>
  <li>What will happen if an single entity exists on multiple 3rd party system? For instance, the sales
order may be presented on both Shopify and on another Shipping service. How would you deal with
it? Keep adding more columns? What if we introduct another integration?
    <ul>
      <li>A Json (Jsonb) column could solve the above issue but also creates a whole new problem. How
  about schema enforcement and constraint? How do we make sure that nobody will accidentally
  update it the an incorrect schema? How about <code class="language-plaintext highlighter-rouge">null</code> and <code class="language-plaintext highlighter-rouge">undefined</code> values (in case you are
  working with Javascript)? How about indexing the values for quick access? You can index inside
  the json but it just makes things more complicated due to those schema problems mentioned
  above.</li>
    </ul>
  </li>
</ul>

<p>The solution, of course, is a SQL approach: make an entity integration table
(<em>sales_order_integration</em> in this case). It’s a 1-N relationship, 1 sales order could have 0 or
multiple integrations</p>

<p><em>sales_order</em> table</p>

<table class="table">
  <thead>
    <tr>
      <th>id</th>
      <th>shipping_address</th>
      <th>price</th>
      <th>weightMg</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Ho Chi Minh city</td>
      <td>10</td>
      <td>20</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Hanoi</td>
      <td>20</td>
      <td>30</td>
    </tr>
  </tbody>
</table>

<p><em>sales_order_integration</em> table</p>

<table class="table">
  <thead>
    <tr>
      <th>id</th>
      <th>sales_order_id</th>
      <th>external_entity_id</th>
      <th>source</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>external-id1</td>
      <td>SHOPIFY</td>
    </tr>
    <tr>
      <td>2</td>
      <td>1</td>
      <td>external-id2</td>
      <td>WOOCOMMERCE</td>
    </tr>
    <tr>
      <td>3</td>
      <td>2</td>
      <td>external-id3</td>
      <td>SHOPIFY</td>
    </tr>
  </tbody>
</table>

<!-- more -->

<p>You may add another <em>integration</em> table (and sub-tables if needed) as a generalization to store
other information like the access/refresh token, for example</p>

<table class="table">
  <thead>
    <tr>
      <th>id</th>
      <th>client_id</th>
      <th>source</th>
      <th>access_token</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>SHOPIFY</td>
      <td>xxx-xxx-xxx</td>
    </tr>
    <tr>
      <td>2</td>
      <td>1</td>
      <td>WOOCOMMERCE</td>
      <td>yyy-yyy-yyy</td>
    </tr>
    <tr>
      <td>3</td>
      <td>2</td>
      <td>SHOPIFY</td>
      <td>zzz-zzz-zzz</td>
    </tr>
  </tbody>
</table>

<p>and then the <em>sales_order_integration</em> table would become</p>

<table class="table">
  <thead>
    <tr>
      <th>id</th>
      <th>sales_order_id</th>
      <th>external_entity_id</th>
      <th>integration_id</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>external-id1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>1</td>
      <td>external-id2</td>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>2</td>
      <td>external-id3</td>
      <td>3</td>
    </tr>
  </tbody>
</table>

<p>Here are some query scenarios</p>
<ul>
  <li>Find <em>sales_order</em> by id: of course, you always have index on primary key</li>
  <li>Find external ids by <em>sales_order_id</em>: simply add an index on <em>sales_order_id</em> column of the
<em>sales_order_integration</em> table and you’are good to go.
    <ul>
      <li>You could use this when you want to refecth new data of the entity from a specific 3rd party system</li>
      <li>You could also use this when you want to write updated data to the other systems</li>
    </ul>
  </li>
  <li>Find <em>sales_order_id</em> by <em>external_entity_id</em>: you can add an index on <em>external_entity_id</em>
column. Another option is a unique constraint on <em>integration_id, external_entity_id</em> (which makes
more sense since each entity in your system should correspond to only one entity in the other
system). A unique constraint also acts as an index. A simple JOIN like this will utilize both the
unique index and the primary key index on 2 tables
    <div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">sales_order</span> <span class="n">s</span> <span class="k">INNER</span> <span class="k">JOIN</span> <span class="n">sales_order_integration</span> <span class="n">i</span>
<span class="k">ON</span> <span class="n">s</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">i</span><span class="p">.</span><span class="n">sales_order_id</span>
<span class="k">WHERE</span> <span class="n">i</span><span class="p">.</span><span class="n">integration_id</span> <span class="o">=</span> <span class="err">$</span><span class="mi">1</span> <span class="k">AND</span> <span class="n">i</span><span class="p">.</span><span class="n">external_entity_id</span> <span class="o">=</span> <span class="err">$</span><span class="mi">2</span>
</code></pre></div>    </div>
    <ul>
      <li>This is usually seen in webhook handler, where you receive the update about each individual
sales order. You can use this method to quickly look up the sales order using its external id.</li>
    </ul>
  </li>
</ul>]]></content><author><name>TruongTX</name><email>me@truongtx.me</email></author><category term="misc" /><summary type="html"><![CDATA[Just a collection of tips to make working with Postgres (and other SQL-like databases) easier]]></summary></entry></feed>