<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kelvin Amoaba</title>
    <description>The latest articles on DEV Community by Kelvin Amoaba (@amoabakelvin).</description>
    <link>https://dev.to/amoabakelvin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F813948%2F2debab2c-2ebb-4d8c-8f22-64889793e3b3.png</url>
      <title>DEV Community: Kelvin Amoaba</title>
      <link>https://dev.to/amoabakelvin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amoabakelvin"/>
    <language>en</language>
    <item>
      <title>What Actually Determines a File's Type</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Sat, 13 Dec 2025 06:13:45 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/what-actually-determines-a-files-type-48d0</link>
      <guid>https://dev.to/amoabakelvin/what-actually-determines-a-files-type-48d0</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Extensions are just hints, the real determining of the type is done through “Magic Numbers”&lt;/p&gt;

&lt;h4&gt;
  
  
  Magic Numbers
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;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.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;Eg, for PNG files, this magic number is 89 50 4E 47, for zip files, it’s 50 4B 03 04. Bitmap images start with 42 4D, which is just BM in ASCII (short for “bitmap”).&lt;/p&gt;

&lt;p&gt;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&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmp&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Read the first 2 bytes (The Magic Number)&lt;/span&gt;
    &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// BMP signature is 0x42, 0x4D&lt;/span&gt;
    &lt;span class="n"&gt;bmpSig&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;0x42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0x4D&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bmpSig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="n"&gt;BMP&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="n"&gt;Invalid&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;file&lt;/code&gt; 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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Categories of File Structures
&lt;/h4&gt;

