<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Kelvin's Insights]]></title><description><![CDATA[Discovering the magic behind code and systems!]]></description><link>https://thoughts.kelvinamoaba.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 14 May 2026 13:41:23 GMT</lastBuildDate><atom:link href="https://thoughts.kelvinamoaba.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[What Actually Determines a File's Type]]></title><description><![CDATA[Every file format has a specification, “an agreed-upon structure that defines how the bytes in that file are organized”. Just like we have standards for internet protocols, we have standards for file types. When an application opens a PDF or parses a...]]></description><link>https://thoughts.kelvinamoaba.com/what-actually-determines-a-files-type</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/what-actually-determines-a-files-type</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[operating system]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Sat, 13 Dec 2025 06:05:28 GMT</pubDate><content:encoded><![CDATA[<p>Every file format has a specification, “an agreed-upon structure that defines how the bytes in that file are organized”. Just like we have standards for internet protocols, we have standards for file types. When an application opens a PDF or parses a PNG, it’s reading bytes according to that format’s predefined rules.</p>
<p>We usually identify files by their extension: .zip, .txt, .jpg. But extensions are really just hints for humans and the operating system. They’re convenient labels, not the actual source of truth, which is why renaming photo.jpg to photo.png doesn’t convert the image.</p>
<p>Extensions are just hints, the real determining of the type is done through “Magic Numbers”</p>
<h4 id="heading-magic-numbers">Magic Numbers</h4>
<p><em>A magic number is a sequence of bytes, located at the beginning or specific offsets of a file that serves as a unique signature to identify the file format or type.</em></p>
<p>Each file format has the universally agreed upon magic number, this is what applications check anytime they need to or have to determine the file format of a file regardless of what the extension claims.</p>
<p>Eg, for PNG files, this magic number is <code>89 50 4E 47</code>, for zip files, it’s <code>50 4B 03 04</code>. Bitmap images start with <code>42 4D</code>, which is just <code>BM</code> in ASCII (short for “bitmap”).</p>
<p>Here is an example that reads a file with a bmp extension, but actually digs into the bytes to confirm whether or not it’s a bitmap image</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    “bytes”
    “fmt”
    “io”
    “log”
    “os”
)


