<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-10-09T03:28:17+00:00</updated><id>/feed.xml</id><title type="html">Abdullah’s Lab</title><subtitle>My explorations, experiments, and projects.
</subtitle><entry><title type="html">When is it ok to use inheritance?</title><link href="/2025/10/08/when-is-it-ok-to-use-inheritance.html" rel="alternate" type="text/html" title="When is it ok to use inheritance?" /><published>2025-10-08T00:00:00+00:00</published><updated>2025-10-08T00:00:00+00:00</updated><id>/2025/10/08/when-is-it-ok-to-use-inheritance</id><content type="html" xml:base="/2025/10/08/when-is-it-ok-to-use-inheritance.html"><![CDATA[<p>There is a software engineering principle that suggests to:</p>
<blockquote>
  <p>Prefer inheritance over composition.</p>
</blockquote>

<p>Nah just kidding, it’s the opposite!</p>
<blockquote>
  <p>Prefer composition over inheritance.</p>
</blockquote>

<h1 id="why-inheritance-is-generally-bad">Why Inheritance is Generally Bad</h1>

<p>The reasons being that:</p>
<ul>
  <li>Inheritance introduces sneaky (hidden) behavior.</li>
  <li>Understanding deep inheritance hierarchies are difficult.</li>
  <li>Restricts flexibility in terms of mixing and matching behaviors.</li>
</ul>

<p>Let’s expand on these.</p>

<h2 id="hidden-behavior">Hidden Behavior</h2>
<p>When you are looking at the source code of a component (class in this case), and the component inherits, you are missing a bunch of hidden methods/fields. You are not looking at the full picture of the class’s data/behavior. There is a hidden repository of behavior, the base class.</p>

<p>This situation is exacerbated when the base class also has a base class and so on; in other words, <strong>when the inheritance hierarchy is deep</strong>.</p>

<p>You may think that a class is very small and cohesive when in actuality it is not.</p>

<h2 id="understanding-deep-inheritance-hierarchies-are-difficult">Understanding Deep Inheritance Hierarchies are Difficult</h2>

<p>Deep inheritance hierarhcies require you to jump around several files to understand a single class. Typically one file for each class in the inheritance chain. This makes understanding them more difficult and thus maintainance more difficult.</p>

<h2 id="restricts-flexibility">Restricts Flexibility</h2>

<p>There are well known problems with multiple inheritance (diamond inheritance problem). So if you “inherit” behavior you can only inherit it via the inheritance chain, a class cannot (reliably) “inherit” multiple behaviors by inheriting from multiple base classes.</p>

<p>This restricts your ability to mix and match behaviors in a derived class (because it can only inherit from <em>one</em> base class - reliably).</p>

<h1 id="composition-to-the-rescue">Composition to the Rescue</h1>

<p>Instead of inheriting data/behavior (fields/methods) from a base class, just use the base class through composition (delegate to it).</p>

<p>When you need to inherit just behavior (just methods), just make free functions, no need to inherit at all.</p>

<p>When you need to also inherit data, create an instance of the class and delegate to it.</p>

<p>This way, if you need to inherit data/behavior from multiple “base” classes, you just create each of them as an instance variable and delegate to them!</p>

<p>This makes all the methods of your class <em>explicit</em> (even though most of them will simply be pass through methods).</p>

<p>Speaking of which, you will get a lot of pass through methods when choosing composition over inheritance, but the idea is that these additional pass through methods are worth 1) making the behavior explicty (no hidden behaviors) and more importantly 2) <strong>allowing mix and match flexibility</strong>.</p>

<h1 id="proper-application-of-inheritance">Proper Application of Inheritance</h1>

<p>Like most things in software engineering (and in life) things are not black and white. Inheritance isn’t <em>always</em> bad, and there are times when it is the perfect tool.</p>

<p>If you have a short inheritance hierarchy (2-3 levels) it can save you a lot of pass through functions. It is well suited for situations like in a GUI frameworks where you have a base GuiElement-like class with a ton of basic functionality common to all GUI widgets.</p>

<h1 id="summary">Summary</h1>
<blockquote admonition="summary">
  <ul>
    <li>Yes, composition is generally better than inheritance.</li>
    <li>But inheritance isn’t <em>always</em> bad.
      <ul>
        <li>Keep your inheritance hierarchies <em>short</em>.</li>
      </ul>
    </li>
  </ul>
</blockquote>