&lt;p&gt;File formats generally fall into a few structural categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Binary formats with rigid structure (PNG, JPEG, MP3): every byte position has specific meaning according to the spec. Programs parse these by reading exact offsets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Text-based structured formats (JSON, XML, HTML, CSV): human-readable text following grammar rules. Easier to debug but larger file sizes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Container formats (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.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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. &lt;/p&gt;

</description>
      <category>systems</category>
      <category>software</category>
    </item>
    <item>
      <title>Logs Multiplexing in Docker</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Fri, 17 Oct 2025 12:36:02 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/logs-multiplexing-in-docker-31ko</link>
      <guid>https://dev.to/amoabakelvin/logs-multiplexing-in-docker-31ko</guid>
      <description>&lt;p&gt;Logs multiplexing is the way that docker sends logs from containers to whatever client might be requesting for those logs. Logs multiplexing is when the various data from the output streams of the process being run in the container is combined into one stream and passed to clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem Docker Tried to Solve
&lt;/h3&gt;

&lt;p&gt;Whenever programs are being executed, there are 2 available streams on which they can channel results / outputs to, we have the standard output (&lt;code&gt;stdout&lt;/code&gt;) and the standard error (&lt;code&gt;stderr&lt;/code&gt;); there is standard input (&lt;code&gt;stdin&lt;/code&gt;) but that is mostly for receiving inputs into programs. Whenever you run the command like &lt;code&gt;docker logs &amp;lt;container&amp;gt;&lt;/code&gt; the problem was now how docker is going to ensure that those outputs from the different streams arrive in the exact order they were being produced inside the container and also making sure that the different streams could be identified by the clients making the request to view those logs.&lt;/p&gt;

&lt;p&gt;The naive approach could be managing two different networks on which results from stdout could be passed on one and the results from stderr could also be passed on the other. But then that would mean managing two different network streams and the whole complexity associated with that. Assuming one network stream goes down, what happens? How do we keep track of the order that the outputs were produced, these among many more reasons are the reason for multiplexing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiplexer
&lt;/h3&gt;

&lt;p&gt;In electronics, a multiplexer looks like something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3v3g7y4j4wly4xedhet.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3v3g7y4j4wly4xedhet.jpg" alt="Multiplexer" width="800" height="725"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://people.iitism.ac.in/~sarun/notes/phc504/figs/mux.jpg" rel="noopener noreferrer"&gt;Image source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the simple eye view, you can see that there are a number of input streams that are combined to form one output. You can think of docker logs multiplexing as the same concept, combining the various streams into one single stream.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoding the Multiplexed Stream
&lt;/h3&gt;

&lt;p&gt;Docker uses a simple &lt;strong&gt;framing protocol&lt;/strong&gt;. Each chunk of data gets prefixed with an &lt;strong&gt;8-byte header&lt;/strong&gt;. The first byte identifies which stream it came from (0 for stdin, 1 for stdout, 2 for stderr), bytes 1-3 are reserved (always 0x00) and the next bytes (4-7) contain the payload size.&lt;/p&gt;

&lt;p&gt;The header looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[STREAM_TYPE] [0x00, 0x00, 0x00] [PAYLOAD_SIZE]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;PAYLOAD_SIZE&lt;/code&gt; allows the client to parse the exact content in the stream coming in without buffering or figuring out where one chunk ends and the another begins.&lt;/p&gt;

&lt;p&gt;This framing header lets the receiving end parse the stream unambiguously. The data stays &lt;em&gt;intact and in order&lt;/em&gt;, but now it's carrying metadata about its origin. When you use commands like &lt;code&gt;docker logs&lt;/code&gt;, you're actually reading from this multiplexed stream that Docker has stored. Docker can show you just stdout, just stderr, or both together because it knows which bytes came from which stream thanks to that multiplexing metadata. This solves the problem of how to manage two different network streams and the whole complexity associated with that, you just focus on having a single stream to deal with.&lt;/p&gt;

&lt;h3&gt;
  
  
  Breakdown of the 8-byte header
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Byte 0 : Stream &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0 &lt;span class="o"&gt;=&lt;/span&gt; stdin, 1 &lt;span class="o"&gt;=&lt;/span&gt; stdout, 2 &lt;span class="o"&gt;=&lt;/span&gt; stderr&lt;span class="o"&gt;)&lt;/span&gt;
Bytes 1-3 : Reserved &lt;span class="o"&gt;(&lt;/span&gt;always 0x00&lt;span class="o"&gt;)&lt;/span&gt;
Bytes 4-7 : Payload size &lt;span class="o"&gt;(&lt;/span&gt;big-endian uint32&lt;span class="o"&gt;)&lt;/span&gt;
Bytes 8-n : Payload &lt;span class="o"&gt;(&lt;/span&gt;the actual log data&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a simple example of how you might parse this in Python when connecting to Docker's attach API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_docker_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

        &lt;span class="n"&gt;stream_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unpack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;BBBBI&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stream_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;STDOUT: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;stream_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;STDERR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What goes over the wire for Hello?
&lt;/h3&gt;

&lt;p&gt;Assuming your container outputs Hello to standard output, here is how docker will send it over the wire:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 00, 00, 00, 00, 00, 00, 05] [48 65 6c 6c 6f]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;[48 65 6c 6c 6f]&lt;/code&gt; is the hex representation of the ASCII representation of the string "Hello". The &lt;code&gt;05&lt;/code&gt; is the payload size and the &lt;code&gt;1&lt;/code&gt; is the stream type, in this case, stdout.&lt;/p&gt;




&lt;p&gt;This idea of multiplexing is not unique to Docker. It's a common pattern in systems engineering whenever there is a need to combine multiple logical channels into a single physical channel. HTTP/2 does this with web requests, SSH does this when you have multiple terminal sessions over one encrypted connection and so on.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>containers</category>
    </item>
    <item>
      <title>Monotonic and Wall Clock Time</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Sun, 16 Mar 2025 13:17:26 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/monotonic-and-wall-clock-time-3mp</link>
      <guid>https://dev.to/amoabakelvin/monotonic-and-wall-clock-time-3mp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Monotonic&lt;/strong&gt; and &lt;strong&gt;wall clock&lt;/strong&gt; time are two ways we measure time.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Monotonic times have two characteristics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They tick forward at a regular rate&lt;/li&gt;
