<?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>Forem: John Eliud Odhiambo</title>
    <description>The latest articles on Forem by John Eliud Odhiambo (@johneliud).</description>
    <link>https://forem.com/johneliud</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%2F1459938%2F57cf98f3-ee3a-432e-9d06-b280c4f141d8.jpg</url>
      <title>Forem: John Eliud Odhiambo</title>
      <link>https://forem.com/johneliud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/johneliud"/>
    <language>en</language>
    <item>
      <title>A Story About Pluralization In Code (2 Items vs 2 Boxes)</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Mon, 05 Jan 2026 13:20:47 +0000</pubDate>
      <link>https://forem.com/johneliud/a-story-about-pluralization-in-code-2-items-vs-2-boxes-371g</link>
      <guid>https://forem.com/johneliud/a-story-about-pluralization-in-code-2-items-vs-2-boxes-371g</guid>
      <description>&lt;p&gt;I was building a small console application. A simple cart. It was nothing fancy but a chance to experiment with input, calculations, and formatted output. Here’s the first version I wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.Scanner;

public class Cart {
    static void cart() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter item name: ");
        String item = scanner.nextLine();

        System.out.print("Enter price for each: ");
        double price = scanner.nextDouble();

        if (price &amp;lt;= 0) {
            throw new IllegalArgumentException("Price must be positive.");
        }

        System.out.print("Enter quantity to buy: ");
        int quantity = scanner.nextInt();

        if (quantity &amp;lt;= 0) {
            throw new IllegalArgumentException("Quantity must be positive.");
        }

        double total = price * quantity;

        String itemLabel = quantity == 1 ? item : item + "s";