<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    f, err := os.Open(”sample.bmp”)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> f.Close()

    <span class="hljs-comment">// Read the first 2 bytes (The Magic Number)</span>
    header := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">byte</span>, <span class="hljs-number">2</span>)
    <span class="hljs-keyword">if</span> _, err := io.ReadFull(f, header); err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    <span class="hljs-comment">// BMP signature is 0x42, 0x4D</span>
    bmpSig := []<span class="hljs-keyword">byte</span>{<span class="hljs-number">0x42</span>, <span class="hljs-number">0x4D</span>}

    <span class="hljs-keyword">if</span> bytes.Equal(header, bmpSig) {
        fmt.Println(”Valid BMP detected”)
    } <span class="hljs-keyword">else</span> {
        fmt.Println(”Invalid file format”)
    }
}
</code></pre>
<p>The <code>file</code> command on Unix uses these signatures to identify files regardless of extension. After the signature, most formats include metadata describing the content, dimensions for images, sample rate for audio, author information for documents, etc.</p>
<h4 id="heading-categories-of-file-structures">Categories of File Structures</h4>
<p>File formats generally fall into a few structural categories:</p>
<ul>
<li><p><strong>Binary formats with rigid structure</strong> (PNG, JPEG, MP3): every byte position has specific meaning according to the spec. Programs parse these by reading exact offsets.</p>
</li>
<li><p><strong>Text-based structured formats</strong> (JSON, XML, HTML, CSV): human-readable text following grammar rules. Easier to debug but larger file sizes.</p>
</li>
<li><p><strong>Container formats</strong> (ZIP, MP4, PDF): these are like filesystems within a file, containing multiple embedded files or streams. An MP4 might contain separate video, audio, and subtitle tracks. A DOCX is actually a ZIP containing XML files.</p>
</li>
</ul>
<p>Essentially, knowing how to move bytes around and going through specs, you can write your own parsers for lots of file types, I will demostrate this in another writing of a simple script to convert images to greyscale by modifying the bytes that make up the image.</p>
]]></content:encoded></item><item><title><![CDATA[Obscurity is your biggest enemy]]></title><description><![CDATA[One thing about the current world is that people can decide to be everywhere. With technology, we can all be engaged in matters happening in other parts of the world so far from where we are and also be in touch with people from all over the world.
O...]]></description><link>https://thoughts.kelvinamoaba.com/obscurity-is-your-biggest-enemy</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/obscurity-is-your-biggest-enemy</guid><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Sun, 15 Jun 2025 22:48:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750027534627/4d89c33c-4ffa-46a9-b376-72ac45a2915d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One thing about the current world is that people can decide to be everywhere. With technology, we can all be engaged in matters happening in other parts of the world so far from where we are and also be in touch with people from all over the world.</p>
<p>One very important thing that is greatly overlooked is our need to put ourselves out there and be known. More often than not, we don't want people to know our business, what we are up to and what we do. Ask yourself, what good is it to be very good at something if you are not known for it? Even the Bible talks about how unwise it is to light a candle and put it under a bed.</p>
<p>That ancient wisdom applies directly to our modern lives. Whatever we do, whatever we're good at, we should strive so hard to relentlessly publicize it. That's the only way to get others to know what you're into and what you're good at. The goal should be to <strong>let people think about you whenever your field, industry, or area of expertise is mentioned</strong>. Until people know what you do and what you're good at, you cannot be recommended for anything. People only recommend others based on what they know about them and what they see them to be really good at. Never forget, society pays a lot of attention to whatever you do and put out there.</p>
<p>You should have it in mind: <strong>OBSCURITY IS YOUR BIGGEST ENEMY.</strong> Do everything you can to dominate the space you are in. When you dominate the space, you will be the first person that comes to mind when the topic is mentioned. You should not want to be in a race, you should be at the top of the list of considerations.</p>
<p>If you are in a field that even pays more attention to skills than to one's level of education, you should even be more crazy about being known. Are you a tailor? Well then put your designs and your work out there. Are you a software engineer? Well then, write about what you do, write on topics, work on projects and put them out there. People may mock you for putting yourself out there, but that is a small price to pay. <strong>The alternative is silence and obscurity, and that is a cost no one should be willing to accept.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Monotonic and Wall Clock Time]]></title><description><![CDATA[Monotonic and wall clock time are two ways we measure time.
Wall clock time is the time we see on our clocks. It's the time we are all used to and respond with when someone asks "what time it is?". Monotonic time on the other hand, is one that simply...]]></description><link>https://thoughts.kelvinamoaba.com/monotonic-and-wall-clock-time</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/monotonic-and-wall-clock-time</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Sun, 16 Mar 2025 09:42:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/AMzC2RVurO4/upload/85f1d90a36312c07f4685706143a03b8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Monotonic</strong> and <strong>wall clock</strong> time are two ways we measure time.</p>
<p>Wall clock time is the time we see on our clocks. It's the time we are all used to and respond with when someone asks "what time it is?". Monotonic time on the other hand, is one that simply continues to increase since the computer started. When used in programming, it's the time that has passed from the point the timer was started. Monotonic time is mostly used to measure the time that has elapsed between two events.</p>
<p>Monotonic times have two characteristics:</p>
<ol>
<li><p>They tick forward at a regular rate</p>
</li>
<li><p>They are detached from current time of day</p>
</li>
</ol>
<p>The value you get from reading a monotonic clock is typically a long integer. It's usefulness is greatly seen when it's compared with other monotonic times.</p>
<p>The reason why we need to keep track of the two types of time is because, <em>wall clock time does not uniformly increase</em>. It can be affected by the user's manual adjustments to the clock, daylight saving time, and other factors like network time changes. Since it can be affected by these factors, it's not a good idea to use it to measure the time that has elapsed between two events.</p>
<p>Using wall clock time in programming can cause weird bugs where your programs might be thinking a certain duration of time has passed, when in reality, it's been longer or shorter. One major assumptions people make is that "Time difference cannot be negative". Going back to our reason why we need to keep track of the two types of time, we can see why this might be the case. Assuming we have two times, <code>t1</code> and <code>t2</code>, and we want to find the difference between them, we can do so by subtracting <code>t1</code> from <code>t2</code>. Should time <code>t1</code> be before time <code>t2</code>, the result will be negative, which breaks our assumption. Time <code>t1</code> can always be before time <code>t2</code> because we learnt that wall clock time can be affected by the user's manual adjustments to the clock, daylight saving time, and other factors like network time changes.</p>
<p>Time difference being negative actually caused a big issue one time for Cloudflare DNS.</p>
<blockquote>
<p>In 2017, Cloudflare experienced a significant outage during a leap second adjustment. Their RRDNS software compared timestamps before and after the leap second was inserted, resulting in negative time differences. This violated the code's assumptions and caused the software to crash repeatedly. You can read more about it <a target="_blank" href="https://blog.cloudflare.com/how-and-why-the-leap-second-affected-cloudflare-dns/">here</a></p>
</blockquote>
<p>When dealing with time, you should never ever think that time difference cannot be negative, never think that time cannot go backwards. Having these ideas in your mind will help you build programs that are more robust and reliable. Wall clock time is suitable for displaying time to users and scheduling based on the time of day, but it's inappropriate for measuring elapsed time due to its susceptibility to adjustments. Monotonic time, with its steady forward progression, is the correct choice for duration measurements, timeouts, and performance profiling.</p>
]]></content:encoded></item><item><title><![CDATA[What does it mean to write your own smtp server?]]></title><description><![CDATA[Writing your own SMTP server basically means that you go by the SMTP RFCSs and make sure that your system responds appropriately to whatever commands that come in from other mail servers. Under the hood, smtp servers are doing the same things with sl...]]></description><link>https://thoughts.kelvinamoaba.com/what-does-it-mean-to-write-your-own-smtp-server</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/what-does-it-mean-to-write-your-own-smtp-server</guid><category><![CDATA[server]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Mon, 17 Jun 2024 08:00:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718496180383/f0ebdc4e-2eb1-480d-9258-82c53e64175d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Writing your own SMTP server basically means that you go by the SMTP RFCSs and make sure that your system responds appropriately to whatever commands that come in from other mail servers. Under the hood, smtp servers are doing the same things with slight modifications but the fundamentals all stick to the SMTP RFCs proposed.</p>
<p>So writing a simple mail server means that your server has to run on the appropriate port of SMTP, mostly <code>25</code> (these are all well-known ports and should not be changed without reason), and also accept and respond with the appropriate status codes for each and every request that comes to play. For example, if the sending mail server sends the command <code>helo</code>, you must know that the right thing to do is respond with the <code>250 OK</code> code which is mostly the standard response..</p>
<p>These are all fundamental concepts that are highlighted in the various RFCs proposed for the protocol. Once all these are taken into consideration, the initial exchanges can go through without any hassle.</p>
<p>The only thing about this that becomes quite of a hassle is when it comes to <strong>mail delivery</strong>. There are lots of barricades on the web that prevent the sending of mail from any mail server due to the potential security risks. Although the sending might go through, it is the matter of deliverability that is of major concern.</p>
<p>There are many ways to mitigate that problem such as using relays to send your email. This simply means relying on other established services to forward your mail since they have all the fundamentals done right to ensure that all your mails is delivered to the receiving mail servers. These relays can be done through services like Mailgun.</p>
<p>Building a simple mail server that actually works is not only dependent on you going by the RFCs but also making sure that you follow the standard procedures, including setting up your domain name and the associated Zone files to include the <code>MX</code> records.</p>
<p>To actually understand the keywords and the various subtle workings of smtp by building your own, you can rely on some libraries to take out a chunk of the work needed to go about it. For example, you can use the <code>sockets</code> library in python to set up the necessary tcp sockets needed in order to listen in for connections and also respond appropriately to those requests. You don't need to build everything from the socket level, as that would be a significant hassle.</p>
<p>There are other important factors that need to be considered to actually build a really solid SMTP server. Since this is mostly a basic overview, detailed insights into protecting your mail server and meeting other necessary criteria have not been covered.</p>
<p>In the next post, we will be looking at how to build a simple smtp server using python and the <code>sockets</code> library. Stay tuned for that, but then, to ensure we are on the same page, you can read up on the SMTP RFCs to get a better understanding of how the protocol works.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><p><a target="_blank" href="https://tools.ietf.org/html/rfc5321">SMTP RFC</a></p>
</li>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/smtp-commands/">SMTP Commands</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/List_of_SMTP_server_return_codes">SMTP Status Codes</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol">SMTP Overview</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Email_relay">SMTP Relay</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Zone_file">Zone Files</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/MX_record">MX Records</a></p>
</li>
<li><p><a target="_blank" href="https://docs.python.org/3/library/socket.html">Python Sockets</a></p>
</li>
<li><p><a target="_blank" href="https://www.mailgun.com/">Mailgun</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[IP Addresses]]></title><description><![CDATA[An IP address is a unique 32-bit address that identifies any device connected to the internet. It is of the form X.X.X.X. Each networked device has a unique IP address attached to it.
The definition for the IP address above is that of the IPV4 IP add...]]></description><link>https://thoughts.kelvinamoaba.com/ip-addresses</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/ip-addresses</guid><category><![CDATA[ip address]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Mon, 18 Mar 2024 16:47:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/SwVkmowt7qA/upload/41e42b23150348cdc16150ad50ef5a55.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>An IP address is a unique 32-bit address that identifies any device connected to the internet. It is of the form X.X.X.X. Each networked device has a unique IP address attached to it.</p>
<p>The definition for the IP address above is that of the IPV4 IP address since it was the first variation of IP addresses. IP addresses, however, come in two variants, the IPV4 and the IPV6 addresses.</p>
<p>The reason there are different variations of the IP address is as a result of the growing number of devices that are connected to the internet. Since an IPV4 address is only a 32-bit number, it allows for a maximum of 4 billion IPV4 addresses.</p>
<p>$$\text{Total IPv4 addresses} = 2^{32}=4,294,967,296$$</p><p>This led to the introduction of the IPV6 address, which supports even more devices. It is estimated that there can be a total of 340 trillion trillion trillion IP addresses. IPv6 addresses are 128 bits in length and are written as eight groups of four hexadecimal digits separated by colons.<br />An example of an IPV6 address is this: <code>2001:db8:3333:4444:5555:6666:7777:8888</code><br />They do not only consist of numbers but also letters in general.</p>
<p>$$\text{Total IPv6 addresses} = 2^{128} \approx 3.4 \times 10^{38}$$</p><h3 id="heading-types-of-ip-addresses">Types of IP Addresses</h3>
<p>IP addresses are grouped based on the following criteria: the <mark>location of the device in a network</mark> and the <mark>static or dynamic nature of the IP address</mark> generated for the device. As a result, there are 4 types of IP addresses:</p>
<ul>
<li><p>Static IP address</p>
</li>
<li><p>Dynamic IP address</p>
</li>
<li><p>Private IP address</p>
</li>
<li><p>Public IP address</p>
</li>
</ul>
<p><strong>PUBLIC IP ADDRESS:</strong> Public IP addresses are those that are assigned to a device in order to make it communicate over the internet. These addresses are generated by the ISP for every device, which makes it possible for the devices to be reachable over the internet. You can check your public IP address using <a target="_blank" href="https://whatismyipaddress.com/">this</a> service.</p>
<p><strong>Private IP Address:</strong> Private IP addresses are assigned to devices in a network and are not meant to be exposed to the internet. They are assigned by the router and are used to uniquely identify devices that are in the current network of the router. IP addresses that are private are only limited to the current router they are connected to, meaning that outside of the current router network, there can be the same IP address again in another router’s network. That is to say, they are only unique to their current network.</p>
<p><strong>Static IP Address:</strong> A static IP address is one that is manually assigned to a device and does not change. These are the typical IP addresses used by servers over the internet. Because they are static, it is easier for clients to resolve their domain names to their IP addresses using a DNS resolver.</p>
<p><strong>Dynamic IP Address:</strong> Dynamic IP addresses are those that are assigned by ISPs to devices when they connect to the network. Dynamic IP addresses are only present for some time, after which they expire and have to be reassigned. Dynamic IP addresses are created by the ISPs using the Dynamic Host Configuration Protocol (DHCP).</p>
<h3 id="heading-dhcp-dynamic-host-configuration-protocol"><strong>DHCP (Dynamic Host Configuration Protocol)</strong></h3>
<p>The Dynamic Host Configuration Protocol is a client-server architecture used in networking to ensure that devices get assigned IP addresses when they connect to a network. The DHCP server maintains a pool of IP addresses that are currently being used and those that are not currently being used. For each request from a DHCP enabled client that comes in, the server <strong><em>leases</em></strong> one of its unused IP addresses to it.</p>
<p>A DHCP client is a piece of software that runs on devices that can connect to the internet, such as mobile phones, laptop, etc. Immediately the device gets connected to the network, the client broadcasts a request for the IP address and other configuration of which the DHCP server responds to with one of the ip addresses from its pool. Clients receive IP addresses for a certain amount of time known as <strong><em>Lease time</em></strong>. Before this time is up, the client can request to renew the IP address, think of it like requesting a new access token with your refresh token in your web applications.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710779335088/f1b3e0c8-6b40-4895-a3b8-f27cb8bf0165.png" alt class="image--center mx-auto" /></p>
<p>DHCP servers eliminate the need to manually assign IP addresses and reduce the overall risk of making a mistake when assigning IP addresses. Having DHCP servers ensures that devices do not get static IP addresses since static addresses are becoming more and more scarce with the growing number of networked devices.</p>
<p>More details about the DHCP protocol is defined in <a target="_blank" href="https://www.rfc-editor.org/pdfrfc/rfc1531.txt.pdf">RFC 1531</a></p>
<p>IP addresses, in combination with port numbers, ensure that devices over the internet can send and receive information from one device to another.</p>
]]></content:encoded></item><item><title><![CDATA[Improving Response Times and Reducing DB Reads]]></title><description><![CDATA[Did you know that a 1-second delay in page load can lead to a 7% decrease in conversions?
One of the most important metrics for ensuring that the users of your software are happy with the general service is speed 🏎️. No matter how good your service ...]]></description><link>https://thoughts.kelvinamoaba.com/improving-response-times-and-reducing-db-reads</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/improving-response-times-and-reducing-db-reads</guid><category><![CDATA[software development]]></category><category><![CDATA[systemdesign]]></category><category><![CDATA[System Architecture]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Wed, 31 Jan 2024 23:51:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/iR8m2RRo-z4/upload/4f1c09a3a77a67158ae8f8f12d649f8d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Did you know that a 1-second delay in page load can lead to a 7% decrease in conversions?</p>
<p>One of the most important metrics for ensuring that the users of your software are happy with the general service is speed 🏎️. No matter how good your service is, once it is slow, users begin to look out for alternatives that will work much faster.</p>
<p><a target="_blank" href="https://ishortn.ink">My URL shortening platform</a> was getting some traction—about 1 signup daily and over 850 redirects per day—but its popularity came at a cost: a skyrocketing number of database read operations. This meant sluggish redirects and frustrated users, which was the exact opposite of what I wanted.</p>
<p>Response times for resolving shortened links were around 1.2 seconds, and it had already made over 44 million row reads 🤯. I got very particular about the row reads because everything is being run on a free tier, and the database has a maximum of 1B row reads. 40 million is very low compared to 1B, but I was still very concerned.</p>
<p>Armed with some system design knowledge, I embarked on making sure that this problem was looked into.</p>
<h3 id="heading-quickest-thoughts-caching">Quickest thoughts: Caching</h3>
<p>The first thing that came to mind was Caching. Sitting to reflect, I was wondering why I had not thought about including this before the earliest release. My sole reason was <em>premature optimization</em>; basically, I was thinking I was the only user, so why would I want to spend so much time thinking and implementing this?</p>
<p>The idea of caching made a lot of sense, and it is by far one of the most basic things to include in systems to increase response times and performance. Think about CDNs and domain name resolution caches, among other things.</p>
<p>Before I delve further, you might already have an idea of what the problem statement is, but then let me go ahead and state it once more!</p>
<p>PROBLEM STATEMENT:</p>
<blockquote>
<p>We are currently using a free tier database, which has a limit of 1B read operations. We are currently reading every link from the database everytime a new request is made, which is increasing our read operations and thus, getting us closer to the free tier limit. We want to improve response times and also reduce read operations.</p>
</blockquote>
<h3 id="heading-implementation-mechanism">Implementation Mechanism</h3>
<p>The next thing was how I would go about the implementation. Because getting the implementation wrong can lead to a whole lot of consequences.</p>
<ul>
<li><p>What if a link's destination is updated and the wrong data is being stored in the cache?</p>
</li>
<li><p>What if a link's alias has changed? Does that mean users are redirected to a 404 page, although the link is really there?</p>
</li>
</ul>
<p>Like I said, getting this wrong will lead to your users having the worst experiences. In the sections below, I will try to explain my thoughts clearly so you understand why I did certain things.</p>
<h3 id="heading-caching-service-used">Caching Service Used</h3>
<p>I opted for Redis since it is the most common and the one with the most available resources on it, be it platforms offering it as a service or even supporting documentation. Since my site is built around Nextjs, I used Redis through <code>Upstash</code> service.</p>
<h3 id="heading-caching-strategy">Caching Strategy</h3>
<p>Although there are numerous caching strategies, I stuck to the <strong>write-through cache</strong> strategy. Here, we write data to both the cache (Redis in this case) and the underlying database (MySQL) simultaneously. With this in place, what essentially happens is that, until a cache is invalidated or evicted, we will not hit <code>cache-miss</code> since the cache is readily pre-populated.</p>
<h3 id="heading-cache-invalidation-strategy">Cache Invalidation Strategy</h3>
<blockquote>
<p>Cache invalidation is a process in a computer system whereby entries in a cache are replaced or removed. [Wikipedia]</p>
</blockquote>
<p>Sometimes, the allowed cache storage sizes might get close to filling up; when it is approaching this instance, we will have to either get rid of some of the items in the cache or clear the whole cache. This also has different ways of being done, and each has its own intention. I will list some below, then talk about the one I settled for.</p>
<ul>
<li><p><strong>Random Replacement:</strong> Randomly selects an item for eviction when space is needed.</p>
</li>
<li><p><strong>Least Frequently Used (LFU):</strong> a strategy that prioritizes keeping items in the cache that have been accessed the most often while removing those that have been used the least</p>
</li>
<li><p><strong>Least Recently Used (LRU):</strong> a strategy that removes the data items that have been <strong>accessed the least recently.</strong></p>
</li>
<li><p><strong>Time To Live (TTL):</strong> Each item in the cache is assigned a specific expiration time. When the time expires, the item is automatically evicted, regardless of its access history.</p>
</li>
</ul>
<p>I ended up using the <strong>LFU (Least Frequently Used)</strong> strategy for our cache eviction. This is because we want to keep the most frequently used links in the cache and remove the least frequently used links from the cache. Sometimes a link might only be clicked on once; in that case, it is of no use lying in the cache and taking up precious free-tier space 🥺</p>
<h3 id="heading-general-design">General Design</h3>
<pre><code class="lang-markdown">Request -&gt; Cache -&gt; Database -&gt; Cache -&gt; Response
</code></pre>
<p>Since we are using the write-through cache approach, every time a user creates a link (probably they are going to share that link in the next instance), so we concurrently write that particular link to both the cache and the database being used.</p>
<p>Once a request for a particular link comes through, for example, <code>ishortn.ink/someAlias</code> I check the cache to see if we have that particular link in there. I used the aliases as the cache keys since they are unique and there will not be more than one of the same aliases in the system.</p>
<p>If the link exists in the cache, we go ahead, retrieve it, and also record some other things that need to be recorded, and the response is sent back to the requester.</p>
<p>In situations where the link is not found in the cache, it is retrieved from the database, written to the cache, and finally returned to the user.</p>
<h3 id="heading-outcomes">Outcomes</h3>
<p>So you will realise that for the current implementation, if a new link is created and the next moment there are 600 clicks on it, it means that the only DB action we did was to just write the link to the table 🤯. Cutting down 600 read operations.</p>
<p>Even if the link is not found in the cache and we have to read from the DB, it means that we will just have one DB read and 599 cache reads 😎.</p>
<p>Not to forget, reading from the cache also means avoiding all the network overhead in retrieving something from the DB, and hence, we are able to respond to requests even much faster.</p>
<p>Initially, a single redirect resolution could take about 1.2s, but with all this implemented, we can literally do the same work in just shy of 200ms 🚀. Over 800 ms of work cut off!</p>
<p>In fact, implementing this and thinking through everything has really been fun and interesting! Now I can save precious free-tier resources and also ensure that my users are still happy with the service, so they keep referring more individuals.</p>
<p>Caching is really a game-changer!!!!</p>
<p>I hope you learned a lot from this and enjoyed reading. If you would like to inquire further, please leave a comment, and I will do my best to answer!</p>
<p>Happy Hacking!</p>
]]></content:encoded></item><item><title><![CDATA[Paying Attention to Details as a Developer]]></title><description><![CDATA[I recently got the chance to work with some individuals on a project. Most of the open source contributions I've done did not really have a specific set of designs to follow, so each contributor had to hack their way into building something that, in ...]]></description><link>https://thoughts.kelvinamoaba.com/paying-attention-to-details-as-a-developer</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/paying-attention-to-details-as-a-developer</guid><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Sun, 07 Jan 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/F_yOvTzX8b4/upload/f6646c521b3b227aa3fa84c4e661bc80.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently got the chance to work with some individuals on a project. Most of the open source contributions I've done did not really have a specific set of designs to follow, so each contributor had to hack their way into building something that, in the end, would be appealing. That was very easy and straight to the point, so it was a lot of fun.</p>
<p>This time around, I had to work with a team of designers and other developers to build a project. The designs weren't really complex, but I managed to mess up a lot of things. Just like my other contributions, <em>I tried to get many things done in a short time</em>. This made me make a lot of mistakes that sometimes made me feel stupid when they were brought forth by the designers and other developers. The period of working with these people made me realize that it is not all about getting things done swiftly but also ensuring you get them done correctly.</p>
<p>You see, user interfaces are not like backend APIs or SQL queries that are mostly not device-specific. Once you write your select statement correctly, it will work on any database. Once you write your API correctly, it will work for any device that requests it correctly. I mean, you get the point. But then, this is not the case with UIs. You have to ensure that your UI works on all devices and that it looks the same on all devices. This is where the problem lies. <em>Measurements are very different here, and there can be several different measurements for different devices, so you have to ensure that you get the measurements right while also getting the interactions right</em>. (I mean, think about the number of Android devices out there; you have to ensure that your UI works on all of them 😅).</p>
<p>Getting into the specifics of the project, I had to build a landing page that was designed in Figma. Every design comes with specific design guides such as spacing, font sizes, user interaction feedback, shadows, and the list goes on.</p>
<p>When I started out, I did not really pay attention to these, my ultimate goal was this: <strong>Get it done and get it done extremely fast</strong>. It is good to get things done quickly but not at the cost of not producing the right stuff. Every pull request I submitted, there was a little issue, and most of these issues are some of the most obvious things I overlooked. Some of these issues were:</p>
<ul>
<li><p><strong>Using wrong margins and paddings</strong>: As an avid tailwindcss user, I was used to using the default utility classes I thought were right based on my Eye test <em>(Eye Driven Development 😂)</em>. I did not really pay attention to the design guide and I ended up using the wrong classes. This was a very big issue because it made the UI look slightly different from the design, which obviously the UI designers were not happy about. Having these things pointed out to me all the time really made me feel bad because I knew I could have done better.</p>
</li>
<li><p><strong>Using wrong font weights</strong>: When designing, font sizes are usually not the problem here, but then the weights of the font vary greatly and are not always determined by just looking at the design in the figma file unless that particular element is inspected to see the actual font weight. I made a couple of these mistakes, and in the end, I had to go back and make a lot of changes to the codebase.</p>
</li>
</ul>
<p>This list goes on and on, but then I will stop here.</p>
<p>Making all these mistakes made me realize something, it is good to develop things swiftly but you <em>must not compromise on the quality of the work you are doing</em>. It is better to take your time and get things done correctly than to rush and get things done wrongly. I am not saying you should not be fast, but then, you should not be too fast that you end up making a lot of mistakes. Remember, <strong>Quality over Quantity</strong>.</p>
<p>Also note that we are all humans no matter how much you and your colleagues try to be perfect, you will still make mistakes. The most important thing is to learn from these mistakes and try not to repeat them again. <em>Too many mistakes can make people question your abilities</em> and that is not a good thing so always try to do your best and pay attention to details.</p>
<p>Before I sign off though, I will share some things I decided to do early in each project to ensure I always produce work that is of high quality. Some might be specific to some tools like TailwindCSS but then, you can always find the equivalent in your own stack.</p>
<ul>
<li><p><strong>Always read the design guide</strong>: Quickly go through the design guide and see what the designers have to say about the project. This will give you a good idea of what to expect and what to look out for.</p>
</li>
<li><p><strong>Setting up the right project configuration</strong>: Now, I go through each design and note down all the colors that will used in the project. This I mostly do in the <code>tailwind.config.ts/js</code> file. I also note down the font sizes and font weights that will be used in the project. This will help me to always use the right classes when building the UI. This also makes it much easier to change things later along the line, like when the designers decide to change the font size of a particular element, you can just go to the config file and change it there and it will reflect across the whole project.</p>
</li>
<li><p><strong>Using the right sizes</strong>: In some cases were you might need to design a particular thing at just one point and you did not add the config for that, please do not rush into using the default utility classes that you think are right. It is better to use the exact value in the figma design than to use the wrong utility class. This will save you a lot of time and review stress. Example, say an element used in only one particular section has a font size of 45px. You might be tempted to use the <code>text-4xl</code> class but then, that is not the right class to use. It is better to use the <code>text-[45px]</code> class. This is what TailwindCSS calls the <strong>Arbitrary Values</strong>. You can read more about it <a target="_blank" href="https://tailwindcss.com/docs/just-in-time-mode#arbitrary-values">here</a>.</p>
</li>
</ul>
<p>These are some of the things I have learnt and I hope you find them useful. If you have any suggestions, please let me know. I am open to feedback. Thanks for reading.</p>
]]></content:encoded></item><item><title><![CDATA[A 5-Step Approach to Problem Solving (DSA)]]></title><description><![CDATA[When starting to practice the data structures and algorithms you've learned on platforms such as Leetcode, Codewars or Hackerrank, you can go from being pretty excited to pretty down in a matter of few minutes behind a problem.
I encountered this a l...]]></description><link>https://thoughts.kelvinamoaba.com/a-5-step-approach-to-problem-solving-dsa</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/a-5-step-approach-to-problem-solving-dsa</guid><category><![CDATA[data structures]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Sat, 18 Nov 2023 07:02:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/DnXqvmS0eXM/upload/878e2dab7224742cd552014716babee7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When starting to practice the data structures and algorithms you've learned on platforms such as Leetcode, Codewars or Hackerrank, you can go from being pretty excited to pretty down in a matter of few minutes behind a problem.</p>
<p>I encountered this a lot. It makes you start to question a whole lot of things, from whether it's your brain that cannot process much to whether you are not built for this field and a whole lot of other things.</p>
<p>But then, after spending some time questioning my skills and going back and forth between problems, it turned out that <em>I was not really doing some things right from the onset</em> and that had to do with <strong>the way I approached the problems</strong> I tried to solve.</p>
<p>In this article, I will try and explain why certain things should be avoided or embraced as I go over the 5 steps I used to improve at solving these problems.</p>
<h3 id="heading-1-understand-the-problem-like-seriously-take-time-to-understand-the-problem">1. Understand the problem, like seriously, take time to understand the problem</h3>
<p>So for me, one major mistake I made was immediately starting to think about concepts to solve the problem as I read the problem. I believe this was the main ingredient in preventing me from solving these problems correctly. The reason why this is an issue is that you do not get to really get into the ins and outs of the question before you start thinking about implementation.</p>
<p>Note that, <strong>understanding the question is also part of the answer</strong>.</p>
<p>One time, I rushed into writing code for a problem when I had not even finished reading the problem and instead of returning an array of integers from the function, I was returning a single integer 🤦‍♂️. As you can tell, after countless times questioning why I was failing the test cases, it was going back to reading the problem that made me finally pass them.</p>
<p>As simple as a problem might be from the introductory sentences, please and please refrain from shifting focus to finding the right algorithm or data structure to use. Just take time to read and digest, before doing anything else.</p>
<h3 id="heading-2-pseudocodes-and-paper-solutions-still-rock">2. Pseudocodes and Paper Solutions Still Rock</h3>
<p>The second thing was that I jumped into coding real quick after lazily skimming through the question. This is the biggest mistake you can ever make, once you don't understand how something should work really well or the type of inputs your function will take, you know that you are definitely doomed and you cannot really do anything tangible.</p>
<p>Even if you understand the problem, you should not start with coding from your computer, just try and write some pseudocode on a piece of paper or notebook you have beside you or just say your thought processes out aloud (after all, you'll do this in a real interview). This is really going to improve your overall understanding of the problem and you might catch all the edge cases that come with the problem.</p>
<p>With your plan in place, it's just a matter of transcribing them into code using the correct syntax. Easy Peezy :)</p>
<h3 id="heading-3-avoid-premature-optimization-at-all-costs">3. Avoid Premature Optimization at all Costs</h3>
<p>To add to my already existing stack of wrong approaches, I was also trying to code out the perfect algorithm from the start (Premature Optimization).</p>
<blockquote>
<p>Premature Optimization: Trying to improve something especially with the goal of perfecting it when it's too early to do so.</p>
</blockquote>
<p>When you start writing the solution to a problem and you start thinking in this way, it becomes a big issue. So rather than moving from the ground up, you try to hit the jackpot on the first try. Everyone knows that this is rarely even the case in casinos.</p>
<p>The best way to start solving a problem is to start off with the most basic and unoptimized approach, what we usually call the <strong>"Brute Force"</strong> solution, and slowly work your way up because, at this point, you have something that solves the problem but is inefficient that you just have to transform into an efficient solution. This is in contrast to you trying to optimize something you have not even written.</p>
<h3 id="heading-4-it-takes-time-to-get-things-right">4. It takes time to get things right</h3>
<p>Like it was or is in some of your university classes, it is not all the time you get a problem right on the first spot. It takes time and practice to become good at something. Don't get the wrong feeling for failing all the test cases, that is how we end up learning. As you fail these problems, you should spend some time trying to figure out what really went wrong rather than jumping into viewing the solutions that have been posted by other users. I found myself doing that and that really did not make me any better. It is much better to struggle a little bit more, if you still do not get it, you can go on and use the hints from the problem and also, log as much as possible, it is very important to know what is going on at each point in your code.</p>
<h3 id="heading-5-compare-and-contrast">5. Compare and Contrast</h3>
<p>One of the best feelings you can get is the satisfaction of being able to solve a problem correctly. You get really excited and happy, feeling on top of the world, cool right? One thing though is that you should not jump on to the next problem but then, try to always view solutions posted by other developers on the problem. Look, you will really learn a lot by going through it.</p>
<p>This is really something I use to my advantage and I learn a lot of handy handy functions, methods and even parameters to some functions.</p>
<p>This will also make you see the thought process of others and get a complete overview of the problem from other points of view.</p>
<h3 id="heading-to-conclude">To Conclude</h3>
<p>I can assure you that fully utilizing this thought process is going to really improve how well you do in solving problems relating to DSA and programming in general. Also, do note that although it will be great to jump into practising problems on algorithms, you should make sure you have really learnt enough and mastered some very necessary foundational algorithms and data structures as these are mostly what other algorithms are based on and problems require you to understand.</p>
<p><strong>All the best in your journey 🎊</strong></p>
]]></content:encoded></item><item><title><![CDATA[Deep Dive into Stacks: A Practical Guide for Software Engineers]]></title><description><![CDATA[What is a Stack?
A stack is a very important data structure that is used to work on data temporarily. Unlike other data structures that are built into a language, a stack is rather a layer added to an existing data structure, such as an array or link...]]></description><link>https://thoughts.kelvinamoaba.com/deep-dive-into-stacks-a-practical-guide-for-software-engineers</link><guid isPermaLink="true">https://thoughts.kelvinamoaba.com/deep-dive-into-stacks-a-practical-guide-for-software-engineers</guid><category><![CDATA[General Programming]]></category><category><![CDATA[data structures]]></category><category><![CDATA[data structures and algorithm course]]></category><dc:creator><![CDATA[Kelvin Amoaba]]></dc:creator><pubDate>Thu, 09 Nov 2023 19:40:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/wstYTyWtGac/upload/d1ae6fdfc834744111ba65a912501eb4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-a-stack">What is a Stack?</h2>
<p>A stack is a very important data structure that is used to work on data <em>temporarily</em>. Unlike other data structures that are built into a language, a stack is rather a layer added to an existing data structure, such as an array or linked list. In this tutorial, however, we will focus on the array-based implementation of a stack.</p>
<p>So just like arrays, the data added to a stack is stored in contiguous memory. The main difference between a stack and an array is how operations on data are performed. A stack behaves differently from an array due to a <strong><em>set of rules</em></strong> that are added to the behavior of the array.</p>
<p>Data structures that are built on top of rules from other data structures are called <mark>abstract data types</mark>. Another type of abstract data type is the <strong>queue</strong>, which we will discuss in another post.</p>
<p>The stack data structure is a very important data structure used in various areas of computer science, like recursion. A stack helps to implement various things. The undo and redo functionalities of your IDE are based on a stack; your browser navigation, forward and back, is also based on a stack.</p>
<h2 id="heading-how-does-it-differ-from-an-array">How does it differ from an array?</h2>
<p>The following rules differentiate how a stack operates from how an array operates.</p>
<ol>
<li><p>You can only <strong>add</strong> to the end of the stack.</p>
</li>
<li><p>You can only <strong>read</strong> from the end of the stack.</p>
</li>
<li><p>You can only <strong>delete</strong> from the end of the stack.</p>
</li>
</ol>
<p>In a typical array, one can insert data into any index they want, but in a stack, that is prohibited. If this rule is broken, then it is no longer a stack but something else. (#1)</p>
<p>Reading from a typical array does not restrict where in the array you read from. You can read from the beginning of the array, the middle, or the end, wherever you want to read from. But then, in a stack, it is mandatory to only read from the end of the stack.</p>
<p>The third rule states that you can only delete from the end of the stack. This is a very different behavior from a normal array because, in an array, one can delete at any index they want.</p>
<p>It should be noted that these rules are not pre-written in most languages but are implemented when the stack data structure is built. It is typically not a built-in structure but rather something that the programmer explicitly creates.</p>
<blockquote>
<p>The end of the stack is referred to as the top. This is because we look at the stack not like a horizontal array but as a vertical array.</p>
</blockquote>
<h2 id="heading-scenario">Scenario</h2>
<p>You can think of a stack data structure as stones placed on top of each other, like in the preview picture above. To add another stone, you place it on top of the already existing stones, not below or in the middle (Rule #1)</p>
<p>If the stones were colored and you want to see (read) the color of the most recent one, you will obviously look down at the stones. The latest one simply refers to the one you just added to the stack. (Rule #2)</p>
<p>Also, to remove a stone, you would have to remove the one from the top first, as this is the only logical way to go about it if you don't want your stone empire to come crumbling down (Rule #3)</p>
<p>This behaviour of the stack is referred to as the <strong><mark>LIFO</mark></strong> This is an acronym for Last In, First Out. This basically means that the first thing you add to the array is the last thing that comes out.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699291262795/6659f108-28bf-4f32-9b53-12cf105a35f2.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-operations-performed-on-a-stack">Operations Performed on a Stack</h2>
<p>The operations performed on a stack are:</p>
<ul>
<li><p>Reading, a.k.a. "Peeking,"</p>
</li>
<li><p>Adding: AKA "Pushing to the Stack".</p>
</li>
<li><p>Removing: AKA "Popping from the Stack".</p>
</li>
</ul>
<h2 id="heading-implementation-of-a-stack-in-python">Implementation of a Stack in Python</h2>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Stack</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.data = []

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">push</span>(<span class="hljs-params">self, value</span>):</span>
        self.data.append(value)
        <span class="hljs-keyword">return</span> len(self.data) - <span class="hljs-number">1</span> <span class="hljs-comment"># return the index of the item</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">peek</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-comment"># Return the last value if the data array is not empty else</span>
        <span class="hljs-comment"># return None</span>
        <span class="hljs-keyword">return</span> self.data[<span class="hljs-number">-1</span>] <span class="hljs-keyword">if</span> len(self.data) &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> <span class="hljs-literal">None</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">remove</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-comment"># Here too when the user tries removing the last item, return</span>
        <span class="hljs-comment"># it if there are elements in the array else return None</span>
        <span class="hljs-keyword">return</span> self.data.pop() <span class="hljs-keyword">if</span> len(self.data) &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> <span class="hljs-literal">None</span>
</code></pre>
<h3 id="heading-code-explanation">Code Explanation</h3>
<p>We define the Stack class; as previously stated, the stack is a data structure that you create and does not come pre-built in most programming languages.</p>
<p>In the<code>__init__</code> method, we create an empty array and attach it to the object. As you can see here, the stack we are implementing is based on the array data structure.</p>
<p>Next, we define the <code>push</code> method, the push method is responsible for inserting a new value onto a stack. This is accomplished by invoking the append method and passing in the user-supplied value. The append method adds to the end of the list, which is referred to as the <strong><em>TOP</em></strong> in a stack. The index of the last item is then returned.</p>
<p>Next, we define the <code>peek</code> method, the peek method simply returns the last item in the array if there are items in it; otherwise, it returns None.</p>
<p>The <code>remove</code> method is next. Here, we return the last item in the array. This is done by calling the pop() method on a list. This will remove the last item in the list and return it.</p>
<p>Let's quickly go through an example of this implementation.</p>
<pre><code class="lang-python">s1 = Stack()
s1.push(<span class="hljs-number">1</span>) <span class="hljs-comment"># This adds 1 to the stack</span>
print(s1.peek()) <span class="hljs-comment"># This prints out 1, since it's the item at the top</span>
s1.push(<span class="hljs-number">2</span>)
s1.push(<span class="hljs-number">3</span>)
print(s1.peek()) <span class="hljs-comment"># This prints out 3, since it's the latest item at the top</span>

s1.remove()
print(s1.peek()) <span class="hljs-comment"># this prints 2 since 3 has been removed from the stack</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699292885137/046bfb6d-0dd8-4f50-a38c-ba3c7a1912f5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699293075698/604b1ac7-5d21-4d7e-b783-99569e389795.png" alt class="image--center mx-auto" /></p>
<p>As you can see from above, the LIFO behavior is working in full effect. The first item added will be the last item to leave.</p>
<h2 id="heading-real-world-use-cases">Real-world use cases</h2>
<ul>
<li><p><strong>Browser Forward and Back Navigation</strong><br />  Web browsers implement forward and back navigation using two stacks: the undo stack and the redo stack. As the user navigates between pages, the current URL is pushed onto the undo stack. Pressing the back button pops the URL from the undo stack and pushes it onto the redo stack, allowing the user to move backward and forward through their browsing history. This dual-stack system ensures efficient navigation between visited pages. This is a very simple breakdown; a lot gets built on this, though :D</p>
</li>
<li><p><strong>Function Call Management</strong><br />  In programming, a call stack is a stack data structure that controls a function call. When a function is called, its parameters, local variables, and return address are pushed onto the call stack. As functions complete execution, they are deleted from the stack, returning the program to the previous execution context. This is mostly used in recursive programming.</p>
</li>
<li><p><strong>Solving Algorithmic Problems</strong><br />  Several problems you will encounter will require some comprehension of stacks in order to solve them efficiently. Some include:</p>
<ul>
<li><p>First-depth search problem</p>
</li>
<li><p>Reversing items in a list or string</p>
</li>
</ul>
</li>
</ul>
]]></content:encoded></item></channel></rss>