&lt;li&gt;They are detached from current time of day&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The reason why we need to keep track of the two types of time is because, &lt;em&gt;wall clock time does not uniformly increase&lt;/em&gt;. 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.&lt;/p&gt;

&lt;p&gt;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, &lt;code&gt;t1&lt;/code&gt; and &lt;code&gt;t2&lt;/code&gt;, and we want to find the difference between them, we can do so by subtracting &lt;code&gt;t1&lt;/code&gt; from &lt;code&gt;t2&lt;/code&gt;. Should time &lt;code&gt;t1&lt;/code&gt; be before time &lt;code&gt;t2&lt;/code&gt;, the result will be negative, which breaks our assumption. Time &lt;code&gt;t1&lt;/code&gt; can always be before time &lt;code&gt;t2&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;Time difference being negative actually caused a big issue one time for Cloudflare DNS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;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 &lt;a href="https://blog.cloudflare.com/how-and-why-the-leap-second-affected-cloudflare-dns/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>A 5-Step Approach to Problem Solving (DSA)</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Sat, 18 Nov 2023 07:00:49 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/a-5-step-approach-to-problem-solving-dsa-4o6d</link>
      <guid>https://dev.to/amoabakelvin/a-5-step-approach-to-problem-solving-dsa-4o6d</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;But then, after spending some time questioning my skills and going back and forth between problems, it turned out that &lt;em&gt;I was not really doing some things right from the onset&lt;/em&gt; and that had to do with &lt;strong&gt;the way I approached the problems&lt;/strong&gt; I tried to solve.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Understand the question, like seriously, take time to understand the problem
&lt;/h3&gt;

&lt;p&gt;So for me, one major mistake I made 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.&lt;/p&gt;

&lt;p&gt;Note that, &lt;strong&gt;understanding the question is also part of the answer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;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 really read the problem that made me finally pass them.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pseudocodes and Paper Solutions Still Rock
&lt;/h3&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;With your plan in place, it's just a matter of transcribing them into code using the correct syntax. Easy Peezy :)&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Avoid Premature Optimization at all Costs
&lt;/h3&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Premature Optimization: Trying to improve something especially with the goal of perfecting it when it's too early to do so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;The best way to start solving a problem is to start off with the most basic and unoptimized approach, what we usually call the &lt;strong&gt;"Brute Force"&lt;/strong&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. It takes time to get things right
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Compare and Contrast
&lt;/h3&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;This will also make you see the thought process of others and get a complete overview of the problem from other points of view.&lt;/p&gt;

&lt;h3&gt;
  
  
  To Conclude
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All the best in your journey 🎊&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dsa</category>
      <category>algorithms</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Deep Dive into Stacks: A Practical Guide for Software Engineers</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Thu, 09 Nov 2023 20:08:47 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/deep-dive-into-stacks-a-practical-guide-for-software-engineers-5h7p</link>
      <guid>https://dev.to/amoabakelvin/deep-dive-into-stacks-a-practical-guide-for-software-engineers-5h7p</guid>
      <description>&lt;h2&gt;
  
  
  What is a Stack?
&lt;/h2&gt;

&lt;p&gt;A stack is a very &lt;strong&gt;important&lt;/strong&gt; data structure that is used to work on data &lt;em&gt;temporarily&lt;/em&gt;. &lt;br&gt;
Unlike other data structures that are built into a language, a stack is rather a &lt;em&gt;layer added&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;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 set of rules that are added to the behavior of the array.&lt;/p&gt;

&lt;p&gt;Data structures that are built on top of rules from other data structures are called abstract data types. Another type of abstract data type is the queue, which we will discuss in another post.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;
  
  
  How does it differ from an array?
&lt;/h2&gt;