<p>Have an awesome day!</p>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><summary type="html"><![CDATA[There is a software engineering principle that suggests to: Prefer inheritance over composition.]]></summary></entry><entry><title type="html">GCP IAP (Identity Aware Proxy)</title><link href="/2025/09/11/gcp-iap-identity-aware-prox.html" rel="alternate" type="text/html" title="GCP IAP (Identity Aware Proxy)" /><published>2025-09-11T00:00:00+00:00</published><updated>2025-09-11T00:00:00+00:00</updated><id>/2025/09/11/gcp-iap-identity-aware-prox</id><content type="html" xml:base="/2025/09/11/gcp-iap-identity-aware-prox.html"><![CDATA[<p>Identity Aware Proxy (IAP) is a facility GCP provides for easily adding authentication to your services.</p>

<h2 id="using-with-cloud-run">Using With Cloud Run</h2>

<p>Let’s assume you have a service running in Cloud Run. Internally a load balancer is used by Cloud Run to route traffic between different instances of your service.</p>

<pre><code class="language-mermaid">graph LR;
    A[Client] --&gt;|Request| B[Load Balancer];
    B --&gt;|Routes to| C[Cloud Run Service Instance];
</code></pre>

<p>In the settings of your Cloud Run service, you can enable IAP. When you enable this, the load balancer will now authenticate incoming requests before routing them.</p>

<pre><code class="language-mermaid">graph LR;
    A[Client] --&gt;|Request| B[Load Balancer with IAP];
    B --&gt;|Routes to| C[Cloud Run Service Instance];
</code></pre>

<p>If a request is unauthenticated, the load balancer (IAP) will respond with:</p>
<ul>
  <li><strong>If client is a browser:</strong> HTTP 302 redirecting the user to a Google sign-in page (which has query parameters to redirect back to the original URL after sign-in).</li>
  <li><strong>If client is not a browser:</strong> HTTP 401 Unauthorized.</li>
</ul>

<p>In the latter case (client is not a browser), client is expected to fill the Authorization header with a valid token.</p>

<p>You can generate a token by using the key associated with a service account that has the <code class="language-plaintext highlighter-rouge">IAP-secured Web App User</code> role (or another role with the <code class="language-plaintext highlighter-rouge">iap.httpsResourceAccessor</code> permission).</p>

<h2 id="using-with-other-services">Using With Other Services</h2>

<p>If you’re service is not running in Cloud Run, you can still enable IAP by placing your service behind google’s load balancer.</p>

<p>For example, if your service is running in a VM, you can enable a load balancer in front of it, and then enable IAP on that load balancer.</p>

<blockquote admonition="notes">
  <ul>
    <li>IAP can be used to enable authentication for your GCP services (like Cloud Run, Compute Engine, etc) without having to modify your application code.</li>
    <li>If you are using Cloud Endpoints, enable auth there, you can’t use IAP (cloud endpoints API gateway has its own auth mechanism)</li>
  </ul>
</blockquote>

<blockquote admonition="summary">
  <p>IAP is a quick and dirty way in GCP to add authentication to your services. For cloud run, just enable IAP in the console settings and it’ll be enabled in the load balancer. For other resources, first place them behind a GCP load balancer, and then enable IAP on that load balancer. For anything you want to grant access, just give the service account the <code class="language-plaintext highlighter-rouge">IAP-secured Web App User</code> role.</p>
</blockquote>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><summary type="html"><![CDATA[Identity Aware Proxy (IAP) is a facility GCP provides for easily adding authentication to your services.]]></summary></entry><entry><title type="html">Public-Private Key Cryptography Re-examined</title><link href="/2025/09/02/tls.html" rel="alternate" type="text/html" title="Public-Private Key Cryptography Re-examined" /><published>2025-09-02T00:00:00+00:00</published><updated>2025-09-02T00:00:00+00:00</updated><id>/2025/09/02/tls</id><content type="html" xml:base="/2025/09/02/tls.html"><![CDATA[<p>Let’s do a free form thought experiment to learn about some central software security concepts.</p>

<blockquote admonition="Topics Covered">
  <ul>
    <li>What “proving possession” is and how to prove it. I.e. how do you know you are talking to who you <em>think</em> you are talking to?
      <ul>
        <li>What is a “challenge”?</li>
      </ul>
    </li>
    <li>What “signing” is, how to sign something, and how to verify that someone <em>specific</em> signed something.</li>
    <li>What TLS is and how it works (including mutual TLS).
      <ul>
        <li>What a certificate authority (CA) is. How to verify certificates with a CA.</li>
      </ul>
    </li>
    <li>What HTTPS is and how it works.</li>
  </ul>
</blockquote>

<h1 id="public-private-key-pair">Public-Private Key Pair</h1>
<p>Let’s start with an axiom: anything encrypted with a public key can only be decrypted with the corresponding private key, and vice versa. We won’t get into the math (because I don’t know it lmao).</p>

<h1 id="proving-possession">Proving Possession</h1>
<p>You (A) want to establish a communication channel with some entity B. How do you verify that it is really B that you are communicating with? You have B’s public key (you know who you <em>want</em> to communicate with), you issue “him” (person claiming to be B) a challenge, and he uses his private key to solve the challenge. Now you know it’s really B.</p>

<pre caption="Sequence diagram illustrating the generic challenge-response flow."><code class="language-mermaid">sequenceDiagram
    participant A
    participant B
   
    A-&gt;&gt;B: Challenge
    B-&gt;&gt;A: Response
    Note right of B: B used his private key to solve the challenge
    A-&gt;&gt;A: Verify
    Note right of A: A verifies the challenge was correctly solved
</code></pre>

<p><strong>Essentially, someone can prove they are B by knowing something only B would know (his private key). The challenge is to prove he has the private key.</strong></p>

<p>Let’s dive in a little. There are two main ways to do this challenge. Let me explain via diagrams. Less words more diagrams :).</p>

<pre caption="One way to do a challenge."><code class="language-mermaid">sequenceDiagram
    participant A
    participant B

    A-&gt;&gt;B: Challenge
    Note right of B: A's challenge is a random string encrypted with B's public key
    B-&gt;&gt;A: Response
    Note right of B: B decrypts it with his private key, returns the original random string
    A-&gt;&gt;A: Verify
    Note right of A: A verifies he got back the same random string he sent
</code></pre>

<p admonition="key">By the way, this whole thing is called “proving possession”. This is how you can prove that someone possesses the private key corresponding to a public key.</p>

<p>Here’s a second way to do a challenge.</p>

<pre caption="Another way to do a challenge."><code class="language-mermaid">sequenceDiagram
    participant A
    participant B

    A-&gt;&gt;B: Challenge
    Note right of B: A generates a random string, Asks B to sign it with his private key
    B-&gt;&gt;A: Response
    Note right of B: B signs the random string with his private key
    A-&gt;&gt;A: Verify
    Note right of A: A decrypts the signature using B's public key, sees if original string is there
</code></pre>

<p>So, you start with a random string S, B encrypts (transforms) it with his private key into S’. You transform S’ using B’s public key and you get back S, thus possession is proven.</p>

<pre><code class="language-mermaid">graph LR
    S --&gt;|transform with B's private key| S'
    S' --&gt;|transform with B's public key| S
</code></pre>

<h1 id="signing">Signing</h1>
<p>When you want to sign a message, you create a hash of the message and then encrypt the hash with your private key. This (the encrypted hash) is called the <strong>signature</strong> of the message (it is included with the message).</p>

<p>When someone wants to verify that it was you (A) who signed it. They will take your public key and decrypt the signature. If the decrypted hash matches the hash of the message, then it was indeed you who signed it.</p>

<pre><code class="language-mermaid">graph TD
    Hash --&gt;|transform with private key| Signature
    Signature --&gt;|transform with public key| Hash'
    Hash' --&gt; C{Same as original hash?}
    C --&gt;|yes| Verified
    C --&gt;|no| NotVerified
</code></pre>

<p admonition="key">Signing a message is done with a private key. Verification is done with a public key.</p>

<h1 id="tls">TLS</h1>
<p>TLS is when you want to establish a secure communication channel over an insecure network.</p>

<p>Goes back to what we started with. If you are A and you want to talk to B. You need to verify that it is really B you are talking to (“proving possession” via a challenge).</p>

<p>Once you have verified B’s identity, you need to establish a secure communication channel. You do this by agreeing on a symmetric key (a key that both A and B know). This symmetric key is then used to encrypt all communication between A and B.</p>

<p admonition="key">A symmetric key is a key that can be used to both encrypt and decrypt a message.</p>

<p>The actual technology of the channel can be anything, though often it is a TCP connection.</p>

<h2 id="certificates-and-certificate-authorities">Certificates and Certificate Authorities</h2>
<p>One caveat - in TLS, the server presents a “certificate” to the client. This certificate contains the server’s public key (as well as some “claims”/”roles”). This certificate is signed by a 3rd party, called a certificate authority (CA).</p>

<p>You 1) verify validity of the certificate (check if it’s signed by a trusted CA) 2) verify that server identity is who is stated on the cert (the public key stated in the cert).
1 is done by verifying the signature on the certificate presented (that it is the signiture of the CA). 2 is done by a challenge.</p>

<p>The purpose of the certificate is to bind the public key to certain things like the identity, permissions, and other attributes of the entity it represents.</p>

<h1 id="mutual-tls">Mutual TLS</h1>
<p>In non mutual TLS, only one entity (generally called the “server”) is authenticated (proves identity, proves possession). In mutual TLS, both entities (the “client” and the “server”) authenticate each other.</p>

<p>You can imagine how this works. Both have certificates issues by a CA. Both exchange certificates with one another. Both verify the other’s certificate using the CA.</p>

<p admonition="key">Verifying a certificate means checking that it was signed by a CA.</p>

<h1 id="https">HTTPS</h1>
<p>HTTPS is simply HTTP over a TLS (TCP) socket. That’s it! Short and sweet :).</p>