        System.out.printf(
            "You bought %d %s. Your grand total is KES %.2f.%n",
            quantity, itemLabel, total
        );
    }

    static void main(String[] args) {
        cart();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I ran it with something simple like &lt;code&gt;apple&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter item name: apple
Enter price for each: 100
Enter quantity to buy: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You bought 2 apples. Your grand total is KES 200.00.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect, simple and predictable. It worked exactly as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Spark Of Curiosity
&lt;/h2&gt;

&lt;p&gt;But then I tried a word that wasn’t so straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter item name: box
Enter price for each: 100
Enter quantity to buy: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the program printed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You bought 2 boxs. Your grand total is KES 200.00.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I paused and thought I could maybe just add some rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Words ending in &lt;code&gt;x&lt;/code&gt; get appended with &lt;code&gt;es&lt;/code&gt;. This would also apply for &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;sh&lt;/code&gt;, and &lt;code&gt;ch&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Words ending with &lt;code&gt;y&lt;/code&gt; become &lt;code&gt;ies&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But what about words like &lt;code&gt;mouse&lt;/code&gt; and &lt;code&gt;child&lt;/code&gt;?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was exciting as it felt like executing the real craft of programming beyond just making something work.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Attempt Towards A Smarter Solution
&lt;/h2&gt;

&lt;p&gt;I decided to write a small helper function to handle the obvious cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static String pluralize(String word, int quantity) {
    if (quantity == 1) return word;

    if (word.endsWith("s") || word.endsWith("x") || word.endsWith("z")
        || word.endsWith("ch") || word.endsWith("sh")) {
        return word + "es";
    }

    if (word.endsWith("y") &amp;amp;&amp;amp; word.length() &amp;gt; 1 
        &amp;amp;&amp;amp; !"aeiou".contains("" + word.charAt(word.length() - 2))) {
        return word.substring(0, word.length() - 1) + "ies";
    }

    return word + "s";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I could run tests with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.out.println(pluralize("box", 2));    // boxes
System.out.println(pluralize("city", 2));   // cities
System.out.println(pluralize("class", 2));  // classes
System.out.println(pluralize("apple", 2));  // apples
System.out.println(pluralize("mouse", 2));  // mouses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results were mostly correct; &lt;code&gt;boxes&lt;/code&gt;, &lt;code&gt;cities&lt;/code&gt;, &lt;code&gt;classes&lt;/code&gt; but &lt;code&gt;mouse&lt;/code&gt; to &lt;code&gt;mouses&lt;/code&gt; stood out. Irregular nouns weren’t going to be solved by simple rules. And every new edge case made the code longer and more fragile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/mddf8o/even_numbers_are_so_hard/#lightbox" rel="noopener noreferrer"&gt;This felt like the 'even numbers are hard' meme&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I realized that my 'make it perfect' curiosity was bumping into the limitations of language itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering ICU4J
&lt;/h2&gt;

&lt;p&gt;Searching for solutions, I found ICU4J's Java library used in production for internationalization and pluralization and it looked promising. However after reading the documentation more carefully, I realized ICU4J doesn’t actually change the spelling of words. It decides when to use a singular versus plural form. For example, it can help you display:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You have 1 item
You have 2 items
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it does not automatically turn &lt;code&gt;box&lt;/code&gt; into &lt;code&gt;boxes&lt;/code&gt; or &lt;code&gt;child&lt;/code&gt; into &lt;code&gt;children.&lt;/code&gt; It solves the category problem, not the word-inflection problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tempting Idea
&lt;/h2&gt;

&lt;p&gt;It was disappointing after realizing that rule-based pluralization was incomplete and that even production-grade libraries like ICU4J weren’t meant to pluralize raw nouns.&lt;/p&gt;

&lt;p&gt;Just as I was about to give up, another thought crossed my mind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What if I just ask an AI to do this?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It felt reasonable as modern AI models are excellent at language. They know that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;box&lt;/code&gt; pluralizes to &lt;code&gt;boxes&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;class&lt;/code&gt; to &lt;code&gt;classes&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mouse&lt;/code&gt; to &lt;code&gt;mice&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;child&lt;/code&gt; to &lt;code&gt;children&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In theory, this meant making an API call, passing the noun, and getting back the correct plural. This guaranteed no grammar rules, and no irregular noun lists. Just letting the model handle the complexity.&lt;/p&gt;

&lt;p&gt;For a moment, this felt like the perfect solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the AI Idea Actually Makes Sense (At First)
&lt;/h2&gt;

&lt;p&gt;To be fair, this approach isn’t foolish. In fact, it has real strengths because an AI model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understands irregular nouns&lt;/li&gt;
&lt;li&gt;Handles borrowed words and edge cases&lt;/li&gt;
&lt;li&gt;Adapts to language naturally&lt;/li&gt;
&lt;li&gt;Requires very little code on my end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a small personal project, the idea is genuinely attractive. I wouldn’t need to maintain pluralization logic at all. I’d just delegate the problem to the AI via an API.&lt;/p&gt;

&lt;p&gt;But then I paused and started thinking like a system designer, not just a coder.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Red Flag: Cost
&lt;/h2&gt;

&lt;p&gt;Pluralization is a low-value, high-frequency operation. If every time a user adds an item to a cart the app needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make a network request&lt;/li&gt;
&lt;li&gt;Pay for tokens&lt;/li&gt;
&lt;li&gt;Wait for a response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That cost adds up quickly. Paying for AI inference to decide whether to print &lt;code&gt;boxes&lt;/code&gt; or &lt;code&gt;items&lt;/code&gt; is hard to justify, especially when that same operation could be done locally with zero cost.&lt;/p&gt;

&lt;p&gt;For small scripts or experiments, this might be fine. At scale, it becomes expensive very fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Second Red Flag: Latency
&lt;/h2&gt;

&lt;p&gt;Pluralization sits on the critical path of user feedback. It happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;While rendering UI&lt;/li&gt;
&lt;li&gt;While printing output&lt;/li&gt;
&lt;li&gt;During fast interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An AI call introduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network latency&lt;/li&gt;
&lt;li&gt;Timeout risk&lt;/li&gt;
&lt;li&gt;Retry logic&lt;/li&gt;
&lt;li&gt;Failure modes you don’t control (500 errors)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Something as simple as printing a sentence suddenly depends on the availability of an external service. That outright felt wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Third Red Flag: Non-Determinism
&lt;/h2&gt;

&lt;p&gt;This was by far the biggest concern. Language is flexible, and AI reflects that. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cactus&lt;/code&gt; to &lt;code&gt;cacti&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cactus&lt;/code&gt; to &lt;code&gt;cactuses&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are correct but if the application prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You bought 2 cacti
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You bought 2 cactuses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You just introduced inconsistency. An answer that is 'sometimes right' is often worse than a simpler one that is always consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fourth Red Flag: Control and Safety
&lt;/h2&gt;

&lt;p&gt;To pluralize a word using AI, I have to send user input to an external service. This raises the questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What if the item name contains sensitive information?&lt;/li&gt;
&lt;li&gt;What if this data must stay on-device?&lt;/li&gt;
&lt;li&gt;What happens if the API changes behavior?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suddenly, a simple console program is tied to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network access
-API keys&lt;/li&gt;
&lt;li&gt;Privacy considerations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the picture became clear. Opting to use AI for pluralization solves a hard linguistic problem but introduces cost, latency, inconsistency, dependency and still does not guarantee perfect results.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Practical Tradeoff
&lt;/h2&gt;

&lt;p&gt;At this point, I had to step back and ask myself what the real goal of my program is.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Showing the number of items bought&lt;/li&gt;
&lt;li&gt;Showing the total cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact spelling of the product name in plural wasn’t critical.&lt;/p&gt;

&lt;p&gt;That’s when it clicked almost every app I use does the same thing. Shopping sites, notification systems, and dashboards don’t attempt to pluralize arbitrary nouns. They simply use a safe, controlled noun:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You bought 2 items
You have 5 notifications
Your cart contains 3 products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is predictable, safe, and scales well since there are no edge cases to handle and also works perfectly if you later translate your application into other languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Code Snippet
&lt;/h2&gt;

&lt;p&gt;Here’s how my original shopping cart code evolved after all this reflection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;double total = price * quantity;

String message = quantity == 1 ? "item" : "items";

System.out.printf(
    "You bought %d %s. Your grand total is KES %.2f.%n",
    quantity, message, total
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You bought 1 item. Your grand total is KES 100.00.
You bought 2 items. Your grand total is KES 200.00.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No edge cases, no dictionary of irregular nouns, no fragile rules. This approach is exactly what large production systems do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Curiosity is important. Trying to improve the code teaches you a lot about programming, language, and tradeoffs.&lt;/li&gt;
&lt;li&gt;Language is messy and even simple pluralization can have dozens of edge cases.&lt;/li&gt;
&lt;li&gt;Production code values simplicity, correctness, and consistency.&lt;/li&gt;
&lt;li&gt;Using ICU4J helps in the right context and should be used for plural-aware messages and not for spelling every noun correctly.&lt;/li&gt;
&lt;li&gt;Opting for controlled vocabulary wins,is safe, predictable, and maintainable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Thought
&lt;/h2&gt;

&lt;p&gt;The journey from &lt;code&gt;apple&lt;/code&gt; to &lt;code&gt;apples&lt;/code&gt; to understanding why &lt;code&gt;2 boxes&lt;/code&gt; is rarely shown in apps is more than a lesson in pluralization. It is a lesson in designing software systems that works reliably, even when human language does not cooperate.&lt;/p&gt;

&lt;p&gt;Sometimes, the simplest solution like displaying &lt;code&gt;2 items&lt;/code&gt; is also the most elegant.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Hidden Environmental Cost of Your Cloud Storage</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Mon, 28 Jul 2025 17:54:27 +0000</pubDate>
      <link>https://forem.com/johneliud/the-hidden-environmental-cost-of-your-cloud-storage-58e1</link>
      <guid>https://forem.com/johneliud/the-hidden-environmental-cost-of-your-cloud-storage-58e1</guid>
      <description>&lt;p&gt;We live in the age of infinite storage. Photos, videos, and documents get uploaded to the cloud without a second thought. Google Drive, iCloud, and Dropbox all sell on the idea of limitless space. But here’s the thing: the cloud isn’t magic. It’s a physical network of massive, power-hungry data centers, and they’re leaving a bigger carbon footprint than you might realize.&lt;/p&gt;

&lt;p&gt;This made me write about the hidden environmental cost of cloud storage. Why "just uploading it" isn’t as clean as it seems, and what we can do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  "The Cloud" Is Just Someone Else’s Computer (And It’s Using A Lot Of Energy)
&lt;/h2&gt;

&lt;p&gt;When you upload a file to the cloud, it doesn’t just float in space; it gets stored in a data center, a room full of servers running 24/7.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A single data center can use as much electricity as 50,000 homes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Globally, data centers account for 1-2% of the world’s electricity use, and that number is growing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cooling these servers alone takes billions of gallons of water annually.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of that energy isn’t even renewable. Many cloud providers still rely on fossil fuels to keep their data centers running. So every time you back up another 4K video of your pet, you’re indirectly contributing to that demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Dark Data" Problem (Why Your Forgotten Files Matter)
&lt;/h2&gt;

&lt;p&gt;Think about how much stuff you’ve uploaded over the years. A lot of that just sits there, untouched. That’s called dark data. These are files stored but never used.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Estimates suggest up to 60% of stored data is dark data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keeping it all online means servers are working overtime to store useless files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deleting unnecessary files could cut energy waste significantly, but nobody does it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s like leaving every light in your house on 24/7, even in rooms you never enter. Sure, one person doing it doesn’t matter, but multiply that by billions of users and suddenly it’s a big problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can We Do? (Realistic Solutions)
&lt;/h2&gt;

&lt;p&gt;Cloud storage isn’t going away, but we can be smarter about it. Here’s how:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clean Up Your Digital Hoarding&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Delete duplicates, blurry photos, and old files you’ll never need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use tools like Google Photos' Free Up Space or iCloud’s storage manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unsubscribe from services you don’t use.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Choose Greener Cloud Providers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some companies are pushing for renewable energy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Google &amp;amp; Microsoft aim for carbon-neutral data centers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apple's iCloud runs on 100% renewable energy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Smaller providers like GreenGeeks focus on sustainability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Local Backups Aren't Dead&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Instead of uploading everything, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;External SSDs for large files you rarely access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network-attached storage (NAS) for home backups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Physical archives (hard drives still have a place).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thought: The Cloud Isn’t Evil, But It’s Not Invisible Either
&lt;/h2&gt;

&lt;p&gt;The convenience of cloud storage is undeniable, but like any tech, it comes with trade-offs. Small changes add up. If enough people clean up their unused files and push for greener tech, the cloud's environmental impact can shrink.&lt;/p&gt;

&lt;p&gt;So next time you get that storage full notification, maybe don't just blindly upgrade, but take a minute to delete what you don't need. The planet (and your wallet) might thank you.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudstorage</category>
    </item>
    <item>
      <title>Understanding Load Shedding</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Tue, 24 Jun 2025 13:07:35 +0000</pubDate>
      <link>https://forem.com/johneliud/understanding-load-shedding-41md</link>
      <guid>https://forem.com/johneliud/understanding-load-shedding-41md</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today’s digital landscape, applications must handle unpredictable traffic spikes without collapsing. Whether it’s a sudden surge in users or a distributed denial-of-service (DDoS) attack, systems need mechanisms to protect themselves from being overwhelmed. One such mechanism is load shedding, a defensive strategy that prioritizes critical functionality by selectively rejecting non-essential requests when the system is under stress.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is load shedding, and why is it necessary?&lt;/li&gt;
&lt;li&gt;A practical demo that shows load shedding in action.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By the end, you should understand how to apply this technique to keep your services resilient under pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Load Shedding?
&lt;/h2&gt;

&lt;p&gt;Load shedding is the deliberate termination or deferral of non-critical requests to prevent system overload. It ensures that essential services remain available even when demand exceeds capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is It Necessary?
&lt;/h2&gt;

&lt;p&gt;Without load shedding, a system might experience:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resource exhaustion: Too many requests consume CPU, memory, or network bandwidth.&lt;/li&gt;
&lt;li&gt;Cascading failures: One overloaded service can bring down dependent systems.&lt;/li&gt;
&lt;li&gt;Degraded performance: Even critical requests slow down, leading to timeouts and errors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By shedding non-essential load, a system will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preserve core functionality (e.g., login, payment processing).&lt;/li&gt;
&lt;li&gt;Prevent total outages by avoiding system collapse.&lt;/li&gt;
&lt;li&gt;Improve user experience by failing fast instead of slow degradation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How Load Shedding Works In Code
&lt;/h2&gt;

&lt;p&gt;Let us examine a practical implementation in Go and JavaScript. The demo consists of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Essential services (always available).&lt;/li&gt;
&lt;li&gt;Non-essential services (shed under high load).&lt;/li&gt;
&lt;li&gt;A global request tracker to enforce limits.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tracking Active Requests
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;shed_wrapper.go&lt;/strong&gt; file defines a middleware that monitors concurrent requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var (
    maxRequests     = int32(50)  // Maximum allowed concurrent requests
    currentRequests int32        // Global counter for active requests
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;maxRequests&lt;/strong&gt;: A threshold beyond which we start shedding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;currentRequests&lt;/strong&gt;: An atomic counter to track active requests safely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Shedding Logic
&lt;/h3&gt;

&lt;p&gt;The ShedWrapper middleware wraps HTTP handlers and applies load shedding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func ShedWrapper(h http.HandlerFunc, canShed bool) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // Increment request count
        if atomic.AddInt32(&amp;amp;currentRequests, 1) &amp;gt; maxRequests {
            atomic.AddInt32(&amp;amp;currentRequests, -1) // Revert increment
            if canShed { // Only shed if allowed
                w.WriteHeader(http.StatusServiceUnavailable)
                fmt.Fprintln(w, "Service unavailable due to high load.")
                return
            }
        }
        defer atomic.AddInt32(&amp;amp;currentRequests, -1) // Decrement on exit
        h(w, r) // Proceed if under limit
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Decisions:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;canShed flag: Determines whether a request can be rejected (e.g., non-essential vs. essential).&lt;/li&gt;
&lt;li&gt;Atomic operations: Ensure thread-safe increments/decrements.&lt;/li&gt;
&lt;li&gt;Graceful rejection: Returns HTTP 503 (Service Unavailable) for shed requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Essential vs. Non-Essential Services
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Essential Handler (essential_handler.go)&lt;/strong&gt;
Always processes requests, even under load:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fmt.Fprintf(w, "Essential service responded! (Load: %v)", simulatedLoad)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-Essential Handler (non_essential_handler.go)&lt;/strong&gt;
Rejects requests when load exceeds 50:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if simulatedLoad &amp;gt; 50 {
    w.WriteHeader(http.StatusServiceUnavailable)
    fmt.Fprintln(w, "Non-essential service unavailable!")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Simulating Traffic Spikes
&lt;/h3&gt;

&lt;p&gt;The frontend &lt;strong&gt;(script.js)&lt;/strong&gt; lets users simulate load:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function simulateLoad(requestCount) {
    for (let i = 0; i &amp;lt; requestCount; i++) {
        fetch('/simulate-load'); // Triggers 2-second delay per request
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;strong&gt;/simulate-load&lt;/strong&gt; request &lt;strong&gt;(simulate_handler.go)&lt;/strong&gt; artificially increases load:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func SimulateLoadHandler(w http.ResponseWriter, r *http.Request) {
    time.Sleep(2 * time.Second) // Simulate processing
    w.WriteHeader(http.StatusOK)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Demo Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;User selects a load level (e.g., 75 concurrent requests).&lt;/li&gt;
&lt;li&gt;Essential services remain available even under high loads, demonstrating prioritization.&lt;/li&gt;
&lt;/ol&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%2F3p0c1e92e1m8kgz7f7w5.png" 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%2F3p0c1e92e1m8kgz7f7w5.png" alt="Webpage screenshot demonstarting an essential service online even under high loads" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The system tracks active requests:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;If under 50, all services respond normally.&lt;/li&gt;
&lt;li&gt;If over 50, non-essential requests are rejected.&lt;/li&gt;
&lt;/ul&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%2F63jvpcgfa3zuou0djhie.png" 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%2F63jvpcgfa3zuou0djhie.png" alt="Webpage screenshot demonstarting a non-essential service online  under normal load" width="800" height="436"&gt;&lt;/a&gt;&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%2Fe0dt44s2rtdke7qxmlpf.png" 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%2Fe0dt44s2rtdke7qxmlpf.png" alt="Webpage screenshot demonstarting a non-essential service offline  under high loads to give priority to essential service" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;You can experiment with this implementation by checking out the &lt;a href="https://github.com/johneliud/load_shedder" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. The demo includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A frontend to simulate load.&lt;/li&gt;
&lt;li&gt;Backend logic for essential/non-essential services.&lt;/li&gt;
&lt;li&gt;Configurable thresholds for testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Applications of Load Shedding
&lt;/h2&gt;

&lt;p&gt;While our demo is simplified, load shedding is used in many production systems:&lt;/p&gt;

&lt;h3&gt;
  
  
  E-Commerce Platforms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Critical: Checkout, payment processing, inventory management.&lt;/li&gt;
&lt;li&gt;Non-Critical: Product recommendations, reviews, wishlist updates.&lt;/li&gt;
&lt;li&gt;During Black Friday sales, non-essential features might be temporarily disabled to ensure checkout remains stable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloud APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Critical: Authentication, billing, core compute services.&lt;/li&gt;
&lt;li&gt;Non-Critical: Logging, metrics, secondary APIs.&lt;/li&gt;
&lt;li&gt;If a cloud provider faces unexpected demand, it may throttle non-critical API calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Social Media Platforms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Critical: Posting content, direct messaging.&lt;/li&gt;
&lt;li&gt;Non-Critical: "Like" counts, friend suggestions.&lt;/li&gt;
&lt;li&gt;During viral events, platforms might delay updating engagement metrics to prioritize content delivery.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Financial Systems
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Critical: Stock trading, fund transfers.&lt;/li&gt;
&lt;li&gt;Non-Critical: Transaction history, analytics.&lt;/li&gt;
&lt;li&gt;At market open, trading systems prioritize order execution over historical data queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Considerations
&lt;/h2&gt;

&lt;p&gt;While our demo uses a fixed threshold, real-world systems might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust maxRequests dynamically based on CPU/memory usage.&lt;/li&gt;
&lt;li&gt;Implement retries for shed requests with exponential backoff.&lt;/li&gt;
&lt;li&gt;Use circuit breakers to fail fast when dependencies are struggling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Load shedding is a proactive way to handle traffic surges. By:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitoring request volume,&lt;/li&gt;
&lt;li&gt;Prioritizing critical functions, and&lt;/li&gt;
&lt;li&gt;Gracefully degrading non-essential features,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;we can build systems that fail well instead of collapsing entirely. Try the &lt;a href="https://load-shedder.onrender.com" rel="noopener noreferrer"&gt;demo&lt;/a&gt; yourself to see load shedding in action!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>development</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building a Dynamic User Profile Dashboard with GraphQL</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Sat, 24 May 2025 18:50:38 +0000</pubDate>
      <link>https://forem.com/johneliud/building-a-dynamic-user-profile-dashboard-with-graphql-670</link>
      <guid>https://forem.com/johneliud/building-a-dynamic-user-profile-dashboard-with-graphql-670</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's web development landscape, efficient data fetching is crucial for creating responsive and user-friendly applications. This article explores a project that leverages GraphQL to create a personalized profile dashboard for Zone01 users, demonstrating how modern web technologies can be combined to deliver a seamless user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;The GraphQL Profile Dashboard is a web application that connects to Zone01's GraphQL API to fetch and display user data in an interactive and visually appealing manner. The project showcases several key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure JWT Authentication&lt;/strong&gt;: Users can log in with their Zone01 credentials to access their personalized dashboard&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Data Visualization&lt;/strong&gt;: Interactive SVG-based charts display user progress and statistics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Design&lt;/strong&gt;: A clean, modern interface that adapts to different screen sizes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark/Light Theme Toggle&lt;/strong&gt;: User preference-based theming with persistent settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication Flow
&lt;/h3&gt;

&lt;p&gt;The application implements a secure authentication flow using JWT (JSON Web Tokens). When users provide their credentials, the application makes a request to Zone01's authentication endpoint, receives a JWT token, and stores it in the browser's localStorage for subsequent API requests.&lt;/p&gt;

&lt;p&gt;This approach provides a secure way to maintain user sessions without storing sensitive credentials on the client side. The authentication status is monitored throughout the application, ensuring that protected routes are only accessible to authenticated users.&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL Integration
&lt;/h3&gt;

&lt;p&gt;At the core of this application is its integration with Zone01's GraphQL API. Unlike traditional REST APIs, GraphQL allows the client to specify exactly what data it needs, reducing over-fetching and under-fetching of data.&lt;/p&gt;

&lt;p&gt;The application uses a custom GraphQL client that handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication header inclusion&lt;/li&gt;
&lt;li&gt;Error handling and token expiration&lt;/li&gt;
&lt;li&gt;Structured query execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of how the application queries user data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_PROFILE_QUERY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`query{
  user{
    id
    firstName
    lastName
    login
    email
    campus
    auditRatio
    totalUp
    totalDown
    totalXp: transactions_aggregate(where:{type:{_eq:"xp"},eventId:{_eq:75}}){
      aggregate{
        sum{
          amount
        }
      }
    }
    // Additional fields...
  }
}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query fetches all the necessary user information in a single request, which is then processed and displayed across different sections of the dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Visualization
&lt;/h3&gt;

&lt;p&gt;One of the standout features of this application is its use of custom SVG-based data visualizations. Rather than relying on heavy third-party libraries, the project implements lightweight, custom visualization components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line Graphs&lt;/strong&gt;: For tracking XP progress over time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bar Graphs&lt;/strong&gt;: For comparing project completion statistics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pie Charts&lt;/strong&gt;: For displaying audit ratios&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Donut Charts&lt;/strong&gt;: For showing pass/fail ratios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These visualizations are created using SVG elements, providing a responsive and interactive experience while maintaining a small footprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Theme Management
&lt;/h3&gt;

&lt;p&gt;The application implements a theme management system that allows users to toggle between light and dark modes. This preference is stored in localStorage, ensuring that the user's preferred theme persists across sessions.&lt;/p&gt;

&lt;p&gt;The theme implementation uses CSS variables and class-based styling, making it easy to maintain and extend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="m"&gt;0.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--dark-text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;62&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;62&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--light-bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--dark-bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#121212&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--dark-box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;15px&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;h2&gt;
  
  
  User Experience
&lt;/h2&gt;

&lt;p&gt;The dashboard is designed with user experience at its core. Upon logging in, users are presented with a clean, organized interface that provides immediate access to their most important information:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Basic Information&lt;/strong&gt;: User details including name, email, and campus&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit Statistics&lt;/strong&gt;: Visualization of audit ratios and activity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XP Statistics&lt;/strong&gt;: Progress tracking with interactive charts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Statistics&lt;/strong&gt;: Overview of completed and current projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt;: Visualization of skill development across different areas&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Navigation is streamlined through a sidebar menu that allows users to quickly jump to different sections of their profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication Security
&lt;/h3&gt;

&lt;p&gt;Implementing secure authentication required careful consideration of token storage and transmission. The application uses localStorage for token storage, which provides a balance between persistence and security. All API requests include the JWT in the Authorization header, ensuring secure communication with the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Data Loading
&lt;/h3&gt;

&lt;p&gt;Fetching and processing complex nested data from GraphQL required a structured approach to data handling. The application implements a loading state system that provides visual feedback during data fetching operations, enhancing the perceived performance of the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  SVG Rendering Compatibility
&lt;/h3&gt;

&lt;p&gt;Creating cross-browser compatible SVG visualizations presented challenges, particularly with text rendering and animation. The solution involved implementing fallback options and ensuring that visualizations degrade gracefully in environments with limited support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This GraphQL Profile Dashboard demonstrates how modern web technologies can be combined to create a powerful, user-friendly application. By leveraging GraphQL for efficient data fetching, implementing custom SVG visualizations, and focusing on user experience, the project delivers a polished and performant solution for displaying user profile data.&lt;/p&gt;

&lt;p&gt;The modular architecture and clean separation of concerns make the codebase maintainable and extensible, providing a solid foundation for future enhancements. Whether you're looking to implement GraphQL in your own projects or seeking inspiration for data visualization techniques, this project offers valuable insights and practical examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Demo
&lt;/h2&gt;

&lt;p&gt;Experience the GraphQL Profile Dashboard in action at &lt;a href="https://graphql-uvsx.onrender.com" rel="noopener noreferrer"&gt;https://graphql-uvsx.onrender.com&lt;/a&gt;. Note that you'll need Zone01 credentials to log in and explore the full functionality.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Will A Project Manager Expect Nine Expectant Mothers To Deliver Nine Babies In One Month? A Dive Into Project Management</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Sat, 10 May 2025 19:30:03 +0000</pubDate>
      <link>https://forem.com/johneliud/will-a-project-manager-expect-nine-expectant-mothers-to-deliver-nine-babies-in-one-month-a-dive-1dp1</link>
      <guid>https://forem.com/johneliud/will-a-project-manager-expect-nine-expectant-mothers-to-deliver-nine-babies-in-one-month-a-dive-1dp1</guid>
      <description>&lt;p&gt;There has always been a joke in project management that tries to paint a picture of how project managers plan and manage projects, as well as people. This has always been about project managers (PMs) expecting nine expectant mothers to deliver nine babies in one month. The purpose of this article will be to give my opinion on how truthful or false this statement is, what role PMs play in any project, my experience as a technical project manager during my internship, and my advice to any newbie PM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The article will be more specific about technical project management based on my software development background, but most opinions will be applicable to the broader project management field.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Is Project Management?
&lt;/h2&gt;

&lt;p&gt;In simple terms, it's all about the process of planning, organizing, and overseeing to achieve a specific goal within defined constraints, scope, time, and budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Is A PM, And What Role Do They Play?
&lt;/h2&gt;

&lt;p&gt;I define a PM as someone responsible for creating a clear vision for the project, building trust with all stakeholders, and ensuring everyone understands their role in the bigger picture, as well as identifying and managing risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Agile Methodology?
&lt;/h2&gt;

&lt;p&gt;This is one of the approaches used in project management that emphasizes flexibility and adaptability. Work is broken into short cycles, often referred to as sprints, that last for a few weeks. This allows teams to deliver parts of the project incrementally, gather feedback quickly, and make adjustments as needed throughout the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project I Am Working On
&lt;/h2&gt;

&lt;p&gt;In the spirit of bringing like-minded people together, my team has been tasked with developing a web platform that will provide a medium for enabling creatives and activists to identify and network with fellow creatives, discover places of interest, and collaborate on projects. I won't share many details for now due to organizational regulations.&lt;/p&gt;

&lt;p&gt;It takes great people to come up with a great product, and this is reflected in this project as we have a team comprising two designers, four developers, two PMs, the design team lead, the development team lead, and the PM team lead. The size of the team already justifies how high the stakes are for the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sprint
&lt;/h2&gt;

&lt;p&gt;With agile as our approach for the project delivery, the first objective was to align with all stakeholders, including the client, for familiarity. This is crucial to clearly define everyone's role and foster the spirit of collaboration. To effectively manage the team, we leveraged project management tools like Jira, Confluence, GitHub Projects, as well as meeting tools like Google Meet. Jira and GitHub Projects are used to assign tasks, supervise individual progress on the assigned tasks, alongside estimate the schedule for each assigned task. It is from this that a PM can determine if everything is progressing as scheduled. An alternative to Jira can be Asana. To better manage our design team workflows, we opted for Jira and GitHub Projects for the development team.&lt;/p&gt;

&lt;p&gt;Apart from issuing tasks, a lot of documentation on every event that takes place, be it client meetings, team stand-ups, and so on, needs to be captured. For this, we used both Confluence for managing team events such as daily stand-ups, retrospectives, and meeting notes, and Google Docs for sharing project essentials with the client. For every meeting that happens, a good PM should always ensure they have a notebook and a pen. In the age of artificial intelligence, some note-taking assistants can also do this, but are often limited to some selected languages and dialects.&lt;/p&gt;

&lt;p&gt;It is also at the sprint phase where we establish our work processes that include daily stand-ups. A stand-up is a very brief meeting among the internal team, usually about fifteen minutes, conducted as the first thing in the morning, that seeks to set the mood for every team member for the day. It highlights the problems/blockers faced by an individual and their priority for the day. During this meeting, a PM needs to act fast to address any blockers that are delaying an individual's progress.&lt;/p&gt;

&lt;p&gt;For the project the team was working on, the first sprint deliverable was for our design team to have high fidelity prototypes for both web and mobile screens of the landing page, signup, and login. The second sprint was for our development team to implement the design templates into actual code for both the frontend and backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Highs: Moments That Made Me Believe
&lt;/h2&gt;

&lt;p&gt;The toughest task our team has is to ensure that what we deliver is in line with the client's vision, as well as manage client expectations. Among the presentations we have had with the client was a review of what was achieved during sprint one. I was very nervous during the entire presentation since any feedback from the client, whether positive or negative, at this point would have a change in the trajectory of the project's overall direction. Apart from some minor adjustments to the designs suggested by the client, the meeting ended on a high note as the presented deliverables were approved. The same also applied to the second sprint deliverable meeting. Such moments where the client expresses their gratitude are what every PM should strive for. This will involve frequent meetings with the client and asking a lot of questions to ensure you share the same vision as the client. I believe a PM should have a vast understanding of the project, as compared to the client, because you get to interact with every stakeholder in the project. The team spirit and morale are always boosted on such occasions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lows: Moments That Made Me Doubt
&lt;/h2&gt;

&lt;p&gt;Despite the bed of roses, there is always a period of uncertainty and pressure. One such moment was during the second sprint when we faced version control merge conflicts while integrating the backend and frontend, with barely thirty minutes to a presentation meeting. As a PM, I initially assumed (the worst mistake a PM can make) that the handoff would be seamless after all, we had stand-ups, documentation, and alignment meetings. But I quickly learned that even with the best planning, miscommunications can occur, especially when team members interpret requirements differently. To mitigate this, we have embraced continuous communication, especially among our internal team, to ensure we all know what each person is doing.&lt;/p&gt;

&lt;p&gt;Time estimation is also a tricky part. Early in the project, we underestimated the time required for deliverables, which caused a delay in one of our internal milestones. We had to regroup, reassess, and communicate this shift in expectations to the client with transparency. This was tough but taught me the value of managing not only tasks but also expectations, both for the team and stakeholders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons I Have Learned So Far
&lt;/h2&gt;

&lt;p&gt;One of the biggest lessons I have learned is that communication is important to any project. It is not about overcommunicating, but about ensuring that everyone knows the WHY behind what they are doing. A team that understands the end goal is more motivated and aligned.&lt;/p&gt;

&lt;p&gt;Another important realization is that leadership as a PM isn’t about having all the answers. It is about being resourceful enough to ask the right questions and build bridges when gaps appear.&lt;/p&gt;

&lt;p&gt;It is also crucial to adapt. What worked in the first sprint might not work for the next sprint. Flexibility in processes and even timelines can make the difference between a bottleneck and a breakthrough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I Expect Nine Expectant Mothers to Deliver Nine Babies in One Month?
&lt;/h2&gt;

&lt;p&gt;Let me finally address the elephant in the room. A good PM needs to understand that just because you have more hands doesn’t mean the work gets done faster and to the required standards. Sometimes, it’s about the right skills, the right timing, and respecting the natural rhythm of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advice To New PMs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Be curious by learning the basics of the tools your team is using. It helps in making informed decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apart from chasing deadlines, build relationships by getting to know your team, understanding their strengths, and supporting them as people. Have open sessions with your team to get a better perspective of them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don’t be afraid to ask whether it's clarity from a client or technical help from your dev lead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Always document decisions, changes, and feedback. This will come in handy at some points of the project cycle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Celebrate small wins as they build momentum and remind everyone of the progress being made.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conduct A/B tests among a number of users on occasions where a decision has to be made from multiple options. This builds trust, especially from the client.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we progress more into the project, I will document the experience and publish another article based on a continuation of this. I hope this was worth reading. Thanks.&lt;/p&gt;

</description>
      <category>management</category>
      <category>projectmanagement</category>
    </item>
    <item>
      <title>FETCHING ADVENT OF CODE INPUT DYNAMICALLY IN GO</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Wed, 04 Dec 2024 20:04:23 +0000</pubDate>
      <link>https://forem.com/johneliud/fetching-advent-of-code-inputs-dynamically-in-go-1c67</link>
      <guid>https://forem.com/johneliud/fetching-advent-of-code-inputs-dynamically-in-go-1c67</guid>
      <description>&lt;p&gt;Advent of Code is a fun way for programmers to test and improve their problem-solving skills. While solving the puzzles, you might want to automate the fetching of your personalized puzzle input directly using its URL instead of copying the input to a text file that will be available locally. However, trying to access the input URL using a simple HTTP request, results in the message below:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Puzzle inputs differ by user. Please log in to get your puzzle input.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article explains why this happens and how to correctly fetch your inputs dynamically using Go programming language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem: Why Can't We Fetch The Input Directly?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Advent of Code requires you to log in to access your personalized puzzle inputs. When you log in through the browser, Advent of Code sets a session cookie in your browser. This cookie is used to identify your account and provide your unique input.&lt;/p&gt;

&lt;p&gt;If your HTTP requests don’t include this session cookie, the Advent of Code server cannot recognize you as a logged-in user, hence the error message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: Using the Session Cookie in HTTP Requests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We must include the session cookie in our HTTP requests to fetch the puzzle input. Here is a step-by-step guideline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Log in to Advent of Code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open your browser's Developer Tools (Press F12 key) and navigate to the Network tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refresh the Advent of Code page and look for the cookie header in the request headers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fm1hyayiktm92axd7og4u.png" 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%2Fm1hyayiktm92axd7og4u.png" alt="Screenshot showing developers tools" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extract the value of the session cookie.&lt;/li&gt;
&lt;/ul&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%2Fn8brceblo16gyn3b7ne9.png" 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%2Fn8brceblo16gyn3b7ne9.png" alt="Screenshot showing developers tools session cookie" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: It's important to keep your session cookie a secret since someone else can access your Advent of Code account if they get access to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Code To Fetch The Input&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is a simple program we will use to fetch our puzzle input dynamically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting Up The Base URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We start by defining the base URL for fetching inputs and creating a function to read the input for a specific day.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const baseURL = "https://adventofcode.com/2024/day/%s/input"

func readInput(day string) {
    url := fmt.Sprintf(baseURL, day)
    fmt.Println(url)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Creating The HTTP Request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we create an HTTP request and include the session cookie.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;client := &amp;amp;http.Client{}
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Printf("Error creating HTTP request: %v\n", err)
        return
    }

    // Add the session cookie
    req.Header.Add("Cookie", "session=[YOUR_SESSION_TOKEN]")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;http.NewRequest&lt;/code&gt;: Creates an HTTP GET request for the input URL.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;req.Header.Add&lt;/code&gt;: Adds a header to the request with the session token for authentication. (Replace [YOUR_SESSION_TOKEN] with your actual token).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sending The Request And Handling The Response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we send the HTTP request and read the server's response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("Error making HTTP request: %v\n", err)
        return
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        fmt.Printf("Unexpected HTTP status: %d\n", resp.StatusCode)
        return
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;client.Do(req)&lt;/code&gt;: Sends the HTTP request and stores the response.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;defer resp.Body.Close()&lt;/code&gt;: Ensures the response body is closed after reading.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;resp.StatusCode&lt;/code&gt;: Checks the HTTP status code. A code other than 200 indicates an error.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading And Printing The Input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we read the response body and print the puzzle input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Error reading response body: %v\n", err)
        return
    }

    fmt.Println(string(body))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;io.ReadAll(resp.Body)&lt;/code&gt;: Reads the response body.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;string(body)&lt;/code&gt;: Converts the body from a slice of bytes to a string for easy display.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defining The Main Function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We invoke the readInput function from the main function to fetch the input for day 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {
    readInput("1") // Fetches input puzzle for day 1
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Enhancing Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hardcoding the session token in our code isn’t safe. Instead, we should store it as an environment variable using the steps below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export the session token using the terminal:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AOC_SESSION="[YOUR_SESSION_TOKEN]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Modify the code to read the session token from the environment variable. (Ensure to have "os" among your imports):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;req.Header.Add("Cookie", "session="+os.Getenv("AOC_SESSION"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps, the session token stay outside the source code, reducing the risk of accidental exposure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full Program Code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the complete program for reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

const baseURL = "https://adventofcode.com/2024/day/%s/input"

func readInput(day string) {
    url := fmt.Sprintf(baseURL, day)

    client := &amp;amp;http.Client{}
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Printf("Error creating HTTP request: %v\n", err)
        return
    }

    // Use session token from environment variable
    req.Header.Add("Cookie", "session="+os.Getenv("AOC_SESSION"))

    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("Error making HTTP request: %v\n", err)
        return
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        fmt.Printf("Unexpected HTTP status: %d\n", resp.StatusCode)
        return
    }

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Error reading response body: %v\n", err)
        return
    }

    fmt.Println(string(body))
}

func main() {
    readInput("1")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Output&lt;/li&gt;
&lt;/ul&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%2Fu3mps71qs7a9asbep9xv.png" 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%2Fu3mps71qs7a9asbep9xv.png" alt="Screenshot showing output" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Things To Keep In Mind&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Session Expiry: Session tokens may expire after a while. If you encounter issues, log in again and retrieve a fresh token.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privacy: Never share your session token publicly, including in blog posts or GitHub repositories.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can dynamically fetch your Advent of Code inputs by including your session cookie in HTTP requests.&lt;/p&gt;

&lt;p&gt;Feel free to share your tips or ask questions in the comment section. Happy coding, and good luck with Advent of Code 2024!&lt;/p&gt;

</description>
      <category>go</category>
      <category>adventofcode</category>
      <category>coding</category>
    </item>
    <item>
      <title>MY EXPERIENCE ATTENDING GOPHERCON AFRICA 2024</title>
      <dc:creator>John Eliud Odhiambo</dc:creator>
      <pubDate>Tue, 12 Nov 2024 01:18:04 +0000</pubDate>
      <link>https://forem.com/johneliud/my-experience-attending-gophercon-africa-2024-171e</link>
      <guid>https://forem.com/johneliud/my-experience-attending-gophercon-africa-2024-171e</guid>
      <description>&lt;h2&gt;
  
  
  What is Gophercon?
&lt;/h2&gt;

&lt;p&gt;GopherCon is a global series of conferences dedicated to the Go programming language that provides a space for learning, networking, and collaboration within the Go community.&lt;/p&gt;

&lt;p&gt;As the first-ever GopherCon Africa ended after a two-day successful conference, I reflected on what a monumental event it was for the Go programming community on the continent. Despite being the first of its kind, GopherCon Africa 2024 exceeded all expectations by bringing together developers of diverse experience levels, offering state-of-the-art talks, and creating countless opportunities for networking and growth for anyone who attended.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Promising Beginning for the African Go Community
&lt;/h2&gt;

&lt;p&gt;This being the inaugural GopherCon in Africa made it special. It felt like the start of something big and something that would grow and shape the future of the Go language across the continent. Attendees, speakers, and organizers all shared a sense of pride in being part of something so significant.&lt;/p&gt;

&lt;p&gt;What made the event particularly successful was the way it struck a balance between serving seasoned developers and those just starting with Go. I earlier feared that the talks might cater only to advanced developers, leaving beginners behind, but the speakers did an exceptional job of making their content accessible to all, especially by giving room for asking as many questions as possible. Whether being interested in the technical talks or wanting to understand the broader vision for Go's future, there was something for everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Venue Fit for Innovation
&lt;/h2&gt;

&lt;p&gt;The venue itself was nothing short of world-class. It was not just a place to sit and listen but a space that fostered meaningful conversations, learning, and connection. The environment played a huge role in the success of the event with modern facilities and thoughtful setups for both the talks and networking sessions. The venue elevated the experience and allowed me to focus on the content and connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  State-of-the-Art Talks
&lt;/h2&gt;

&lt;p&gt;The talks were the heart of the event, and they certainly delivered. I had the privilege of hearing from industry leaders who presented on a wide range of topics, from event-driven architecture to advanced testing strategies. One talk that stood out to me was a session on "Empowering the Future with Go: Africa’s Role in the Go Community." It was inspiring to hear how Africa can lead the charge in growing Go adoption globally. Adesina Hassan’s quote "If there’s no community around you, build one" hit home for me. It was a reminder that the future of Go in Africa is in our hands, and we all have a part to play. &lt;br&gt;
The technical depth of the sessions was complemented by the speakers' ability to make the content relatable and actionable. Below are some topics that were covered at the conference: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Empowering the Future with Go: Africa’s Role in the Go Community&lt;br&gt;
The keynote underscored the importance of building communities and encouraged developers to initiate Go user groups locally. The speakers’ message emphasized Africa’s unique role in advancing Go, highlighting how community-driven support can make a lasting impact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event-Driven Architecture with Go and Kafka &lt;br&gt;
This session explored how Go can be used to create robust, event-driven architectures with Kafka. The talk covered the benefits of decoupling services, which improves scalability and resilience, and demonstrated how to use Kafka’s features to build a seamless data flow in distributed systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Effective Testing Strategies for Large Data Inserts &lt;br&gt;
We learned strategies to ensure efficient, resilient, and scalable data operations. From unit and integration testing to load testing and benchmarking, the session emphasized the need for data integrity checks, latency testing, and optimizing indexing strategies for handling large data volumes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advanced Monitoring and Observability with OpenTelemetry and APItoolkit&lt;br&gt;
This hands-on workshop provided a deep dive into leveraging OpenTelemetry alongside APItoolkit to develop comprehensive monitoring and observability for modern applications. Attendees learned practical techniques to instrument distributed systems and analyze telemetry data for improved insights.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SDK Secrets: Unlocking API Magic &lt;br&gt;
This session was a deep dive into building efficient and user-friendly Software Development Kits (SDKs) for APIs. Key focus areas included error handling, concurrency, and designing SDKs that meet real user needs with structured logging, testing, and a strong emphasis on developer empathy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unveiling the Power of Interfaces: Go’s Secret Weapon &lt;br&gt;
Go’s approach to interfaces stands out due to its implicit implementation and structural typing. This talk not only highlighted the benefits of Go’s interfaces for achieving modular and testable code but also delved into advanced techniques, comparing Go’s interface capabilities with those of other languages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Taming Code Chaos: Reducing Entropy in Go Design Systems &lt;br&gt;
Addressing common sources of code entropy, such as unstructured code and inconsistent styles, this session focused on modular architecture, dependency injection, and interface-driven design to create maintainable and scalable systems. The practical refactoring techniques discussed were valuable for increasing team efficiency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mastering Intra-service Communication in Go with gRPC &lt;br&gt;
This technical session examined how Go and gRPC simplify communication in microservices architectures, addressing issues like latency, performance, and reliability. Comparing gRPC with REST, the talk demonstrated how gRPC can streamline cross-service interactions, particularly for high-performance applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing in Go: Unlocking Confidence and Efficiency &lt;br&gt;
This talk emphasized the importance of test-driven development and table-driven tests, explaining how testing improves focus and builds confidence for developers. I learned practical techniques, including subtests, parallelism in testing, and using popular test packages like Testify and GoConvey to create robust test suites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The State of Go in Africa &lt;br&gt;
In a special panel discussion, industry leaders discussed the unique challenges and growth opportunities for Go across the continent. Panelists shared insights on Go adoption and how Go is being introduced in universities and boot camps across the region.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these sessions provided actionable insights and real-world examples, reinforcing why Go continues to grow in popularity for both small and large-scale applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Importance of Communities and Open-Source Contributions
&lt;/h2&gt;

&lt;p&gt;A key theme throughout the event was the importance of communities. I repeatedly heard that joining (or starting) a Go community is one of the best ways to grow as a developer. Being part of a community helps one learn faster, share knowledge, and stay up-to-date with the latest developments in the Go ecosystem. And it’s not just about personal growth; communities help raise awareness about Go, making it more accessible to others and driving adoption.&lt;/p&gt;

&lt;p&gt;Open-source contributions were also highlighted as an avenue to not only improve our technical skills but also gain visibility in the wider tech world. Africa, in particular, faces the challenge of limited job opportunities for Go developers. By contributing to open-source projects, we can showcase our skills to global audiences, helping to bridge that gap. Many speakers encouraged us to jump into open-source, not only to learn but to help build the Go ecosystem and demonstrate to employers what Go and African developers are capable of.&lt;/p&gt;

&lt;h2&gt;
  
  
  Networking
&lt;/h2&gt;

&lt;p&gt;One of the best parts of GopherCon Africa was the networking opportunities. The event provided a rare chance to meet veteran Gophers face-to-face, exchange ideas, and even brainstorm potential collaborations. There were students, junior developers, industry veterans, startup founders, and entrepreneurs each bringing a unique perspective. The diversity of attendees made the networking sessions even more valuable, as we got to learn from each other’s experiences, challenges, and successes. &lt;br&gt;
In one of the sessions, I had a conversation with a fellow developer about the increasing use of Go in fintech. We discussed how Go’s efficiency and scalability make it the go-to language for many fintech companies across Africa. This was just one example of the countless conversations that expanded my understanding of Go’s applications and the industries it’s shaping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating More Awareness Around Go in Africa
&lt;/h2&gt;

&lt;p&gt;One thing that became clear during the event is that there is still much work to be done to create awareness around Go in Africa. Go is already making waves in industries like fintech, cloud computing, and telecommunications, but there are still many developers and companies who aren’t aware of its potential. The event made it clear that we need to continue advocating for Go, both through community efforts and by encouraging companies to adopt it in their tech stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Forward: The Future of Go in Africa
&lt;/h2&gt;

&lt;p&gt;As GopherCon Africa came to a close, I left feeling both inspired and optimistic. There is a real sense that this is just the beginning. The language’s simplicity, performance, and scalability make it perfectly suited for solving many of the challenges African developers face. And with a growing community of passionate developers, I am confident that Go will continue to thrive here. &lt;br&gt;
We have the opportunity to drive Go adoption forward by contributing to open-source, building communities, and showing the world what African developers are capable of. I’m excited to see what the future holds, and even more excited to be part of it.&lt;/p&gt;

&lt;p&gt;To many more successful GopherCons in Africa! &lt;/p&gt;

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