&lt;p&gt;The following rules differentiate how a stack operates from how an array operates.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can only &lt;strong&gt;add&lt;/strong&gt; to the end of the stack&lt;/li&gt;
&lt;li&gt;You can only &lt;strong&gt;read&lt;/strong&gt; from the end of the stack&lt;/li&gt;
&lt;li&gt;You can only &lt;strong&gt;delete&lt;/strong&gt; from the end of the stack&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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)&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Scenario
&lt;/h2&gt;

&lt;p&gt;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)&lt;/p&gt;

&lt;p&gt;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)&lt;/p&gt;

&lt;p&gt;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)&lt;/p&gt;

&lt;p&gt;This behaviour of the stack is referred to as the &lt;strong&gt;&lt;em&gt;LIFO&lt;/em&gt;&lt;/strong&gt; This is an acronym for &lt;strong&gt;Last In, First Out&lt;/strong&gt;. This basically means that the first thing you add to the array is the last thing that comes out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1699291262795%2F6659f108-28bf-4f32-9b53-12cf105a35f2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1699291262795%2F6659f108-28bf-4f32-9b53-12cf105a35f2.png" alt="Stack Illustration"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Operations Performed on a Stack
&lt;/h2&gt;

&lt;p&gt;The operations performed on a stack are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading, aka "Peeking"&lt;/li&gt;
&lt;li&gt;Adding, aka "Pushing to the stack"&lt;/li&gt;
&lt;li&gt;Removing, aka "Popping from the Stack"&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Implementation of a Stack in Python
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# return the index of the item
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Return the last value if the data array is not empty else
&lt;/span&gt;        &lt;span class="c1"&gt;# return None
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Here too when the user tries removing the last item, return
&lt;/span&gt;        &lt;span class="c1"&gt;# it if there are elements in the array else return None
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Code Explanation
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;__init__&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;Next, we define the &lt;code&gt;push&lt;/code&gt; 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 TOP in a stack. The index of the last item is then returned.&lt;/p&gt;

&lt;p&gt;Next, we define the &lt;code&gt;peek&lt;/code&gt; method, the peek method simply returns the last item in the array if there are items in it; otherwise, it returns None.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;remove&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;Let's quickly go through an example of this implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# This adds 1 to the stack
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;# This prints out 1, since it's the item at the top
&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;# This prints out 3, since it's the latest item at the top
&lt;/span&gt;
&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;# this prints 2 since 3 has been removed from the stack
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Walkthrough
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1699292885137%2F046bfb6d-0dd8-4f50-a38c-ba3c7a1912f5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1699292885137%2F046bfb6d-0dd8-4f50-a38c-ba3c7a1912f5.png" alt="First"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1699293075698%2F604b1ac7-5d21-4d7e-b783-99569e389795.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1699293075698%2F604b1ac7-5d21-4d7e-b783-99569e389795.png" alt="Second"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-world use cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser Forward and Back Navigation&lt;/strong&gt;&lt;br&gt;
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&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Function Call Management:&lt;/strong&gt;&lt;br&gt;
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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solving Algorithmic Problems&lt;/strong&gt;&lt;br&gt;
Several problems you will encounter will require some comprehension of stacks in order to solve them efficiently. Some include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First-depth search problem&lt;/li&gt;
&lt;li&gt;Reversing items in a list or string&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>datastructures</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Python Functions</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Wed, 25 Oct 2023 20:52:25 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/understanding-python-functions-23p0</link>
      <guid>https://dev.to/amoabakelvin/understanding-python-functions-23p0</guid>
      <description>&lt;p&gt;Well, let's dive straight into it. &lt;/p&gt;

&lt;p&gt;Functions are blocks of code written to perform a particular task. Well, this definition is quite simple and straightforward. This simply means, your functions should do only one thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Functions In Python
&lt;/h2&gt;

&lt;p&gt;To create a function, python provides a special keyword, &lt;code&gt;def&lt;/code&gt;. This keyword is used in combination with a user defined name you give to the function. Let's take a look&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name_of_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
   &lt;span class="c1"&gt;# function block
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every function should have a name, but not every name is allowed because some are reserved by Python itself.&lt;/p&gt;