<p admonition="key">This is the benefit of learning fundamentals well, higher level concepts barely add anything new!</p>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><category term="software security" /><summary type="html"><![CDATA[Let’s do a free form thought experiment to learn about some central software security concepts.]]></summary></entry><entry><title type="html">Finite State Machines and Various Implementations</title><link href="/2025/08/29/fsm.html" rel="alternate" type="text/html" title="Finite State Machines and Various Implementations" /><published>2025-08-29T00:00:00+00:00</published><updated>2025-08-29T00:00:00+00:00</updated><id>/2025/08/29/fsm</id><content type="html" xml:base="/2025/08/29/fsm.html"><![CDATA[<h1 id="finite-state-machine">Finite State Machine</h1>
<p>A finite state machine (FSM) has a bunch of states that it can be in, and while in a certain state, it transitions to other states based on inputs (events/actions) received while in that state.</p>

<pre><code class="language-mermaid">graph LR;
    State1 --&gt;|input| State2;
    State2 --&gt;|input| State3;
    State2 --&gt;|input2| State4;
</code></pre>

<h1 id="in-software">In Software</h1>
<p>In software, certain things can be modeled as FSMs, and when done so, makes their implementation/maintenance/extensibility significantly easier.</p>

<p>Examples include:</p>
<ul>
  <li>User interface navigation (e.g. different screens/states)</li>
  <li>Game character behavior (e.g. idle, walking, jumping)</li>
  <li>Protocols (e.g. TCP connection states)</li>
</ul>

<h1 id="gof-state-pattern">GoF State Pattern</h1>
<p>The Gang of Four (GoF) State Pattern is one implementation of a FSM in software.</p>

<p>First, identify (methods) that depend on state. This is usually input/event handlers, and <code class="language-plaintext highlighter-rouge">process()</code>/<code class="language-plaintext highlighter-rouge">update()</code> type of methods. Some examples:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">on_key_pressed()</code></li>
  <li><code class="language-plaintext highlighter-rouge">on_mouse_clicked()</code></li>
  <li><code class="language-plaintext highlighter-rouge">update(dt)</code></li>
  <li><code class="language-plaintext highlighter-rouge">on_message_received()</code></li>
</ul>

<p>Then create an interface with these methods.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">abc</span> <span class="kn">import</span> <span class="n">ABC</span><span class="p">,</span> <span class="n">abstractmethod</span>

<span class="k">class</span> <span class="nc">HeroState</span><span class="p">(</span><span class="n">ABC</span><span class="p">):</span>
    <span class="nd">@abstractmethod</span>
    <span class="k">def</span> <span class="nf">on_key_pressed</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">pass</span>

    <span class="nd">@abstractmethod</span>
    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">dt</span><span class="p">):</span>
        <span class="k">pass</span>
</code></pre></div></div>

<p>Then, have the main object hold a reference to its current state. It should delegate state-dependent methods to its current state.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Hero</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="k">def</span> <span class="nf">on_key_pressed</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">.</span><span class="nf">on_key_pressed</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">dt</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">dt</span><span class="p">)</span>
</code></pre></div></div>

<p>Generally, you want each State to have an <code class="language-plaintext highlighter-rouge">enter()</code> and <code class="language-plaintext highlighter-rouge">exit()</code> method to initialize/cleanup when that state is entered or exited.</p>

<p>You also usually want the Context class (Hero) to have a <code class="language-plaintext highlighter-rouge">set_state()</code> method. When a particular State, wants to change the state of the Context, it can call <code class="language-plaintext highlighter-rouge">set_state()</code> on the context. Obviously, this means each State needs a reference to the Context.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">HeroState</span><span class="p">(</span><span class="n">ABC</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">context</span><span class="p">:</span> <span class="n">Hero</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_context</span> <span class="o">=</span> <span class="n">context</span>

    <span class="nd">@abstractmethod</span>
    <span class="k">def</span> <span class="nf">enter</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">pass</span>

    <span class="nd">@abstractmethod</span>
    <span class="k">def</span> <span class="nf">exit</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">pass</span>

    <span class="nd">@abstractmethod</span>
    <span class="k">def</span> <span class="nf">on_key_pressed</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">pass</span>

    <span class="nd">@abstractmethod</span>
    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">dt</span><span class="p">):</span>
        <span class="k">pass</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Hero</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="k">def</span> <span class="nf">set_state</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">state</span><span class="p">:</span> <span class="n">HeroState</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">:</span>
            <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">.</span><span class="nf">exit</span><span class="p">()</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span> <span class="o">=</span> <span class="n">state</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">.</span><span class="nf">enter</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">on_key_pressed</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">.</span><span class="nf">on_key_pressed</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">dt</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">_state</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">dt</span><span class="p">)</span>
</code></pre></div></div>

<p>In GoF State Pattern, you encapsulate the data/behavior of each state in its own class.</p>

<h1 id="further-reading">Further Reading</h1>
<p>This article was based on <a href="https://gameprogrammingpatterns.com/state.html">game programming patterns - state</a></p>]]></content><author><name>Abdullah</name></author><category term="computer science" /><category term="software engineering" /><summary type="html"><![CDATA[Finite State Machine A finite state machine (FSM) has a bunch of states that it can be in, and while in a certain state, it transitions to other states based on inputs (events/actions) received while in that state.]]></summary></entry><entry><title type="html">Deploying Your Service to Cloud Run</title><link href="/2025/08/28/cloud-run.html" rel="alternate" type="text/html" title="Deploying Your Service to Cloud Run" /><published>2025-08-28T00:00:00+00:00</published><updated>2025-08-28T00:00:00+00:00</updated><id>/2025/08/28/cloud-run</id><content type="html" xml:base="/2025/08/28/cloud-run.html"><![CDATA[<p>Here’s how you deploy your service to cloud run (and then have it use a Cloud Endpoint API Gateway).</p>

<h1 id="create-a-basic-service">Create a Basic Service</h1>
<p>Let’s say you have a basic service with some endpoints.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">flask</span> <span class="kn">import</span> <span class="n">Flask</span>

<span class="n">app</span> <span class="o">=</span> <span class="nc">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>

<span class="nd">@app.route</span><span class="p">(</span><span class="sh">'</span><span class="s">/hello</span><span class="sh">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
    <span class="k">return</span> <span class="sh">'</span><span class="s">Hello, World!</span><span class="sh">'</span>

<span class="nd">@app.route</span><span class="p">(</span><span class="sh">'</span><span class="s">/goodbye</span><span class="sh">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">goodbye</span><span class="p">():</span>
    <span class="k">return</span> <span class="sh">'</span><span class="s">Goodbye, World!</span><span class="sh">'</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">'</span><span class="s">__main__</span><span class="sh">'</span><span class="p">:</span>
    <span class="n">app</span><span class="p">.</span><span class="nf">run</span><span class="p">()</span>
</code></pre></div></div>

<h1 id="basic-deploy">Basic Deploy</h1>
<p>You can deploy your service to Cloud Run by running the following command:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcloud run deploy <span class="nt">--image</span> gcr.io/PROJECT_ID/IMAGE_NAME <span class="nt">--platform</span> managed <span class="nt">--concurrency</span> 20 <span class="nt">--allow-unauthenticated</span>
</code></pre></div></div>

<p>Where:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">--image</code> specifies the docker image of your service.</li>
  <li><code class="language-plaintext highlighter-rouge">--platform managed</code> tells GCP to automatically scale the number of instances based on volume of requests.</li>
  <li><code class="language-plaintext highlighter-rouge">--concurrency</code> specifies the max number of concurrent requests each instance should handle. GCP will spin a new instance if the number of requests exceeds this limit. Defaults to 80.</li>
  <li><code class="language-plaintext highlighter-rouge">--allow-unauthenticated</code> allows unauthenticated access to your service.</li>
</ul>

<p>You can optionally add <code class="language-plaintext highlighter-rouge">--region REGION</code> to deploy to a specific region.</p>

<p>This command returns a URL for your deployed service, which you can use to access it via HTTP.</p>

<h1 id="adding-api-gateway-cloud-endpoints">Adding API Gateway (Cloud Endpoints)</h1>

<p>Create an OpenAPI spec for Cloud Endpoints.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">swagger</span><span class="pi">:</span> <span class="s1">'</span><span class="s">2.0'</span>
<span class="na">info</span><span class="pi">:</span>
  <span class="na">title</span><span class="pi">:</span> <span class="s">My Service</span>
  <span class="na">description</span><span class="pi">:</span> <span class="s">My Service API</span>
  <span class="na">version</span><span class="pi">:</span> <span class="s">1.0.0</span>
<span class="na">host</span><span class="pi">:</span> <span class="s">YOUR_API_GATEWAY_HOST</span>
<span class="na">x-google-endpoints</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">YOUR_API_GATEWAY_HOST</span>
    <span class="na">allowCors</span><span class="pi">:</span> <span class="kc">true</span>
<span class="na">paths</span><span class="pi">:</span>
  <span class="na">/hello</span><span class="pi">:</span>
    <span class="na">get</span><span class="pi">:</span>
      <span class="na">summary</span><span class="pi">:</span> <span class="s">Hello World</span>
      <span class="na">operationId</span><span class="pi">:</span> <span class="s">hello</span>
      <span class="na">responses</span><span class="pi">:</span>
        <span class="s1">'</span><span class="s">200'</span><span class="err">:</span>
          <span class="na">description</span><span class="pi">:</span> <span class="s">A successful response</span>
          <span class="na">schema</span><span class="pi">:</span>
            <span class="na">type</span><span class="pi">:</span> <span class="s">string</span>
  <span class="na">/goodbye</span><span class="pi">:</span>
    <span class="na">get</span><span class="pi">:</span>
      <span class="na">summary</span><span class="pi">:</span> <span class="s">Goodbye World</span>
      <span class="na">operationId</span><span class="pi">:</span> <span class="s">goodbye</span>
      <span class="na">responses</span><span class="pi">:</span>
        <span class="s1">'</span><span class="s">200'</span><span class="err">:</span>
          <span class="na">description</span><span class="pi">:</span> <span class="s">A successful response</span>
          <span class="na">schema</span><span class="pi">:</span>
            <span class="na">type</span><span class="pi">:</span> <span class="s">string</span>
</code></pre></div></div>

<p>“Deploy” your API spec to cloud endpoints:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcloud endpoints services deploy OPENAPI_SPEC.yaml
</code></pre></div></div>

<p>Deploy ESP (proxy HTTP server) to Cloud Run (in front of your service, which is also running in a Cloud Run instance):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcloud run deploy espv2-gateway \
  --image=gcr.io/endpoints-release/endpoints-runtime:latest \
  --args="--config=/etc/endpoints/OPENAPI_SPEC.yaml,--backend=https://YOUR_CLOUD_RUN_URL" \ # &lt;-- the URL of your service
  --platform managed \
  --allow-unauthenticated \
  --region REGION
</code></pre></div></div>

<p>This returns the URL of the ESP (proxy HTTP server), which is what you should ask clients to use when accessing your API.</p>

<h1 id="adding-authentication">Adding Authentication</h1>

<p>In your OpenAPI spec, specify that authentication is required and the type(s) of authentication.</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">securityDefinitions</span><span class="pi">:</span>
    <span class="na">api_key</span><span class="pi">:</span>
        <span class="na">type</span><span class="pi">:</span> <span class="s2">"</span><span class="s">apiKey"</span>
        <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">key"</span>
        <span class="na">in</span><span class="pi">:</span> <span class="s2">"</span><span class="s">query"</span>
    <span class="na">firebase_auth</span><span class="pi">:</span>
        <span class="na">type</span><span class="pi">:</span> <span class="s2">"</span><span class="s">oauth2"</span>
        <span class="na">flow</span><span class="pi">:</span> <span class="s2">"</span><span class="s">implicit"</span>
        <span class="na">authorizationUrl</span><span class="pi">:</span> <span class="s2">"</span><span class="s">https://your-auth-server.com/auth"</span> <span class="c1"># documentation purpose only, clients must know this themselves</span>
        <span class="na">x-google-issuer</span><span class="pi">:</span> <span class="s2">"</span><span class="s">https://your-auth-server.com/"</span>
        <span class="na">x-google-jwks_uri</span><span class="pi">:</span> <span class="s2">"</span><span class="s">https://your-auth-server.com/.well-known/jwks.json"</span>
        <span class="na">x-google-audiences</span><span class="pi">:</span> <span class="s2">"</span><span class="s">https://your-auth-server.com/"</span>
<span class="na">paths</span><span class="pi">:</span>
    <span class="na">/api/hello</span><span class="pi">:</span>
        <span class="na">get</span><span class="pi">:</span>
            <span class="na">security</span><span class="pi">:</span>
                <span class="pi">-</span> <span class="na">api_key</span><span class="pi">:</span> <span class="pi">[]</span>
    <span class="na">/api/goodbye</span><span class="pi">:</span>
        <span class="na">get</span><span class="pi">:</span>
            <span class="na">security</span><span class="pi">:</span>
                <span class="pi">-</span> <span class="na">api_key</span><span class="pi">:</span> <span class="pi">[]</span>
                <span class="pi">-</span> <span class="na">firebase_auth</span><span class="pi">:</span> <span class="pi">[]</span>
</code></pre></div></div>

<p>Redeploy your service in cloud run but be sure to <strong>not</strong> specify <code class="language-plaintext highlighter-rouge">--allow-unauthenticated</code>.</p>

<h1 id="diagrams">Diagrams</h1>
<p>Here are some diagrams that visually depict this “architecture”.</p>

<p>An API Gateway (ESP) sits between your clients and your service. Note that ESP is also running in cloud run:</p>

<pre><code class="language-mermaid">flowchart LR
    Client[Client]
    ESP[ESP]
    Service[Service]

    Client --&gt; ESP --&gt; Service
</code></pre>

<p>The ESP just forwards requests from clients to the service:</p>

<pre><code class="language-mermaid">sequenceDiagram
    participant Client
    participant ESP as ESP
    participant Service

    Client-&gt;&gt;ESP: HTTP Request e.g., /hello
    ESP-&gt;&gt;Service: Forwarded Request
    Service--&gt;&gt;ESP: Response
    ESP--&gt;&gt;Client: Response
</code></pre>

<p>If you have setup your ESP to authenticate (via the OpenAPI spec of your API), here is how authentication flow happens:</p>

<pre><code class="language-mermaid">sequenceDiagram
    participant Client
    participant ESP as ESP
    participant Service

    Client-&gt;&gt;ESP: HTTP Request e.g., /hello
    ESP-&gt;&gt;ESP: Validate Token Using public Key
    alt Token Valid
        ESP-&gt;&gt;Service: Forwarded Request
        Service--&gt;&gt;ESP: Response
        ESP--&gt;&gt;Client: Response
    else Token Invalid or Missing
        ESP--&gt;&gt;Client: 401 Unauthorized
    end
</code></pre>

<p>If token is missing/invalid, it is the job of the client to redirect to the identity provider, get a token, and try the HTTP request again:</p>

<pre><code class="language-mermaid">sequenceDiagram
    participant Client
    participant Auth as Auth Server

    Client-&gt;&gt;Auth: Redirect for Token
    Auth--&gt;&gt;Client: Token
    Client-&gt;&gt;ESP: HTTP Request e.g., /hello
</code></pre>

<h1 id="summary">Summary</h1>

<blockquote admonition="summary">
  <p>Basic (no authentication):</p>
  <ol>
    <li>Upload the docker image of your service to Google’s artifact registry.</li>
    <li><code class="language-plaintext highlighter-rouge">gcloud run deploy</code> your service to deploy it in cloud run; you get back a URL to access it through.</li>
  </ol>

  <p>With Authentication:</p>
  <ol>
    <li>Create an OpenAPI spec for your API, specifying the authentication methods you want to support (token-based, external identity provider, etc.)</li>
    <li><code class="language-plaintext highlighter-rouge">gcloud run deploy</code> your service to deploy it in cloud run; you get back a URL to access it through, don’t provide this to clients.</li>
    <li><code class="language-plaintext highlighter-rouge">gcloud endpoints services deploy</code> your OpenAPI spec to create/update the API config.</li>
    <li><code class="language-plaintext highlighter-rouge">gcloud run deploy</code> your ESP (proxy) service to Cloud Run. You’ll need to specify the URL of your service as the target of the proxy.</li>
  </ol>
</blockquote>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><summary type="html"><![CDATA[Here’s how you deploy your service to cloud run (and then have it use a Cloud Endpoint API Gateway).]]></summary></entry><entry><title type="html">Token Based Authentication With External Identity Provider (3PO)</title><link href="/2025/08/26/identity-providers.html" rel="alternate" type="text/html" title="Token Based Authentication With External Identity Provider (3PO)" /><published>2025-08-26T00:00:00+00:00</published><updated>2025-08-26T00:00:00+00:00</updated><id>/2025/08/26/identity-providers</id><content type="html" xml:base="/2025/08/26/identity-providers.html"><![CDATA[<p>Here is how your service can authenticate requests using tokens issued by an external identity provider:</p>

<pre><code class="language-mermaid">sequenceDiagram
    participant Client
    participant Server
    participant IdentityProvider

    Client-&gt;&gt;Server: Request without token
    Server--&gt;&gt;Client: 401 Unauthorized, redirect to IdentityProvider
    Client-&gt;&gt;IdentityProvider: Login
    IdentityProvider--&gt;&gt;Client: JWT Token
    Client-&gt;&gt;Server: Request with token
    Note right of Server: Server verifies token signature using public key from IdentityProvider
    alt Token valid
        Server--&gt;&gt;Client: Access granted
    else Token invalid
        Server--&gt;&gt;Client: 401 Unauthorized
    end
</code></pre>

<p>This is also refered to as “third-party authentication” (3PO).</p>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><category term="software security" /><summary type="html"><![CDATA[Here is how your service can authenticate requests using tokens issued by an external identity provider:]]></summary></entry><entry><title type="html">Unit Tests Should Only Break If Class Under Test Breaks</title><link href="/2025/08/18/unit-test-should-only-break-if-class-under-test-breaks.html" rel="alternate" type="text/html" title="Unit Tests Should Only Break If Class Under Test Breaks" /><published>2025-08-18T00:00:00+00:00</published><updated>2025-08-18T00:00:00+00:00</updated><id>/2025/08/18/unit-test-should-only-break-if-class-under-test-breaks</id><content type="html" xml:base="/2025/08/18/unit-test-should-only-break-if-class-under-test-breaks.html"><![CDATA[<p>This’ll be a short one.</p>

<h1 id="bluf-unit-tests-should-only-break-if-class-under-test-breaks">BLUF: Unit Tests Should Only Break If Class Under Test Breaks</h1>

<p>Unit tests should only break if the class under test breaks, <strong>not if one of its dependencies breaks</strong>.</p>

<p>When you see a unit test failing, assume that the code/logic of the class under test is failing, not the code/logic of one of its dependencies (assuming the unit tests were witten properly).</p>

<p>How do you ensure that your unit test only fails if the class under test fails? Simple: <strong>mock/fake its dependencies</strong>.</p>

<p>How you should mock/fake (and which you should use) depends on that particular <em>test case</em>. Assume a particular test case and a particular dependency.</p>

<h1 id="class-to-dependency-communication">Class to Dependency Communication</h1>
<p>If in that particular test case, and for that particular dependency, communication is only from the class under test to the the dependency, i.e., the class under test calls the dependency’s methods, not the other way around, use a mock. Mock the dependency and assert the correct methods were called with the correct type/values. Simple.</p>

<h1 id="dependency-to-class-communication">Dependency to Class Communication</h1>
<p>If the dependency needs to communicate with the class under test, use a fake.</p>

<p>A fake is a lightweight implementation of the dependency that behaves like the real one but is easier to control and set up for testing. It also only implements methods/functionality that is needed <em>for that test case</em>!</p>

<h1 id="example">Example</h1>
<p>In python, you can easily create fakes that have certain attributes mocked! This allows creating fakes extremely easily.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">pytest</span>
<span class="kn">from</span> <span class="n">unittest.mock</span> <span class="kn">import</span> <span class="n">MagicMock</span>

<span class="k">class</span> <span class="nc">Publisher</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">subscribers</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">subscribe</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">subscriber</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">subscribers</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">subscriber</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">notify</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">subscriber</span> <span class="ow">in</span> <span class="n">self</span><span class="p">.</span><span class="n">subscribers</span><span class="p">:</span>
            <span class="nf">subscriber</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">FakeWebsocketServer</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">on_client_connected</span> <span class="o">=</span> <span class="nc">Publisher</span><span class="p">()</span> <span class="c1"># faked
</span>        <span class="n">self</span><span class="p">.</span><span class="n">on_client_disconnected</span> <span class="o">=</span> <span class="nc">Publisher</span><span class="p">()</span> <span class="c1"># faked
</span>        <span class="n">self</span><span class="p">.</span><span class="n">on_message_received</span> <span class="o">=</span> <span class="nc">Publisher</span><span class="p">()</span> <span class="c1"># faked
</span>
        <span class="n">self</span><span class="p">.</span><span class="n">broadcast</span> <span class="o">=</span> <span class="nc">MagicMock</span><span class="p">()</span> <span class="c1"># mocked
</span>
<span class="k">def</span> <span class="nf">test_lockstep_server_sends_welcome_message_when_client_connects</span><span class="p">():</span>
    <span class="n">websocket</span> <span class="o">=</span> <span class="nc">FakeWebsocketServer</span><span class="p">()</span>
    <span class="n">lockstep</span> <span class="o">=</span> <span class="nc">LockstepServer</span><span class="p">(</span><span class="n">websocket</span><span class="p">)</span>

    <span class="c1"># simulate client connecting ("message" going from dependency to class under test)
</span>    <span class="n">websocket</span><span class="p">.</span><span class="n">on_client_connected</span><span class="p">.</span><span class="nf">notify</span><span class="p">(</span><span class="sh">"</span><span class="s">client1</span><span class="sh">"</span><span class="p">)</span>

    <span class="c1"># assert that the lockstep server sent a welcome message
</span>    <span class="n">websocket</span><span class="p">.</span><span class="n">broadcast</span><span class="p">.</span><span class="nf">assert_called_once_with</span><span class="p">(</span><span class="sh">"</span><span class="s">Welcome client1!</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>

<p>In the above example:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">FakeWebsocketServer</code> is a fake WebsocketServer implementation.</li>
  <li>It has some fake implementations and some mocked.</li>
  <li>The events <code class="language-plaintext highlighter-rouge">on_client_connected</code>, <code class="language-plaintext highlighter-rouge">on_client_disconnected</code>, and <code class="language-plaintext highlighter-rouge">on_message_received</code> are faked, because our class under test listens to these events, so they need actual subscribe methods and when we emit events on them, we need to ensure the class under test receives the emitted events.</li>
  <li>The <code class="language-plaintext highlighter-rouge">broadcast</code> method is mocked, because we just have to ensure this is called.</li>
</ul>

<h1 id="integration-tests">Integration Tests</h1>
<p>To reiterate, unit tests should only break if the class under test breaks, not one of its dependencies.</p>

<p>If you want tests that check whether multiple classes work together correctly, write integration tests.</p>

<p>Generally keep these seperate from your unit tests, something like:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/src
/tests
    /unit
    /integration
</code></pre></div></div>

<h1 id="summary">Summary</h1>
<ul admonition="summary">
  <li>Unit tests should only break if the class under test breaks.</li>
  <li>Mock dependencies when the class under test only calls their methods.</li>
  <li>Use fakes when the dependency needs to call back into the class under test.</li>
</ul>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><summary type="html"><![CDATA[This’ll be a short one.]]></summary></entry><entry><title type="html">Clock Drift and Computing Client Offset</title><link href="/2025/08/13/computing-client-offset.html" rel="alternate" type="text/html" title="Clock Drift and Computing Client Offset" /><published>2025-08-13T00:00:00+00:00</published><updated>2025-08-13T00:00:00+00:00</updated><id>/2025/08/13/computing-client-offset</id><content type="html" xml:base="/2025/08/13/computing-client-offset.html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>In lockstep multiplayer games, all clients must start executing the simulation <strong>at the same exact time</strong>. Once the server has connected with the expected number of clients, it will broadcast a “start executing the simulation at time t” message to all the clients. Each client may receive this message at a different time, but ultimately they will all start the simulation at the same exact time.</p>

<p>This sounds a bit easier than it is (thought it ain’t <em>that</em> hard).</p>

<h1 id="naive-solution">Naive Solution</h1>
<p>The immediate solution that may have popped into your head is to use some universal measure of time (agnostic of timezone). That way, all clients, irrespective of their local time, could start the simulation simultaneously. However, the problem with this is that the clock on each client may be slightly out of sync (by milliseconds) due to <strong>clock drift</strong>.</p>

<h1 id="clock-drift">Clock Drift</h1>
<p>Timers in hardware usually have an oscillating crystal that is used to keep track of how much time has passed. The crystal oscillates at some known frequency (say 32.768 kHz for a typical crystal), and the number of oscillations is counted to measure passage of time. The problem is, that the frequency of oscillation is not perfect (i.e. not <em>exactly</em> 32.768 kHz), there is some margin of error. This means that two timers over time will drift apart and begin showing different times. How fast they drift depends on the margin of error in their crystals.</p>

<h1 id="time-syncing">Time Syncing</h1>
<p>If this is true, why is it your phone and computer time don’t keep on drifting apart until they show different minutes? Because both devices periodically synchronize their clocks with a more accurate time source, such as an NTP (Network Time Protocol) server. The more frequently two devices sync with a common time source, the less drift they experience.</p>

<h1 id="time-syncing-is-not-good-enough-for-multiplayer-games">Time Syncing is not Good Enough for Multiplayer Games</h1>
<p>In multiplayer games, you are dealing with extremely tight/sensitive timing constraints. If you’re lockstep simulating at 60 ticks per second, that means you only have about 1/60 or 16 milliseconds per tick. With common PC timer crystals, two computers can drift about 20 ms in 10 minutes (if they don’t sync with a common time source during that time).</p>

<p>So, we have to find a way to deal with, to “cancel out”, this clock drift. In other words, we have to find a way to <em>measure</em> the clock drift between two devices (so that we can compensate for it).</p>

<h1 id="computing-client-offset">Computing Client Offset</h1>
<p>The difference between two device’s timers is called an offset. For our two devices, let’s consider a server and a client.</p>

<p>You send a message from the client to the server, which sends a message back to the client. We’ll record time at each point.</p>

\[\text{client } (t_0) \longrightarrow \text{server } (t_1) \\
	\text{client } (t_3) \longleftarrow \text{server } (t_2)\]

<ul>
  <li>\(t_0\) is the time when the client sends the message (in client time)</li>
  <li>\(t_1\) is the time when the server receives the message (in server time)</li>
  <li>\(t_2\) is the time when the server sends the response (in server time)</li>
  <li>\(t_3\) is the time when the client receives the response (in client time)</li>
</ul>

<p>Assume \(\theta\) is the offset between the server and the client, meaning (all equivalent):</p>

\[t_s - t_c = \theta\]

\[t_s = t_c + \theta\]

\[t_c = t_s - \theta\]

<p>Where:</p>
<ul>
  <li>\(t_c\) is the time on the client</li>
  <li>\(t_s\) is the time on the server</li>
  <li>\(\theta\) is the offset between the server and the client</li>
</ul>

<p>Server’s receive time in <em>client frame</em> is:</p>

\[t_1 - \theta\]

<p>Thus uplink time (time for packet to go from client to server) is:</p>

\[(t_1 - \theta) - t_0\]

<p>Server’s send time in <em>client frame</em> is:</p>

\[t_2 - \theta\]

<p>Thus downlink time is:</p>

\[t_3 - (t_2 - \theta)\]

<p>If we assume that the the network is “symmetric” (uplink time is equal to downlink time):</p>

\[(t_1 - \theta) - t_0 = t_3 - (t_2 - \theta)\]

<p>Let’s simplify:</p>

\[t_1 - \theta - t_0 = t_3 - t_2 + \theta\]

<p>Rearrange to solve for theta:</p>

\[t_1 - t_0 - t_3 + t_2 = 2\theta\]

<p>Thus:</p>

\[\theta = \frac{(t_1 - t_0) - (t_2 - t_3)}{2}\]

<h1 id="conclusion">Conclusion</h1>
<p>To find offset (theta) between the client and the server, we send RTT packets (Round Trip Time packets) and use the timestamps to compute the offset. We keep doing this for several packets and take the median (to avoid outliers).</p>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><category term="math" /><summary type="html"><![CDATA[Introduction In lockstep multiplayer games, all clients must start executing the simulation at the same exact time. Once the server has connected with the expected number of clients, it will broadcast a “start executing the simulation at time t” message to all the clients. Each client may receive this message at a different time, but ultimately they will all start the simulation at the same exact time.]]></summary></entry><entry><title type="html">Balancing Planning and Execution in Personal Projects</title><link href="/2025/07/07/balancing-planning-and-execution-in-personal-projects.html" rel="alternate" type="text/html" title="Balancing Planning and Execution in Personal Projects" /><published>2025-07-07T00:00:00+00:00</published><updated>2025-07-07T00:00:00+00:00</updated><id>/2025/07/07/balancing-planning-and-execution-in-personal-projects</id><content type="html" xml:base="/2025/07/07/balancing-planning-and-execution-in-personal-projects.html"><![CDATA[<p>For my personal projects, I often find myself jumping straight into coding instead of doing much brainstorming or planning.</p>

<p>This “jump into code” approach has its benefits, but also its downfalls, but those downfalls can be mitigated by following certain habits.</p>

<h1 id="-benefits">🎉 Benefits</h1>
<p>Often, you have a lot of <strong>initial excitement</strong> when you first think of an idea. Jumping right into the code allows you to leverage that excitement/motivation to make progress quickly.</p>

<p>This allows you to <strong>quickly see what works, what doesn’t, what is fun, and what isn’t</strong>.</p>

<h1 id="️-downfalls">⚠️ Downfalls</h1>
<p>The main problem I face with this wild west approach is that <strong>I often lose focus on priorities</strong>. I end up implementing nice-to-haves instead of core features.</p>

<p>The other issue is when I take a break for a few days, <strong>I forget what I was doing, and what I should do next</strong>. I also have to re-read/skim the code to understand high level design/architecture, and “how it works”. I really think I can benefit from some visuals about high level design/architecture/how-it-works, especially after breaks.</p>

<h1 id="️-mitigation">🛠️ Mitigation</h1>
<p>Just to re-iterate, <strong>I still want to follow the low planning, high execution approach</strong>, but I want to mitigate the downfalls stated above.</p>

<h2 id="-do-a-5-15-minute-planning-session">📝 Do a 5-15 Minute Planning Session</h2>
<p>In order to mitigate the “losing focus on priorities” problem, <strong>I will spend about 5-15 minutes planning</strong> before I start the project, I’ll write down:</p>
<ul>
  <li>Overall, one statement <strong>goal of the project</strong>. E.g. “A tool that gives you visual context as you browse your codebase.”</li>
  <li>The <strong>core features</strong> that I want to implement.</li>
  <li><strong>Questions I may have</strong>. This is to try to illicit risks early on. What are the different approaches to do X? What libraries are available?</li>
  <li>The <strong>nice-to-haves</strong> that I can implement later.</li>
</ul>

<p>Remember, <strong>you should only spend 5-15 minutes on this</strong>. You will get it wrong, but that is okay. It’ll still help a lot.</p>

<h2 id="️-write-brief-note-before-ending-each-session">🗒️ Write Brief Note Before Ending Each Session</h2>
<p>To mitigate the “forgetting what I was doing” problem, <strong>I will jot down a note before the end of each session explaining what I was working on, and what I should do next</strong>. I can write this note in a sticky, or if I am using a lightweight kanban, I can write it as a comment on the card I’m currently working on.</p>

<h2 id="️-write-high-level-designarchitecturehow-it-works">🏗️ Write High Level Design/Architecture/How-It-Works</h2>
<p>In order to mitigate the “needing to re-read/skim the code to understand it” problem, I have a few ideas.</p>

<p>For one, <strong>I can write a high level design description, a “how it works” in the README</strong> and maybe include a hastily drawn diagram.</p>

<p>I can also <strong>leverage AI each time I need to re-understand the code</strong>. Especially for small codebases, which most personal projects are, I can pass the entire codebase to the AI (or at least the entire repo map) and ask it to explain me the high level design and data flow.</p>

<p>Sometimes I don’t need diagrams, I can just explain with words, but I need to ensure that I use formatting (headings, bold, <strong>frequent blank lines</strong>), structure, and even emojis to make it more engaging (for myself) to read. Just staring at a wall of text is hard. I want to emphasize the importance of frequent blank lines. It makes it much easier for me to read.</p>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><summary type="html"><![CDATA[For my personal projects, I often find myself jumping straight into coding instead of doing much brainstorming or planning.]]></summary></entry><entry><title type="html">Common Race Conditions in Async/Await Code</title><link href="/2025/07/06/async-await-race-conditions.html" rel="alternate" type="text/html" title="Common Race Conditions in Async/Await Code" /><published>2025-07-06T00:00:00+00:00</published><updated>2025-07-06T00:00:00+00:00</updated><id>/2025/07/06/async-await-race-conditions</id><content type="html" xml:base="/2025/07/06/async-await-race-conditions.html"><![CDATA[<p>In this article, we’ll briefly compare async/await implementations in Python with C#, and then discuss common race conditions that still occur even when using async/await.</p>

<h1 id="asyncawait-in-python-vs-c">Async/Await in Python vs C#</h1>
<p>In Python, all coroutines are run a single thread (the event loop thread), which means that there is absolutely no risk of <strong>data races</strong> (of course, there is still the risk of other <strong>race conditions</strong>, which we’ll talk about later).</p>

<p>In C#, different coroutines may run simultaneously on different threads. This is because coroutines in C# run in a thread pool. So you <em>can</em> have data races.</p>

<h1 id="common-race-conditions">Common Race Conditions</h1>
<p>Let’s assume you are using async/await in an environment where you can’t have data race. What are race conditions that can still occur? These are basically all race conditions that are not data races lol. Let’s go over some of the most common, so that you can recognize/avoid them in your async/await code.</p>

<h2 id="check-then-act">Check-then-Act</h2>
<p>This is when you check a condition, and then act, but in between the check and the act, the condition may have changed (by another coroutine).</p>

<p>Here’s a classical bank account example:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">async</span> <span class="k">def</span> <span class="nf">withdraw</span><span class="p">(</span><span class="n">account</span><span class="p">,</span> <span class="n">amount</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">account</span><span class="p">.</span><span class="n">balance</span> <span class="o">&gt;=</span> <span class="n">amount</span><span class="p">:</span>  <span class="c1"># Check
</span>        <span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>  <span class="c1"># Yield control to the event loop (other coroutines may run here)
</span>        <span class="n">account</span><span class="p">.</span><span class="n">balance</span> <span class="o">-=</span> <span class="n">amount</span> 

<span class="n">account</span><span class="p">.</span><span class="n">balance</span> <span class="o">=</span> <span class="mi">120</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">gather</span><span class="p">(</span><span class="nf">withdraw</span><span class="p">(</span><span class="n">account</span><span class="p">,</span> <span class="mi">100</span><span class="p">),</span> <span class="nf">withdraw</span><span class="p">(</span><span class="n">account</span><span class="p">,</span> <span class="mi">100</span><span class="p">))</span> <span class="c1"># may succeed and leave account.balance = -80
</span></code></pre></div></div>

<p>Two coroutines can both get past the check, withdraw money, and you may end up with a negative balance.</p>

<p>To avoid this, make sure both the check and the act are done atomically. You can do this either by not putting an <code class="language-plaintext highlighter-rouge">await</code> between them, or by using a lock (asyncio.Lock in Python).</p>

<h2 id="read-modify-write">Read-Modify-Write</h2>
<p>This is when you read a value, modify it, and then write it back. If another coroutine modifies the value in between the read and the write, you may end up with an incorrect value.</p>

<p>Here’s an example:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">async</span> <span class="k">def</span> <span class="nf">increment</span><span class="p">(</span><span class="n">counter</span><span class="p">):</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">counter</span><span class="p">.</span><span class="n">value</span>  <span class="c1"># Read
</span>    <span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>  <span class="c1"># Yield
</span>    <span class="n">counter</span><span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span> <span class="o">+</span> <span class="mi">1</span>  <span class="c1"># Write
</span>
<span class="n">counter</span><span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">gather</span><span class="p">(</span><span class="nf">increment</span><span class="p">(</span><span class="n">counter</span><span class="p">),</span> <span class="nf">increment</span><span class="p">(</span><span class="n">counter</span><span class="p">))</span>  <span class="c1"># may end up with counter.value = 1
</span></code></pre></div></div>

<p>Again, to avoid this, you can either not yield control between the read and the write, or use a lock.</p>

<h2 id="event-ordering-dependencies">Event Ordering Dependencies</h2>
<p>This is when you are depending on the order of execution of your coroutines. The problem is, in Python, this order is not guaranteed.</p>

<p>The best solution here is to avoid depending on the order of execution of coroutines. If you must, you can use <code class="language-plaintext highlighter-rouge">asyncio.Event</code> to signal when a coroutine has completed its work, and then wait for that event in the other coroutines.</p>

<h2 id="lock-starvation">Lock Starvation</h2>
<p>This is when a coroutine is waiting for a lock, but other coroutines keep acquiring the lock. In Python (and in underlying Operating Systems), lock acquiring is not fair, meaning that the one waiting the longest may not be the one to acquire the lock next. Thus anytime you use a lock, you should be aware of the possibility of starvation.</p>

<h1 id="javascript-note">Javascript Note</h1>
<p>Both Python and Javascript use a single-threaded event loop for async/io, so in Javascript as well, you don’t have to worry about <strong>data races</strong>.</p>]]></content><author><name>Abdullah</name></author><category term="software engineering" /><summary type="html"><![CDATA[In this article, we’ll briefly compare async/await implementations in Python with C#, and then discuss common race conditions that still occur even when using async/await.]]></summary></entry></feed>