&lt;p&gt;Inside the function block is where you write what the function should do when called.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parameters
&lt;/h3&gt;

&lt;p&gt;When writing a function, you can define parameters that you want the function to take in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A parameter is used to represent data you want as input to the function&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Parameters are defined inside the parenthesis in the function definition.&lt;/p&gt;

&lt;p&gt;Example, let's say you want to write a function that adds two numbers, we will name the function, add.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, the function add has two parameters, a and b which we are using to represent the two numbers we will pass in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calling Functions
&lt;/h3&gt;

&lt;p&gt;Once a function is written, then it must be used somewhere. I mean, I'm not sure you will write a function without the intention of using it 😅&lt;/p&gt;

&lt;p&gt;To use a function, you call the function with its name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above example, we called the function with it's name and passed in the parameters it requires.&lt;br&gt;
Suppose the function had no parameters, you will just call it with its name and the brackets. &lt;code&gt;add()&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Parameters and Arguments - Revisited
&lt;/h3&gt;

&lt;p&gt;In the above section, I explained what parameters are. Reiterating, a parameter is used to represent data you want to pass as input to a function.&lt;/p&gt;

&lt;p&gt;When calling a function that has some parameters, the actual values you pass in to that function are called the &lt;code&gt;Arguments&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's go over the example again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we were defining the functions, we passed a, b inside the brackets, those are called the &lt;strong&gt;function parameters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The real/actual values we pass to the function when calling it are what we call the &lt;strong&gt;arguments&lt;/strong&gt;. In our "add" example, "2" and "4" are the arguments.&lt;/p&gt;

&lt;p&gt;Arguments are also called &lt;strong&gt;"Actual Parameters"&lt;/strong&gt; and the parameters specified in the function definition are called "Formal Parameters"&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters are specified in the function definition and arguments are the values passed into the function when calling it&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Types of Functions
&lt;/h3&gt;

&lt;p&gt;There are two types of functions in Python: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;User-Defined Functions&lt;/em&gt;&lt;/strong&gt;: These are the functions you create, like the "add" function we defined. You choose the name and define what it does.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Built-In Functions&lt;/em&gt;&lt;/strong&gt;: Python comes with a collection of pre-made functions that perform common tasks. These are functions like &lt;code&gt;print()&lt;/code&gt;, &lt;code&gt;len()&lt;/code&gt;, and &lt;code&gt;input()&lt;/code&gt;, which are available for you to use without defining them yourself. Built-in functions save you time and effort, as they are already part of the Python language.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To conclude, functions are really powerful and understanding it will really be important in your programming journey.&lt;br&gt;
Here are some importance of functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Improving code reusability:  Once a function is defined, it can be used over and over and over again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code Organisation: It helps to divide the large programs into small groups to read the code and debug it faster and better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functions can be shared and used by other programmers. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Safeguarding Critical Keys</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Wed, 09 Aug 2023 03:03:01 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/safeguarding-critical-keys-4dki</link>
      <guid>https://dev.to/amoabakelvin/safeguarding-critical-keys-4dki</guid>
      <description>&lt;p&gt;These days, almost any service you interact with through an API will require some sought of permissions to be able to use it. These permissions are done through the use of what is known as API keys, which is a sequence of some characters. These act like the username and password you use when logging in to any website and we all know how much we would not want to share those credentials with others. That is how we have to treat these keys as well, because when they get into the wrong hands, they can be used to perpetuate acts you have not yet prepared for. Some might include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unauthorized Data Access&lt;/strong&gt;: A malicious actor could misuse stolen API keys to gain unauthorized access to sensitive data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Overuse&lt;/strong&gt;: An attacker might use compromised keys to overload a service, causing downtime or additional costs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Securing API Keys: Best Practices&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To bolster the security of API keys, a fundamental approach is to leverage &lt;strong&gt;Environment Variables&lt;/strong&gt; within your source code. Environment variables are external to your program and should never appear explicitly in your codebase. As the name suggest, they are variables, and we all know variables store values. But then, when you reference the variable, you get the value in place of it, and this value, you might not be aware of. When you reference an environment variable, you retrieve its value, which remains concealed from your code. These variables are typically configured at the system level and can be accessed by the executing program. A typical way of getting environment variables in python is using the &lt;code&gt;os&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"HIGHLY_IMPORTANT_SECRET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual value of &lt;strong&gt;&lt;code&gt;secret_key&lt;/code&gt;&lt;/strong&gt; isn't known until runtime, and it can vary based on the environment, enhancing security by keeping sensitive information hidden.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Embracing Security Audits&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As we grow in the field on engineering and software building, we should not only take into consideration that because a code is running, it is okay to be pushed to the general public. As engineers, we also need to sit down, analyze typical bugs we might have present and also, the security of the code we have written. Rushing to deploy features might lead to exposing private information unintentionally. For instance, directly embedding an API key without proper handling can be a security risk. An example will be you passing an API key directly into a variable without using a method like we discussed about, due to the rush to get things done.&lt;/p&gt;

&lt;p&gt;We must learn to add to the pipeline before deploying, the need to sit down and perform some auditing before going ahead to push out our changes. These days, any slight loophole an attacker gets within your system, they tend to really do great dame with it.&lt;/p&gt;

&lt;p&gt;Libraries we use in our codes can also contribute to the overall security weakness of our application. We should really try as much as possible to stay away from packages or libraries that have not been maintained in a really long time. While the advice against reinventing the wheel is well-known, choosing a package that hasn't been updated in five years might end up causing more harm than spending a bit of time to create it yourself.&lt;/p&gt;

&lt;p&gt;For code checks and auditing, there are various 3rd party services that we can use, some even, directly within our IDEs. By integrating these tools, you can identify and mitigate security concerns before they become real threats..  I will leave some links below so you check them out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.redhat.com/blog/2020/08/28/vulnerability-analysis-with-red-hat-codeready-dependency-analytics-and-snyk"&gt;Dependency analytics by Redhat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sourcery.ai/"&gt;Sourcery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://snyk.io/code-checker/"&gt;Snyk.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/codewhisperer/"&gt;Amazon Codewhisper&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In conclusion, safeguarding API keys and fortifying your application against security risks are paramount. Employing environment variables, conducting thorough security audits, and leveraging third-party tools all contribute to maintaining a robust and secure software ecosystem.&lt;/p&gt;

</description>
      <category>security</category>
      <category>programming</category>
      <category>vulnerabilities</category>
    </item>
    <item>
      <title>@mentions Notifications Design</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Fri, 05 May 2023 00:32:31 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/mentions-notifications-design-2phm</link>
      <guid>https://dev.to/amoabakelvin/mentions-notifications-design-2phm</guid>
      <description>&lt;p&gt;So we have all used platforms where we receive notifications whenever we are mentioned in a post or a comment. These notifications are to keep us engaged in conversations.&lt;/p&gt;

&lt;p&gt;I am going to be explaining at the high level how to build out a simple @mentions notifications feature in any system. Note that this post is only giving you a fair idea about how to go about the whole implementation and not showing you how to actually do it in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Receive the incoming post / comment text from your UI, this data could be from an endpoint that your frontend sends posts requests to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once this data is retrieved, you would need to parse the content of the post to find every instance of an @mention. This can be done by by using regular expressions. An example is given by &lt;code&gt;r'(^|\s)@(\w+)'&lt;/code&gt;, this would match all mentions like &lt;a class="mentioned-user" href="https://dev.to/someone"&gt;@someone&lt;/a&gt; and not weird cases like &lt;a href="mailto:some@One"&gt;some@One&lt;/a&gt;. &lt;br&gt;
Note that, you would have to store every mention in some form of data structure to be referenced later, probably storing it in an array. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, you would have to filter the mentions to see if they are actually present in your users table. If not, you eliminate them from the final list of users to send the notifications to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, you can pass these users to the notification service to then send the notifications via your favorite channel, either In-app, email or other media.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;Note that, if the above steps are done in the request-response cycle, it will not be very convenient as your users will be waiting for all these steps to complete before you send back a response to them. To overcome that, you can use tools such as &lt;a href="https://redis.io/"&gt;Redis&lt;/a&gt; or &lt;a href="https://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt; as a message broker and &lt;a href="https://www.fullstackpython.com/celery.html"&gt;Celery&lt;/a&gt; to perform these steps in the background.&lt;/p&gt;

&lt;p&gt;That's it, a high level overview of the implementation. Let me know if you have any questions in the comments. &lt;br&gt;
Cheers 🥂&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>codenewbie</category>
      <category>learning</category>
    </item>
    <item>
      <title>Creating a Custom Authentication Backend In Django</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Wed, 22 Jun 2022 00:08:09 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/creating-a-custom-authentication-backend-in-django-17bl</link>
      <guid>https://dev.to/amoabakelvin/creating-a-custom-authentication-backend-in-django-17bl</guid>
      <description>&lt;p&gt;You may have noticed that the built in authentication system in Django has quite some few limitations. For example, it only allows your website's users to only log in using their username and password. But in modern day websites, you might want to enable your users to be able to log in to your site using either their username or email address. If your website is for a company, you can even implement an authentication backend to make users log in using lets say a secret key.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;What is an authentication backend in django?&lt;br&gt;
An authentication backend is a python class which provides two methods for authenticating a user and also retrieving a user.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;To implement a custom authentication backend, you need to define a python class with two(2) methods. One for retrieving a user and the other for authenticating a user. The two methods are, &lt;code&gt;get_user()&lt;/code&gt; and &lt;code&gt;authenticate()&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;authenticate()&lt;/code&gt; method takes in a request object and the user credentials as parameters. It then returns a user object that matches the given credentials, if they are valid. It returns None if the credentials are not valid.&lt;br&gt;
&lt;code&gt;get_user()&lt;/code&gt; method takes a user ID as a parameter and has to return a user.&lt;/p&gt;

&lt;p&gt;In this tutorial, we are going to create a new authentication backend to allow users login using their email addresses also.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: THIS TUTORIAL ASSUMES YOU HAVE ALREADY CONFIGURED A VIRTUAL ENVIRONMENT AND ALSO CREATED A NEW DJANGO PROJECT.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's create a new django application called &lt;code&gt;account&lt;/code&gt; by running the command in your project root directory.:&lt;/p&gt;

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

python manage.py startapp account


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

&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;account&lt;/code&gt; to your installed applications.&lt;/p&gt;

&lt;p&gt;The account app should have the following directory structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3qgdtcr8dbn608d15h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3qgdtcr8dbn608d15h4.png" alt="The green dots there just mean they are untracked by git"&gt;&lt;/a&gt;&lt;br&gt;
Next, create a new file called &lt;code&gt;authentication.py&lt;/code&gt; in the account app.&lt;br&gt;
In &lt;code&gt;authentication.py&lt;/code&gt;, we add the following code:&lt;/p&gt;

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

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailAuthBackend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Custom authentication backend.

    Allows users to log in using their email address.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Overrides the authenticate method to allow users to log in using their email address.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoesNotExist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Overrides the get_user method to allow users to log in using their email address.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoesNotExist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Remember, the authenticate() method will be used to authenticate your users, and will be called when you call the authenticate() method in your view.&lt;br&gt;
In the &lt;code&gt;authenticate()&lt;/code&gt; method above, we are having the parameters request, username and password. The entered email address will be found in the username parameter and the password in the password parameter.&lt;/p&gt;

&lt;p&gt;We are using a try, except block because, fetching a user that does not exist will raise a &lt;code&gt;DoesNotExist&lt;/code&gt; error.&lt;br&gt;
We retrieve a user with the incoming email address, note that the email address must be set to &lt;code&gt;unique=True&lt;/code&gt; otherwise a &lt;code&gt;MultipleObjectsReturned&lt;/code&gt; error will be raised if more than one user has the same email address. This can be done by creating a custom user model. If you're not familier with a custom user model, let me know in the comments.&lt;/p&gt;

&lt;p&gt;Next, we're using the method, user.check_password(). This will take the password argument, hash it and then compare it with the hashed password in the database. If there is a match, it will return &lt;code&gt;True&lt;/code&gt;, else &lt;code&gt;False&lt;/code&gt;.&lt;br&gt;
In our case, if the result is True, we return the user, else we return None.&lt;br&gt;
Also, if there is no user in the database with that email address, in that case a user.DoesNotExist error will be raised. If there's no user, we return None.&lt;/p&gt;

&lt;p&gt;The get_user() method takes a user_id as an argument. It returns the user if it exists or else it returns None.&lt;/p&gt;

&lt;p&gt;Thats it, we are done with our custom authentication backend. Phew.&lt;br&gt;
But now, users will still not be able to log in using their email address. This is because, we have not told django to add our authentication backend to the list of authentication backends available. To do that we need to edit our &lt;code&gt;settings.py&lt;/code&gt; file.&lt;br&gt;
Add the following to it.&lt;/p&gt;

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

&lt;span class="n"&gt;AUTHENTICATION_BACKENDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.backends.ModelBackend&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# This is the default that allows us to log in via username
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;account.authentication.EmailAuthBackend&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, django is aware of our authentication backend.&lt;/p&gt;

&lt;p&gt;But how does django apply our authentication backend?&lt;br&gt;
When we call the &lt;code&gt;authenticate()&lt;/code&gt; method from django.contrib.auth in our view, django authenticates the user agains each of the authentication backend specified in the &lt;code&gt;AUTHENTICATION_BACKENDS&lt;/code&gt;setting. In other words, it calls the authenticate method of each of the authentication backends specified. &lt;br&gt;
Django will stop at the first backend that authenticates successfully.&lt;/p&gt;

&lt;p&gt;Go ahead and run your development server and try out your new authentication method. &lt;br&gt;
You can extend this to authenticate against whatever you wish.&lt;/p&gt;

&lt;p&gt;Thanks for reading. If you have any questions, please let me know in the comments section. And also, dont forget to follow for more tutorials.&lt;br&gt;
If you would like to request for a tutorial, let me know. Thanks and &lt;strong&gt;happy coding.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Speeding up Django Project Setup</title>
      <dc:creator>Kelvin Amoaba</dc:creator>
      <pubDate>Fri, 20 May 2022 14:36:32 +0000</pubDate>
      <link>https://dev.to/amoabakelvin/speeding-up-django-development-15lp</link>
      <guid>https://dev.to/amoabakelvin/speeding-up-django-development-15lp</guid>
      <description>&lt;p&gt;Since I’ve started to work on a lot of Django projects lately. &lt;br&gt;
I realized I was spending much time working on the configurations of the project. Such as creating a new virtual environment for each project, installing prerequisites and the likes. This shifted the time needed to build the project to rather configuring it. &lt;br&gt;
Working on a Linux machine, I decided to create a little bash script that can automate the process right from creating a new project to setting up the directory structure for the project and installing dependencies. &lt;br&gt;
Here’s a link to the project for those who might be interested. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AmoabaKelvin/django-starter/tree/v0.1.0"&gt;https://github.com/AmoabaKelvin/django-starter/tree/v0.1.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have some time to spear kindly go through it and tell me ways I can improve it. &lt;br&gt;
If you would like to contribute, I’ll be very glad. &lt;br&gt;
Also don’t forget to leave a star☺️&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
