<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Developer - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Developer - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 07 May 2026 09:27:25 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/developer/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How the Factory and Abstract Factory Design Patterns Work in Flutter ]]>
                </title>
                <description>
                    <![CDATA[ In software development, particularly object-oriented programming and design, object creation is a common task. And how you manage this process can impact your app's flexibility, scalability, and maintainability. Creational design patterns govern how... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-the-factory-and-abstract-factory-design-patterns-work-in-flutter/</link>
                <guid isPermaLink="false">6978f477116625d0304ed264</guid>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Factory Design Pattern ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mobile Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mobile apps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ OOPS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Object Oriented Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design principles ]]>
                    </category>
                
                    <category>
                        <![CDATA[ object oriented design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dart ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Abstract Factory Patterns ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwaseyi Fatunmole ]]>
                </dc:creator>
                <pubDate>Tue, 27 Jan 2026 17:23:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769533734673/8b5ad88a-13d2-4fec-969b-55fd854df5c1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In software development, particularly object-oriented programming and design, object creation is a common task. And how you manage this process can impact your app's flexibility, scalability, and maintainability.</p>
<p>Creational design patterns govern how classes and objects are created in a systematic and scalable way. They provide blueprints for creating objects so you don't repeat code. They also keep your system consistent and makes your app easy to extend.</p>
<p>There are five major Creational Design patterns:</p>
<ol>
<li><p><strong>Singleton:</strong> Ensures a class has only one instance and provides a global point of access to it.</p>
</li>
<li><p><strong>Factory Method</strong>: Provides an interface for creating objects but lets subclasses decide which class to instantiate.</p>
</li>
<li><p><strong>Abstract Factory</strong>: Creates families of related objects without specifying their concrete classes.</p>
</li>
<li><p><strong>Builder</strong>: Allows you to construct complex objects step by step, separating construction from representation.</p>
</li>
<li><p><strong>Prototype</strong>: Creates new objects by cloning existing ones, rather than creating from scratch.</p>
</li>
</ol>
<p>Each of these patterns solves specific problems around object creation, depending on the complexity and scale of your application.</p>
<p>In this tutorial, I'll explain what Creational Design Patterns are and how they work. We'll focus on two primary patterns: the Factory and Abstract Factory patterns.</p>
<p>Many people mix these two up, so here we'll explore:</p>
<ol>
<li><p>How each pattern works</p>
</li>
<li><p>Practical examples in Flutter</p>
</li>
<li><p>Applications, best practices, and usage</p>
</li>
</ol>
<p>By the end, you'll understand when to use Factory, when to switch to Abstract Factory, and how to structure your Flutter apps for scalability and maintainability.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-how-the-factory-pattern-works-in-flutter">How the Factory Pattern Works in Flutter</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-define-the-product-and-abstract-creator">Step 1: Define the Product and Abstract Creator</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-implement-concrete-products">Step 2: Implement Concrete Products</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-create-the-factory">Step 3: Create the Factory</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-use-the-factory">Step 4: Use the Factory</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-factory-pattern-for-security-checks">Factory Pattern for Security Checks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-the-abstract-factory-pattern-works-in-flutter">How the Abstract Factory Pattern Works in Flutter</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-define-abstract-product-interfaces">Step 1: Define Abstract Product Interfaces</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-implement-platform-specific-products">Step 2: Implement Platform-Specific Products</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-define-the-abstract-factory-interface">Step 3: Define the Abstract Factory Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-implement-platform-specific-factories">Step 4: Implement Platform Specific Factories</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-client-code-using-abstract-factory">Step 5: Client Code Using Abstract Factory</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving into this tutorial, you should have:</p>
<ul>
<li><p>a basic understanding of the Dart programming language</p>
</li>
<li><p>familiarity with Object-Oriented Programming (OOP) concepts (particularly classes, inheritance, and abstract classes)</p>
</li>
<li><p>basic knowledge of Flutter development (helpful but not required)</p>
</li>
<li><p>an understanding of interfaces and polymorphism</p>
</li>
<li><p>and experience creating and instantiating classes in Dart.</p>
</li>
</ul>
<h2 id="heading-how-the-factory-pattern-works-in-flutter">How the Factory Pattern Works in Flutter</h2>
<p>You'll typically use the Factory Pattern when you want to manage data sets that might be related, but only for a single type of object.</p>
<p>Let's say you want to manage themes for Android and iOS. Using the Factory Pattern allows you to encapsulate object creation and keep your app modular. We'll build this step by step so you can see how the pattern works.</p>
<h3 id="heading-step-1-define-the-product-and-abstract-creator">Step 1: Define the Product and Abstract Creator</h3>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppTheme</span> </span>{
  <span class="hljs-built_in">String?</span> data;
  AppTheme({<span class="hljs-keyword">this</span>.data});
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationThemeData</span> </span>{
  Future&lt;AppTheme&gt; getApplicationTheme();
}
</code></pre>
<p>Here, <code>AppTheme</code> is a simple data class that holds theme information. This represents the product our factory will create. <code>ApplicationThemeData</code> serves as an abstract base class. This abstraction is crucial because it defines a contract that all concrete theme implementations must follow.</p>
<p>By requiring a <code>getApplicationTheme()</code> method, we ensure consistency across different platforms.</p>
<h3 id="heading-step-2-implement-concrete-products">Step 2: Implement Concrete Products</h3>
<p>Now we create platform-specific implementations that provide actual theme data.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AndroidAppTheme</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ApplicationThemeData</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;AppTheme&gt; getApplicationTheme() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> AppTheme(data: <span class="hljs-string">"Here is android theme"</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IOSThemeData</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ApplicationThemeData</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;AppTheme&gt; getApplicationTheme() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> AppTheme(data: <span class="hljs-string">"This is IOS theme data"</span>);
  }
}
</code></pre>
<p>The concrete implementations, <code>AndroidAppTheme</code> and <code>IOSThemeData</code>, extend the abstract class and provide platform-specific theme data. Each returns an <code>AppTheme</code> object with content tailored to its respective platform.</p>
<h3 id="heading-step-3-create-the-factory">Step 3: Create the Factory</h3>
<p>The factory encapsulates the object creation logic, so client code doesn't need to know which specific theme class it's working with.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ThemeFactory</span> </span>{
  ThemeFactory({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.theme});
  ApplicationThemeData theme;

  loadTheme() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> theme.getApplicationTheme();
  }
}
</code></pre>
<p><code>ThemeFactory</code> acts as the factory itself. It accepts any <code>ApplicationThemeData</code> implementation and provides a unified <code>loadTheme()</code> method. This encapsulates the object creation logic cleanly.</p>
<h3 id="heading-step-4-use-the-factory">Step 4: Use the Factory</h3>
<p>Finally, we use the factory in our application code.</p>
<pre><code class="lang-dart">ThemeFactory(
  theme: Platform.isAndroid ? AndroidAppTheme() : IOSThemeData()
).loadTheme();
</code></pre>
<p>Here, you choose a theme (Android or iOS) and get the corresponding <code>AppTheme</code>. This approach is simple and effective when you only care about one functionality, like loading a theme.</p>
<p>The beauty of this pattern is that the client code remains clean and doesn't need to change if you add new platforms later.</p>
<h2 id="heading-factory-pattern-for-security-checks">Factory Pattern for Security Checks</h2>
<p>Another excellent use case for the Factory Pattern is when implementing security checks during your application bootstrap.</p>
<p>For instance, Android and iOS require different logic for internal security. Android might check for developer mode or rooted devices, while iOS checks for jailbroken devices. This scenario is a perfect example of when to apply the Factory Pattern, as it allows you to encapsulate platform-specific security logic cleanly and maintainably. Let's implement this step by step.</p>
<h3 id="heading-step-1-define-security-check-result-and-abstract-checker">Step 1: Define Security Check Result and Abstract Checker</h3>
<p>First, we need a standardized way to communicate security check outcomes and a contract for performing security checks.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// Base security check result class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecurityCheckResult</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">bool</span> isSecure;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> message;

  SecurityCheckResult({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.isSecure, <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.message});
}

<span class="hljs-comment">// Abstract security checker</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecurityChecker</span> </span>{
  Future&lt;SecurityCheckResult&gt; performSecurityCheck();
}
</code></pre>
<p>The <code>SecurityCheckResult</code> class provides a standardized way to communicate security check outcomes across platforms.</p>
<p>It contains a boolean flag indicating security status and a descriptive message for the user. The abstract <code>SecurityChecker</code> class defines the contract that all platform-specific security implementations must follow.</p>
<p>This ensures that, regardless of the platform, we can always call <code>performSecurityCheck()</code> and receive a consistent result type.</p>
<h3 id="heading-step-2-implement-platform-specific-security-checkers">Step 2: Implement Platform-Specific Security Checkers</h3>
<p>Now we create the actual security checking implementations for each platform.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// Android-specific security implementation</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AndroidSecurityChecker</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SecurityChecker</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;SecurityCheckResult&gt; performSecurityCheck() <span class="hljs-keyword">async</span> {
    <span class="hljs-built_in">bool</span> isRooted = <span class="hljs-keyword">await</span> checkIfDeviceIsRooted();
    <span class="hljs-keyword">if</span> (isRooted) {
      <span class="hljs-keyword">return</span> SecurityCheckResult(
        isSecure: <span class="hljs-keyword">false</span>,
        message: <span class="hljs-string">"Device is rooted. App cannot run on rooted devices."</span>
      );
    }

    <span class="hljs-built_in">bool</span> isDeveloperMode = <span class="hljs-keyword">await</span> checkDeveloperMode();
    <span class="hljs-keyword">if</span> (isDeveloperMode) {
      <span class="hljs-keyword">return</span> SecurityCheckResult(
        isSecure: <span class="hljs-keyword">false</span>,
        message: <span class="hljs-string">"Developer mode is enabled. Please disable it to continue."</span>
      );
    }

    <span class="hljs-keyword">return</span> SecurityCheckResult(
      isSecure: <span class="hljs-keyword">true</span>,
      message: <span class="hljs-string">"Device security check passed."</span>
    );
  }

  Future&lt;<span class="hljs-built_in">bool</span>&gt; checkIfDeviceIsRooted() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>; 
  }

  Future&lt;<span class="hljs-built_in">bool</span>&gt; checkDeveloperMode() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>; <span class="hljs-comment">// Placeholder</span>
  }
}

<span class="hljs-comment">// iOS-specific security implementation</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IOSSecurityChecker</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SecurityChecker</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;SecurityCheckResult&gt; performSecurityCheck() <span class="hljs-keyword">async</span> {
    <span class="hljs-built_in">bool</span> isJailbroken = <span class="hljs-keyword">await</span> checkIfDeviceIsJailbroken();

    <span class="hljs-keyword">if</span> (isJailbroken) {
      <span class="hljs-keyword">return</span> SecurityCheckResult(
        isSecure: <span class="hljs-keyword">false</span>,
        message: <span class="hljs-string">"Device is jailbroken. App cannot run on jailbroken devices."</span>
      );
    }

    <span class="hljs-keyword">return</span> SecurityCheckResult(
      isSecure: <span class="hljs-keyword">true</span>,
      message: <span class="hljs-string">"Device security check passed."</span>
    );
  }

  Future&lt;<span class="hljs-built_in">bool</span>&gt; checkIfDeviceIsJailbroken() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>; 
  }
}
</code></pre>
<p>The Android implementation focuses on detecting rooted devices and developer mode, which are common security concerns on Android.</p>
<p>A rooted device has elevated permissions that could allow malicious apps to access sensitive data, while developer mode can expose debugging interfaces.</p>
<p>The iOS implementation checks for jailbroken devices, which is the iOS equivalent of rooting. Jailbroken devices bypass Apple's security restrictions and can pose similar security risks.</p>
<h3 id="heading-step-3-create-the-security-factory">Step 3: Create the Security Factory</h3>
<p>The factory wraps the chosen security checker and provides a clean interface for running checks.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// Security Factory</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecurityCheckFactory</span> </span>{
  SecurityCheckFactory({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.checker});
  SecurityChecker checker;

  Future&lt;SecurityCheckResult&gt; runSecurityCheck() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> checker.performSecurityCheck();
  }
}
</code></pre>
<p>The <code>SecurityCheckFactory</code> provides a simple interface that accepts any <code>SecurityChecker</code> implementation. This means your app initialization code doesn't need to know about platform-specific security details – it just calls <code>runSecurityCheck()</code> and handles the result.</p>
<h3 id="heading-step-4-use-the-security-factory-in-app-bootstrap">Step 4: Use the Security Factory in App Bootstrap</h3>
<p>Finally, we integrate the security factory into our app's initialization process.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// In your app's bootstrap/initialization</span>
Future&lt;<span class="hljs-keyword">void</span>&gt; initializeApp() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> securityFactory = SecurityCheckFactory(
    checker: Platform.isAndroid 
      ? AndroidSecurityChecker() 
      : IOSSecurityChecker()
  );

  <span class="hljs-keyword">final</span> result = <span class="hljs-keyword">await</span> securityFactory.runSecurityCheck();

  <span class="hljs-keyword">if</span> (!result.isSecure) {
    <span class="hljs-comment">// Show error dialog and prevent app from continuing</span>
    showSecurityErrorDialog(result.message);
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-comment">// Continue with normal app initialization</span>
  runApp(MyApp());
}
</code></pre>
<p>This usage example demonstrates how the Factory Pattern makes your app initialization code clean and maintainable.</p>
<p>The platform detection happens in one place, the factory handles the creation of the appropriate checker, and your code simply deals with the standardized result.</p>
<p><strong>Key takeaway:</strong> Factory is great when you need one type of object, but you want to abstract away the creation logic.</p>
<h2 id="heading-how-the-abstract-factory-pattern-works-in-flutter">How the Abstract Factory Pattern Works in Flutter</h2>
<p>The Abstract Factory Pattern comes into play when you have more than two data sets for comparison, and each set includes multiple functionalities.</p>
<p>For example, imagine you now want to manage themes, widgets, and architecture for Android, iOS, and Linux. Managing this with just a Factory becomes messy, so Abstract Factory provides a structured way to handle multiple related objects for different platforms.</p>
<p>So let's see how you can handle this using the abstract factory method.</p>
<h3 id="heading-step-1-define-abstract-product-interfaces">Step 1: Define Abstract Product Interfaces</h3>
<p>Before we dive into this implementation, it's important to understand what abstract product interfaces are. An abstract product interface is essentially a contract that defines what methods a product must implement, without specifying how they're implemented.</p>
<p>Think of it as a blueprint that ensures all related products share a common structure. In our case, we're defining three core functionalities that every platform must provide:</p>
<ol>
<li><p>Theme management</p>
</li>
<li><p>Widget handling</p>
</li>
<li><p>Architecture configuration.</p>
</li>
</ol>
<p>By creating these abstract interfaces first, we establish a consistent API that all platform-specific implementations will follow.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ThemeManager</span> </span>{
  Future&lt;<span class="hljs-built_in">String</span>&gt; getTheme();
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WidgetHandler</span> </span>{
  Future&lt;<span class="hljs-built_in">bool</span>&gt; getWidget();
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArchitechtureHandler</span> </span>{
  Future&lt;<span class="hljs-built_in">String</span>&gt; getArchitechture();
}
</code></pre>
<p>Here, we’re defining three base functionalities that every platform will implement: theme, widgets, and architecture.</p>
<p>Each interface declares a single method that returns platform-specific information.</p>
<p>The <code>ThemeManager</code> retrieves theme data, <code>WidgetHandler</code> determines widget compatibility, and <code>ArchitechtureHandler</code> provides architecture details.</p>
<h3 id="heading-step-2-implement-platform-specific-products">Step 2: Implement Platform-Specific Products</h3>
<p>Now that we have our abstract interfaces defined, we need to create concrete implementations for each platform. This step is where we provide the actual, platform-specific behavior for each product type. Think of this as filling in the blueprint with real details.</p>
<p>While the abstract interfaces told us what methods we need, these concrete classes tell us how those methods behave on each specific platform. Each platform (Android, iOS, Linux) will have its own unique implementation of themes, widgets, and architecture.</p>
<h4 id="heading-android">Android:</h4>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AndroidThemeManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ThemeManager</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; getTheme() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Android Theme"</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AndroidWidgetHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WidgetHandler</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">bool</span>&gt; getWidget() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AndroidArchitechtureHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ArchitechtureHandler</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; getArchitechture() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Android Architecture"</span>;
  }
}
</code></pre>
<p>For Android, we're creating three specific product classes. The <code>AndroidThemeManager</code> returns Material Design theme data, the <code>AndroidWidgetHandler</code> returns true to indicate that Android supports home screen widgets, and the <code>AndroidArchitechtureHandler</code> provides information about Android's architecture (which could include details about ARM, x86, or other processor architectures).</p>
<h4 id="heading-ios">iOS:</h4>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IOSThemeManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ThemeManager</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; getTheme() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"IOS Theme"</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IOSWidgetHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WidgetHandler</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">bool</span>&gt; getWidget() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IOSArchitechtureHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ArchitechtureHandler</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; getArchitechture() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"iOS Architecture"</span>;
  }
}
</code></pre>
<p>The iOS implementations follow the same structure but provide iOS-specific values. Notice that <code>IOSWidgetHandler</code> returns false, this could represent a scenario where certain widget features aren't available or behave differently on iOS compared to Android.</p>
<h4 id="heading-linux">Linux:</h4>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LinuxThemeManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ThemeManager</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; getTheme() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Linux Theme"</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LinuxWidgetHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WidgetHandler</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">bool</span>&gt; getWidget() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LinuxArchitechtureHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ArchitechtureHandler</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; getArchitechture() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Linux Architecture"</span>;
  }
}
</code></pre>
<p>Similarly, Linux gets its own set of implementations, providing Linux-specific theme data and architecture information.</p>
<h3 id="heading-step-3-define-the-abstract-factory-interface">Step 3: Define the Abstract Factory Interface</h3>
<p>With our product classes ready, we now need to create the factory that will produce them.</p>
<p>The abstract factory interface is the master blueprint that declares which products our factory must be able to create. This interface doesn't create anything itself, it simply declares that any concrete factory must provide methods to create all three product types (theme, widget, and architecture handlers). This ensures that, regardless of which platform factory we use, we can always access all three functionalities.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppFactory</span> </span>{
  ThemeManager themeManager();
  WidgetHandler widgetManager();
  ArchitechtureHandler architechtureHandler();
}
</code></pre>
<p>Here, we define a factory blueprint. Any platform specific factory will have to implement all three functionalities. This guarantees consistency: every platform will have all three capabilities available.</p>
<h3 id="heading-step-4-implement-platform-specific-factories">Step 4: Implement Platform Specific Factories</h3>
<p>This is where everything comes together. We're now creating the actual factories that will produce the platform-specific products we defined earlier. Each factory is responsible for creating all the related products for its platform. The key advantage here is encapsulation: the factory knows how to create all the related objects for a platform, and it ensures they're compatible with each other. For example, <code>AndroidFactory</code> creates Android-specific theme managers, widget handlers, and architecture handlers that all work together seamlessly.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AndroidFactory</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppFactory</span> </span>{
  <span class="hljs-meta">@override</span>
  ThemeManager themeManager() =&gt; AndroidThemeManager();

  <span class="hljs-meta">@override</span>
  WidgetHandler widgetManager() =&gt; AndroidWidgetHandler();

  <span class="hljs-meta">@override</span>
  ArchitechtureHandler architechtureHandler() =&gt; AndroidArchitechtureHandler();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IOSFactory</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppFactory</span> </span>{
  <span class="hljs-meta">@override</span>
  ThemeManager themeManager() =&gt; IOSThemeManager();

  <span class="hljs-meta">@override</span>
  WidgetHandler widgetManager() =&gt; IOSWidgetHandler();

  <span class="hljs-meta">@override</span>
  ArchitechtureHandler architechtureHandler() =&gt; IOSArchitechtureHandler();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LinuxFactory</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppFactory</span> </span>{
  <span class="hljs-meta">@override</span>
  ThemeManager themeManager() =&gt; LinuxThemeManager();

  <span class="hljs-meta">@override</span>
  WidgetHandler widgetManager() =&gt; LinuxWidgetHandler();

  <span class="hljs-meta">@override</span>
  ArchitechtureHandler architechtureHandler() =&gt; LinuxArchitechtureHandler();
}
</code></pre>
<p>Each concrete factory (AndroidFactory, IOSFactory, LinuxFactory) implements all three methods from the <code>AppFactory</code> interface. When you call <code>themeManager()</code> on <code>AndroidFactory</code>, you get an <code>AndroidThemeManager</code>. When you call it on <code>IOSFactory</code>, you get an <code>IOSThemeManager</code>. The same pattern applies to all products.</p>
<h3 id="heading-step-5-client-code-using-abstract-factory">Step 5: Client Code Using Abstract Factory</h3>
<p>Finally, we create the client code that uses our abstract factory. This is the layer that your application will actually interact with. The beauty of this pattern is that the client code doesn't need to know anything about the specific platform implementations, it just works with the abstract factory interface.</p>
<p>The <code>AppBaseFactory</code> class accepts any factory that implements <code>AppFactory</code> and provides a simple method to initialize all platform settings. The <code>CheckDevice</code> class determines which factory to use based on the current platform, completely abstracting this decision away from the rest of your application.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppBaseFactory</span> </span>{
  AppBaseFactory({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.<span class="hljs-keyword">factory</span>});
  AppFactory <span class="hljs-keyword">factory</span>;

  getAppSettings() {
    <span class="hljs-keyword">factory</span>
      ..architechtureHandler()
      ..themeManager()
      ..widgetManager();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckDevice</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">get</span>() {
    <span class="hljs-keyword">if</span> (Platform.isAndroid) <span class="hljs-keyword">return</span> AndroidFactory();
    <span class="hljs-keyword">if</span> (Platform.isIOS) <span class="hljs-keyword">return</span> IOSFactory();
    <span class="hljs-keyword">if</span> (Platform.isLinux) <span class="hljs-keyword">return</span> LinuxFactory();
    <span class="hljs-keyword">throw</span> UnsupportedError(<span class="hljs-string">"Platform not supported"</span>);
  }
}

<span class="hljs-comment">// Usage</span>
AppBaseFactory(<span class="hljs-keyword">factory</span>: CheckDevice.<span class="hljs-keyword">get</span>()).getAppSettings();
</code></pre>
<p>Here's what's happening in this code:</p>
<p>The <code>AppBaseFactory</code> class acts as a wrapper around any <code>AppFactory</code> implementation. It provides a convenient <code>getAppSettings()</code> method that initializes all three components (architecture handler, theme manager, and widget manager) using Dart's cascade notation.</p>
<p>The <code>CheckDevice</code> class contains the platform detection logic. Its static <code>get()</code> method checks the current platform and returns the appropriate factory. This centralizes all platform detection in one place. When you call <code>AppBaseFactory(factory: CheckDevice.get()).getAppSettings()</code>, the code automatically detects your platform, creates the right factory, and initializes all platform-specific components, all without the calling code needing to know any platform-specific details.</p>
<p>Each platform factory produces all related products. The client only interacts with <code>AppBaseFactory</code>, remaining unaware of the internal implementation. This ensures your code is scalable, maintainable, and consistent.</p>
<h2 id="heading-real-world-application-payment-provider-management">Real-World Application: Payment Provider Management</h2>
<p>Another good use case for abstract factory is when you need to switch between multiple payment providers in your application and you only want to expose the necessary functionality to the client (presentation layer).</p>
<p>The abstract factory design pattern properly helps you manage this scenario in terms of concrete implementation, encapsulation, clean code, separation of concerns, and proper code structure and management. For example, you might support Stripe, PayPal, and Flutterwave in your application.</p>
<p>Each provider requires different initialization, transaction processing, and webhook handling. By using the Abstract Factory pattern, you can create a consistent interface for all payment operations while keeping provider-specific details encapsulated within their respective factory implementations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You should now feel more comfortable deciding when to use the Factory design pattern vs the Abstract Factory design pattern.</p>
<p>Understanding the factory and abstract factory patterns and their usages properly will help with object creation based on the particular use case you are trying to implement.</p>
<p>The Factory Pattern is ideal when you need one product and want to encapsulate creation logic while the Abstract Factory Pattern works well when you have multiple related products across platforms, need consistency, and want scalability. Using these patterns will help you write clean, maintainable, and scalable Flutter apps.</p>
<p>They give you a systematic approach to object creation and prevent messy, hard-to-maintain code as your app grows.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Fix the Python ENOENT Error When Setting Up MCP Servers – A Complete Guide ]]>
                </title>
                <description>
                    <![CDATA[ Getting the "spawn python ENOENT" error while setting up an MCP (Model Context Protocol) server on macOS can be frustrating. But don't worry – in this tutorial, I'll guide you through fixing it by rebuilding your Python virtual environment. By the en... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-fix-the-python-enoent-error-when-setting-up-mcp-servers-a-complete-guide/</link>
                <guid isPermaLink="false">68963890790ac4491c15b00a</guid>
                
                    <category>
                        <![CDATA[ mcp server ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Idris Olubisi ]]>
                </dc:creator>
                <pubDate>Fri, 08 Aug 2025 17:49:04 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754675334533/6a05e45a-9703-49c0-b427-6c4960c01d86.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Getting the "spawn python ENOENT" error while setting up an MCP (Model Context Protocol) server on macOS can be frustrating. But don't worry – in this tutorial, I'll guide you through fixing it by rebuilding your Python virtual environment.</p>
<p>By the end, you'll have a fully functional MCP server integrated with Claude Desktop in about 10 minutes. This solution applies to any MCP setup facing this standard error after Python upgrades.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-causes-the-enoent-error">What Causes the ENOENT Error?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-diagnose-your-broken-virtual-environment">How to Diagnose Your Broken Virtual Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-completely-rebuild-your-virtual-environment">How to Completely Rebuild Your Virtual Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-mcp-server-dependencies">How to Install MCP Server Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-locate-your-server-files">How to Locate Your Server Files</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-your-server-setup">How to Test Your Server Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-claude-desktop">How to Configure Claude Desktop</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-restart-claude-desktop-and-test-integration">How to Restart Claude Desktop and Test Integration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-mcp-server-capabilities">Understanding MCP Server Capabilities</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-alternative-installation-methods">Alternative Installation Methods</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-method-1-direct-package-installation">Method 1: Direct Package Installation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-method-2-using-uv-package-manager">Method 2: Using UV Package Manager</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prevent-future-enoent-errors">How to Prevent Future ENOENT Errors</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-troubleshooting-common-issues">Troubleshooting Common Issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-causes-the-enoent-error">What Causes the ENOENT Error?</h2>
<p>The ENOENT (Error NO ENTry) error means your system can’t locate the Python executable at the specified path. This occurs when the file is missing or inaccessible.</p>
<p>On macOS, this typically happens when:</p>
<ul>
<li><p>You've upgraded Python through Homebrew</p>
</li>
<li><p>The <code>brew cleanup</code> command removed old Python versions</p>
</li>
<li><p>Your virtual environment's symlinks now point to non-existent files</p>
</li>
</ul>
<p>What makes this particularly challenging is that your virtual environment folder still exists – it looks fine from the outside, but the Python executable inside is completely broken.</p>
<p>When MCP servers try to spawn Python processes using these broken paths, you get the dreaded ENOENT error. This affects any Python-based MCP server, whether you're building custom tools, connecting to APIs, or working with file systems.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow this tutorial, you'll need:</p>
<ul>
<li><p>macOS with <a target="_blank" href="https://brew.sh/">Homebrew</a> installed</p>
</li>
<li><p>Python 3.10 or higher</p>
</li>
<li><p>An MCP server repository cloned locally</p>
</li>
<li><p><a target="_blank" href="https://claude.ai/download">Claude Desktop</a> installed</p>
</li>
<li><p>Basic familiarity with terminal commands and Python virtual environments</p>
</li>
</ul>
<p>If you haven't cloned an MCP server repository yet, you can start with any open-source MCP server. For this tutorial, I'll use generic examples that work with any MCP setup:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/your-username/your-mcp-server.git
<span class="hljs-built_in">cd</span> your-mcp-server
</code></pre>
<h2 id="heading-how-to-diagnose-your-broken-virtual-environment">How to Diagnose Your Broken Virtual Environment</h2>
<p>First, you need to confirm that your virtual environment is actually the problem. Open your terminal and navigate to your MCP directory:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /path/to/your/mcp-server
</code></pre>
<p>Now check if your Python executable exists:</p>
<pre><code class="lang-bash">ls -la venv/bin/python*
</code></pre>
<p>If you see broken symlinks or get "No such file or directory" errors, you've found your problem. You might see output like:</p>
<pre><code class="lang-bash">lrwxr-xr-x  1 username  staff  16 Jan  1 12:00 python -&gt; /usr/<span class="hljs-built_in">local</span>/bin/python3.11
lrwxr-xr-x  1 username  staff  16 Jan  1 12:00 python3 -&gt; /usr/<span class="hljs-built_in">local</span>/bin/python3.11
</code></pre>
<p>But when you try to run these Python executables:</p>
<pre><code class="lang-bash">./venv/bin/python --version
</code></pre>
<p>You'll get an error because the target files no longer exist. This confirms your virtual environment is broken and needs rebuilding.</p>
<h2 id="heading-how-to-completely-rebuild-your-virtual-environment">How to Completely Rebuild Your Virtual Environment</h2>
<p>The most reliable solution is to rebuild your virtual environment from scratch. This ensures all paths and dependencies are correctly configured for your current Python installation.</p>
<p>Here's your step-by-step rebuild process:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Make sure you're in the MCP server directory</span>
<span class="hljs-built_in">cd</span> /path/to/your/mcp-server

<span class="hljs-comment"># Remove the corrupted virtual environment</span>
rm -rf venv

<span class="hljs-comment"># Create a fresh virtual environment</span>
python3 -m venv venv

<span class="hljs-comment"># Activate the new environment</span>
<span class="hljs-built_in">source</span> venv/bin/activate
</code></pre>
<p>You should now see <code>(venv)</code> in your terminal prompt, indicating the virtual environment is active. This prefix confirms you're working within the isolated Python environment.</p>
<h2 id="heading-how-to-install-mcp-server-dependencies">How to Install MCP Server Dependencies</h2>
<p>With your fresh virtual environment active, install the MCP server and its dependencies. The exact installation command depends on your specific MCP server, but typically follows one of these patterns:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># For package-based installation</span>
pip install -e .

<span class="hljs-comment"># Or for requirements file</span>
pip install -r requirements.txt

<span class="hljs-comment"># Or for specific MCP frameworks</span>
pip install fastmcp
</code></pre>
<p>Common MCP server dependencies include:</p>
<ul>
<li><p>FastMCP for the server framework</p>
</li>
<li><p>JSON-RPC libraries for communication protocols</p>
</li>
<li><p>HTTP clients for API integrations</p>
</li>
<li><p>File system utilities for local operations</p>
</li>
</ul>
<p>The installation process displays all packages as they install. Don't worry if you see deprecation warnings – they're normal and won't affect functionality.</p>
<h2 id="heading-how-to-locate-your-server-files">How to Locate Your Server Files</h2>
<p>After installation, identify where your main server file lives. Run this command to find all server.py files:</p>
<pre><code class="lang-bash">find . -name <span class="hljs-string">"server.py"</span> -<span class="hljs-built_in">type</span> f
</code></pre>
<p>You may see results like:</p>
<ul>
<li><p><code>./server.py</code> (in the root directory)</p>
</li>
<li><p><code>./src/server.py</code> (in a source directory)</p>
</li>
<li><p><code>./mcp_server/server.py</code> (in a package directory)</p>
</li>
</ul>
<p>Check your current directory structure:</p>
<pre><code class="lang-bash">ls -la
</code></pre>
<p>Look for the main server entry point. Most MCP servers follow standard Python project structures with either a root-level server file or one nested in a package directory.</p>
<h2 id="heading-how-to-test-your-server-setup">How to Test Your Server Setup</h2>
<p>Now you’ll want to test your server to ensure it's working correctly. Start with the main server file you identified:</p>
<pre><code class="lang-bash">python server.py
</code></pre>
<p>If this is the correct server and everything is configured correctly, you'll see output similar to:</p>
<pre><code class="lang-typescript">╭─ MCP Server ───────────────────────────────────────────────────────────────╮
│ 🖥️  Server name: Example-MCP                                              │
│ 📦 Transport: STDIO                                                        │
│ 🤝 Protocol: <span class="hljs-built_in">JSON</span>-RPC                                                      │
╰────────────────────────────────────────────────────────────────────────────╯
[INFO] Starting MCP server <span class="hljs-keyword">with</span> transport <span class="hljs-string">'stdio'</span>
[INFO] Server ready <span class="hljs-keyword">for</span> connections
</code></pre>
<p>This output confirms your MCP server is working correctly. The server uses standard input/output (STDIO) for communication, which is perfect for Claude Desktop integration. You can stop the server with <code>Ctrl+C</code>.</p>
<h2 id="heading-how-to-configure-claude-desktop">How to Configure Claude Desktop</h2>
<p>Now that your server runs properly, configure Claude Desktop to connect to it. The configuration file location depends on your operating system:</p>
<p><strong>For macOS:</strong></p>
<pre><code class="lang-bash">~/Library/Application Support/Claude/claude_desktop_config.json
</code></pre>
<p><strong>For Windows:</strong></p>
<pre><code class="lang-bash">%APPDATA%\Claude\claude_desktop_config.json
</code></pre>
<p><strong>For Linux:</strong></p>
<pre><code class="lang-bash">~/.config/Claude/claude_desktop_config.json
</code></pre>
<p>Create or edit this file with your exact paths. Your configuration should look like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"example-mcp"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"/Users/yourusername/path/to/mcp-server/venv/bin/python"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"/Users/yourusername/path/to/mcp-server/server.py"</span>],
      <span class="hljs-attr">"cwd"</span>: <span class="hljs-string">"/Users/yourusername/path/to/mcp-server"</span>
    }
  }
}
</code></pre>
<p>Replace <code>/Users/yourusername/path/to/mcp-server/</code> with your actual path. You can get your precise path by running <code>pwd</code> in your MCP server directory.</p>
<p>The configuration tells Claude Desktop:</p>
<ul>
<li><p>Which Python interpreter to use (from your virtual environment)</p>
</li>
<li><p>Where to find the server script</p>
</li>
<li><p>Which directory to run the server from</p>
</li>
</ul>
<h2 id="heading-how-to-restart-claude-desktop-and-test-integration">How to Restart Claude Desktop and Test Integration</h2>
<p>After saving your configuration file, altogether quit Claude Desktop (not just close the window). On macOS, use <code>Cmd+Q</code> or right-click the dock icon and select Quit. Then restart Claude Desktop.</p>
<p>Once Claude Desktop is running again, test your MCP integration. You can verify the connection by:</p>
<ol>
<li><p>Looking for your MCP server name in Claude's interface</p>
</li>
<li><p>Testing basic MCP functionality with prompts like:</p>
<ul>
<li><p>"What MCP tools are available?"</p>
</li>
<li><p>"Can you check the MCP server status?"</p>
</li>
<li><p>"Show me the available MCP commands"</p>
</li>
</ul>
</li>
</ol>
<p>If everything is working correctly, Claude will respond using the MCP server tools, confirming successful integration.</p>
<h2 id="heading-understanding-mcp-server-capabilities">Understanding MCP Server Capabilities</h2>
<p>MCP servers extend Claude's capabilities by providing structured access to external tools and data sources. Common MCP server implementations include:</p>
<ol>
<li><p>File system operations: MCP servers can provide controlled access to local files, allowing Claude to read, analyze, and process documents while maintaining security boundaries.</p>
</li>
<li><p>API integrations: Connect Claude to external services through MCP servers that handle authentication, rate limiting, and data formatting for various APIs.</p>
</li>
<li><p>Database connections: Query databases safely through MCP servers that manage connections, handle credentials securely, and format results for Claude's consumption.</p>
</li>
<li><p>Custom tools: Build specialized tools for your workflow, from code analysis to data processing, all accessible through the standardized MCP interface.</p>
</li>
</ol>
<p>The beauty of MCP is its flexibility – you can create servers for virtually any tool or service you need Claude to interact with.</p>
<h2 id="heading-alternative-installation-methods">Alternative Installation Methods</h2>
<p>If you want more streamlined approaches for future setups, here are two excellent alternatives:</p>
<h3 id="heading-method-1-direct-package-installation">Method 1: Direct Package Installation</h3>
<p>For MCP servers available as packages, you can install directly:</p>
<pre><code class="lang-bash">pip install mcp-server-package
</code></pre>
<p>Then use this simpler configuration:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"example-mcp"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"mcp-server-command"</span>
    }
  }
}
</code></pre>
<p>This method works when the MCP server provides a command-line entry point through its setup configuration.</p>
<h3 id="heading-method-2-using-uv-package-manager">Method 2: Using UV Package Manager</h3>
<p>UV provides more robust dependency management – perfect if you're tired of Python version conflicts:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install UV</span>
curl -LsSf https://astral.sh/uv/install.sh | sh

<span class="hljs-comment"># Use UV in your configuration</span>
{
  <span class="hljs-string">"mcpServers"</span>: {
    <span class="hljs-string">"example-mcp"</span>: {
      <span class="hljs-string">"command"</span>: <span class="hljs-string">"uv"</span>,
      <span class="hljs-string">"args"</span>: [
        <span class="hljs-string">"run"</span>,
        <span class="hljs-string">"--with"</span>, <span class="hljs-string">"fastmcp"</span>,
        <span class="hljs-string">"python"</span>,
        <span class="hljs-string">"/path/to/mcp-server/server.py"</span>
      ],
      <span class="hljs-string">"cwd"</span>: <span class="hljs-string">"/path/to/mcp-server"</span>
    }
  }
}
</code></pre>
<p>UV automatically manages Python versions and dependencies, reducing the likelihood of environment-related errors.</p>
<h2 id="heading-how-to-prevent-future-enoent-errors">How to Prevent Future ENOENT Errors</h2>
<p>To avoid this issue in the future, follow these best practices:</p>
<h3 id="heading-1-use-virtual-environment-copies-instead-of-symlinks">1. Use Virtual Environment Copies Instead of Symlinks</h3>
<p>When creating virtual environments, use the <code>--copies</code> flag:</p>
<pre><code class="lang-bash">python3 -m venv venv --copies
</code></pre>
<p>This creates actual copies of files instead of symlinks, making your environment more resilient to Python upgrades.</p>
<h3 id="heading-2-pin-your-homebrew-python-version">2. Pin Your Homebrew Python Version</h3>
<p>Prevent automatic Python upgrades that break environments:</p>
<pre><code class="lang-bash">brew pin python@3.11
</code></pre>
<p>Remember to unpin when you're ready to upgrade intentionally.</p>
<h3 id="heading-3-create-a-health-check-script">3. Create a Health Check Script</h3>
<p>Save this script as <code>health_check.sh</code> in your MCP server directory:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-comment"># health_check.sh</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Checking Python virtual environment..."</span>
<span class="hljs-built_in">source</span> venv/bin/activate

python -c <span class="hljs-string">"import sys; print(f'Python: {sys.executable}')"</span>
python -c <span class="hljs-string">"print('✓ Python is working')"</span>

<span class="hljs-comment"># Check for common MCP dependencies</span>
python -c <span class="hljs-string">"import json; print('✓ JSON module available')"</span>
python -c <span class="hljs-string">"import asyncio; print('✓ Asyncio available')"</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"Health check complete!"</span>
</code></pre>
<p>Make it executable and run it periodically:</p>
<pre><code class="lang-bash">chmod +x health_check.sh
./health_check.sh
</code></pre>
<h3 id="heading-4-document-your-python-version">4. Document Your Python Version</h3>
<p>Create a <code>.python-version</code> file in your project:</p>
<pre><code class="lang-bash">python --version &gt; .python-version
</code></pre>
<p>This helps you remember which Python version the project was built with.</p>
<h2 id="heading-troubleshooting-common-issues">Troubleshooting Common Issues</h2>
<p>Even with the fix applied, you might encounter these challenges:</p>
<h3 id="heading-import-errors">Import Errors</h3>
<p>If you see import-related errors, ensure all dependencies are installed:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> venv/bin/activate
pip list  <span class="hljs-comment"># Check installed packages</span>
pip install -r requirements.txt  <span class="hljs-comment"># Reinstall if needed</span>
</code></pre>
<h3 id="heading-permission-denied-errors">Permission Denied Errors</h3>
<p>Make sure your server file is executable:</p>
<pre><code class="lang-bash">chmod +x server.py
</code></pre>
<h3 id="heading-claude-desktop-not-finding-the-server">Claude Desktop Not Finding the Server</h3>
<p>Double-check your configuration paths are absolute, not relative:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Good - absolute path</span>
<span class="hljs-string">"/Users/username/projects/mcp-server/server.py"</span>

<span class="hljs-comment"># Bad - relative path</span>
<span class="hljs-string">"./server.py"</span>
</code></pre>
<h3 id="heading-server-starts-but-claude-cant-connect">Server Starts, But Claude Can't Connect</h3>
<p>Verify that the transport method matches between your server and the configuration. Most MCP servers use STDIO, but some might use HTTP or WebSocket transports.</p>
<h3 id="heading-multiple-python-installations">Multiple Python Installations</h3>
<p>If you have multiple Python versions, be explicit about which one to use:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Check available Python versions</span>
ls -la /usr/<span class="hljs-built_in">local</span>/bin/python*

<span class="hljs-comment"># Use a specific version</span>
/usr/<span class="hljs-built_in">local</span>/bin/python3.11 -m venv venv
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've successfully fixed the "spawn python ENOENT" error by rebuilding your Python virtual environment and properly configuring your MCP server for Claude Desktop. You've also learned how to prevent future mistakes and troubleshoot common issues.</p>
<p>With your MCP server running smoothly, you can now:</p>
<ul>
<li><p>Build custom tools that extend Claude's capabilities</p>
</li>
<li><p>Create integrations with your favorite services</p>
</li>
<li><p>Develop specialized workflows for your specific needs</p>
</li>
<li><p>Share your MCP servers with the community</p>
</li>
</ul>
<p>The <a target="_blank" href="https://www.anthropic.com/news/model-context-protocol">MCP</a> ecosystem is growing rapidly, with new servers and tools being developed constantly. Whether you're building file system tools, API integrations, or custom utilities, you now have the foundation to create and maintain robust MCP servers.</p>
<p>Happy building, and enjoy your error-free development journey! For more tutorials, follow my work on <a target="_blank" href="https://github.com/Olanetsoft">GitHub</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Beginner Developer's Guide to Kanban ]]>
                </title>
                <description>
                    <![CDATA[ First, a confession: When I was learning to code, my “workflow” was a mess. Sticky notes. Google Docs. Random Trello boards I never checked again. And a to-do list that somehow never got any shorter. Then I joined a real team. Suddenly, I was introdu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-beginner-developers-guide-to-kanban/</link>
                <guid isPermaLink="false">68815e6054ad71fa4b3b7bb6</guid>
                
                    <category>
                        <![CDATA[ agile ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agile methodology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Agile Software Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Career ]]>
                    </category>
                
                    <category>
                        <![CDATA[ interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ kanban ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kanban boards ]]>
                    </category>
                
                    <category>
                        <![CDATA[ project management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Product Management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Product Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ workflow ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aditya Vikram Kashyap ]]>
                </dc:creator>
                <pubDate>Wed, 23 Jul 2025 22:12:48 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753300952223/508231c9-f0bc-4aa8-9c97-5ad4157891b9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>First, a confession<strong>:</strong> When I was learning to code, my “workflow” was a mess. Sticky notes. Google Docs. Random Trello boards I never checked again. And a to-do list that somehow never got any shorter.</p>
<p>Then I joined a real team.</p>
<p>Suddenly, I was introduced to this thing called <strong>Kanban</strong> – and I realized I’d been treating software like a solo art project, not a process.</p>
<p>If that sounds familiar, you’re in the right place.</p>
<p>This guide will walk you through <strong>how Kanban actually works</strong>, how developers use it to track and prioritize work, and how it can help you stay sane when juggling bugs, features, and real-world deadlines.</p>
<p>Without further delay, lets get into it.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-so-what-is-kanban">So… What Is Kanban?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-classic-kanban-board-three-simple-columns">The Classic Kanban Board: Three Simple Columns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-developers-use-kanban-in-real-life">How Developers Use Kanban in Real Life</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-kanban-vs-scrum-whats-the-difference">Kanban vs Scrum: What’s the Difference?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-so-which-one-should-you-use-scrum-or-kanban">So which one should you use Scrum or Kanban?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-tools-do-teams-use-for-kanban">What Tools Do Teams Use for Kanban?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-kanban-to-manage-your-own-coding-projects">How to Use Kanban to Manage Your Own Coding Projects</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts-why-kanban-isnt-just-a-board">Final Thoughts: Why Kanban Isn’t Just a Board</a></p>
</li>
</ul>
<h2 id="heading-so-what-is-kanban">So… What Is Kanban?</h2>
<p>At its core, Kanban is a <strong>visual way to manage work</strong>. It helps teams (or team members) see:</p>
<ul>
<li><p>What needs to get done</p>
</li>
<li><p>What’s in progress</p>
</li>
<li><p>What’s finished</p>
</li>
<li><p>Where things are getting stuck</p>
</li>
</ul>
<p>The concept comes from lean manufacturing, but in tech, it’s often used in Agile teams that need flexibility without the structure of Scrum sprints.</p>
<p>Think of Kanban like a whiteboard that tells a story. Not just what’s done, but how work flows.</p>
<h2 id="heading-the-classic-kanban-board-three-simple-columns">The Classic Kanban Board: Three Simple Columns</h2>
<p>So what exactly is a Kanban board? At its core, it’s a visual representation of your workflow – a board that shows all the work your team (or you, solo warrior) are juggling, and where each task stands.</p>
<p>It can be physical, like an actual whiteboard with sticky notes that move from one column to the next. Or digital, using tools like Trello, Jira, GitHub Projects, or Notion. The key is that it’s visual and up-to-date. You can walk into a room or open a tab and instantly understand: What’s being worked on? What’s ready to go? Where are things stuck?</p>
<p>It’s like having your brain on a wall, but organized. And slightly less chaotic.</p>
<p>The beauty of Kanban is how dead simple it is to get started. At minimum, your board has three columns:</p>
<table><tbody><tr><td><p><strong>&nbsp;To Do</strong></p></td><td><p><strong>In Progress</strong></p></td><td><p><strong>Done</strong></p></td></tr></tbody></table>

<p>Each task – or <strong>card</strong> – moves from left to right as it gets worked on.</p>
<p>Let’s say your team is building a blog platform. Your Kanban board might have cards like:</p>
<ul>
<li><p>“Create signup form”</p>
</li>
<li><p>“Fix image upload bug”</p>
</li>
<li><p>“Deploy staging build”</p>
</li>
</ul>
<p>Now, while Kanban is flexible, it can absolutely be taken too far.</p>
<p>I’ve seen boards with more columns than a Greek temple: “Needs Review,” “Pending Client Feedback,” “QA Rework Round 2,” “Blocked but Still Hopeful,” “In Existential Limbo,” and so on. Every card had six tags, three owners, two checklists, and one migraine.</p>
<p>The lesson? Don’t turn your board into a bureaucratic jungle.</p>
<p>You don’t need to account for every edge case. Start simple: “To Do,” “In Progress,” “Review,” “Done.” These basic stages cover most workflows. If you discover a real need for something more – like a dedicated “QA” column or “Blocked” column – add it intentionally, not because you feel like your board needs to look fancy.</p>
<p>Remember: A Kanban board should be helpful, not overwhelming. If you spend more time managing the board than doing the work on it… it’s doing the opposite of what it’s meant to do.</p>
<h2 id="heading-how-developers-use-kanban-in-real-life">How Developers Use Kanban in Real Life</h2>
<p>Here’s how you might interact with a Kanban board on a dev team:</p>
<ol>
<li><p>You pick up a card from “To Do” – let’s say, “Add dark mode toggle.”</p>
</li>
<li><p>You move it to “In Progress.”</p>
</li>
<li><p>When it’s ready for review, you might move it to a temporary “Review” or “Testing” column.</p>
</li>
<li><p>Once it’s merged, tested, and deployed, you move it to “Done.”</p>
</li>
<li><p>You smile, drink some coffee, and grab the next card.</p>
</li>
</ol>
<p>That’s it. But over time, this process helps the whole team:</p>
<ul>
<li><p>Spot bottlenecks</p>
</li>
<li><p>Prevent duplicate work</p>
</li>
<li><p>Reduce context switching</p>
</li>
<li><p>Keep everyone aligned</p>
</li>
</ul>
<h3 id="heading-whats-a-wip-limit-and-why-should-you-care">What’s a WIP Limit — And Why Should You Care?</h3>
<p>WIP = <strong>Work In Progress</strong>. This is the most important concept to keep us in check.</p>
<p>One of Kanban’s key principles is <strong>limiting how many things you’re working on at once</strong>. Because guess what? Multitasking kills momentum.</p>
<p>A typical WIP limit might look like:</p>
<ul>
<li><p>No more than 2–3 cards per person in “In Progress” Again this is best practice, but folks do pick up a lot and then they end up being the bottleneck.</p>
</li>
<li><p>No more than 5 tasks waiting on QA.</p>
</li>
</ul>
<p>Why? Because when everything’s urgent, nothing gets done. WIP limits force you to finish one thing before you start more – and that’s how real velocity happens.</p>
<p>If there are more than 5 tasks in the “To Do” column, the team doesn’t take up new ones. Instead, everyone chips in to see how they can help unclog the bottleneck. A bottleneck is your worst enemy in Kanban, and you want to resolve it so items move smoothly on time and on target.</p>
<p><a target="_blank" href="https://youtu.be/R8dYLbJiTUE?si=Hh00XXI4_1urv4Mp">Here’s a video</a> recapping key concepts.</p>
<h2 id="heading-kanban-vs-scrum-whats-the-difference"><strong>Kanban vs Scrum: What’s the Difference?</strong></h2>
<p>You’ve probably heard Scrum and Kanban mentioned in the same breath – and both are popular Agile frameworks. But they’re not interchangeable.</p>
<p>Scrum is structured, with roles like Product Owner and Scrum Master, and work gets organized into time-boxed sprints. It’s perfect for teams that benefit from rhythm and rituals – like sprint planning, daily standups, and retrospectives.</p>
<p>Kanban, on the other hand, is a little looser. No official roles, no set sprint timelines. Work flows continuously, and change can happen anytime. It’s perfect for teams who need more flexibility and fewer ceremonies.</p>
<p>So how do they compare in practice? Let’s break it down:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Key Differentiating Factors</strong></td><td><strong>Scrum</strong></td><td><strong>Kanban</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Time-based</td><td>Yes – 1–2 week sprints</td><td>No – continuous flow</td></tr>
<tr>
<td>Roles</td><td>PO, SM, Developers</td><td>No specific roles required</td></tr>
<tr>
<td>Planning</td><td>Sprint planning, retros, and so on</td><td>On-demand, just-in-time</td></tr>
<tr>
<td>Cadence</td><td>Fixed sprint cycle</td><td>Flexible, ongoing</td></tr>
<tr>
<td>Use case</td><td>Complex, structured teams</td><td>Continuous delivery teams</td></tr>
</tbody>
</table>
</div><p><strong>Bottom line:</strong></p>
<ul>
<li><p>Scrum is a scheduled loop. Kanban is a living flow.</p>
</li>
<li><p>One’s a playbook. The other’s a status window.</p>
</li>
</ul>
<p><a target="_blank" href="https://youtu.be/F5QIqFEDv2k?si=jvNoAiHmrv_iq-Lx">Here’s a video</a> on the main differences between Scrum and Kanban you can watch if you want more detail.</p>
<h2 id="heading-so-which-one-should-you-use-scrum-or-kanban"><strong>So which one should you use Scrum or Kanban?</strong></h2>
<p>So… which one should you use?</p>
<p>It really depends on your team, your product, and your pain points.</p>
<p>✔️ If you’re working on a brand-new product where requirements shift a lot, and your team thrives with structure and routines – Scrum is likely the better fit. Sprints give you a sense of pacing, and ceremonies help ensure alignment.</p>
<p>✔️ If you’re managing ongoing work like bug triage, tech debt, infrastructure tasks, or anything that’s more “whenever it comes in” than “we need to ship this in two weeks” – Kanban gives you flexibility and visibility without the overhead.</p>
<p>And yes, there’s such a thing as <strong>Scrumban</strong> – a hybrid approach where teams use visual boards and WIP limits from Kanban, but keep some of Scrum’s structure like standups and retros. It’s like Agile tapas: you get the flavors that work best for your appetite.</p>
<p><a target="_blank" href="https://youtu.be/kiI3IweyAeQ?si=M1mtS5HCCcGcT78J">Here is a detailed video</a> that’'ll teach you more about how Scrumban works in practice.</p>
<p>Watch the Scrumban video only when you are familiar and comfortable with both Scrum and Kanban – otherwise, you might get confused from the cross-pollination of ideas and frameworks.</p>
<p>I personally have never seen a Scrumban implementation thats scaled well – too many folks trying too many things and none of them work. But thats just based on my experience – it may work for you and your team. I’ll let you be the judge.</p>
<h2 id="heading-what-tools-do-teams-use-for-kanban"><strong>What Tools Do Teams Use for Kanban?</strong></h2>
<p>You’ve probably seen (or used) one already:</p>
<ul>
<li><p><strong>Trello</strong> – Simple and great for solo or small teams</p>
</li>
<li><p><strong>Jira</strong> – Enterprise-level, customizable workflows</p>
</li>
<li><p><strong>GitHub Projects</strong> – Lightweight but powerful for devs</p>
</li>
<li><p><strong>ClickUp / Asana / Notion</strong> – Integrated with docs/tasks</p>
</li>
</ul>
<p>Kanban isn’t tied to any one tool – you can use an app, a browser tab, or a whiteboard and a pack of sticky notes from the office supply closet. What matters is how you use it. But let’s walk through some of the most common tools and what they offer in a Kanban context:</p>
<h3 id="heading-trello">🟩 <strong>Trello</strong></h3>
<p>Trello is probably the easiest way to start with Kanban. It gives you a simple digital board with columns and cards you can drag and drop. It’s great for devs or small teams who don’t need tons of automation – just a clean place to track work visually.</p>
<h3 id="heading-jira">🟨 <strong>Jira</strong></h3>
<p>Jira is a heavyweight – and while it’s built for Scrum, it also supports robust Kanban boards. You can define custom workflows, use built-in reports like cumulative flow diagrams, enforce WIP limits, and manage team velocity. Ideal for large teams that need traceability, integrations, and permissions.</p>
<h3 id="heading-github-projects">🟦 <strong>GitHub Projects</strong></h3>
<p>If your code lives in GitHub, GitHub Projects is a clean way to stay close to your codebase. It lets you create Kanban-style boards with issues and pull requests as cards, so you’re never toggling between tools just to track what’s in progress.</p>
<h3 id="heading-clickup-asana-notion">🟧 <strong>ClickUp / Asana / Notion</strong></h3>
<p>These are all-in-one productivity platforms. They combine Kanban boards with documentation, team chat, calendars, and reporting. If your team needs more than just “move card left to right,” these tools let you manage projects, meetings, notes, and workflows in one place.</p>
<h3 id="heading-whiteboard-sticky-notes">🟪 <strong>Whiteboard + Sticky Notes</strong></h3>
<p>Don’t underestimate the analog approach. It’s fast. It’s visible. It’s tactile. Physically moving a task from “Doing” to “Done” gives you a sense of progress no digital tool can match. And when something’s blocked? Slap a red sticky on it and call it a day.</p>
<p>Bottom line: The best tool is the one your team will <em>actually</em> use. Fancy doesn’t beat consistent. And the actual tool doesn’t matter as much as the <strong>discipline</strong> your team has to actually use it.</p>
<h2 id="heading-how-to-use-kanban-to-manage-your-own-coding-projects"><strong>How to Use Kanban to Manage Your Own Coding Projects</strong></h2>
<p>Even if you're not on a team yet, Kanban is great for your own workflow. Here’s how you can use it to help yourself out:</p>
<ol>
<li><p>Create a basic 3-column board (To Do, In Progress, Done)</p>
</li>
<li><p>Write out every task, big or small</p>
</li>
<li><p>Set a WIP limit (for example, no more than 2 tasks at once)</p>
</li>
<li><p>Update it daily. Make it a ritual.</p>
</li>
<li><p>Review your flow weekly – What got stuck? What moved fast?</p>
</li>
</ol>
<p> Example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>To-Do</strong></td><td><strong>In Progress</strong></td><td><strong>Done</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Fix CSS Layout</td><td>Add blog search bar</td><td>Set up Netlify</td></tr>
<tr>
<td>Write README</td><td></td><td>Deploy v1</td></tr>
</tbody>
</table>
</div><p>You’ll be shocked how much clearer your thinking gets when you can <em>see</em> your work. It’s simple but super powerful to visualize your work it in this way.</p>
<h2 id="heading-final-thoughts-why-kanban-isnt-just-a-board"><strong>Final Thoughts: Why Kanban Isn’t Just a Board</strong></h2>
<p>Kanban isn’t just a tool – it’s a mindset.</p>
<p>It helps you focus. It helps your team collaborate. And it gives everyone – even non-technical folks – visibility into what’s going on.</p>
<p>If you’re learning to code and want to feel more confident working with others, <strong>learning Kanban is low-effort, high-impact</strong>.</p>
<p>So don’t wait until your first job. Start using it now – and show up to that standup with confidence.</p>
<p>I hope this small 101 Guide to Kanban was helpful to you all. My sole purpose to write this was to help beginner developers understand Kanban as a practical workflow system – especially for those transitioning from solo coding to collaborative, real-world development environments. It aims to demystify the methodology in a casual, beginner-friendly tone while still offering actionable guidance.</p>
<p>I hope you enjoyed my beginners guide to Kanban.</p>
<p>Until next time, keep Learning, Unlearning and Relearning, folks….</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Beginner Developer's Guide to Scrum ]]>
                </title>
                <description>
                    <![CDATA[ Let me guess: you’re learning to code…alone. You’ve been grinding through tutorials. You've built a portfolio site, maybe deployed a few projects on GitHub. And now you're trying to land a job or join a team. Then the interviews start. Suddenly, peop... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-beginner-developers-guide-to-scrum/</link>
                <guid isPermaLink="false">68813c7579e092b166d373b6</guid>
                
                    <category>
                        <![CDATA[ Scrum ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agile development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ project management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ education ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Product Management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Career ]]>
                    </category>
                
                    <category>
                        <![CDATA[ workflow ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aditya Vikram Kashyap ]]>
                </dc:creator>
                <pubDate>Wed, 23 Jul 2025 19:48:05 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753300058064/7046dd6c-1d9e-4f06-9ca1-65b3bb7eec83.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let me guess: you’re learning to code…alone.</p>
<p>You’ve been grinding through tutorials. You've built a portfolio site, maybe deployed a few projects on GitHub. And now you're trying to land a job or join a team.</p>
<p>Then the interviews start.</p>
<p>Suddenly, people ask:</p>
<ul>
<li><p>"Are you familiar with Agile?"</p>
</li>
<li><p>"Have you worked in a Scrum environment?"</p>
</li>
<li><p>"What’s your experience with sprints?"</p>
</li>
</ul>
<p>Cue the imposter syndrome. Because no one teaches this stuff in JavaScript 101.</p>
<p>This guide is for you.</p>
<p>I’ll help make the Scrum process – a very common way developers work together – <em>make actual sense</em>. I’ll walk you through the basics, but also tell you what developers actually <em>do</em>, how standups feel when you're new, and what’s expected of you when you’re no longer coding in a vacuum.</p>
<p>Let’s break it down.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-even-is-scrum">What Even Is Scrum?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-three-roles-in-scrum-and-who-does-what">The Three Roles in Scrum (and Who Does What)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-scrum-rhythm-what-a-sprint-actually-looks-like">The Scrum Rhythm: What a Sprint Actually Looks Like</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-who-attends-the-ceremonies">Who attends the Ceremonies:</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-standups-where-you-talk-like-a-human-not-a-robot">Standups: Where You Talk Like a Human, Not a Robot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sprint-planning">Sprint Planning</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-a-user-story-and-why-does-it-sound-like-a-childrens-book">What’s a User Story and Why Does It Sound Like a Children’s Book?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-counts-as-done-definition-of-done-and-why-its-important">What Counts as “Done”? Definition of Done and Why It’s Important</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demos-retros-and-saying-the-hard-things">Demos, Retros, and Saying the Hard Things</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-you-might-encounter">Tools You Might Encounter</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-if-youre-preparing-for-a-job-heres-what-you-can-do">If You’re Preparing for a Job, Here’s What You Can Do</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ul>
<h2 id="heading-what-even-is-scrum"><strong>What Even Is Scrum?</strong></h2>
<p>Scrum is not a tool. It’s not a software. It’s not some elite thing only PMs care about.</p>
<p>It’s a lightweight framework that helps software teams build things incrementally, together, in short focused cycles called sprints.</p>
<p>Scrum is used by everyone from FAANG teams to indie dev shops because it helps:</p>
<ul>
<li><p>Keep teams aligned</p>
</li>
<li><p>Deliver working software fast</p>
</li>
<li><p>Course-correct often</p>
</li>
<li><p>Spot problems early (before they go nuclear)</p>
</li>
</ul>
<p>It’s the opposite of the old-school “build for a year and pray it works” model.</p>
<h2 id="heading-the-three-roles-in-scrum-and-who-does-what"><strong>The Three Roles in Scrum (and Who Does What)</strong></h2>
<p>Scrum officially defines three roles. Here's what that means in practice:</p>
<h3 id="heading-1-product-owner-po"><strong>1. Product Owner (PO)</strong></h3>
<p>Think: Vision-holder. They decide <em>what</em> the team builds and <em>why</em>. A product owner:</p>
<ul>
<li><p>Writes user stories (think of these as feature requests written from a user’s point of view)</p>
</li>
<li><p>Prioritizes the work</p>
</li>
<li><p>Clarifies what success looks like</p>
</li>
<li><p>Says “yes” or “not yet” to features</p>
</li>
</ul>
<h3 id="heading-2-scrum-master-sm"><strong>2. Scrum Master (SM)</strong></h3>
<p>Think: Air-traffic controller meets therapist. They make sure the process works. The are master Facilitators, like between Dev and PO’s. A Scrum Master:</p>
<ul>
<li><p>Facilitates meetings</p>
</li>
<li><p>Removes blockers (“Your AWS access is stuck? I’ll escalate it.”)</p>
</li>
<li><p>Coaches the team on Scrum practices</p>
</li>
<li><p>Doesn’t manage people – manages <em>flow</em></p>
</li>
</ul>
<h3 id="heading-3-developers-you"><strong>3. Developers (YOU!)</strong></h3>
<p>Think: Builders. You write code, test it, ship it, fix it, and improve it. You also:</p>
<ul>
<li><p>Break down stories into tasks</p>
</li>
<li><p>Pick up work from the team board (like Jira or Trello)</p>
</li>
<li><p>Communicate progress</p>
</li>
<li><p>Demo what you’ve built at the end of the sprint</p>
</li>
</ul>
<p>You might also work with designers, testers, or DevOps folks – but within Scrum, you’re all “developers” building a product together.</p>
<h2 id="heading-the-scrum-rhythm-what-a-sprint-actually-looks-like"><strong>The Scrum Rhythm: What a Sprint Actually Looks Like</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752809790048/253fd92b-1ebe-4f3e-bfbc-48719676dc82.png" alt="253fd92b-1ebe-4f3e-bfbc-48719676dc82" class="image--center mx-auto" width="900" height="530" loading="lazy"></p>
<p>Image Source: <a target="_blank" href="https://www.invensislearning.com/blog/what-are-scrum-ceremonies/">https://www.invensislearning.com/blog/what-are-scrum-ceremonies/</a></p>
<h3 id="heading-understanding-the-scrum-cycle"><strong>Understanding the Scrum Cycle</strong></h3>
<p>So, what does it <em>actually</em> look like when a team uses Scrum to build software?</p>
<p>Let’s walk through a full sprint – not just the buzzwords, but what really happens when a group of humans tries to plan, build, review, and improve together. Think of this as your backstage pass to the rhythm of modern teamwork.</p>
<h3 id="heading-step-1-build-and-refine-the-product-backlog">📦 Step 1: Build and Refine the Product Backlog</h3>
<p>Before any coding starts, the team needs to agree on <em>what</em> they might build – not just this week, but in the near future too.</p>
<p>That’s where the <strong>Product Backlog</strong> comes in. This is a big, running list of everything the product might need – features, bug fixes, improvements, ideas, and maybe a few wild dreams. It’s like the wishlist for the product, but more organized (ideally).</p>
<p>The Product Owner is responsible for maintaining and prioritizing this list. They decide what’s most important to work on based on customer needs, business goals, and feedback.</p>
<p>But the PO doesn’t do this in isolation. Enter the <strong>Backlog Refinement meeting</strong>.</p>
<p>In these sessions, the Scrum Team – that’s the PO, the Scrum Master (SM), and the Developers – come together to:</p>
<ul>
<li><p><strong>Review</strong> the most important upcoming items</p>
</li>
<li><p><strong>Clarify</strong> any vague or confusing parts of each task</p>
</li>
<li><p><strong>Break big items</strong> down into smaller, buildable pieces called <strong>user stories</strong></p>
</li>
<li><p><strong>Estimate effort</strong> (how much time or complexity is involved for each story)</p>
</li>
</ul>
<p>This meeting makes sure the team isn’t caught off guard in the sprint – that they understand the work ahead and can actually start sprinting when the time comes.</p>
<h3 id="heading-step-2-sprint-planning-what-are-we-building-this-time">🧭 Step 2: Sprint Planning – What Are We Building This Time?</h3>
<p>Now that we’ve got a solid backlog, it’s time to pick what to build <em>right now</em>.</p>
<p>At the start of each sprint (which typically lasts 1 to 4 weeks), the team holds a <strong>Sprint Planning meeting</strong>. This meeting sets the stage for the entire sprint – it’s like the huddle before the big game.</p>
<p>In Sprint Planning, the team:</p>
<ul>
<li><p>Reviews the top items from the backlog</p>
</li>
<li><p>Discusses what can realistically be completed based on their availability and capacity</p>
</li>
<li><p>Chooses a handful of these stories to commit to</p>
</li>
<li><p><strong>Defines a Sprint Goal</strong> – a simple statement that captures the purpose of this sprint</p>
</li>
</ul>
<p>For example, the Sprint Goal might be:<br>🎯 <em>“Allow users to reset their passwords.”</em></p>
<p>Every user story chosen should contribute to that goal. The collection of these stories becomes the <strong>Sprint Backlog</strong> – basically, the to-do list for the sprint.</p>
<p>So when we say:</p>
<p>“The team selects an ordered list of user stories to comprise the Sprint Backlog for the next sprint, which will be achievable to satisfy the Sprint Goal...”</p>
<p>We’re really just saying:<br>👉 <em>“Pick a realistic number of important tasks that, if completed, will help us hit our target for the sprint.”</em></p>
<p>Not too vague. Not too ambitious. Just achievable and focused.</p>
<h3 id="heading-step-3-daily-standups-stay-in-sync">☀️ Step 3: Daily Standups – Stay in Sync</h3>
<p>Now the sprint is underway! But how does everyone stay aligned and avoid working in silos?</p>
<p>That’s where the <strong>Daily Standup</strong> comes in. Every day – usually in the morning – the team has a quick check-in (about 15 minutes) where each person answers three questions:</p>
<ol>
<li><p><strong>What did I do yesterday?</strong></p>
</li>
<li><p><strong>What am I working on today?</strong></p>
</li>
<li><p><strong>Is anything blocking me?</strong> (that is, am I stuck?)</p>
</li>
</ol>
<p>Example:</p>
<p>“Yesterday I set up the login API integration. Today I’ll work on the UI validation. I’m blocked on getting access to the staging database — may need help.”</p>
<p>These standups keep the team in sync and surface blockers early so they can be addressed quickly. They’re not about micromanaging or showing off. They’re about visibility and support.</p>
<h3 id="heading-whats-a-sprint-burndown-chart">📉 What’s a Sprint Burndown Chart?</h3>
<p>You might hear your team mention a “burndown chart.” No, this isn’t about things going down in flames (hopefully).</p>
<p>A <strong>Sprint Burndown Chart</strong> is a graph that shows how much work is left in the sprint – day by day.</p>
<ul>
<li><p>The <strong>y-axis</strong> is the amount of work remaining (often measured in story points or tasks)</p>
</li>
<li><p>The <strong>x-axis</strong> is the number of days left in the sprint</p>
</li>
</ul>
<p>The line should ideally trend downward as work gets completed – hence “burning down.” If it flattens out or slopes up, that’s a red flag that the team might be stuck, behind schedule, or not updating the board.</p>
<p>Think of it as a visual heartbeat of the sprint. You can learn more via a practical example <a target="_blank" href="https://youtu.be/2K84aZn9AY8?si=tS8oMGxVD0CYtnlw">in this video</a>.</p>
<h3 id="heading-step-4-sprint-review-show-what-youve-built">🖥️ Step 4: Sprint Review – Show What You’ve Built</h3>
<p>At the end of the sprint, the team holds a <strong>Sprint Review</strong> (also called a “demo”). This is where you show what was actually built during the sprint.</p>
<ul>
<li><p>The <strong>Developers</strong> demo working features – live, not just screenshots</p>
</li>
<li><p>The <strong>Product Owner</strong> reviews whether the Sprint Goal was achieved</p>
</li>
<li><p>Stakeholders may ask questions, give feedback, or suggest tweaks</p>
</li>
</ul>
<p>This meeting isn’t just for show – it’s a feedback loop. It helps the team validate that what they built is useful, usable, and meets expectations. If changes are needed, those get added to the backlog for future sprints.</p>
<h3 id="heading-step-5-sprint-retrospective-look-back-to-move-forward">🔍 Step 5: Sprint Retrospective – Look Back to Move Forward</h3>
<p>Once the review is done, the team shifts focus from <em>what</em> they built to <em>how</em> they worked together.</p>
<p>Enter the <strong>Sprint Retrospective</strong> – a meeting to reflect on the process, not the product.</p>
<p>The team discusses:</p>
<ul>
<li><p>✅ What went well</p>
</li>
<li><p>❌ What didn’t go so well</p>
</li>
<li><p>🔁 What could be improved next time</p>
</li>
</ul>
<p>This isn’t about pointing fingers. It’s about learning, adapting, and continuously improving how the team collaborates.</p>
<p>The <strong>Scrum Master</strong> often facilitates this meeting and helps turn feedback into action items for the next sprint. For example:</p>
<p>“We underestimated testing time. Next sprint, let’s budget for QA earlier.”</p>
<p>The best teams take retros seriously. Why? Because even if your code is perfect, your <em>process</em> needs tuning too – and small process changes often lead to big gains.</p>
<h3 id="heading-scrum-is-a-loop">♻️ Scrum Is a Loop</h3>
<p>Here’s the rhythm:</p>
<ol>
<li><p>Plan the sprint</p>
</li>
<li><p>Check in daily</p>
</li>
<li><p>Build and demo the product</p>
</li>
<li><p>Reflect and improve</p>
</li>
</ol>
<p>Then do it all over again – with slightly better coordination and slightly more trust each time.</p>
<p>It’s not about being fast. It’s about being intentional, consistent, and collaborative.</p>
<h3 id="heading-example-sprint">Example Sprint</h3>
<p>Let’s say, for example, that your team does 4-week sprints. (Keep in mind that Sprints can differ by team, nature of product, release cycles, and so on.)</p>
<p>Here’s the rough beat:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Week</strong></td><td><strong>What Happens (Sprint Ceremonies)</strong></td><td><strong>Your Role</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td><strong>Sprint Planning</strong></td><td>Help estimate effort, pick what to build</td></tr>
<tr>
<td>1-4</td><td><strong>Daily Stand ups</strong> (15 mins)</td><td>Share what you’re doing &amp; any blockers</td></tr>
<tr>
<td>1-3</td><td><strong>Development Time</strong></td><td>Code, test, commit, fix, push, repeat</td></tr>
<tr>
<td>3.5-4</td><td><strong>Sprint Review</strong></td><td>Demo what you built</td></tr>
<tr>
<td>4</td><td><strong>Sprint Retrospective</strong></td><td>Reflect on how the sprint went as a team</td></tr>
</tbody>
</table>
</div><p>Scrum works in <strong>loops</strong>. Every 2-4 weeks (depending on your cadence and sprint cycle), your team should have working, demo-able software to show for it – even if it’s small.</p>
<p>And no, it’s not about “speed.” It’s about consistency, communication, and collaboration.</p>
<h2 id="heading-who-attends-the-ceremonies"><strong>Who attends the Ceremonies:</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Ceremony</strong></td><td><strong>Who Attends</strong></td><td><strong>Why They’re There</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Sprint Planning</strong></td><td>Product Owner (PO), Scrum Master (SM), Development Team</td><td>To define what will be delivered and how the work will be accomplished</td></tr>
<tr>
<td><strong>Daily Standup</strong></td><td>Development Team, Scrum Master (optional), PO (optional)</td><td>To sync on progress, share blockers, and coordinate efforts</td></tr>
<tr>
<td><strong>Sprint Review</strong></td><td>Development Team, Scrum Master, Product Owner, Stakeholders</td><td>To demo the work, get feedback, and assess if goals were met</td></tr>
<tr>
<td><strong>Sprint Retrospective</strong></td><td>Development Team, Scrum Master, Product Owner (optional)</td><td>To reflect on the process, identify what worked/what didn’t, and improve the next sprint</td></tr>
<tr>
<td><strong>Backlog Refinement</strong></td><td>Product Owner, Development Team, Scrum Master (optional)</td><td>To clarify upcoming stories, estimate work, and prepare for future sprint planning</td></tr>
</tbody>
</table>
</div><p>Now lets dive deeper and understand practically how each of these ceremonies work:</p>
<h2 id="heading-standups-where-you-talk-like-a-human-not-a-robot"><strong>Standups: Where You Talk Like a Human, Not a Robot</strong></h2>
<p>So how does the team actually stay connected day to day? That’s where standups come in.</p>
<p>Every morning, your team meets briefly – usually on Zoom or in a circle – and you answer 3 questions:</p>
<ol>
<li><p>What did I work on yesterday?</p>
</li>
<li><p>What will I work on today?</p>
</li>
<li><p>What’s blocking me? Any impediments?</p>
</li>
</ol>
<p>Example:</p>
<p>"Yesterday I cleaned up the signup validation logic. Today I’m working on the email verification flow. I’m stuck on SendGrid config – might need help setting up credentials."</p>
<p>It’s not about impressing anyone. It’s about keeping everyone in sync. Some days you’ll say, “I spent the whole day debugging a CSS bug that turned out to be a semicolon.” That’s okay.</p>
<p>How does it work?</p>
<p>The Scrum Master gathers everyone in a huddle room, the PO and Dev Team included, and opens the the Standup. They are the facilitator of the ceremony. Everyone gets a chance to answer the 3 questions above (usually about 2-5 minutes each). It’s not a full report – it’s quick. When one person is done, they pass it on to someone else.</p>
<p>This ensures there is team cohesion and transparency.</p>
<p><a target="_blank" href="https://youtu.be/q_R9wQY4G5I?si=W1AcvcLXB-mnUM1f">Here is a video example of a standup</a>.</p>
<h2 id="heading-sprint-planning"><strong>Sprint Planning</strong></h2>
<p>The goal of the planning meeting is to answer the questions “What are we going to work on, and how are we going to do it?” It is critical for the team to have a shared goal and a shared commitment to this goal before beginning this ceremony.</p>
<p>Participants should:</p>
<ul>
<li><p>Measure growth</p>
</li>
<li><p>Sync with the Scrum Master</p>
</li>
<li><p>Sync with the Product Owner</p>
</li>
</ul>
<p>Sprint planning happens just before the sprint starts, and usually lasts for an hour or two. In this meeting, the team goes over a collection of <strong>user stories</strong> and discuss, plan, measure, and prioritize. This is where they decide what is going to be in scope for their upcoming sprint cycle.</p>
<p>The Product Owner will have a prioritized view of things in the backlog. They work with the team on each object or customer experience. Together, as a group they go through and make calculations, deciding to what they can commit.</p>
<h2 id="heading-whats-a-user-story-and-why-does-it-sound-like-a-childrens-book"><strong>What’s a User Story and Why Does It Sound Like a Children’s Book?</strong></h2>
<p>So you might be wondering: how do you know what to work on? What to build? So much work, so little time? Thats where <strong>user stories</strong> come in.</p>
<p>In Scrum, teams don’t just write vague tasks like “code the login.” Instead, they write user stories – short, human-centered feature descriptions that describe what the user needs, why they need it, and what success looks like.</p>
<p>Here’s an example:</p>
<p><em>As a user, I want to be able to reset my password, so I can access my account if I forget it.</em></p>
<p>User stories are the scaffolding of teamwork. They’re written with empathy, not just efficiency. And each one comes with <strong>acceptance criteria</strong> – a checklist that clarifies what “done” actually means:</p>
<ul>
<li><p>A “Forgot Password” link is visible</p>
</li>
<li><p>Clicking it shows a form</p>
</li>
<li><p>An email gets sent with a reset link</p>
</li>
</ul>
<p>Once a story is agreed upon, developers break it down into tasks, like “build form,” “hook into backend,” or “handle email validation.” It’s collaborative, not prescriptive. And user stories have priority so you know what’s the most important and what’s the least.</p>
<p>A helpful rule of thumb many teams use is the <a target="_blank" href="https://medium.com/@nic/writing-user-stories-with-gherkin-dda63461b1d2"><strong>Gherkin</strong>-style "Given–When–Then"</a> format:</p>
<ul>
<li><p><strong>Given</strong> some initial context</p>
</li>
<li><p><strong>When</strong> an event occurs</p>
</li>
<li><p><strong>Then</strong> a specific outcome should happen</p>
</li>
</ul>
<p>This ensures that everyone – devs, testers, and product owners – shares the same understanding of behavior and expectations.</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=7hoGqhb6qAs">Here is a great video example</a> thats outlines how to draft effective and powerful user stories.</p>
<h2 id="heading-what-counts-as-done-definition-of-done-and-why-its-important"><strong>What Counts as “Done”? Definition of Done and Why It’s Important</strong></h2>
<p>Now you might be wondering – how do I know when a task is done and can be closed out?</p>
<p>The <strong>Definition of Done</strong> is a type of documentation in the form of a <strong>team agreement</strong>. The Definition of Done identifies the conditions that need to be achieved in order for the product to be considered done (as in <strong>potentially shippable</strong>).</p>
<p>This is how we know that we "did the thing right". Meaning, we built the correct level of quality into the product. The Definition of Done is not the same as the acceptance criteria, which are written by the product owner to help us know we did the "right thing".</p>
<p>Every team has a Definition of Done – it’s not just “I pushed code.” It could mean:</p>
<ul>
<li><p>Code is written</p>
</li>
<li><p>Reviewed by a peer</p>
</li>
<li><p>Merged into main</p>
</li>
<li><p>Tested on staging</p>
</li>
<li><p>Possibly deployed</p>
</li>
</ul>
<p>This clarity keeps teams honest and accountable. No “it works on my machine” energy here. The DoD sets a quality bar. It prevents ambiguity, rework, and “it works on my machine” moments. When every card on the board passes the same finish line, teams move faster – and trust each other more.</p>
<p>Everyone should know what done is in a team. Either its Done as per DoD standards or its not.</p>
<p><a target="_blank" href="https://youtu.be/pYOJyQoBT3U?si=nVygkQQx79NaAOo4">Here is a beautiful video</a> highlighting the impotence of DoD.</p>
<h2 id="heading-demos-retros-and-saying-the-hard-things"><strong>Demos, Retros, and Saying the Hard Things</strong></h2>
<p>Once you’ve built the product, then comes demos (showcasing your work) and retros (analysis as a team on what when well and what areas to improve on).</p>
<p>In the retro, everyone’s encouraged to speak up:</p>
<ul>
<li><p>What went well?</p>
</li>
<li><p>What didn’t?</p>
</li>
<li><p>What should we try next time?</p>
</li>
</ul>
<p>Example:</p>
<p>“We missed a lot of stories because we didn’t account for testing time. Maybe we buffer next sprint with fewer tasks.”</p>
<p>The goal is not to blame – it’s to <em>improve</em>. Over time, this feedback loop becomes gold. The Scrum Master usually facilitates, collects feedback (via tools like Parabol, Miro, or sticky notes), and helps turn insights into actionable experiments for the next sprint.</p>
<p>Over time, retros become the heartbeat of team evolution.</p>
<p><a target="_blank" href="https://youtu.be/5eu1HotNmWs?si=1DZaSmztB6rHyawj">Here is a video</a> highlighting the importance of a Retro and Sprint Review.</p>
<h3 id="heading-why-retrospection-matters-more-than-you-think">🧠 Why Retrospection Matters More Than You Think</h3>
<p>The Sprint Retrospective is more than just another meeting. It’s a mirror for your team – a safe, structured space to pause, reflect, and improve together.</p>
<p>You discuss:</p>
<p>✅ what went well</p>
<p>❌ what did not go well</p>
<p>🔁 what could we do better next time</p>
<p>Great teams don't just deliver great software, they continually deliver better ways of working.</p>
<p>This is why many experienced Scrum practitioners consider the retro to be the most important event in Scrum. Code is deployed once, but process improvements grow exponentially, sprint after sprint.</p>
<h2 id="heading-tools-you-might-encounter"><strong>Tools You Might Encounter</strong></h2>
<p>Scrum doesn’t require software, but real-world teams use a variety of tools:</p>
<ul>
<li><p><strong>Jira</strong> – Tracks sprints, issues, velocity</p>
</li>
<li><p><strong>Trello</strong> – Simple board, good for small teams</p>
</li>
<li><p><strong>Slack</strong> – Where standups often happen if async</p>
</li>
<li><p><strong>Notion / Confluence</strong> – Docs, retros, notes</p>
</li>
<li><p><strong>GitHub Projects</strong> – Lightweight planning for devs</p>
</li>
</ul>
<p>Don’t worry if you’re not fluent in these yet. They’re tools – you’ll learn them on the job.</p>
<h2 id="heading-if-youre-preparing-for-a-job-heres-what-you-can-do"><strong>If You’re Preparing for a Job, Here’s What You Can Do</strong></h2>
<ul>
<li><p>✍️ Practice writing user stories from your side projects</p>
</li>
<li><p>🧪 Run a mini-sprint: Plan your weekend project, set goals, and “review” it at the end</p>
</li>
<li><p>🤝 Contribute to an open-source project that uses Scrum or Agile workflows</p>
</li>
<li><p>🧾 Write about what you learned – maybe as a tutorial (<em>hint hint</em>)</p>
</li>
</ul>
<h2 id="heading-final-thoughts"><strong>Final Thoughts</strong></h2>
<p>So to recap, Scrum is a simple yet powerful way for teams to work together, stay organized, and deliver results quickly. It runs in short cycles called <strong>sprints</strong>, where the team plans what to do, checks in daily, shows their progress at the end, and reflects on how to improve.</p>
<p>The four key ceremonies – <strong>Sprint Planning</strong>, <strong>Daily Scrum</strong>, <strong>Sprint Review</strong>, and <strong>Sprint Retrospective</strong> – help keep everyone aligned and focused. With clear roles and regular feedback, Scrum makes it easier to handle changes, solve problems early, and continuously get better as a team.</p>
<p>But scrum isn’t a magic spell. It’s just a way for humans to build complex things – together – without falling apart.</p>
<p>You don’t need to be a Scrum Master. You don’t need a certification. But if you understand how sprints work, what’s expected of you, and how to show up to meetings with clarity and candor, you’re 10 steps ahead of most.</p>
<p>Scrum helps teams talk, plan, build, and learn. And now? You can too.</p>
<p>If you liked this, please do share. You never know who it might help out.</p>
<p>Until then…keep learning, unlearning, and relearning!!!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Best AWS Services to Deploy Front-End Applications in 2025 ]]>
                </title>
                <description>
                    <![CDATA[ As front-end development evolves, finding the right deployment service is more important than ever. Amazon Web Services (AWS), a cloud-based service, offers a number of helpful tools and platforms for hosting modern front-end applications. Although i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/best-aws-services-for-frontend-deployment/</link>
                <guid isPermaLink="false">68363d68d27e47d637cc580b</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ deployment ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Tue, 27 May 2025 22:32:08 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748382386996/10b7c32c-f456-4717-b37c-b1668565bede.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As front-end development evolves, finding the right deployment service is more important than ever. Amazon Web Services (AWS), a cloud-based service, offers a number of helpful tools and platforms for hosting modern front-end applications. Although it may present challenges for beginners, AWS can help give companies an edge with its global reach.</p>
<p>In this article, I’ll break down the best AWS services for frontend deployment in 2025, covering their use cases and their pros and cons. Whether you’re launching a static website, a React/Vue application, or a complex web application, this article will help you find the most effective AWS solution for your needs.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-choose-aws-for-frontend-hosting">Why Choose AWS for Frontend Hosting?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aws-services-for-frontend-hosting">AWS Services for Frontend Hosting</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-amazon-s3-simple-storage-service">Amazon S3 (Simple Storage Service)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aws-elastic-beanstalk">AWS Elastic Beanstalk</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-amazon-ec2-elastic-compute-cloud">Amazon EC2 (Elastic Compute Cloud)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aws-amplify">AWS Amplify</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aws-lightsail">AWS LightSail</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aws-app-runner">AWS App Runner</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-related-articles">Related Articles</a></p>
</li>
</ul>
<h2 id="heading-why-choose-aws-for-frontend-hosting">Why Choose AWS for Frontend Hosting?</h2>
<p>Before we explore the specific AWS services for frontend hosting, let’s first look at why developers and companies often choose AWS over more familiar platforms like <a target="_blank" href="https://www.netlify.com/">Netlify</a> or <a target="_blank" href="https://vercel.com/">Vercel</a>.</p>
<ul>
<li><p>AWS has data centers worldwide, reducing latency and ensuring high availability. This means that apps deployed using their services can be easily and quickly accessed anywhere in the world (as long as that region has a nearby data center).</p>
</li>
<li><p>Any provisioned AWS service has security features like encryption, IAM, and DDoS protection.</p>
</li>
<li><p>AWS automatically scales to handle high traffic spikes without downtime.</p>
</li>
<li><p>AWS is flexible – it supports frameworks like React, Vue, Angular, and Next.js.</p>
</li>
<li><p>AWS easily integrates with other AWS services like databases (DynamoDB, RDS), APIs (API Gateway), and authentication (Cognito).</p>
</li>
</ul>
<h2 id="heading-aws-services-for-frontend-hosting">AWS Services for Frontend Hosting</h2>
<h3 id="heading-amazon-s3-simple-storage-service"><strong>Amazon S3 (Simple Storage Service)</strong></h3>
<p>Amazon S3 is a storage service from AWS mainly used to store files like HTML, CSS, JavaScript, Images, and Videos. These files make up static websites – that is, websites that don’t change based on user actions.</p>
<p>Many developers use S3 to host their static websites because it’s reliable, it works well, and it doesn’t cost much. You just upload your files to an S3 bucket, make them public, and your website is live. You can also connect a custom domain and add extra features like faster loading through a CDN (like CloudFront).</p>
<p><strong>Use Case:</strong><br>AWS S3 is perfect for hosting static websites and storing media files, such as portfolio sites, blogs, documentation pages, or any site that doesn't require a server to run backend code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746277600652/c2a29581-edd7-478e-8993-9bf1d951aab8.png" alt="c2a29581-edd7-478e-8993-9bf1d951aab8" class="image--center mx-auto" width="1767" height="343" loading="lazy"></p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Easy to use and affordable for most projects.</p>
</li>
<li><p>Keeps your files available almost all the time.</p>
</li>
<li><p>Your data is stored safely and can be backed up automatically.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>It doesn’t support backend features like running code, handling forms, or connecting to databases.</li>
</ul>
<p>To help you get started using S3 for hosting, here’s an article that explains <a target="_blank" href="https://www.freecodecamp.org/news/host-a-static-website-on-aws-s3-and-cloudfront/">how to host a static website using AWS S3 and Cloudfront</a>.</p>
<h3 id="heading-aws-elastic-beanstalk"><strong>AWS Elastic Beanstalk</strong></h3>
<p>AWS Elastic Beanstalk is a service that helps you quickly deploy and manage web applications without needing to handle the underlying infrastructure. While it’s often used for backend services, it also works well for frontend apps that need server-side features.</p>
<p><strong>Use Case:</strong><br>AWS Elastic Beanstalk is ideal for hosting full-stack applications, especially those built with server-side frameworks like Next.js or Nuxt.js. It handles both the frontend and backend in one environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746279088455/a417bf0a-8cb6-4d1e-bddb-33a470e082f9.png" alt="Using AWS Elastic BeanStalk to create a full-stack application" class="image--center mx-auto" width="1891" height="413" loading="lazy"></p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Automatically scales your app based on traffic</p>
</li>
<li><p>Includes load balancing to manage high traffic smoothly</p>
</li>
<li><p>Works well with other AWS tools like RDS for databases and CloudWatch for monitoring</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>More complex to set up compared to simpler services like Amplify or S3</p>
</li>
<li><p>Not the best choice for static websites that don’t require server-side logic</p>
</li>
</ul>
<p>To better understand how it works, I used AWS Elastic Beanstalk to set up a CI/CD pipeline. You can read this article: <a target="_blank" href="https://dev.to/ijay/how-to-create-a-cicd-using-aws-elastic-beanstalk-15nh">How to Create a CI/CD Using AWS Elastic BeanStalk</a>.</p>
<h3 id="heading-amazon-ec2-elastic-compute-cloud"><strong>Amazon EC2 (Elastic Compute Cloud)</strong></h3>
<p>Amazon EC2 lets you run your virtual server in the cloud. You can install any software, upload a website, open or close ports, and have full control over how your application runs. It's similar to having your physical computer, but it's hosted online and it’s more flexible.</p>
<p><strong>Use Case:</strong><br>AWS EC2 is great for developers or teams who need full control over their hosting setup. It's useful for projects where the frontend and backend are closely connected, or where you need to run custom services, tools, or configurations that simpler platforms can’t handle.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746280458269/6acafa6a-70f5-4a31-807c-de3cc3c09dfa.png" alt="using the EC2 for running your web application" class="image--center mx-auto" width="1542" height="394" loading="lazy"></p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Full control over the server environment.</p>
</li>
<li><p>Supports custom setups, tools, and applications.</p>
</li>
<li><p>It is a flexible way to run any application on it.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Takes time to learn and manage.</p>
</li>
<li><p>You’re responsible for handling updates, scaling, and security.</p>
</li>
</ul>
<p>To help you understand how it works and how to connect it to your code editor (IDE), here's an article that walks you through the process: <a target="_blank" href="https://www.freecodecamp.org/news/how-to-connect-your-aws-ec2-instance-to-vs-code/">How to Connect Your AWS EC2 Instance to VS Code</a>.</p>
<h3 id="heading-aws-amplify"><strong>AWS Amplify</strong></h3>
<p>AWS Amplify is a platform that makes it easy to build and host frontend and mobile applications. It’s designed for developers working with frameworks like React, Vue, Angular, or Next.js.</p>
<p>Amplify handles things like hosting, authentication, APIs, and data storage. It supports Git-based CI/CD, which means your app can automatically update every time you push code. It comes with built-in support for popular tools like Cognito (for login systems), AppSync (for APIs), and DynamoDB (for databases). You can even create different environments based on your Git branches.</p>
<p><strong>Use Case:</strong><br>AWS Amplify is ideal for teams or solo developers building full-stack apps with modern frontend tools, especially when you want built-in features like user authentication, cloud APIs, and easy deployment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746282073570/9392f80c-aede-400a-a8f8-207167f44545.png" alt="using amplify for frontend or full-stack application" class="image--center mx-auto" width="1811" height="797" loading="lazy"></p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Simple full-stack hosting – frontend and backend in one place.</p>
</li>
<li><p>Fast setup with automatic scaling.</p>
</li>
<li><p>Comes with HTTPS, custom domain setup, and performance monitoring.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>More expensive than simpler solutions like S3 for basic static sites.</p>
</li>
<li><p>Less flexibility for developers who want full control over infrastructure.</p>
</li>
</ul>
<p>Here is a simple guide for building with AWS Amplify. I hope it helps you understand it better: <a target="_blank" href="https://dev.to/ijay/how-can-aws-amplify-improve-your-development-process-2gj5">How Can AWS Amplify Improve Your Development Process?</a></p>
<p>And here’s an in-depth guide that walks you through <a target="_blank" href="https://www.freecodecamp.org/news/ultimate-guide-to-aws-amplify-and-reacxt/">building a full-stack app with AWS Amplify and React</a>.</p>
<h3 id="heading-aws-lightsail"><strong>AWS LightSail</strong></h3>
<p>AWS LightSail is a beginner-friendly cloud hosting service that offers a quick and easy way to launch small applications. It works like a simpler version of EC2 and comes with pre-configured environments for Node.js, LAMP (Linux, Apache, Mysql, PHP), and WordPress. This means that you don’t have to spend time setting everything up from scratch.</p>
<p><strong>Use Case:</strong><br>It is perfect for freelancers, small businesses, or anyone who wants to host a simple website or app, such as a blog, a small web app, or an online portfolio.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746348715984/c013a2de-b004-4c44-a5c6-23ddb9226962.png" alt="using AWS light sail for your application" class="image--center mx-auto" width="290" height="512" loading="lazy"></p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>More affordable than EC2.</p>
</li>
<li><p>Easy to set up and manage.</p>
</li>
<li><p>Comes with ready-to-use application stacks.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Not ideal for large or fast-growing projects.</p>
</li>
<li><p>Has fewer customisation and scaling options compared to EC2 or Amplify.</p>
</li>
</ul>
<p>For a fun, project-based tutorial, check out this guide that teaches you <a target="_blank" href="https://www.freecodecamp.org/news/how-do-deploy-docker-containers-to-the-cloud-with-aws-lightsail/">how to use AWS LightSail to deploy Docker containers to the cloud</a>.</p>
<h3 id="heading-aws-app-runner"><strong>AWS App Runner</strong></h3>
<p>AWS App Runner is a service that helps you run web applications without setting up or managing any servers. You just connect your source code or a container image, and App Runner handles everything. It's a quick way to get your frontend or backend app online, especially if your app needs server-side processing.</p>
<p><strong>Use Case:</strong><br>App Runner is a good choice for frontend applications built with server-side rendering (like Next.js), full-stack apps, or APIs. It’s also helpful if your app is containerised and you want it to scale automatically based on traffic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746351485218/748d06a5-b4dd-493d-b809-e72af84d0f5c.png" alt="Using AWS App Runner" class="image--center mx-auto" width="1628" height="360" loading="lazy"></p>
<p><strong>Pros:</strong></p>
<ul>
<li><p>No server setup or management.</p>
</li>
<li><p>Automatically scales your app as needed.</p>
</li>
<li><p>Easy to connect with GitHub or Amazon ECR.</p>
</li>
<li><p>HTTPS and custom domain support included.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>It’s not the best choice for very simple websites that only show static content like HTML, CSS, and JavaScript files. Other services like S3 are easier and cheaper for that kind of site.</p>
</li>
<li><p>It doesn’t give you as much control as EC2 or ECS. For example, you can’t fully customise the server environment or how things run behind the scenes. So, it’s great for simple or standard setups, but not ideal if you need to fine-tune advanced settings.</p>
</li>
</ul>
<p>If you want to learn more about deploying apps with AppRunner, here’s a tutorial about <a target="_blank" href="https://www.freecodecamp.org/news/kotlin-aws-app-runner/">deploying a Kotlin microservice to AppRunner</a> that you can check out.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>AWS offers a variety of powerful tools for hosting frontend applications, from simple static site hosting on S3 to full-stack managed deployments with Amplify. Whether you’re a solo developer launching your portfolio or a team deploying a production web app, AWS has the flexibility and scalability to support your frontend needs.</p>
<p>By understanding each service’s purpose and use case, you can confidently pick the best fit for your project and scale as needed. Start small, experiment, and grow with AWS.</p>
<p>If you found this article helpful, please share it with others who may find it interesting.</p>
<p>Stay updated with my projects by following me on <a target="_blank" href="https://twitter.com/ijaydimples">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/ijeoma-igboagu/">LinkedIn</a> and <a target="_blank" href="https://github.com/ijayhub">GitHub</a>.</p>
<h3 id="heading-related-articles">Related Articles</h3>
<ul>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/how-to-deploy-websites-and-applications/">How to Deploy Your Websites and Apps – User-Friendly Deployment Strategies</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/backend-as-a-service-beginners-guide/">What is Backend as a Service (BaaS)? A Beginner's Guide</a></p>
</li>
<li><p><a target="_blank" href="https://dev.to/ijay/how-to-use-aws-s3-console-for-website-deployment-2mhh">How to Use AWS S3 Console for Website Deployment</a></p>
</li>
<li><p><a target="_blank" href="https://dev.to/ijay/how-to-secure-aws-infrastructure-1k8h">How to Secure AWS Infrastructure</a></p>
</li>
</ul>
<p>Thank you for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use TypeSpec for Documenting and Modeling APIs ]]>
                </title>
                <description>
                    <![CDATA[ If you're curious and passionate about technology like I am, and you’re looking for clarity in your code, you've likely already experienced the limitations of conventional tools for documenting and modeling APIs. Tools such as Swagger, JSON Schema, o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-typespec-for-documenting-and-modeling-apis/</link>
                <guid isPermaLink="false">67f96c998b09f2bdfa144c8b</guid>
                
                    <category>
                        <![CDATA[ TypeSpec ]]>
                    </category>
                
                    <category>
                        <![CDATA[ openai ]]>
                    </category>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adalbert Pungu ]]>
                </dc:creator>
                <pubDate>Fri, 11 Apr 2025 19:25:13 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744399481891/de5db16a-2eea-46d8-820d-50c1e66d5019.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're curious and passionate about technology like I am, and you’re looking for clarity in your code, you've likely already experienced the limitations of conventional tools for documenting and modeling APIs.</p>
<p>Tools such as Swagger, JSON Schema, or OpenAPI are powerful, but they can be verbose, inflexible, or not conducive to reuse.</p>
<p>Well, I recently discovered TypeSpec. In this guide, I’ll show you how to take advantage of TypeSpec to create modern, maintainable, and well-documented REST APIs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242129685/403f9a32-8d06-47e2-b551-2ec1de1f6c0a.png" alt="Screenshot of the TypeSpec website. It features a dark background with &quot;Design APIs&quot; in large text and a description about designing data to generate schemas, specifications, code, and more. It includes &quot;Install&quot; and &quot;Playground&quot; buttons at the top." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We'll take a look at:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-typespec">What is TypeSpec?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-use-typespec">Why use TypeSpec?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-configure-typespec">How to Install and Configure TypeSpec</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-typespec-basic-syntax">TypeSpec Basic Syntax</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-rest-api-model">How to Create a REST API Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-api-in-express-and-aspnet-core">How to Build the API in Express and</a> <a target="_blank" href="http://ASP.NET">ASP.NET</a> <a class="post-section-overview" href="#heading-how-to-build-the-api-in-express-and-aspnet-core">Core</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-for-structuring-typespec-projects-and-components">Best Practices for Structuring TypeSpec Projects and Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before we dive into using TypeSpec to document and model APIs, here are a few things you'll need to familiarize yourself with and/or have:</p>
<ul>
<li><p><strong>Node.js</strong> (version 18 or higher)</p>
</li>
<li><p><strong>npm</strong> for dependency management</p>
</li>
<li><p><strong>Visual Studio Code</strong> (recommended to take advantage of the official TypeSpec extension). For an optimal experience, to create your project easily, it provides syntax highlighting, validation, autocompletion, navigation, and more.</p>
</li>
<li><p><strong>TypeSpec Extension</strong> in VS Code (You can install the extension via <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=typespec.typespec-vscode">Visual Studio Marketplace</a>)</p>
</li>
<li><p>An understanding of how to use and create APIs</p>
</li>
</ul>
<h2 id="heading-what-is-typespec">What is TypeSpec?</h2>
<p>TypeSpec is an open-source declarative language, developed by Microsoft, designed to describe APIs in an explicit, reusable, scalable, and standards-based way. It’s designed to model REST, gRPC, GraphQL, and other types of APIs, and offers a modern syntax close to TypeScript.</p>
<p>It can automatically generate:</p>
<ul>
<li><p>OpenAPI, JSON Schema, or Protobuf specifications</p>
</li>
<li><p>server and client code</p>
</li>
<li><p>API documentation</p>
</li>
<li><p>and other interface-related artifacts</p>
</li>
</ul>
<p>TypeSpec isn't just a language – it's an API design platform that favors abstraction, encourages code reuse, and integrates with modern tools like Visual Studio Code via a dedicated extension. You can install the extension via the VS Code <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=typespec.typespec-vscode">Visual Studio Marketplace</a>.</p>
<h2 id="heading-why-use-typespec">Why use TypeSpec?</h2>
<p>Before diving into the code, let's take a minute to understand the TypeSpec philosophy. Microsoft uses TypeSpec internally to deliver high-quality API services to millions of customers, across tens of thousands of endpoints, while ensuring code quality, governance, and scalability.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242196525/a1947dfb-e46d-4083-95c5-218615ab75e6.png" alt="Screenshot with the text on a dark background reads: &quot;Why TypeSpec - API-First for developers. With TypeSpec, remove the handwritten files that slow you down, and generate standards-compliant API schemas in seconds.&quot;" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Unlike generators such as Swagger, Codegen, or Postman, which start from an OpenAPI file to generate code, TypeSpec does the opposite: you first write your API design in a DSL (Domain Specific Language), then generate everything you need.</p>
<p>TypeSpec has been designed to meet the major challenges of large-scale API design and governance:</p>
<ul>
<li><p><strong>Simplification</strong>: clear, concise syntax to focus on business logic.</p>
</li>
<li><p><strong>Reusability</strong>: encapsulates types, request/response models, and directives in modular components.</p>
</li>
<li><p><strong>Productivity</strong>: automatically generates the necessary resources from a single source definition.</p>
</li>
<li><p><strong>Consistency</strong>: maintains compliance with internal standards thanks to shared libraries.</p>
</li>
<li><p><strong>Interoperability</strong>: integrates with the OpenAPI ecosystem and supports multi-format generation.</p>
</li>
<li><p><strong>Scalability</strong>: designed to handle thousands of endpoints like those used by Microsoft Azure.</p>
</li>
</ul>
<p>Let's take a look at how to install and configure the development environment</p>
<h2 id="heading-how-to-install-and-configure-typespec">How to Install and Configure TypeSpec</h2>
<p>Before you can start writing your first API with TypeSpec, you need to set up your development environment. Here's how to install TypeSpec on your machine.</p>
<h4 id="heading-requirements">Requirements:</h4>
<ul>
<li><p><strong>Node.js</strong> (version 18 or higher)</p>
</li>
<li><p><strong>npm</strong> for dependency management</p>
</li>
<li><p><strong>Visual Studio Code</strong> (recommended to take advantage of the official TypeSpec extension). For an optimal experience, it provides syntax highlighting, validation, autocompletion, navigation, and more.</p>
</li>
</ul>
<p>TypeSpec CLI global installation:</p>
<pre><code class="lang-bash">npm install -g @typespec/compiler
</code></pre>
<h3 id="heading-how-to-create-a-typespec-project">How to Create a TypeSpec Project</h3>
<p>The easiest way to create a project is to use Visual Studio Code via the TypeSpec extension you've installed (if you're not comfortable with the command line (CMD)).</p>
<p>Create a folder containing the project and open it with Visual Studio Code. Then click on the <code>View</code> tab, and next on <code>Comment Palette</code> .</p>
<p>In the search bar that appears, enter <code>TypeSpec: Create TypeSpec Project</code>.</p>
<p>Follow the quick selections to select the root folder of the project you've just created. Then choose the Template – for our case this will be <code>Generic REST API</code> – and enter the project name. Leave the emitter <code>OpenAPI 3.1 document</code> (3.1 is the current version at the time of writing) selected by default. This will put us <code>@typespec/http@typespec/openapi3</code>. Finally, wait for the project configuration to finish.</p>
<p>You should have a basic TypeSpec project configuration with a structure that looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242632713/69485276-b885-450c-870a-56af5e6d8122.png" alt="A screenshot of a file explorer showing a folder named &quot;node_modules&quot; and files: .gitignore, main.tsp, package-lock.json, package.json, and tspconfig.yaml." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<ul>
<li><p><strong>node_modules/</strong>: Directory where npm installs project dependencies.</p>
</li>
<li><p><strong>main.tsp</strong>: the entry point for your TypeSpec build. This file generally contains the main definitions of your models, services, and operations.</p>
</li>
<li><p><strong>package.json</strong>: Contains project metadata, including dependencies, scripts, and other project-related information.</p>
</li>
<li><p><strong>tspconfig.yaml</strong>: TypeSpec compiler configuration file, specifying options and parameters for the generation process.</p>
</li>
</ul>
<p>You can also run <code>tsp compile .</code> to compile the project, but it's better to run <code>tsp compile . --watch</code> to automatically compile changes during development each time you save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242865089/dea4c75e-80e3-454d-a1ab-af4186423271.png" alt="A command-line interface showing the successful compilation of a project using TypeSpec compiler v1.0.0-rc.0, with output to &quot;tsp-output/schema/&quot;." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Once the project has been compiled, you'll see the <code>tsp-output</code> and <code>schema</code> folders generated and a file added <code>openai.yaml</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744242771607/ad948a7c-ea56-44df-861d-7fa04cad1a6d.png" alt="File directory structure with folders &quot;node_modules&quot; and &quot;tsp-output&quot;, containing files like &quot;openapi.yaml&quot;, &quot;.gitignore&quot;, &quot;main.tsp&quot;, &quot;package-lock.json&quot;, &quot;package.json&quot;, and &quot;tsconfig.yaml&quot;." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<ul>
<li><p><strong>tsp-output/</strong>: Directory where the TypeSpec compiler generates files.</p>
</li>
<li><p><strong>openapi.yaml</strong>: OpenAPI specification file generated for your API, detailing API endpoints, templates, and operations. Output may vary depending on the target format specified in the <code>tspconfig.yaml</code> file.</p>
</li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-attr">emit:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">"@typespec/openapi3"</span>
<span class="hljs-attr">options:</span>
  <span class="hljs-string">"@typespec/openapi3"</span><span class="hljs-string">:</span>
    <span class="hljs-attr">emitter-output-dir:</span> <span class="hljs-string">"{output-dir}/schema"</span>
    <span class="hljs-attr">openapi-versions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-number">3.1</span><span class="hljs-number">.0</span>
</code></pre>
<p>Thanks to this configuration of the <code>tspconfig.yaml</code> file, one of TypeSpec's major assets is its ability to automatically generate OpenAPI specifications from clear, typed, and modular source code. This means you can write your API as you would in TypeScript (or a well-structured DSL), and get output in <code>.yaml</code> files compatible with the whole OpenAPI ecosystem: Swagger UI, Postman, Redoc, and so on.</p>
<p>In the next section, we'll look at the basic syntax of TypeSpec.</p>
<h2 id="heading-typespec-basic-syntax">TypeSpec Basic Syntax</h2>
<p>Now that you've got a clear idea of what TypeSpec is and what its benefits are in the world of API design, it's time to get to the heart of the matter: the basic syntax.</p>
<p>TypeSpec is a declarative language, inspired by TypeScript, that lets you model the resources, routes, data structures, and behaviors of an API in an explicit, readable, and modular way. Its syntax is based on simple keywords and clear file organization, making it easy to learn yet powerful.</p>
<h3 id="heading-language-basics">Language Basics</h3>
<p>Here's a very simple example of defining a model with TypeSpec:</p>
<pre><code class="lang-typescript">model Book {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span>;
  author: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>This block defines a <code>Book</code> resource with three typed fields. The <code>model</code> keyword is used to describe the JSON objects manipulated by the API. It is equivalent to schemas in JSON Schema or type definitions in OpenAPI.</p>
<h4 id="heading-defining-an-http-operation">Defining an HTTP operation</h4>
<p>TypeSpec lets you bind operations to models using the <code>@route</code> keyword. Here's a minimal example of an endpoint:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@route</span>(<span class="hljs-string">"/books"</span>)
op listBooks(): Book[];
</code></pre>
<p>This syntax declares a REST operation that returns a list of books. <code>@route</code> indicates the URL path, <code>op</code> introduces an operation, and <code>Book[]</code> is the return type.</p>
<p>You can also define path, query, or body parameters very easily.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@route</span>(<span class="hljs-string">"/books/{id}"</span>)
op getBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): Book;
</code></pre>
<p>In this example, we declare that <code>id</code> is a URL parameter (path parameter).</p>
<h3 id="heading-fundamental-concepts"><strong>Fundamental Concepts</strong></h3>
<h4 id="heading-model-defining-data-structures"><code>model</code> Defining data structures</h4>
<p>A <code>model</code> represents an API entity, like a JSON object. Models are the basis of your information exchanges.</p>
<pre><code class="lang-typescript">model User {
  id: <span class="hljs-built_in">string</span>;
  email: <span class="hljs-built_in">string</span>;
  age?: int32;
}
</code></pre>
<h4 id="heading-interface-group-operations"><code>interface</code> <strong>Group operations</strong></h4>
<p>An <code>interface</code> groups together a set of logically linked operations. This is useful for structuring large API sets.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> BookOperations {
  <span class="hljs-meta">@get</span> op listBooks(): Book[];
  <span class="hljs-meta">@get</span> op getBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): Book;
}
</code></pre>
<h4 id="heading-service-entry-point-of-the-api"><code>service</code> <strong>Entry point of the API</strong></h4>
<p>A <code>service</code> defines publicly exposed interfaces, their version, and the basic path.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@service</span>({ title: <span class="hljs-string">"Book API"</span>, version: <span class="hljs-string">"1.0.0"</span> })
<span class="hljs-keyword">namespace</span> BookApi {
  <span class="hljs-keyword">interface</span> BookOperations;
}
</code></pre>
<h3 id="heading-import-and-organize-your-code-with-namespaces"><strong>Import and Organize Your Code with Namespaces</strong></h3>
<p>TypeSpec provides clear organization through namespaces, similar to modules or packages.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">namespace</span> CommonModels {
  model <span class="hljs-built_in">Error</span> {
    message: <span class="hljs-built_in">string</span>;
  }
}
</code></pre>
<p>Then you can import them into another file like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> CommonModels <span class="hljs-keyword">from</span> <span class="hljs-string">"./common.tsp"</span>;
</code></pre>
<h3 id="heading-complete-example-of-a-rest-service"><strong>Complete Example of a REST Service</strong></h3>
<p>Let's take a complete example of a REST service in TypeSpec.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@service</span>({ title: <span class="hljs-string">"Book Service"</span>, version: <span class="hljs-string">"1.0.0"</span> })

<span class="hljs-meta">@route</span>(<span class="hljs-string">"/books"</span>)

<span class="hljs-keyword">namespace</span> BookService {

  model Book {
    id: <span class="hljs-built_in">string</span>;
    title: <span class="hljs-built_in">string</span>;
    author: <span class="hljs-built_in">string</span>;
    publishedYear?: int32;
  }

  <span class="hljs-meta">@get</span>()
  op listBooks(): Book[];

  <span class="hljs-meta">@post</span>()
  op createBook(<span class="hljs-meta">@body</span> book: Book): Book;

  <span class="hljs-meta">@get</span>(<span class="hljs-string">"/{id}"</span>)
  op getBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): Book;

  <span class="hljs-meta">@put</span>(<span class="hljs-string">"/{id}"</span>)
  op updateBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>, <span class="hljs-meta">@body</span> book: Book): Book;

  <span class="hljs-meta">@delete</span>(<span class="hljs-string">"/{id}"</span>)
  op deleteBook(<span class="hljs-meta">@path</span> id: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">void</span>;
}
</code></pre>
<p><strong>Here’s what’s going on</strong>:</p>
<ul>
<li><p><code>@service({ title, version })</code>: Defines service metadata (name, version), useful for generated documentation (for example, Swagger UI).</p>
</li>
<li><p><code>@route("/books")</code>: Defines the basic path for all operations of this API.</p>
</li>
<li><p><code>namespace BookService { ... }</code>: Encapsulates all models and operations linked to this service under a single logical name.</p>
</li>
</ul>
<p><strong>Next come the operations</strong>:</p>
<ul>
<li><p><code>@get() op listBooks()</code>: Endpoint <code>GET /books</code> qui retourne un tableau de livres.</p>
</li>
<li><p><code>@post() op createBook()</code>: Endpoint <code>POST /books</code> which accepts a <code>Book</code> object in the request body (<code>@body</code>) and returns the created book.</p>
</li>
<li><p><code>@get("/{id}")</code>: Endpoint <code>GET /books/{id}</code> which retrieves a book via its identifier (<code>@path</code>).</p>
</li>
<li><p><code>@put("/{id}")</code>: Endpoint <code>PUT /books/{id}</code> which updates a book's data.</p>
</li>
<li><p><code>@delete("/{id}")</code>: Deletes a book via its <code>id</code>. The <code>void</code> type means that no data is returned.</p>
</li>
</ul>
<p>With just a few lines, you get a complete, well-organized, easily readable REST service, ready to be automatically converted into OpenAPI documentation, a client SDK, or backend code.</p>
<h3 id="heading-add-validation-annotations"><strong>Add Validation Annotations</strong></h3>
<p>TypeSpec makes it easy to add validation annotations to your models using:</p>
<pre><code class="lang-typescript">model Book {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span> <span class="hljs-meta">@minLength</span>(<span class="hljs-number">3</span>);
  author: <span class="hljs-built_in">string</span> <span class="hljs-meta">@minLength</span>(<span class="hljs-number">3</span>);
  publishedYear?: int32 <span class="hljs-meta">@minValue</span>(<span class="hljs-number">1800</span>);
}
</code></pre>
<p>This adds validation rules directly to the schema, which will be taken into account during OpenAPI generation.</p>
<h3 id="heading-comparison-with-other-tools-openapi-swagger">Comparison with Other Tools (OpenAPI / Swagger)</h3>
<p>So you might wonder – why should you use TypeSpec rather than writing directly in OpenAPI?</p>
<p>Let's take the example of OpenAPI 3 (YAML):</p>
<pre><code class="lang-yaml"><span class="hljs-attr">paths:</span>
  <span class="hljs-string">/books:</span>
    <span class="hljs-attr">get:</span>
      <span class="hljs-attr">summary:</span> <span class="hljs-string">Get</span> <span class="hljs-string">list</span> <span class="hljs-string">of</span> <span class="hljs-string">books</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'200':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">OK</span>
          <span class="hljs-attr">content:</span>
            <span class="hljs-attr">application/json:</span>
              <span class="hljs-attr">schema:</span>
                <span class="hljs-attr">type:</span> <span class="hljs-string">array</span>
                <span class="hljs-attr">items:</span>
                  <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/Book'</span>
    <span class="hljs-attr">post:</span>
      <span class="hljs-attr">summary:</span> <span class="hljs-string">Create</span> <span class="hljs-string">a</span> <span class="hljs-string">new</span> <span class="hljs-string">book</span>
      <span class="hljs-attr">requestBody:</span>
        <span class="hljs-attr">content:</span>
          <span class="hljs-attr">application/json:</span>
            <span class="hljs-attr">schema:</span>
              <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/Book'</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'201':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">Created</span>
  <span class="hljs-string">/books/{id}:</span>
    <span class="hljs-attr">get:</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'200':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">OK</span>
    <span class="hljs-attr">put:</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
      <span class="hljs-attr">requestBody:</span>
        <span class="hljs-attr">content:</span>
          <span class="hljs-attr">application/json:</span>
            <span class="hljs-attr">schema:</span>
              <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/Book'</span>
    <span class="hljs-attr">delete:</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
<span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">Book:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">id:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">title:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">author:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">publishedYear:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">integer</span>
</code></pre>
<p>As you can see, the OpenAPI definition is much more verbose. Relationships between paths, methods, schemas, and parameters are scattered, which complicates reading and maintenance. Also, it's less typed, given that OpenAPI remains YAML (or JSON), without the typing security or modularity of a real language.</p>
<h4 id="heading-why-typespec-is-useful-here">Why TypeSpec is useful here</h4>
<p>With TypeSpec, everything is centralized in a declarative, modular, typed, and intuitive format.</p>
<ul>
<li><p><strong>Greater legibility</strong>: less noise, more intent.</p>
</li>
<li><p><strong>Reusability</strong>: you can create modular components and share them between projects.</p>
</li>
<li><p><strong>Productivity</strong>: you write less code and generate more (OpenAPI, client, server, doc).</p>
</li>
<li><p><strong>Consistency</strong>: errors are detected early thanks to strong typing.</p>
</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Criteria</strong></td><td><strong>OpenAPI / Swagger</strong></td><td><strong>TypeSpec</strong></td></tr>
</thead>
<tbody>
<tr>
<td></td><td></td><td></td></tr>
<tr>
<td><strong>Syntax</strong></td><td>Verbose (YAML/JSON)</td><td>Declarative, typed, concise</td></tr>
<tr>
<td><strong>Organization</strong></td><td>Fragmented</td><td>Modular (namespace, import)</td></tr>
<tr>
<td><strong>Modular</strong></td><td>Limited</td><td>High (models, services)</td></tr>
<tr>
<td><strong>Built-in validation</strong></td><td>Separate or manual</td><td>Decorators (@minLength, and so on)</td></tr>
<tr>
<td><strong>Automatic generation</strong></td><td>Manual</td><td>Integrated (OpenAPI, SDK, and so on)</td></tr>
</tbody>
</table>
</div><p>Note: TypeSpec doesn't replace OpenAPI, but complements it: you write to TypeSpec, then automatically generate OpenAPI files, SDKs, specs and so on. It gives you a source language for accurately describing your API.</p>
<p>In the next section, we'll look at how to create a REST API template.</p>
<h2 id="heading-how-to-create-a-rest-api-model">How to Create a REST API Model</h2>
<p>To deepen our understanding of REST API creation with TypeSpec, let's continue with the example of managing books. In this example, we'll create a <code>Book</code> model, define a service to manage the books, and add validations to ensure that the data respects the right constraints.</p>
<h3 id="heading-define-a-data-model-for-book">Define a Data Model for <code>Book</code></h3>
<p>First, we'll define a data model for the Book resource. A book can have the following properties:</p>
<ul>
<li><p><code>id</code>: A unique identifier for the book.</p>
</li>
<li><p><code>title</code>: The title of the book.</p>
</li>
<li><p><code>author</code>: The author of the book.</p>
</li>
<li><p><code>publicationYear</code>: The book's year of publication.</p>
</li>
<li><p><code>isbn</code>: The book's ISBN number.</p>
</li>
</ul>
<p><code>Book</code> <strong>model in TypeSpec</strong></p>
<pre><code class="lang-typescript">model Book {
  id: integer;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  title: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  author: <span class="hljs-built_in">string</span>;
  publicationYear: integer;
  <span class="hljs-meta">@pattern</span>(<span class="hljs-string">"^\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}$"</span>)
  isbn: <span class="hljs-built_in">string</span>;
}
</code></pre>
<ul>
<li><p><code>id</code>: Unique book identifier (<code>integer</code> type).</p>
</li>
<li><p><code>title</code> and <code>author</code>: Character strings representing the book's title and author, validated by <code>@minLength(1)</code> to ensure they are not empty.</p>
</li>
<li><p><code>publicationYear</code>: The book's year of publication (<code>integer</code> type).</p>
</li>
<li><p><code>isbn</code>: The book's ISBN number, validated with a regular expression that matches the standard format of an ISBN.</p>
</li>
</ul>
<h3 id="heading-define-a-rest-service-to-manage-books">Define a REST Service to Manage Books</h3>
<p>Now that we have a <code>Book</code> model, we'll create a service to manage CRUD operations on this resource. This service will contain methods for retrieving a book by its identifier, creating a new book, updating an existing book, and deleting a book.</p>
<p><code>BooksService</code> <strong>service in TypeSpec</strong></p>
<pre><code class="lang-typescript">service BooksService {

  <span class="hljs-meta">@get</span>(<span class="hljs-string">"/books/{id}"</span>)
  getBook(id: integer): Book;

  <span class="hljs-meta">@post</span>(<span class="hljs-string">"/books"</span>)
  createBook(book: Book): Book;

  <span class="hljs-meta">@put</span>(<span class="hljs-string">"/books/{id}"</span>)
  updateBook(id: integer, book: Book): Book;

  <span class="hljs-meta">@delete</span>(<span class="hljs-string">"/books/{id}"</span>)
  deleteBook(id: integer): <span class="hljs-built_in">void</span>;
}
</code></pre>
<p>The <code>BooksService</code> contains four methods for performing actions on books:</p>
<ul>
<li><p><code>@get("/books/{id}")</code>: Method for retrieving a book by its <code>id</code>.</p>
</li>
<li><p><code>@post("/books")</code>: Method for creating a new book.</p>
</li>
<li><p><code>@put("/books/{id}")</code>: Method for updating an existing book by its <code>id</code>.</p>
</li>
<li><p><code>@delete("/books/{id}")</code>: Method for deleting a book based on its <code>id</code>.</p>
</li>
</ul>
<p>These methods use HTTP annotations to indicate the type of operation they perform (GET, POST, PUT, DELETE).</p>
<h3 id="heading-add-additional-validations-for-the-book-model"><strong>Add Additional Validations for the</strong> <code>Book</code> <strong>Model</strong></h3>
<p>As in the previous example for users, we can add additional validations on <strong>Book</strong> template properties.</p>
<p><strong>Example of validation on</strong> <code>publicationYear</code> <strong>and</strong> <code>isbn</code></p>
<pre><code class="lang-typescript">model Book {
  id: integer;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  title: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  author: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minValue</span>(<span class="hljs-number">1000</span>)
  publicationYear: integer;
  <span class="hljs-meta">@pattern</span>(<span class="hljs-string">"^\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}$"</span>)
  isbn: <span class="hljs-built_in">string</span>;
}
</code></pre>
<ul>
<li><p><code>@minValue(1000)</code> guarantees that the year of publication is greater than or equal to 1000.</p>
</li>
<li><p>Validation of the <code>isbn</code> remains the same, using a regular expression to validate a standard ISBN format.</p>
</li>
</ul>
<h3 id="heading-a-complete-service-for-managing-books"><strong>A Complete Service for Managing Books</strong></h3>
<p>Now that we have the <code>Book</code> model and the necessary validations, here's a complete service for managing books, with all the essential operations.</p>
<p><strong>Complete</strong> <code>BooksService</code> <strong>in TypeSpec</strong></p>
<pre><code class="lang-typescript">model Book {
  id: integer;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  title: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minLength</span>(<span class="hljs-number">1</span>)
  author: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@minValue</span>(<span class="hljs-number">1000</span>)
  publicationYear: integer;
  <span class="hljs-meta">@pattern</span>(<span class="hljs-string">"^\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}$"</span>)
  isbn: <span class="hljs-built_in">string</span>;
}

service BooksService {
  <span class="hljs-meta">@get</span>(<span class="hljs-string">"/books/{id}"</span>)
  getBook(id: integer): Book;

  <span class="hljs-meta">@post</span>(<span class="hljs-string">"/books"</span>)
  createBook(book: Book): Book;

  <span class="hljs-meta">@put</span>(<span class="hljs-string">"/books/{id}"</span>)
  updateBook(id: integer, book: Book): Book;

  <span class="hljs-meta">@delete</span>(<span class="hljs-string">"/books/{id}"</span>)
  deleteBook(id: integer): <span class="hljs-built_in">void</span>;
}
</code></pre>
<ul>
<li><p>The <code>Book</code> model defines properties and validations for a book.</p>
</li>
<li><p>The <code>BooksService</code> provides endpoints for retrieving, creating, updating, and deleting a book.</p>
</li>
<li><p>Each service method is correctly annotated with the corresponding HTTP verbs (<code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>).</p>
</li>
</ul>
<p>And here’s a summary of everything we’ve done:</p>
<ul>
<li><p>We created a <code>Book</code> model with properties such as title, author, year of publication, and ISBN number.</p>
</li>
<li><p>We defined a <code>BooksService</code> to provide CRUD operations on books.</p>
</li>
<li><p>We added validations to ensure that the data respected specified constraints (for example, ISBN and year of publication).</p>
</li>
<li><p>We designed a complete REST API to manage books with TypeSpec, using a minimum amount of code and staying true to standards.</p>
</li>
</ul>
<p>This example shows just how quickly and efficiently TypeSpec can be used to model a REST API, while ensuring a clear structure and robust validations.</p>
<h2 id="heading-how-to-build-the-api-in-express-and-aspnet-core">How to Build the API in Express and ASP.NET Core</h2>
<p>Now that we've defined a book management REST service with TypeSpec, let's see how we'd implement this same API using two popular frameworks:</p>
<ul>
<li><p><strong>ExpressJS (Node.js / TypeScript)</strong></p>
</li>
<li><p><strong>ASP.NET Core (C#)</strong></p>
</li>
</ul>
<p>This will allow us to better compare TypeSpec's conciseness and readability with traditional implementations.</p>
<p><strong>Manual implementation with ExpressJS (Node.js / TypeScript):</strong></p>
<pre><code class="lang-typescript"><span class="hljs-comment">//server.ts</span>
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;

<span class="hljs-keyword">const</span> app = express();
app.use(express.json());

<span class="hljs-keyword">interface</span> Book {
  id: <span class="hljs-built_in">number</span>;
  title: <span class="hljs-built_in">string</span>;
  author: <span class="hljs-built_in">string</span>;
  publicationYear: <span class="hljs-built_in">number</span>;
  isbn: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">const</span> books: Book[] = [];

<span class="hljs-comment">// GET /books/:id</span>
app.get(<span class="hljs-string">'/books/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);
  <span class="hljs-keyword">const</span> book = books.find(<span class="hljs-function"><span class="hljs-params">b</span> =&gt;</span> b.id === id);
  <span class="hljs-keyword">if</span> (!book) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ message: <span class="hljs-string">'Book not found'</span> });
  res.send(book);
});

<span class="hljs-comment">// POST /books</span>
app.post(<span class="hljs-string">'/books'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> newBook: Book = req.body;
  books.push(newBook);
  res.status(<span class="hljs-number">201</span>).send(newBook);
});

<span class="hljs-comment">// PUT /books/:id</span>
app.put(<span class="hljs-string">'/books/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);
  <span class="hljs-keyword">const</span> index = books.findIndex(<span class="hljs-function"><span class="hljs-params">b</span> =&gt;</span> b.id === id);
  <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ message: <span class="hljs-string">'Book not found'</span> });

  books[index] = req.body;
  res.send(books[index]);
});

<span class="hljs-comment">// DELETE /books/:id</span>
app.delete(<span class="hljs-string">'/books/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id);
  <span class="hljs-keyword">const</span> index = books.findIndex(<span class="hljs-function"><span class="hljs-params">b</span> =&gt;</span> b.id === id);
  <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ message: <span class="hljs-string">'Book not found'</span> });

  books.splice(index, <span class="hljs-number">1</span>);
  res.status(<span class="hljs-number">204</span>).send();
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Server is running on port 3000'</span>);
});
</code></pre>
<p><strong>Observations:</strong></p>
<ul>
<li><p>A lot of repetitive logic.</p>
</li>
<li><p>No automatic validation.</p>
</li>
<li><p>Routes must be maintained manually.</p>
</li>
<li><p>No automatically generated API documentation.</p>
</li>
</ul>
<p><strong>Manual implementation with</strong> <a target="_blank" href="http://ASP.NET"><strong>ASP.NET</strong></a> <strong>Core (C#):</strong></p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Book.cs</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Book</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">Required</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Title { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">string</span>.Empty;

    [<span class="hljs-meta">Required</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Author { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">string</span>.Empty;

    [<span class="hljs-meta">Range(1000, int.MaxValue)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> PublicationYear { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">RegularExpression(@<span class="hljs-meta-string">"^\d{3}-\d{1,5}-\d{1,7}-\d{1,7}-\d{1}$"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Isbn { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">string</span>.Empty;
}
</code></pre>
<pre><code class="lang-csharp"><span class="hljs-comment">// BooksController.cs</span>
[<span class="hljs-meta">ApiController</span>]
[<span class="hljs-meta">Route(<span class="hljs-meta-string">"books"</span>)</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BooksController</span> : <span class="hljs-title">ControllerBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> List&lt;Book&gt; books = <span class="hljs-keyword">new</span>();

    [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetBook</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
    {
        <span class="hljs-keyword">var</span> book = books.FirstOrDefault(b =&gt; b.Id == id);
        <span class="hljs-keyword">if</span> (book == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> NotFound(<span class="hljs-string">"Book not found"</span>);
        <span class="hljs-keyword">return</span> Ok(book);
    }

    [<span class="hljs-meta">HttpPost</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">CreateBook</span>(<span class="hljs-params">[FromBody] Book book</span>)</span>
    {
        books.Add(book);
        <span class="hljs-keyword">return</span> CreatedAtAction(<span class="hljs-keyword">nameof</span>(GetBook), <span class="hljs-keyword">new</span> { id = book.Id }, book);
    }

    [<span class="hljs-meta">HttpPut(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">UpdateBook</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id, [FromBody] Book updatedBook</span>)</span>
    {
        <span class="hljs-keyword">var</span> index = books.FindIndex(b =&gt; b.Id == id);
        <span class="hljs-keyword">if</span> (index == <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> NotFound(<span class="hljs-string">"Book not found"</span>);

        books[index] = updatedBook;
        <span class="hljs-keyword">return</span> Ok(updatedBook);
    }

    [<span class="hljs-meta">HttpDelete(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">DeleteBook</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
    {
        <span class="hljs-keyword">var</span> book = books.FirstOrDefault(b =&gt; b.Id == id);
        <span class="hljs-keyword">if</span> (book == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> NotFound(<span class="hljs-string">"Book not found"</span>);

        books.Remove(book);
        <span class="hljs-keyword">return</span> NoContent();
    }
}
</code></pre>
<p><strong>Observations:</strong></p>
<ul>
<li><p>More formal and structured than Express, thanks to C# annotations (<code>[HttpPost]</code>, <code>[Required]</code>, and so on).</p>
</li>
<li><p>Validation is handled automatically via Data Annotations.</p>
</li>
<li><p>Once again, no automatic OpenAPI generation or SDK client without additional configuration.</p>
</li>
</ul>
<p><strong>Comparison with TypeSpec:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>TypeSpec</strong></td><td><strong>ExpressJS</strong></td><td><a target="_blank" href="http://ASP.NET"><strong>ASP.NET</strong></a> <strong>Core</strong></td></tr>
</thead>
<tbody>
<tr>
<td></td><td></td><td></td><td></td></tr>
<tr>
<td><strong>Syntax</strong></td><td>Declarative</td><td>Imperative</td><td>Structured</td></tr>
<tr>
<td><strong>Validation</strong></td><td>Automatic</td><td>Manual</td><td>Data Annotations</td></tr>
<tr>
<td><strong>Documentation</strong></td><td>Automatic</td><td>Manual</td><td>Generated(Swashbuckle)</td></tr>
<tr>
<td><strong>Reusability</strong></td><td>High</td><td>Low</td><td>Medium</td></tr>
<tr>
<td><strong>Generation</strong></td><td>OpenAPI/SDK</td><td>Non-native</td><td>Possible</td></tr>
</tbody>
</table>
</div><h2 id="heading-best-practices-for-structuring-typespec-projects-and-components">Best Practices for Structuring TypeSpec Projects and Components</h2>
<p>When you start writing API definitions in TypeSpec, it's easy to put everything in a single file. But as with any software project, as the application grows, a good structure becomes essential to guarantee the readability, reusability and maintainability of the code.</p>
<p>Here's a set of best practices I strongly recommend:</p>
<h3 id="heading-organize-by-functional-area"><strong>Organize by Functional Area</strong></h3>
<p>Use namespaces to group models, interfaces, and operations by business domain: <strong>book</strong>, <strong>user</strong>, <strong>auth</strong>, <strong>payment</strong>, and so on.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">namespace</span> MyApi.Books;
</code></pre>
<p>Create a <code>/books</code> folder with the following files:</p>
<pre><code class="lang-yaml"><span class="hljs-string">src/</span>
<span class="hljs-string">├──</span> <span class="hljs-string">books/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">routes.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">service.tsp</span>
</code></pre>
<p>This ensures a clear separation of responsibilities, just like in a well-structured Node.js project.</p>
<h3 id="heading-a-single-maintsp-entry-point"><strong>A Single</strong> <code>main.tsp</code> <strong>Entry Point</strong></h3>
<p>This is the main file that orchestrates:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.tsp</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./books/service.tsp"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./users/service.tsp"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./auth/service.tsp"</span>;
</code></pre>
<p>This allows you to compile the entire project from a single point.</p>
<h3 id="heading-create-reusable-components">Create Reusable Components</h3>
<p>Define common models and types in a shared file. Example:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// common/models.tsp</span>
model ErrorResponse {
  code: <span class="hljs-built_in">string</span>;
  message: <span class="hljs-built_in">string</span>;
}

<span class="hljs-meta">@defaultResponse</span>
op <span class="hljs-built_in">Error</span>(): ErrorResponse;
</code></pre>
<p>Then import them into your other files:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-string">"../common/models.tsp"</span>;
</code></pre>
<p>This is handy for centralizing errors, standard answers, pagination types, and so on.</p>
<h3 id="heading-use-decorators-to-enrich-your-components">Use Decorators to Enrich Your Components</h3>
<p>Decorators such as <code>@doc</code>, <code>@minLength</code>, <code>@server</code>, <code>@route</code> or <code>@tag</code> can be used to generate valid, documented APIs without any extra effort:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@route</span>(<span class="hljs-string">"/books"</span>)
<span class="hljs-meta">@doc</span>(<span class="hljs-string">"Get all books"</span>)
op listBooks(): Book[];
</code></pre>
<p>A well-annotated API is one that is ready for automatic generation of documentation or clients.</p>
<h3 id="heading-define-servers-in-the-right-place">Define Servers in the Right Place</h3>
<p>Add your @server directive to a <code>service.tsp</code> or global <code>api.tsp</code> file:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@server</span>(<span class="hljs-string">"Production"</span>, <span class="hljs-string">"https://api.mysite.com"</span>)
<span class="hljs-meta">@server</span>(<span class="hljs-string">"Staging"</span>, <span class="hljs-string">"https://staging.mysite.com"</span>)
</code></pre>
<p>This allows you to target different environments without duplicating definitions.</p>
<h3 id="heading-validate-regularly">Validate Regularly</h3>
<p>Integrate <code>tsp compile</code> into your CI/CD to ensure that your definitions are always valid. Example with an npm script:</p>
<pre><code class="lang-bash">npm run tsp compile src/main.tsp --emit=./dist
</code></pre>
<p>This avoids last-minute errors and guarantees the consistency of your API over time.</p>
<p><strong>Example of a recommended complete structure:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">project-root/</span>
<span class="hljs-string">├──</span> <span class="hljs-string">src/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">books/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">routes.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">service.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">users/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">service.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">common/</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">models.tsp</span>
<span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">main.tsp</span>
<span class="hljs-string">├──</span> <span class="hljs-string">tspconfig.yaml</span>
<span class="hljs-string">├──</span> <span class="hljs-string">package.json</span>
<span class="hljs-string">└──</span> <span class="hljs-string">README.md</span>
</code></pre>
<p>In summary:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Good practice</strong></td><td><strong>Why it's important</strong></td></tr>
</thead>
<tbody>
<tr>
<td></td><td></td></tr>
<tr>
<td>Use <code>namespaces</code></td><td>Clear organization, readability</td></tr>
<tr>
<td>Dividing files by domain</td><td>Reusability, modularity</td></tr>
<tr>
<td>Centralize shared components</td><td>DRY (Don't Repeat Yourself)</td></tr>
<tr>
<td>Use decorators</td><td>Enrich documentation and validation</td></tr>
<tr>
<td>Integrate with CI/CD</td><td>Continuous quality, no surprises</td></tr>
<tr>
<td>Have a clear input file (<code>main.tsp</code>)</td><td>Simple, centralized compilation</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion</h2>
<p>TypeSpec represents a real evolution in the way we design, document and maintain APIs. By adopting a declarative, modular, and typed approach, it simplifies the definition of APIs while enhancing their quality, readability, and consistency on a large scale.</p>
<p>Whether you're a front-end developer consuming APIs, a software architect looking to standardize your team's practices, or a technical documentation enthusiast, TypeSpec offers you a robust, modern, and extensible solution.</p>
<p>The TypeSpec ecosystem is still young but very promising, supported by Microsoft and used internally on a large scale. So now's the time to start exploring and adopting it for your projects.</p>
<h4 id="heading-ressources">Ressources</h4>
<ol>
<li><p><strong>TypeSpec official website</strong><br> <a target="_blank" href="https://typespec.io/">https://typespec.io</a><br> Full documentation, guides, syntax references and APIs.</p>
</li>
<li><p><strong>TypeSpec GitHub repository (Microsoft)</strong><br> <a target="_blank" href="https://github.com/microsoft/typespec/">https://github.com/microsoft/typespec</a><br> Source code, examples and community discussions.</p>
</li>
<li><p><strong>Playground TypeSpec (essayer dans le navigateur)</strong><br> <a target="_blank" href="https://typespec.io/playground/">https://typespec.io/playground</a><br> Quickly test your models without installing anything.</p>
</li>
<li><p><strong>TypeSpec documentation — Microsoft Learn</strong><br> <a target="_blank" href="https://learn.microsoft.com/en-us/azure/developer/typespec/overview/">https://learn.microsoft.com/en-us/azure/developer/typespec/overview</a><br> Learn how to use TypeSpec to create consistent, high-quality APIs efficiently and integrate them seamlessly with existing toolchains.</p>
</li>
<li><p><strong>OpenAPI Specification</strong><br> <a target="_blank" href="https://swagger.io/specification/">https://swagger.io/specification</a><br> To compare with current API description standards.</p>
</li>
<li><p><strong>TypeSpec 101 by Mario Guerra Product Manager for TypeSpec at Microsoft</strong><br> <a target="_blank" href="https://www.youtube.com/playlist?list=PLYWCCsom5Txglkl_I1XvwzrzM5G3SuVsR/">https://www.youtube.com/playlist?list=PLYWCCsom5Txglkl_I1XvwzrzM5G3SuVsR</a><br> A tutorial series, hosted by Mario Guerra, TypeSpec product manager at Microsoft, will guide you through the process of building a REST API using TypeSpec, and generating an OpenAPI specification from our code.</p>
</li>
<li><p><strong>APIs at Scale with TypeSpec</strong><br> <a target="_blank" href="https://youtu.be/yfCYrKaojDo/">https://youtu.be/yfCYrKaojDo</a><br> A talk given by Mandy Whaley from Microsoft at the 2024 Austin API Summit in Austin, Texas.</p>
</li>
</ol>
<p>Thanks for reading. You can find me on <a target="_blank" href="https://www.linkedin.com/in/AdalbertPungu/">LinkedIn</a>, and follow me on all socials @AdalbertPungu.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Why Your Code is Slow: Common  Performance Mistakes Beginners Make ]]>
                </title>
                <description>
                    <![CDATA[ Maybe you’ve experienced something like this before: you’ve written code that works, but when you hit “run,” it takes forever. You stare at the spinner, wondering if it’s faster to just solve the problem by hand. But you end up looking something like... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/why-your-code-is-slow-common-performance-mistakes-beginners-make/</link>
                <guid isPermaLink="false">67e6c26a4c687a76c3f3934d</guid>
                
                    <category>
                        <![CDATA[ #codenewbies ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rahul ]]>
                </dc:creator>
                <pubDate>Fri, 28 Mar 2025 15:38:18 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743176201295/448f0407-8a15-4b59-a91f-8a197bc07578.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Maybe you’ve experienced something like this before: you’ve written code that works, but when you hit “run,” it takes forever. You stare at the spinner, wondering if it’s faster to just solve the problem by hand.</p>
<p>But you end up looking something like this… 😭⬇️⬇️</p>
<p><img src="https://img.ifunny.co/images/9eeae78f1bc92e6dc422c5e6af2b5a768913d2e4fa9df2d0df499c1202dfe539_1.jpg" alt="6 year old me thinking the game would load faster if i act like don't care  ORIGINALWOLFF - iFunny" width="600" height="400" loading="lazy"></p>
<p>Here’s the truth: slow code doesn’t have to be the end of the world. And it’s a rite of passage if you’re a developer.</p>
<p>When you’re learning to code, you’re focused on making things <em>work</em>—not making them fast. But eventually, you’ll hit a wall: your app freezes, your data script takes hours, or your game lags like a PowerPoint slideshow.</p>
<p>The difference between working code and blazing-fast code often comes down to avoiding a few common mistakes. Mistakes that are easy to make when you’re starting out, like using the wrong tool for the job, writing unnecessary code, or accidentally torturing your computer with hidden inefficiencies.</p>
<p>I’ve been there. I once wrote a “quick” script to analyze data. It ran for 3 hours. Turns out, changing one line of code cut it to 10 seconds. Yes I was dumb when I was learning – but I don’t want you to be, too.</p>
<p>That’s the power of understanding performance.</p>
<p>In this guide, I’ll break down seven common mistakes that can really tank your code’s speed—and how to fix them.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-mistake-1-logging-everything-in-production-without-realizing-it">Mistake #1: Logging Everything in Production (Without Realizing It)</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-to-fix-it">How to Fix It</a></li>
</ul>
</li>
</ol>
<ol start="2">
<li><p><a class="post-section-overview" href="#heading-mistake-2-using-the-wrong-loops-when-theres-a-faster-alternative">Mistake #2: Using the Wrong Loops (When There’s a Faster Alternative)</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-why-this-is-a-problem-1">Why This is a Problem</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-mistake-3-writing-database-queries-inside-loops-killer-of-speed">Mistake #3: Writing Database Queries Inside Loops (Killer of Speed)</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-this-is-a-problem-2">Why This is a Problem</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-fix-it-use-bulk-queries">How to Fix It: Use Bulk Queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-more-scalable-approach">A More Scalable Approach</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-mistake-4-not-knowing-your-hardwares-dirty-secrets">Mistake #4: Not Knowing Your Hardware’s Dirty Secrets</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-problem-1-the-cpus-crystal-ball-is-broken-memory-prefetching">Problem 1: The CPU’s Crystal Ball is Broken (Memory Prefetching)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-fix-use-contiguous-data-structures">The Fix: Use Contiguous Data Structures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-problem-2-the-invisible-tax-of-memory-pages-tlb-thrashing">Problem 2: The Invisible Tax of Memory Pages (TLB Thrashing)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-fix-process-data-in-chunks">The Fix: Process Data in Chunks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-problem-3-your-code-is-a-tourist-in-the-wrong-cpu-neighborhood-numa">Problem 3: Your Code is a Tourist in the Wrong CPU Neighborhood (NUMA)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-fix-pin-processes-to-numa-aware-memory">The Fix: Pin Processes to NUMA-Aware Memory</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-problem-4-the-cpu-is-a-drama-queen-speculative-execution">Problem 4: The CPU is a Drama Queen (Speculative Execution)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-fix-make-branches-predictable">The Fix: Make Branches Predictable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-fight-back">How to Fight Back</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-mistake-5-memory-fragmentation">Mistake #5: Memory Fragmentation</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-whats-happening-under-the-hood">What’s Happening Under the Hood</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-problem-2-the-autoboxing-trap-java-c-and-so-on">Problem 2: The Autoboxing Trap (Java, C#, and so on)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-fix-use-primitive-collections">The Fix: Use Primitive Collections</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-fix-for-c">The Fix for C#</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-mistake-6-the-cache-catch">Mistake #6: The Cache (catch)</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-row-major-vs-column-major-access">Row-Major vs. Column-Major Access</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-plot-twist-your-programming-language-is-gaslighting-you">The Plot Twist: Your Programming Language is Gaslighting You</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-multidimensional-illusion-3d-arrays">The Multidimensional Illusion: 3D+ Arrays</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-nuclear-option-cache-aware-algorithms">The Nuclear Option: Cache-Aware Algorithms</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-mistake-7-the-copy-paste-trap">Mistake #7: The Copy-Paste Trap</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-problem-1-the-ghost-copies-in-harmless-operations">Problem 1: The Ghost Copies in “Harmless” Operations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-problem-2-the-hidden-cost-of-functional-code">Problem 2: The Hidden Cost of “Functional” Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-problem-3-the-ill-just-modify-a-copy-mistake">Problem 3: The “I’ll Just Modify a Copy” Mistake</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-escape-the-copy-paste-hell">How to Escape the Copy-Paste hell?</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-do-pro-developers-write-faster-code">How Do Pro Developers Write Faster Code?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-they-profile-their-code-instead-of-guessing">1. They Profile Their Code Instead of Guessing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-they-avoid-premature-optimization">2. They Avoid Premature Optimization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-they-pick-the-right-data-structures-not-just-whats-familiar">3. They Pick the Right Data Structures (Not Just What’s Familiar)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-they-automate-performance-checks">4. They Automate Performance Checks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-they-think-about-performance-from-day-one">5. They Think About Performance From Day One</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts-lessons-learned-the-hard-way">Final Thoughts: Lessons Learned the Hard Way</a></p>
</li>
</ol>
<h2 id="heading-mistake-1-logging-everything-in-production-without-realizing-it"><strong>Mistake #1: Logging Everything in Production (Without Realizing It)</strong></h2>
<p>Logging is supposed to help you understand what’s happening in your code—but if you’re logging everything, you’re actually slowing it down. A common beginner mistake is leaving <code>print()</code> statements everywhere or enabling verbose logging even in production, where performance matters most.</p>
<p>Instead of logging only what’s useful, they log every function call, every input, every output, and sometimes even entire request bodies or database queries. This might seem harmless, but in a live application handling thousands of operations per second, excessive logging can cause major slowdowns.</p>
<h3 id="heading-why-this-is-a-problem">Why This is a Problem</h3>
<p>Logging isn’t free. Every log message, whether printed to the console or written to a file, adds extra processing time. If logging is done synchronously (which it often is by default), your application can pause execution while waiting for the log to be recorded.</p>
<p>It also wastes disk space. If every request gets logged in detail, log files can grow rapidly, eating up storage and making it harder to find useful information when debugging.</p>
<p>Here’s an example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_data</span>(<span class="hljs-params">data</span>):</span>
    print(<span class="hljs-string">f"Processing data: <span class="hljs-subst">{data}</span>"</span>)  <span class="hljs-comment"># Logging every input</span>
    result = data * <span class="hljs-number">2</span>  
    print(<span class="hljs-string">f"Result: <span class="hljs-subst">{result}</span>"</span>)  <span class="hljs-comment"># Logging every result</span>
    <span class="hljs-keyword">return</span> result
</code></pre>
<p>If this function is running inside a loop handling 10,000+ operations, those print statements are slowing things down massively.</p>
<h3 id="heading-how-to-fix-it">How to Fix It</h3>
<p>Instead of logging everything, focus on logging only what actually matters. Good logging helps you diagnose real issues without cluttering your logs or slowing down your app.</p>
<p>For example, let’s say you're processing user transactions. You don’t need to log every step of the calculation, but logging when a transaction starts, succeeds, or fails is valuable.</p>
<pre><code class="lang-python">// ✅ Bad logging

logging.info(<span class="hljs-string">f"Received input: <span class="hljs-subst">{data}</span>"</span>)  
logging.info(<span class="hljs-string">f"Processing transaction for user <span class="hljs-subst">{user_id}</span>"</span>)  
logging.info(<span class="hljs-string">f"Transaction intermediate step 1 result: <span class="hljs-subst">{some_var}</span>"</span>)  
logging.info(<span class="hljs-string">f"Transaction intermediate step 2 result: <span class="hljs-subst">{another_var}</span>"</span>)  
logging.info(<span class="hljs-string">f"Transaction completed: <span class="hljs-subst">{final_result}</span>"</span>)  

// ✅ Better logging

logging.info(<span class="hljs-string">f"Processing transaction for user <span class="hljs-subst">{user_id}</span>"</span>)  
logging.info(<span class="hljs-string">f"Transaction successful. Amount: $<span class="hljs-subst">{amount}</span>"</span>)
</code></pre>
<p>Next, make sure debugging logs are turned off in production. Debug logs (<code>logging.debug()</code>) are great while developing because they show detailed information, but they shouldn’t be running on live servers.</p>
<p>You can control this by setting the logging level to <code>INFO</code> or higher:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

logging.basicConfig(level=logging.INFO)  <span class="hljs-comment"># Only logs INFO, WARNING, ERROR, CRITICAL messages</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_data</span>(<span class="hljs-params">data</span>):</span>
    logging.debug(<span class="hljs-string">f"Processing data: <span class="hljs-subst">{data}</span>"</span>)  <span class="hljs-comment"># Won't show up in production</span>
    <span class="hljs-keyword">return</span> data * <span class="hljs-number">2</span>
</code></pre>
<p>Finally, for high-performance applications, consider using asynchronous logging. By default, logging operations can block execution, meaning your program waits until the log message is written before continuing. This can be a bottleneck, especially if you're logging to a file or a remote logging service.</p>
<p>Asynchronous logging solves this by handling logs in the background. Here’s how you can set it up with Python’s <code>QueueHandler</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">import</span> logging.handlers
<span class="hljs-keyword">import</span> queue

log_queue = queue.Queue()
queue_handler = logging.handlers.QueueHandler(log_queue)
logger = logging.getLogger()
logger.addHandler(queue_handler)
logger.setLevel(logging.INFO)

logger.info(<span class="hljs-string">"This log is handled asynchronously!"</span>)
</code></pre>
<h2 id="heading-mistake-2-using-the-wrong-loops-when-theres-a-faster-alternative"><strong>Mistake #2: Using the Wrong Loops (When There’s a Faster Alternative)</strong></h2>
<h3 id="heading-why-this-is-a-problem-1">Why This is a Problem</h3>
<p>Loops are one of the first things you learn in programming, and for loops feel natural—they give you control, they’re easy to understand, and they work everywhere. That’s why beginners tend to reach for them automatically.</p>
<p>But just because something works doesn’t mean it’s the best way. In Python, for loops can be slow—especially when there’s a built-in alternative that does the same job faster and more efficiently.</p>
<p>This isn’t just a Python thing. Most programming languages have optimized ways to handle loops under the hood—whether it's vectorized operations in NumPy, functional programming in JavaScript, or stream processing in Java. Knowing when to use them is key to writing fast, clean code.</p>
<h4 id="heading-example">Example</h4>
<p>Let’s say you want to square a list of numbers. A beginner might write this:</p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
squared = []

<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> numbers:
    squared.append(num ** <span class="hljs-number">2</span>)
</code></pre>
<p>Looks fine, right? But there are two inefficiencies here:</p>
<ol>
<li><p>You're manually looping when Python has a better, built-in way to handle this.</p>
</li>
<li><p>You're making repeated <code>.append()</code> calls, which add unnecessary overhead.</p>
</li>
</ol>
<p>In small cases, you won’t notice a difference. But when processing large datasets, these inefficiencies add up fast.</p>
<h3 id="heading-the-better-faster-way">The Better, Faster Way</h3>
<p>Python has built-in optimizations that make loops run faster. One of them is list comprehensions, which are optimized in C and run significantly faster than manual loops. Here’s how you can rewrite the example:</p>
<pre><code class="lang-python">pythonCopyEdit<span class="hljs-comment"># Much faster and cleaner</span>
squared = [num ** <span class="hljs-number">2</span> <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> numbers]
</code></pre>
<h4 id="heading-why-this-is-better">Why this is better:</h4>
<ol>
<li><p><strong>It’s faster.</strong> List comprehensions run in C under the hood, meaning they don’t have the overhead of Python function calls like <code>.append()</code>.</p>
</li>
<li><p><strong>It eliminates extra work.</strong> Instead of growing a list dynamically (which requires resizing in memory), Python pre-allocates space for the entire list. This makes the operation much more efficient.</p>
</li>
<li><p><strong>It’s more readable.</strong> The intent is clear: "I’m creating a list by squaring each number"—no need to scan through multiple lines of code.</p>
</li>
<li><p><strong>It’s less error-prone.</strong> Since everything happens in a single expression, there’s less chance of accidentally modifying the list incorrectly (for example, forgetting to <code>.append()</code>).</p>
</li>
</ol>
<h3 id="heading-when-to-use-for-loops-vs-list-comprehensions">When to Use For Loops vs. List Comprehensions</h3>
<p>For loops still have their place. Use them when:</p>
<ul>
<li><p>You need complex logic inside the loop (for example, multiple operations per iteration).</p>
</li>
<li><p>You need to modify existing data in place rather than create a new list.</p>
</li>
<li><p>The operation involves side effects, like logging, file writing, or network requests.</p>
</li>
</ul>
<p>Otherwise, list comprehensions should be your default choice for simple transformations. They’re faster, cleaner, and make your Python code more efficient.</p>
<h2 id="heading-mistake-3-writing-database-queries-inside-loops-killer-of-speed"><strong>Mistake #3: Writing Database Queries Inside Loops (Killer of Speed)</strong></h2>
<h3 id="heading-why-this-is-a-problem-2"><strong>Why This is a Problem</strong></h3>
<p>This is one of the biggest slow-code mistakes beginners (and even intermediates) make. It happens because loops feel natural, and database queries feel straightforward. But mix the two together, and you’ve got a performance disaster.</p>
<p>Every time you call a database inside a loop, you're making repeated trips to the database. Each query adds network latency, processing overhead, and unnecessary load on your system.</p>
<h4 id="heading-example-1">Example:</h4>
<p>Imagine you’re fetching user details for a list of <code>user_ids</code> like this:</p>
<pre><code class="lang-python">pythonCopyEdituser_ids = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]

<span class="hljs-keyword">for</span> user_id <span class="hljs-keyword">in</span> user_ids:
    user = db.query(<span class="hljs-string">f"SELECT * FROM users WHERE id = <span class="hljs-subst">{user_id}</span>"</span>)
    print(user)  <span class="hljs-comment"># Do something with the user</span>
</code></pre>
<p><strong>What's wrong here?</strong></p>
<ul>
<li><p>You're hitting the database multiple times instead of once.</p>
</li>
<li><p>Each call has network overhead (database queries aren’t instant).</p>
</li>
<li><p>Performance tanks when user_ids gets large.</p>
</li>
</ul>
<h3 id="heading-how-to-fix-it-use-bulk-queries"><strong>How to Fix It: Use Bulk Queries</strong></h3>
<p>Instead of making 5 separate queries, make one:</p>
<pre><code class="lang-python">pythonCopyEdituser_ids = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]

users = db.query(<span class="hljs-string">f"SELECT * FROM users WHERE id IN (<span class="hljs-subst">{<span class="hljs-string">','</span>.join(map(str, user_ids))}</span>)"</span>)

<span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users:
    print(user)  <span class="hljs-comment"># Process users efficiently</span>
</code></pre>
<p><strong>Why this is better:</strong></p>
<ul>
<li><p>In the above code, we just have one database call instead of many. This results in faster performance.</p>
</li>
<li><p>There’s also less network overhead which makes your app feel snappier.</p>
</li>
<li><p>And this works even if <code>user_ids</code> has 10,000+ entries.</p>
</li>
</ul>
<h3 id="heading-a-more-scalable-approach"><strong>A More Scalable Approach</strong></h3>
<p>If you're using an ORM (like SQLAlchemy in Python or Sequelize in JavaScript), use batch fetching instead of looping:</p>
<pre><code class="lang-python">pythonCopyEditusers = db.query(User).filter(User.id.in_(user_ids)).all()
</code></pre>
<h2 id="heading-mistake-4-not-knowing-your-hardwares-dirty-secrets"><strong>Mistake #4: Not Knowing Your Hardware’s Dirty Secrets</strong></h2>
<p>Your code doesn’t run in a magical fairyland—it runs on real hardware. CPUs, memory, and caches have quirks that can turn “logically fast” code into a sluggish mess. Here’s what most tutorials won’t tell you:</p>
<h3 id="heading-problem-1-the-cpus-crystal-ball-is-broken-memory-prefetching"><strong>Problem 1: The CPU’s Crystal Ball is Broken (Memory Prefetching)</strong></h3>
<h4 id="heading-what-you-think-happens">What you think happens:</h4>
<p><em>“I’m looping through data sequentially. The CPU should predict what I need next!”</em></p>
<h4 id="heading-what-actually-happens">What actually happens:</h4>
<p>Modern CPUs have a memory prefetcher—a smart assistant that tries to guess which memory locations you’ll need next and loads them in advance.</p>
<p>But here’s the catch: If your access pattern is too random, the prefetcher gives up. Instead of smoothly fetching data ahead of time, the CPU is left waiting, like someone stuck refreshing Google Maps on a broken internet connection or blind date.</p>
<p>This happens a lot with linked lists and hash tables, where memory jumps around unpredictably.</p>
<h4 id="heading-example-2">Example:</h4>
<pre><code class="lang-python"><span class="hljs-comment"># Linked list traversal (random memory jumps)  </span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span>:</span>  
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, val</span>):</span>  
        self.val = val  
        self.next = <span class="hljs-literal">None</span>  

head = Node(<span class="hljs-number">0</span>)  
current = head  
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(<span class="hljs-number">100000</span>):  <span class="hljs-comment"># Each 'next' points to a random memory location  </span>
    current.next = Node(<span class="hljs-number">0</span>)  
    current = current.next  

<span class="hljs-comment"># Walking this list = 100,000 cache misses</span>
</code></pre>
<h4 id="heading-why-this-hurts">Why this hurts:</h4>
<p>Each time the CPU needs the next <code>Node</code>, it has to fetch it from a random memory location, making prefetching useless and causing frequent cache misses.</p>
<h3 id="heading-the-fix-use-contiguous-data-structures"><strong>The Fix: Use Contiguous Data Structures</strong></h3>
<p>Instead of using a linked list, store your data in a contiguous memory block (like an array or NumPy array). This way, the CPU can easily prefetch the next elements in sequence, speeding things up.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Array traversal (prefetcher-friendly)  </span>
data = [<span class="hljs-number">0</span>] * <span class="hljs-number">100000</span>  <span class="hljs-comment"># Contiguous memory  </span>
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> data:  
    <span class="hljs-keyword">pass</span>  <span class="hljs-comment"># CPU prefetches next elements seamlessly</span>
</code></pre>
<p><strong>Why this is better:</strong></p>
<ul>
<li><p>The CPU efficiently prefetches upcoming values instead of waiting.</p>
</li>
<li><p>Fewer cache misses = way faster execution.</p>
</li>
<li><p>Hot loops (loops that run millions of times) get a huge performance boost.</p>
</li>
</ul>
<p>📌 <strong>Hot loops</strong> are loops that execute a massive number of times, like those in data processing, AI models, and game engines. Even a small speedup in a hot loop can dramatically improve overall performance.</p>
<h3 id="heading-problem-2-the-invisible-tax-of-memory-pages-tlb-thrashing"><strong>Problem 2: The Invisible Tax of Memory Pages (TLB Thrashing)</strong></h3>
<h4 id="heading-what-you-think-happens-1">What you think happens:</h4>
<p><em>“My 10GB dataset is just… there. Accessing it is free, right?”</em></p>
<h4 id="heading-what-actually-happens-1">What actually happens:</h4>
<p>Your OS splits memory into 4KB pages. Every time your program accesses a new memory page, the CPU consults a Translation Lookaside Buffer (TLB)—a “phonebook” for fast page lookups.</p>
<p>If your program jumps between too many pages, you get TLB misses, and the CPU wastes cycles waiting for the OS to fetch memory mappings.</p>
<h4 id="heading-example-3">Example:</h4>
<pre><code class="lang-python"><span class="hljs-comment"># Iterating a giant list with random access  </span>
data = [x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>_000_000)]  
total = <span class="hljs-number">0</span>  
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> random_indexes:  <span class="hljs-comment"># 1,000,000 random jumps  </span>
    total += data[i]  <span class="hljs-comment"># Each jump likely hits a new page</span>
</code></pre>
<h4 id="heading-why-this-hurts-1">Why this hurts:</h4>
<ul>
<li><p>TLB misses can add 10-100 CPU cycles per access.</p>
</li>
<li><p>If you have millions of random accesses, that’s billions of wasted cycles.</p>
</li>
</ul>
<h3 id="heading-the-fix-process-data-in-chunks"><strong>The Fix: Process Data in Chunks</strong></h3>
<p>To reduce TLB misses:</p>
<ul>
<li><p><strong>Process data in chunks</strong> (for example, 4096 elements at a time) instead of randomly jumping around.</p>
</li>
<li><p><strong>Use huge pages</strong> (2MB instead of 4KB) so that more data fits in each memory page.</p>
</li>
</ul>
<h3 id="heading-problem-3-your-code-is-a-tourist-in-the-wrong-cpu-neighborhood-numa"><strong>Problem 3: Your Code is a Tourist in the Wrong CPU Neighborhood (NUMA)</strong></h3>
<h4 id="heading-what-you-think-happens-2">What you think happens:</h4>
<p><em>“My 64-core server is a speed paradise!”</em></p>
<h4 id="heading-what-actually-happens-2">What actually happens:</h4>
<p>On multi-socket servers, memory is divided into NUMA (Non-Uniform Memory Access) zones. Each CPU socket has its own local memory, and accessing memory from another socket is slow—like ordering Uber Eats from another city.</p>
<h4 id="heading-example-4">Example:</h4>
<pre><code class="lang-python"><span class="hljs-comment"># Running this on a 2-socket server:  </span>
<span class="hljs-keyword">from</span> multiprocessing <span class="hljs-keyword">import</span> Pool  
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np  

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process</span>(<span class="hljs-params">chunk</span>):</span>  
    data = np.load(<span class="hljs-string">"giant_array.npy"</span>)  <span class="hljs-comment"># Allocated on Socket 1's RAM  </span>
    <span class="hljs-keyword">return</span> chunk * data  <span class="hljs-comment"># If process runs on Socket 2's CPU... ouch  </span>

<span class="hljs-keyword">with</span> Pool(<span class="hljs-number">64</span>) <span class="hljs-keyword">as</span> p:  
    p.map(process, big_data)  <span class="hljs-comment"># 64 cores fighting over remote RAM</span>
</code></pre>
<h4 id="heading-why-this-hurts-2">Why this hurts:</h4>
<ul>
<li><p>Accessing memory from another NUMA zone can be 2-4x slower.</p>
</li>
<li><p>Your 64 cores end up waiting for memory instead of actually computing.</p>
</li>
</ul>
<h3 id="heading-the-fix-pin-processes-to-numa-aware-memory"><strong>The Fix: Pin Processes to NUMA-Aware Memory</strong></h3>
<p>Instead of letting your processes randomly access memory, you can pin them to the correct NUMA node.</p>
<ul>
<li><p>Use <code>numactl</code> on Linux to allocate memory near the CPU that will use it.</p>
</li>
<li><p>Use <code>numba</code>-aware libraries in NumPy to ensure data is allocated optimally.</p>
</li>
</ul>
<h3 id="heading-problem-4-the-cpu-is-a-drama-queen-speculative-execution"><strong>Problem 4: The CPU is a Drama Queen (Speculative Execution)</strong></h3>
<h4 id="heading-what-you-think-happens-3">What you think happens:</h4>
<p><em>“My code runs in the order I wrote it!”</em></p>
<h4 id="heading-what-actually-happens-3">What actually happens:</h4>
<p>CPUs speculatively execute code ahead of time. If they guess wrong, they have to rollback everything and restart, which slows things down.</p>
<h4 id="heading-example-5"><strong>Example:</strong></h4>
<pre><code class="lang-cpp"><span class="hljs-comment">// Unpredictable branches = CPU's worst nightmare  </span>
<span class="hljs-keyword">if</span> (rare_condition) {  <span class="hljs-comment">// 99% of the time, this is false  </span>
    do_work();  
}
</code></pre>
<h4 id="heading-why-this-hurts-3">Why this hurts:</h4>
<p>A branch misprediction wastes 15-20 cycles. In hot loops, this can really hurt performance.</p>
<h3 id="heading-the-fix-make-branches-predictable"><strong>The Fix: Make Branches Predictable</strong></h3>
<p>Sort data to help the CPU make better predictions:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Process all 'valid' items first, then 'invalid' ones  </span>
sorted_data = sorted(data, key=<span class="hljs-keyword">lambda</span> x: x.is_valid, reverse=<span class="hljs-literal">True</span>)  
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> sorted_data:  
    <span class="hljs-keyword">if</span> item.is_valid:  <span class="hljs-comment"># CPU learns the pattern → accurate predictions  </span>
        process(item)
</code></pre>
<p><strong>Why This Works:</strong></p>
<ul>
<li><p>Branching becomes predictable—the CPU stops guessing wrong.</p>
</li>
<li><p>Sorting ahead of time reduces rollbacks and wasted cycles.</p>
</li>
</ul>
<h3 id="heading-how-to-fight-back"><strong>How to Fight Back</strong></h3>
<p>Here’s how you can stop your CPU from sabotaging your code:</p>
<ol>
<li>Treat Memory Like a Highway: Cache lines matter. Keep data contiguous so the CPU doesn’t have to search for it.</li>
</ol>
<ol start="2">
<li><p>Profile with <code>perf</code>: Use Linux’s <code>perf</code> tool to spot cache misses, page faults, and TLB thrashing:</p>
<pre><code class="lang-bash"> perf <span class="hljs-built_in">stat</span> -e cache-misses,page-faults ./your_code
</code></pre>
</li>
</ol>
<ol start="3">
<li>Assume Nothing. Benchmark Everything: CPUs have a thousand undocumented behaviors. Test different data layouts, loop structures, and memory allocations to see what’s fastest.</li>
</ol>
<h2 id="heading-mistake-5-memory-fragmentation"><strong>Mistake #5: Memory Fragmentation</strong></h2>
<p>You’ve optimized your algorithms. You’ve nailed Big O. Yet your app still crashes with “out of memory” errors or slows to a crawl over time. The culprit? Memory fragmentation—a ghost in the machine that most developers ignore until it’s too late.</p>
<h4 id="heading-whats-happening-under-the-hood">What’s Happening Under the Hood</h4>
<p>When your code allocates and frees memory blocks of varying sizes, it leaves behind a patchwork of free and used spaces. Over time, this creates a Swiss cheese effect in your RAM: plenty of total free memory, but no contiguous blocks for new allocations.</p>
<p><strong>Example:</strong><br>Imagine a C++ server that handles requests by allocating buffers of random sizes:</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">process_request</span><span class="hljs-params">()</span> </span>{  
    <span class="hljs-comment">// Allocate a buffer of random size between 1–1024 bytes  </span>
    <span class="hljs-keyword">char</span>* buffer = <span class="hljs-keyword">new</span> <span class="hljs-keyword">char</span>[rand() % <span class="hljs-number">1024</span> + <span class="hljs-number">1</span>];  
    <span class="hljs-comment">// ... process ...  </span>
    <span class="hljs-keyword">delete</span>[] buffer;  
}
</code></pre>
<p>After millions of requests, your memory looks like this:</p>
<p><code>[USED][FREE][USED][FREE][USED][FREE]...</code></p>
<p>Now, when you try to allocate a 2KB buffer, it fails—not because there’s no space, but because no single free block is large enough.</p>
<h4 id="heading-how-to-fix-it-1">How to Fix it:</h4>
<p>Use a memory pool to allocate fixed-size blocks:</p>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MemoryPool</span> {</span>  
<span class="hljs-keyword">public</span>:  
    MemoryPool(<span class="hljs-keyword">size_t</span> block_size) : block_size_(block_size) {}  
    <span class="hljs-function"><span class="hljs-keyword">void</span>* <span class="hljs-title">allocate</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/* get a pre-allocated block */</span> }  
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">deallocate</span><span class="hljs-params">(<span class="hljs-keyword">void</span>* ptr)</span> </span>{ <span class="hljs-comment">/* return block to pool */</span> }  
};  

<span class="hljs-comment">// All requests use buffers of fixed size (1024 bytes)  </span>
<span class="hljs-function">MemoryPool <span class="hljs-title">pool</span><span class="hljs-params">(<span class="hljs-number">1024</span>)</span></span>;  
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">process_request</span><span class="hljs-params">()</span> </span>{  
    <span class="hljs-keyword">char</span>* buffer = <span class="hljs-keyword">static_cast</span>&lt;<span class="hljs-keyword">char</span>*&gt;(pool.allocate());  
    <span class="hljs-comment">// ... process ...  </span>
    pool.deallocate(buffer);  
}
</code></pre>
<p>By standardizing block sizes, you eliminate fragmentation.</p>
<h3 id="heading-the-autoboxing-trap-java-c-and-so-on">The Autoboxing Trap (Java, C#, and so on)</h3>
<h4 id="heading-whats-happening">What’s Happening?</h4>
<p>In languages that mix primitives (like <code>int</code>, <code>float</code>) and objects (like <code>Integer</code>, <code>Double</code>), converting a primitive to its object wrapper is called <strong>autoboxing</strong>. It feels harmless, but in hot loops, it’s a performance disaster.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Slow: Creates 1,000,000 Integer objects (and garbage!)</span>
List&lt;Integer&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1_000_000</span>; i++) {  
    list.add(i);  <span class="hljs-comment">// Autoboxing 'i' to Integer  </span>
}
</code></pre>
<h4 id="heading-why-this-hurts-performance">Why this hurts performance:</h4>
<ul>
<li><p><strong>Memory overhead:</strong> Each <code>Integer</code> object adds 16–24 bytes of extra memory (object headers, pointers). With 1,000,000 numbers, that’s an extra 16–24MB wasted just on overhead.</p>
</li>
<li><p><strong>Garbage collection (GC) pressure:</strong> Since objects are allocated on the heap, the GC constantly cleans up old <code>Integer</code> objects, leading to latency spikes.</p>
</li>
<li><p><strong>CPU cache inefficiency:</strong> Primitives like <code>int</code> are tightly packed in memory, but <code>Integer</code> objects are scattered across the heap with extra indirection, wrecking cache locality.</p>
</li>
</ul>
<h4 id="heading-the-fix-use-primitive-collections">The Fix: Use Primitive Collections</h4>
<p>To avoid autoboxing, use data structures that store raw primitives instead of objects. In Java, Eclipse Collections provides primitive-friendly lists like <code>IntList</code> that store raw <code>int</code> values directly.</p>
<p><strong>Example: The Faster Version (Primitive Collections)</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Import primitive-friendly collection</span>
<span class="hljs-keyword">import</span> org.eclipse.collections.api.list.primitive.IntList;
<span class="hljs-keyword">import</span> org.eclipse.collections.impl.list.mutable.primitive.IntArrayList;  

<span class="hljs-comment">// Use IntArrayList to store raw ints</span>
IntList list = <span class="hljs-keyword">new</span> IntArrayList();  
<span class="hljs-keyword">for</span> (int i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1</span>_000_000; i++) {  
    list.add(i);  <span class="hljs-comment">// No autoboxing! Stores raw 'int'  </span>
}
</code></pre>
<h4 id="heading-how-this-fix-works">How this fix works:</h4>
<ul>
<li><p>Stores raw <code>int</code> values instead of <code>Integer</code> objects, eliminating memory overhead.</p>
</li>
<li><p>Avoids heap allocations, so the garbage collector doesn’t get involved.</p>
</li>
<li><p>Keeps numbers tightly packed in memory, improving CPU cache efficiency.</p>
</li>
</ul>
<h4 id="heading-the-fix-for-c">The Fix for C</h4>
<p>In C#, you can avoid unnecessary heap allocations by using <code>struct</code>s and <code>Span&lt;T&gt;</code>, which keep data on the stack or in contiguous memory rather than the heap.</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Span&lt;T&gt; avoids heap allocations  </span>
Span&lt;<span class="hljs-keyword">int</span>&gt; numbers = <span class="hljs-keyword">stackalloc</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">1</span>_000_000];  
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numbers.Length; i++) {  
    numbers[i] = i;  <span class="hljs-comment">// No boxing, no heap allocation  </span>
}
</code></pre>
<p>No object wrappers. No GC pressure. Just performance.</p>
<h2 id="heading-mistake-6-the-cache-catch"><strong>Mistake #6: The Cache (catch)</strong></h2>
<p>You’ve heard “cache matters,” but here’s the twist: your loops are lying to your CPU. The way you traverse multi-dimensional arrays can turn a 10x speed difference into a mystery that leaves you questioning reality.</p>
<h3 id="heading-row-major-vs-column-major-access"><strong>Row-Major vs. Column-Major Access</strong></h3>
<p><strong>What you think happens</strong>:<br><em>“Iterating over a 2D array is the same whether I go row-by-row or column-by-column. Right?”</em></p>
<p><strong>What actually happens</strong>:<br>Memory is laid out linearly, but CPUs prefetch data in chunks (cache lines). Traversing against the grain forces the CPU to fetch new cache lines <em>every single step</em>.</p>
<p><strong>Example in C</strong>:</p>
<pre><code class="lang-c"><span class="hljs-comment">// A "tiny" 1024x1024 matrix  </span>
<span class="hljs-keyword">int</span> matrix[<span class="hljs-number">1024</span>][<span class="hljs-number">1024</span>];  

<span class="hljs-comment">// Fast: Row-major traversal (cache-friendly)  </span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1024</span>; i++) {  
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; <span class="hljs-number">1024</span>; j++) {  
        matrix[i][j] = i + j;  
    }  
}  

<span class="hljs-comment">// Slow: Column-major traversal (cache-hostile)  </span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; <span class="hljs-number">1024</span>; j++) {  
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1024</span>; i++) {  
        matrix[i][j] = i + j;  
    }  
}
</code></pre>
<p><strong>The result</strong>:</p>
<ul>
<li><p>Row-major: ~5ms (data flows like a river).</p>
</li>
<li><p>Column-major: ~50ms (CPU drowns in cache misses).</p>
</li>
</ul>
<p><strong>Why it’s worse than you think</strong>:<br>In C/C++, arrays are row-major. But in Fortran, MATLAB, or Julia, they’re column-major. Use the wrong traversal order in these languages, and you’ll get the same penalty.</p>
<h3 id="heading-the-plot-twist-your-programming-language-is-gaslighting-you"><strong>The Pl**</strong>ot Twist: Your Programming Language is Gaslighting You**</h3>
<p>In C and Python (NumPy default), arrays use row-major order. But in Fortran, MATLAB, and Julia, arrays are column-major. If you assume the wrong layout, your loops will be slow for no apparent reason.</p>
<p><strong>Python Example</strong>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np  

<span class="hljs-comment"># Row-major (C-style) → Fast for row-wise loops  </span>
row_major = np.zeros((<span class="hljs-number">1024</span>, <span class="hljs-number">1024</span>), order=<span class="hljs-string">'C'</span>)  

<span class="hljs-comment"># Column-major (Fortran-style) → Fast for column-wise loops  </span>
col_major = np.zeros((<span class="hljs-number">1024</span>, <span class="hljs-number">1024</span>), order=<span class="hljs-string">'F'</span>)  

<span class="hljs-comment"># ❌ Slow: Column-wise access on a row-major array  </span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1024</span>):  
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span class="hljs-number">1024</span>):  
        col_major[i][j] = i + j  <span class="hljs-comment"># Cache-miss chaos!</span>
</code></pre>
<h4 id="heading-why-this-is-a-problem-3">Why this is a problem:</h4>
<ul>
<li><p>Row-major (default in NumPy) expects row-wise access, but the loop accesses it column-wise, causing cache misses.</p>
</li>
<li><p>Fortran-style arrays are stored column-first, so row-wise loops will be slow instead.</p>
</li>
</ul>
<h4 id="heading-the-fix">The Fix:</h4>
<ul>
<li><p>Match the array order to your access pattern using <code>order='C'</code> (row-major) or <code>order='F'</code> (column-major).</p>
</li>
<li><p>Convert data layout with <code>np.asarray()</code> if needed.</p>
</li>
</ul>
<h3 id="heading-the-multidimensional-illusion-3d-arrays"><strong>The Multidimensional Illusion**</strong>: 3D+ Arrays**</h3>
<p><strong>What you think happens</strong>:<br><em>“3D arrays are just 2D arrays with extra steps. No big deal.”</em></p>
<p><strong>What actually happens</strong>:<br>Each dimension adds a layer of indirection. A 3D array in C is an array of arrays of arrays. Traversing the “wrong” dimension forces the CPU to dereference pointers repeatedly, killing locality.</p>
<p><strong>Example</strong>: 3D Array in Traversal in C</p>
<pre><code class="lang-c"><span class="hljs-comment">// ✅ Fast: Iterate in Row-Major Order (Innermost Dimension Last)</span>

<span class="hljs-keyword">int</span> space[<span class="hljs-number">256</span>][<span class="hljs-number">256</span>][<span class="hljs-number">256</span>];  

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> x = <span class="hljs-number">0</span>; x &lt; <span class="hljs-number">256</span>; x++) {  
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> y = <span class="hljs-number">0</span>; y &lt; <span class="hljs-number">256</span>; y++) {  
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> z = <span class="hljs-number">0</span>; z &lt; <span class="hljs-number">256</span>; z++) {  
            space[x][y][z] = x + y + z;  <span class="hljs-comment">// Smooth memory access  </span>
        }  
    }  
}
</code></pre>
<p>So what happens is that the innermost loop moves through contiguous memory, making full use of cache lines.</p>
<pre><code class="lang-c"><span class="hljs-comment">// ❌ Slow: Iterate in the Wrong Order (Innermost Dimension First)</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> z = <span class="hljs-number">0</span>; z &lt; <span class="hljs-number">256</span>; z++) {  
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> y = <span class="hljs-number">0</span>; y &lt; <span class="hljs-number">256</span>; y++) {  
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> x = <span class="hljs-number">0</span>; x &lt; <span class="hljs-number">256</span>; x++) {  
            space[x][y][z] = x + y + z;  <span class="hljs-comment">// Constant cache misses  </span>
        }  
    }  
}
</code></pre>
<p><strong>Why this is bad</strong>:</p>
<ul>
<li><p>This loop jumps across memory every time <code>x</code> changes.</p>
</li>
<li><p>Instead of accessing contiguous memory, it dereferences pointers constantly.</p>
</li>
<li><p>Penalty: Up to 100x slower for large 3D arrays!</p>
</li>
</ul>
<h3 id="heading-the-nuclear-option-cache-aware-algorithms"><strong>The Nuclear Option: Cache-Aware Algorithms</strong></h3>
<p>For extreme performance (game engines, HPC), you need to design for cache lines:</p>
<ol>
<li><p><strong>Tiling</strong>: Split arrays into small blocks that fit in L1/L2 cache.</p>
<pre><code class="lang-python"> // Process <span class="hljs-number">8</span>x8 tiles to exploit <span class="hljs-number">64</span>-byte cache lines  
 <span class="hljs-keyword">for</span> (int i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1024</span>; i += <span class="hljs-number">8</span>) {  
     <span class="hljs-keyword">for</span> (int j = <span class="hljs-number">0</span>; j &lt; <span class="hljs-number">1024</span>; j += <span class="hljs-number">8</span>) {  
         // Process tile[i:i+<span class="hljs-number">8</span>][j:j+<span class="hljs-number">8</span>]  
     }  
 }
</code></pre>
</li>
<li><p><strong>SoA vs. AoS</strong>: Prefer Structure of Arrays (SoA) over Array of Structures for SIMD.</p>
<pre><code class="lang-python"> // Slow: Array of Structures (AoS)  
 struct Particle { float x, y, z; };  
 Particle particles[<span class="hljs-number">1000000</span>];  

 // Fast: Structure of Arrays (SoA)  
 struct Particles {  
     float x[<span class="hljs-number">1000000</span>];  
     float y[<span class="hljs-number">1000000</span>];  
     float z[<span class="hljs-number">1000000</span>];  
 };
</code></pre>
</li>
</ol>
<h2 id="heading-mistake-7-the-copy-paste-trap"><strong>Mistake #7: The Copy-Paste Trap</strong></h2>
<p>You’d never download 10 copies of the same movie. But in code? You’re probably cloning data <em>all the time</em> without realizing it. Here’s how invisible copies turn your app into a bloated, slow mess—and how to fix it.</p>
<h3 id="heading-problem-1-the-ghost-copies-in-harmless-operations"><strong>Problem 1: The Ghost Copies in “Harmless” Operations</strong></h3>
<p><strong>What you think happens</strong>:<br><em>“I sliced a list—it’s just a reference, right?”</em></p>
<p><strong>What actually happens</strong>:<br>In many languages, slicing creates a full copy of the data. Do this with large datasets, and you’re silently doubling memory usage and CPU work.</p>
<p><strong>Python Example</strong>:</p>
<pre><code class="lang-python"><span class="hljs-comment"># A 1GB list of data  </span>
big_data = [ ... ]  <span class="hljs-comment"># 1,000,000 elements  </span>

<span class="hljs-comment"># Accidentally cloning the entire list  </span>
snippet = big_data[:<span class="hljs-number">1000</span>]  <span class="hljs-comment"># Creates a copy (harmless, right?)  </span>

<span class="hljs-comment"># Better: Use a view (if possible)  </span>
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np  
big_array = np.array(big_data)  
snippet = big_array[:<span class="hljs-number">1000</span>]  <span class="hljs-comment"># A view, not a copy (0MB added)</span>
</code></pre>
<h4 id="heading-why-this-hurts-4">Why this hurts:</h4>
<ul>
<li><p>Copying 1GB → 2GB of RAM used.</p>
</li>
<li><p>If this happens in a loop, your program could crash with <code>MemoryError</code>.</p>
</li>
</ul>
<h4 id="heading-the-fix-1">The Fix:</h4>
<ul>
<li><p>Use memory views (<code>numpy</code>, <code>memoryview</code> in Python) or lazy slicing (Pandas <code>.iloc</code>).</p>
</li>
<li><p>In JavaScript, <code>slice()</code> copies arrays—replace with <code>TypedArray.subarray</code> for buffers.</p>
</li>
</ul>
<h3 id="heading-problem-2-the-hidden-cost-of-functional-code"><strong>Problem 2: The Hidden Cost of “Functional” Code</strong></h3>
<h4 id="heading-what-you-think-happens-4">What you think happens:</h4>
<p><em>“I’ll chain array methods for clean, readable code!”</em></p>
<h4 id="heading-what-actually-happens-4">What actually happens:</h4>
<p>Every <code>map</code>, <code>filter</code>, or <code>slice</code> creates a new array. Chain three operations? You’ve cloned your data three times.</p>
<p><strong>JavaScript Example</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// A 10,000-element array  </span>
<span class="hljs-keyword">const</span> data = [ ... ];  

<span class="hljs-comment">// Slow: Creates 3 copies (original → filtered → mapped → sliced)  </span>
<span class="hljs-keyword">const</span> result = data  
  .filter(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x.active)  
  .map(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x.value * <span class="hljs-number">2</span>)  
  .slice(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>);  

<span class="hljs-comment">// Faster: Do it in one pass  </span>
<span class="hljs-keyword">const</span> result = [];  
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; data.length; i++) {  
  <span class="hljs-keyword">if</span> (data[i].active) {  
    result.push(data[i].value * <span class="hljs-number">2</span>);  
    <span class="hljs-keyword">if</span> (result.length === <span class="hljs-number">100</span>) <span class="hljs-keyword">break</span>;  
  }  
}
</code></pre>
<p><strong>Why this hurts</strong>:</p>
<ul>
<li><p>10,000 elements → 30,000 operations + 3x memory.</p>
</li>
<li><p>Functional programming is <em>elegant</em> but can be <em>expensive</em>.</p>
</li>
</ul>
<h4 id="heading-the-fix-2">The Fix:</h4>
<ul>
<li><p>Use generators (Python <code>yield</code>, JS <code>function*</code>) for lazy processing.</p>
</li>
<li><p>Replace method chains with single-pass loops in hot paths.</p>
</li>
</ul>
<h3 id="heading-problem-3-the-ill-just-modify-a-copy-mistake"><strong>Problem 3: The “I’ll Just Modify a Copy” Mistake</strong></h3>
<p><strong>What you think happens</strong>:<br><em>“I need to tweak this object. I’ll duplicate it to avoid side effects.”</em></p>
<p><strong>What actually happens</strong>:<br>Deep cloning complex objects (especially in loops) is like photocopying a dictionary every time you edit a word.</p>
<p><strong>Python Example</strong>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> copy  

config = {<span class="hljs-string">"theme"</span>: <span class="hljs-string">"dark"</span>, <span class="hljs-string">"settings"</span>: { ... }}  <span class="hljs-comment"># Nested data  </span>

<span class="hljs-comment"># Slow: Deep-copying before every edit  </span>
<span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users:  
    user_config = copy.deepcopy(config)  <span class="hljs-comment"># Copies entire nested structure  </span>
    user_config[<span class="hljs-string">"theme"</span>] = user.preference  
    <span class="hljs-comment"># ...  </span>

<span class="hljs-comment"># Faster: Reuse the base config, overlay changes  </span>
<span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users:  
    user_config = {<span class="hljs-string">"theme"</span>: user.preference, **config}  <span class="hljs-comment"># Shallow merge  </span>
    <span class="hljs-comment"># ...</span>
</code></pre>
<p><strong>Why this hurts</strong>:</p>
<ul>
<li><p><code>deepcopy</code> is 10-100x slower than shallow copies.</p>
</li>
<li><p>Multiplied by 1,000 users, you’re wasting minutes.</p>
</li>
</ul>
<h4 id="heading-the-fix-3">The Fix:</h4>
<ul>
<li><p>Use immutable patterns: Create new objects by merging instead of cloning.</p>
</li>
<li><p>For big data, use structural sharing (libraries like <code>immutables</code> in Python).</p>
</li>
</ul>
<h3 id="heading-how-to-escape-the-copy-paste-hell"><strong>How to Escape the Copy-Paste hell?</strong></h3>
<ol>
<li><p><strong>Ask: “Do I need a copy?”</strong>: 90% of the time, you don’t. Use views, generators, or in-place edits.</p>
</li>
<li><p><strong>Profile memory usage</strong>: Tools like <code>memory_profiler</code> (Python) or Chrome DevTools (JS) show copy overhead.</p>
</li>
<li><p><strong>Learn your language’s quirks</strong>:</p>
<ul>
<li><p>Python: Slicing lists copies, slicing NumPy arrays doesn’t.</p>
</li>
<li><p>JavaScript: <code>[...array]</code> clones, <code>array.subarray</code> (TypedArray) doesn’t.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-how-do-pro-developers-write-faster-code">How Do Pro Developers Write Faster Code?</h2>
<p>Most beginners think "fast code" just means writing cleaner syntax or using a different framework. But in reality, performance isn't just about what language or framework you use—it's about how you think.</p>
<p>Pro developers don’t just write code. They measure, test, and optimize it<strong>.</strong> Here’s how they do it.</p>
<h3 id="heading-1-they-profile-their-code-instead-of-guessing"><strong>1. They Profile Their Code Instead of Guessing</strong></h3>
<p>🔥 Beginners: “This function feels slow… maybe I should rewrite it?”<br>💡 Pros: “Let’s profile it and see what’s actually slow.”</p>
<p>Instead of randomly rewriting code, pro developers measure first using <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-pythons-built-in-profiling-tools-examples-and-best-practices/">profiling tools</a>.</p>
<p><strong>Example:</strong> In Python, you can use <code>cProfile</code> to analyze where your code is spending the most time:</p>
<pre><code class="lang-javascript">pythonCopyEditimport cProfile

def slow_function():
    total = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>**<span class="hljs-number">6</span>):
        total += i
    <span class="hljs-keyword">return</span> total

cProfile.run(<span class="hljs-string">'slow_function()'</span>)
</code></pre>
<p>👀 <strong>What this tells you:</strong></p>
<ul>
<li><p>Which function takes the longest</p>
</li>
<li><p>How many times is a function being called</p>
</li>
<li><p>Where is the actual bottleneck</p>
</li>
</ul>
<p>✅ <strong>Takeaway:</strong> Before optimizing, always profile your code. You can’t fix what you don’t measure.</p>
<p>Other useful tools:</p>
<ul>
<li><p><strong>Python:</strong> <code>cProfile</code>, <code>line_profiler</code></p>
</li>
<li><p><strong>JavaScript:</strong> Chrome DevTools Performance Tab</p>
</li>
<li><p><strong>Java:</strong> JProfiler</p>
</li>
<li><p><strong>General:</strong> <code>perf</code>, <code>Valgrind</code></p>
</li>
</ul>
<h3 id="heading-2-they-avoid-premature-optimization"><strong>2. They Avoid Premature Optimization</strong></h3>
<p>🔥 Beginners: “I’ll spend hours optimizing this loop before testing it.”<br>💡 Pros: “I’ll make it work first, then optimize only what matters.”</p>
<p>Donald Knuth famously said, <em>"Premature optimization is the root of all evil."</em> Many beginners waste time optimizing things that aren’t actually slow.</p>
<p><strong>Example:</strong> A beginner might spend hours optimizing a loop that runs in 0.001 seconds, while the real slowdown is an extra database query that takes 500ms.</p>
<p>✅ <strong>Takeaway:</strong></p>
<ul>
<li><p>First, make your code work.</p>
</li>
<li><p>Then, profile and optimize only what’s slow.</p>
</li>
</ul>
<h3 id="heading-3-they-pick-the-right-data-structures-not-just-whats-familiar"><strong>3. They Pick the Right Data Structures (Not Just What’s Familiar)</strong></h3>
<p>🔥 Beginners: “I’ll just use a list.”<br>💡 Pros: “Which data structure is optimal for this task?”</p>
<p>Most slowdowns happen because of bad data structure choices. Pro developers pick the right tool instead of just going with the default.</p>
<p><strong>Example: Fast lookups</strong><br>❌ <strong>Slow (List - O(n))</strong></p>
<pre><code class="lang-javascript">pythonCopyEditusers = [<span class="hljs-string">"alice"</span>, <span class="hljs-string">"bob"</span>, <span class="hljs-string">"charlie"</span>]
<span class="hljs-keyword">if</span> <span class="hljs-string">"bob"</span> <span class="hljs-keyword">in</span> users:  # Searches the entire list
    print(<span class="hljs-string">"Found"</span>)
</code></pre>
<p>✅ <strong>Fast (Set - O(1))</strong></p>
<pre><code class="lang-javascript">pythonCopyEditusers = {<span class="hljs-string">"alice"</span>, <span class="hljs-string">"bob"</span>, <span class="hljs-string">"charlie"</span>}
<span class="hljs-keyword">if</span> <span class="hljs-string">"bob"</span> <span class="hljs-keyword">in</span> users:  # Uses a hash table <span class="hljs-keyword">for</span> instant lookup
    print(<span class="hljs-string">"Found"</span>)
</code></pre>
<p>✅ <strong>Takeaway:</strong> When performance matters, choose the right data structure, not just the most familiar one.</p>
<h3 id="heading-4-they-automate-performance-checks"><strong>4. They Automate Performance Checks</strong></h3>
<p>🔥 Beginners: “I’ll check for performance issues when I feel like it.”<br>💡 Pros: “I’ll use tools to automatically catch performance bottlenecks.”</p>
<p>Instead of manually looking for slow code, pro developers rely on automated tools that flag inefficiencies.</p>
<p><strong>Example:</strong></p>
<ul>
<li><p><strong>Python:</strong> <code>py-spy</code> (lightweight sampling profiler)</p>
</li>
<li><p><strong>JavaScript:</strong> Chrome DevTools Performance Monitoring</p>
</li>
<li><p><strong>Java:</strong> JMH (Java Microbenchmark Harness)</p>
</li>
<li><p><strong>AI-assisted code reviews:</strong> There are tools like <a target="_blank" href="http://codeant.ai">CodeAnt</a> that analyze and auto fix your code automatically when you push on GitHub(or anywhere) and suggest performance improvements.</p>
</li>
</ul>
<p>✅ <strong>Takeaway:</strong> Set up automated checks so you catch performance issues early—before they hit production.</p>
<h3 id="heading-5-they-think-about-performance-from-day-one"><strong>5. They Think About Performance From Day One</strong></h3>
<p>🔥 Beginners: “I’ll optimize later.”<br>💡 Pros: “I’ll write efficient code from the start.”</p>
<p>While premature optimization is bad, writing slow code from the start is worse. Pro developers avoid common pitfalls before they become real problems.</p>
<p><strong>Example: Writing efficient loops from the start</strong><br>❌ <strong>Slow (Unnecessary</strong> <code>.append()</code>)</p>
<pre><code class="lang-javascript">pythonCopyEditresult = []
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>**<span class="hljs-number">6</span>):
    result.append(i * <span class="hljs-number">2</span>)  # This is slow
</code></pre>
<p>✅ <strong>Fast (List Comprehension - Optimized from the Start)</strong></p>
<pre><code class="lang-javascript">pythonCopyEditresult = [i * <span class="hljs-number">2</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>**<span class="hljs-number">6</span>)]  # Faster, more efficient
</code></pre>
<p>✅ <strong>Takeaway:</strong> Small choices add up. Think about performance as you write, rather than fixing it later.</p>
<h3 id="heading-final-thoughts-lessons-learned-the-hard-way"><strong>🚀 Final Thoughts: Lessons Learned the Hard Way</strong></h3>
<p>Thanks for reading! These are some of the tips I’ve personally bookmarked for myself—things I’ve learned the hard way while coding, talking to dev friends, and working on real projects.</p>
<p>When I first started, I used to guess why my code was slow instead of measuring. I’d optimize random parts of my code and still wonder why things weren’t getting faster. Over time, I realized that pro developers don’t just “write fast code” by instinct—they use tools, measure, and optimize what actually matters.</p>
<p>I wrote this to save you from making the same mistakes I did. Hopefully, now you have a clearer roadmap to writing faster, more efficient code—without the frustration I went through! 🚀</p>
<p>If you found this helpful, bookmark it for later, and feel free to share it with a fellow dev who might be struggling with slow code too.</p>
<p>Happy coding! 😊</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Software Design Basics: Key Phases and Best Practices ]]>
                </title>
                <description>
                    <![CDATA[ Coding has become one of the most common tasks in modern society. With computers now central to almost every field, more people are designing algorithms and writing code to solve various problems. From healthcare to finance, robust software systems p... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-software-design-basics/</link>
                <guid isPermaLink="false">67cb6446f54b40e1e9144db0</guid>
                
                    <category>
                        <![CDATA[ software design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ System Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TDD (Test-driven development) ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Coding Best Practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham Banerjee ]]>
                </dc:creator>
                <pubDate>Fri, 07 Mar 2025 21:25:26 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741188275855/9858518f-38c0-4e3b-8be1-7c56b68c77a7.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Coding has become one of the most common tasks in modern society. With computers now central to almost every field, more people are designing algorithms and writing code to solve various problems.</p>
<p>From healthcare to finance, robust software systems power our daily operations, making good software design essential to avoid inefficiencies and bottlenecks. This involves not just writing code but also designing systems that are easy to scale, maintain, and debug, while allowing others to contribute effectively.</p>
<p>Inefficient or ineffective software design can lead to significant issues, like scope creep, miscommunication within teams, project delays, resource misallocation, and complex systems that are difficult to maintain or understand. Without a strong design, teams often accumulate technical debt, which hinders long-term progress and increases maintenance costs.</p>
<p>This article will introduce you to key software design elements that will help you and your team address these challenges and guide you in building efficient, scalable systems. By understanding and applying these elements correctly, you can set up a project for both short-term and long-term success.</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>I’ll explain these concepts through examples, but a basic understanding of programming in any language is required for this article (knowledge of Python will be especially beneficial).</p>
<h2 id="heading-scope"><strong>Scope</strong></h2>
<p>The article will introduce key software design elements and explain them using an example. While I won’t provide a full software design for the example problem, I will include enough details to effectively illustrate each design element.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-overview-of-key-software-design-elements">Overview of Key Software Design Elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-walkthrough-of-the-software-design-process">A Walkthrough of the Software Design Process</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-problem-statement">Problem Statement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-cases">Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-requirements">Requirements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-high-level-system-architecture">High Level System Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-detailed-software-design-and-component-breakdown">Detailed Software Design and Component Breakdown</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion-the-value-of-thoughtful-software-design">Conclusion: The Value of Thoughtful Software Design</a></p>
</li>
</ul>
<h2 id="heading-overview-of-key-software-design-elements"><strong>Overview of Key Software Design Elements</strong></h2>
<p>To fully understand the benefits of the software design process, you’ll need to understand some key elements and their scope.</p>
<p>Once you have a good grasp of these, the next step is to define them for the specific problem at hand. Accurately defining these elements reduces risks and simplifies the implementation phase.</p>
<p>Doing this groundwork before implementation helps prevent late discoveries, minimizes the need for rewriting, and makes sure that the design can handle constraints and corner cases.</p>
<p>Now let’s briefly go over the key elements of the software design process:</p>
<ol>
<li><p><strong>Creating a problem statement</strong>: This step involves creating a clear and concise description of the problem that needs to be solved, along with its scope. The scope is essential because it focuses on the exact problem to be addressed and includes assumptions that must be considered during design.</p>
</li>
<li><p><strong>Identifying use cases</strong>: This step outlines all possible user interactions with the software to achieve the desired outcome. It is a critical input to the architecture, as it helps create a design that addresses both general and edge-case use cases.</p>
</li>
<li><p><strong>Stating requirements</strong>: This step defines the expectations of the software, such as its limitations, behaviors, and capabilities for different use cases.</p>
</li>
<li><p><strong>Designing the architecture</strong>: This step provides a high-level structure of the software design, focusing on how to meet the requirements. The architecture typically includes components, how they interact, and how data flows through the system.</p>
</li>
<li><p><strong>Drafting a detailed design</strong>: This step refines the high-level architecture into detailed, component-specific designs, ready for implementation.</p>
</li>
</ol>
<p>In addition to these core elements, there are two important factors you need to consider throughout the design phase.</p>
<p>First, you’ll need to identify and state any assumptions you have. Assumptions can be present at any stage in the design process. Making correct assumptions increases the likelihood of success, improves focus, and reduces complexity in the design.</p>
<p>Second, you’ll need to create good documentation. Documentation is one of the most important elements in the software design process. It’s essential to document each stage as you go along. Documentation serves as the only formal record of the software design and is invaluable for presentations to management, for onboarding new team members, and for anyone returning to the project after a break. It saves valuable time and ensures continuity, as we often overestimate our own memory.</p>
<p>The figure below provides a visual summary of the key software design elements discussed in this section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738540359869/2ee49614-84b1-439a-ae7e-af637c0f34dd.png?auto=compress,format&amp;format=webp" alt="Figure 1: Key software design elements" width="600" height="400" loading="lazy"></p>
<p>Next, we’ll apply these key software design elements to a practical example, demonstrating how each element contributes to building a robust and scalable system.</p>
<h2 id="heading-a-walkthrough-of-the-software-design-process"><strong>A Walkthrough of the Software Design Process</strong></h2>
<p>In any well-structured software project, clearly defining the problem is the first crucial step before diving into design and implementation. A well-defined problem ensures that the software meets user needs, remains maintainable, and scales effectively over time.</p>
<p>For this walkthrough, we will focus on designing a financial expense categorization system that processes and analyzes transaction data. This system is a part of a larger financial management solution and needs to be easy to debug, maintain, and scale.</p>
<h3 id="heading-problem-statement"><strong>Problem Statement</strong></h3>
<p>The problem statement provides a high-level goal for the software that we’ll design.</p>
<p>For this example, here’s our statement: Design a software solution that categorizes monthly expenses and generates a report from a list of transactions.</p>
<h4 id="heading-define-the-scope"><strong>Define the scope</strong></h4>
<p>Defining the scope clarifies the smaller tasks that must be accomplished to meet the high-level goal. It outlines the focus of the software design and includes some assumptions.</p>
<p>Includes:</p>
<ol>
<li><p>Implementing a parser to process a list of transactions provided as input.</p>
</li>
<li><p>Filtering transactions for a given month.</p>
</li>
<li><p>Analyzing, categorizing, and generating a report for each expense category.</p>
</li>
</ol>
<p>Excludes:</p>
<p>Performance and memory optimization (excluded due to the limited scope of this article). While performance and memory optimizations are not the primary focus here, it’s important to keep future scalability in mind. Small design choices made now, such as selecting data structures, can help avoid significant refactoring later when the system grows.</p>
<p>Assumptions:</p>
<ol>
<li><p>The list of transactions will be provided as a CSV file in the following format:<br> Columns: "Date, Description, Amount, Type, Category Label".</p>
</li>
<li><p>Expense categories will be provided as input through a JSON file.</p>
</li>
<li><p>The software will run in a shell environment, and inputs will be taken as command-line arguments.</p>
</li>
</ol>
<p>Now that the scope is clear, let’s examine how users will interact with the system through various use cases.</p>
<h3 id="heading-use-cases"><strong>Use Cases</strong></h3>
<p>Use cases define how users will interact with the system to accomplish specific goals. Identifying accurate and valid use cases is critical to creating comprehensive requirements. Failing to capture enough use cases can lead to a design that is incomplete and lacks robustness. This may result in the need for redesigns, which increases time and resource consumption.</p>
<p>On the other hand, identifying too many use cases without considering their feasibility can lead to overly complex designs that are difficult to maintain and implement in the short term.</p>
<p>For our specific problem, the user will need to provide the following inputs while running the software in a shell:</p>
<ol>
<li><p>A CSV file containing a list of transactions.</p>
</li>
<li><p>A month number.</p>
</li>
<li><p>A JSON file containing expense categories.</p>
</li>
</ol>
<p>We need to consider all possible ways the user can interact with the script to achieve the desired outcome. For each of the three inputs, there are two possibilities: valid input or invalid input. This gives us 8 potential use cases (2 possibilities per input: valid and invalid). It's important to define what constitutes valid and invalid inputs for this problem:</p>
<ul>
<li><p>CSV File: Valid if it is in the format described in Assumption 1 (columns: "Date, Description, Amount, Type, Category Label").</p>
</li>
<li><p>Month Number: Valid if the value is between 1 and 12.</p>
</li>
<li><p>JSON File: Valid if it contains expense categories in the correct JSON format.</p>
</li>
</ul>
<p>An input is invalid if it doesn't meet these definitions or if the input is absent.</p>
<p>It’s also crucial to consider the correlation between inputs when evaluating the feasibility of certain use cases, as they may interact with each other in unforeseen ways. Based on these use cases, we can now define the specific requirements that the system must meet.</p>
<h3 id="heading-requirements"><strong>Requirements</strong></h3>
<p>Now, let’s define the expected behaviors, limitations, and capabilities for each use case. Requirements serve as the foundation for architecture, specifications, and implementation. Based on our problem statement, the software will need to accomplish the following tasks:</p>
<ol>
<li><p>The script shall take three inputs: a CSV file of transactions, a month number, and a JSON file of expense categories.</p>
</li>
<li><p>The script shall verify all inputs.</p>
</li>
<li><p>The script shall throw an error and exit if the CSV file cannot be opened or if it does not match the format in Assumption 1.</p>
</li>
<li><p>The script shall throw an error and exit if the JSON file cannot be opened.</p>
</li>
<li><p>The script shall throw an error if the month number is not between 1 and 12.</p>
</li>
<li><p>The script shall parse each transaction and load it into a data structure.</p>
</li>
<li><p>The script shall filter transactions by the specified month.</p>
</li>
<li><p>The script shall load the expense categories from the JSON file into a data structure.</p>
</li>
<li><p>The script shall categorize transactions based on the category label provided in the CSV file.</p>
</li>
<li><p>The script shall throw an exception if a category label in the CSV file is not present in the expense categories.</p>
</li>
<li><p>The script shall use a categorizing function to assign transactions to categories from the JSON file.</p>
</li>
<li><p>A class shall encapsulate categorized transactions, providing APIs to modify or access them.</p>
</li>
<li><p>The script shall support statistics calculation and report generation for categorized transactions.</p>
</li>
</ol>
<p>With the requirements in place, we can now design a high-level architecture to meet those needs.</p>
<h3 id="heading-high-level-system-architecture"><strong>High Level System Architecture</strong></h3>
<p>In this stage, we will design the system at a high level, much like creating a master plan. Architecture involves organizing the software's functions into distinct components, illustrating how they interact, and mapping the flow of control and data through the system. While designing the architecture in this tutorial, we’ll incorporate good design principles.</p>
<p>For this example, the high-level requirements include:</p>
<ol>
<li><p>Loading inputs and verifying them.</p>
</li>
<li><p>Applying time-based filtering.</p>
</li>
<li><p>Categorizing transactions based on category labels and descriptions.</p>
</li>
<li><p>Managing categorized transactions in a finance registry.</p>
</li>
<li><p>Generating reports from the categorized data.</p>
</li>
</ol>
<p>One important component of software architecture is telemetry. Telemetry gathers data on the software's behavior, which is invaluable for debugging and performance assessment in real-world environments.</p>
<p>For smaller systems, simpler logging mechanisms may be sufficient to track basic errors and monitor performance. The decision to implement telemetry should depend on the complexity of the system and operational requirements.</p>
<p>Since telemetry provides such a helpful feedback loop for improving the design in future iterations, we’ll add it to the list of components here.</p>
<p>We’ll build our system architecture around a Test-Driven Development (TDD) approach. We’ll design each component with testing in mind to ensure it meets our requirements.</p>
<p>Just keep in mind that while TDD is a strong practice for ensuring code quality, it may not be the best fit for all projects. In scenarios where you need rapid prototyping or exploratory development, testing might be prioritized after initial iterations. Balancing between TDD and other methodologies depends on the project context and team preferences.</p>
<p>Our architecture will follow a modular structure, meaning the system will be divided into self-contained components. Each component will be responsible for specific functionality, making the system easier to test, maintain, and scale.</p>
<p>To achieve this, the architecture will emphasize loose coupling between components. Each component will interact with others through well-defined interfaces or APIs, ensuring minimal dependencies. We’ll abstract and encapsulate internal implementation details, exposing only the necessary information for interaction. Also, each component will handle its own errors and exceptions to ensure robustness and fault isolation.</p>
<p>But it is also important to consider a centralized error-handling strategy in some cases. Centralizing error handling can reduce redundancy, improve consistency, and make maintenance easier. The choice between local and centralized error handling should depend on the system's complexity and how components interact. This will contribute to the overall scalability and maintainability of the system.</p>
<p>Below is a summary of each component's functionality in this architecture:</p>
<ul>
<li><p>Load and verify input: This component will take the CSV file, JSON file, and month number as input, verify their validity, and load the data into structures.</p>
</li>
<li><p>Time-based filter: This component will filter transactions based on the input month and store the filtered transactions in a data structure.</p>
</li>
<li><p>Label-based categorization: This component will categorize transactions based on the category label in the CSV file.</p>
</li>
<li><p>Description-based categorization: This component will categorize transactions using an algorithm based on the transaction description.</p>
</li>
<li><p>Finance registry: This component will store all categorized transactions for further processing. It isolates the post-processing of categorized transactions from the categorization process and provides methods for updating or retrieving datasets.</p>
</li>
<li><p>Report generation: This component will generate expense reports from the categorized transaction data.</p>
</li>
<li><p>Telemetry: This component will monitor the performance of other components. It will track the flow of transactions, ensuring that all transactions are categorized either by label or description. Additional parameters can be added as needed to monitor specific functionalities.</p>
</li>
</ul>
<p>The diagram below demonstrates the flow of data through these components:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738540585066/6236b867-8c57-4a04-b5ea-4f9dd7f1fef3.png?auto=compress,format&amp;format=webp" alt="Figure 2: Flow of data through various components defined in the architecture" width="600" height="400" loading="lazy"></p>
<h3 id="heading-detailed-software-design-and-component-breakdown"><strong>Detailed Software Design and Component Breakdown</strong></h3>
<p>While we won't cover the full system design, this section will highlight key components and their specifications. For this example, I will assume the role of both the designer and implementer of the software.</p>
<p>Software design and specifications depend on several factors, including the designer's knowledge, skill set, available time, and resources. We’ll define some of the design details for the system, starting with the choice of the implementation language.</p>
<p>Choosing the right language is based on several important factors:</p>
<ol>
<li><p>The language must meet the software requirements.</p>
</li>
<li><p>It should be stable, and have strong support from an active developer community.</p>
</li>
<li><p>Additional considerations include performance (speed and memory), scalability (ability to grow with future requirements), and platform support (ability to run on all major operating systems).</p>
</li>
</ol>
<p>If you’re the one implementing this design, you’ll need to be familiar with and confident using that programming language. For this project, I chose Python because it meets all the project requirements, has a robust developer community for support, it’s stable, and I’m confident in using it to complete the implementation successfully.</p>
<h4 id="heading-data-structures"><strong>Data Structures</strong></h4>
<p>Now, let’s look at the fundamental data structures that we’ll use in the design. We need to load the contents of the CSV file into a data structure for further analysis and processing. In Python, the Pandas DataFrame from the Pandas library is ideal for analyzing and processing tables, so we will use it to store the transactions.</p>
<p>For generating report, we will encapsulate categorized transactions along with relevant statistics, such as the total number of transactions, mean amount, and maximum amount, within a dedicated dataset class. This approach ensures a clear separation of concerns, where the dataset class manages data processing, while the reporting component focuses on presentation.</p>
<p>By structuring the system this way, we enhance reusability, maintainability, and scalability, making it easier to extend and modify in the future.</p>
<p>This dataset class will include:</p>
<ul>
<li><p>Member variables: category name, category description, a Pandas DataFrame for transactions, total number of transactions, mean amount, and max amount of transactions.</p>
</li>
<li><p>Member functions: set/get DataFrame, save dataset to CSV (useful for debugging).</p>
</li>
</ul>
<p>Here’s an example of a Dataset class in Python for structured data management and processing:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd  <span class="hljs-comment"># Import Pandas for data handling</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dataset</span>:</span>
    <span class="hljs-string">"""
    A class representing a structured dataset with a name, predefined keys, 
    and a Pandas DataFrame.
    """</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, name, keys</span>):</span>
        <span class="hljs-string">"""
        Initializes the Dataset object.

        Parameters:
        name (str): The name of the dataset.
        keys (list): A list of expected column names for the dataset.

        Attributes:
        self.name (str): Stores the dataset name as a string.
        self.keys (list): Stores the expected column names for data organization.
        self.mean_amt (float): Tracks the mean (average) transaction amount.
        self.max_amt (float): Tracks the maximum transaction amount.
        self.count (int): Stores the total number of transactions in the dataset.
        self.dataframe (pd.DataFrame): A Pandas DataFrame initialized with the specified column names.
        """</span>
        self.name = str(name)  <span class="hljs-comment"># Convert and store dataset name as a string</span>
        self.keys = keys  <span class="hljs-comment"># Store expected column names for consistency</span>
        self.mean_amt = <span class="hljs-number">0</span>  <span class="hljs-comment"># Initialize mean transaction amount to zero</span>
        self.max_amt = <span class="hljs-number">0</span>  <span class="hljs-comment"># Initialize max transaction amount to zero</span>
        self.count = <span class="hljs-number">0</span>  <span class="hljs-comment"># Initialize transaction count to zero</span>
        self.dataframe = pd.DataFrame(columns=keys)  <span class="hljs-comment"># Initialize empty DataFrame with predefined columns</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getName</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Returns the name of the dataset.

        Returns:
        str: The name of the dataset.
        """</span>
        <span class="hljs-keyword">return</span> self.name  <span class="hljs-comment"># Fixed: Removed incorrect parentheses</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getValue</span>(<span class="hljs-params">self, key</span>):</span>
        <span class="hljs-string">"""
        Retrieves a specific column from the DataFrame.

        Parameters:
        key (str): The column name to retrieve.

        Returns:
        pandas.Series or None: The column data if the key exists, otherwise None.
        """</span>
        <span class="hljs-keyword">if</span> key <span class="hljs-keyword">in</span> self.dataframe.columns:
            <span class="hljs-keyword">return</span> self.dataframe[key]
        <span class="hljs-keyword">else</span>:
            print(<span class="hljs-string">f"Warning: Key '<span class="hljs-subst">{key}</span>' not found in DataFrame."</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>  <span class="hljs-comment"># Prevents KeyError</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getKeys</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Returns the list of expected keys (column names) of the dataset.

        Returns:
        list: The keys defining the dataset.
        """</span>
        <span class="hljs-keyword">return</span> self.keys

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setDataFrame</span>(<span class="hljs-params">self, dataframe</span>):</span>
        <span class="hljs-string">"""
        Sets the dataset's DataFrame while ensuring it contains only expected keys.

        Parameters:
        dataframe (pandas.DataFrame): The DataFrame to assign to the dataset.
        """</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> isinstance(dataframe, pd.DataFrame):
            <span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">"Provided data is not a valid pandas DataFrame."</span>)

        <span class="hljs-comment"># Ensure only the expected columns are included</span>
        self.dataframe = dataframe[self.keys].copy() <span class="hljs-keyword">if</span> set(self.keys).issubset(dataframe.columns) <span class="hljs-keyword">else</span> dataframe.copy()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getDataFrame</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Returns the DataFrame associated with the dataset.

        Returns:
        pandas.DataFrame: The dataset's DataFrame.
        """</span>
        <span class="hljs-keyword">return</span> self.dataframe

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">save_to_csv</span>(<span class="hljs-params">self, file_name</span>):</span>
        <span class="hljs-string">"""
        Saves the dataset's DataFrame to a CSV file.

        Parameters:
        file_name (str): The name of the CSV file to save.
        """</span>
        self.dataframe.to_csv(file_name, mode=<span class="hljs-string">'w'</span>, index=<span class="hljs-literal">False</span>)  <span class="hljs-comment"># Save the DataFrame to CSV</span>
</code></pre>
<p>In the previous section, we outlined the high-level system architecture, detailing the core components and their interactions. Now, let’s dive into the detailed design of some of the individual components, specifying how we’ll implement each one and how it’ll function within the system. We’ll also break down the components to explain how they work together to process the input and generate the report.</p>
<p>Below, you can see the flow diagram for the software, illustrating the interaction between the core components and the flow of data through the system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739209441033/60142953-c1f4-4146-b64e-c042039e1ef6.png?auto=compress,format&amp;format=webp" alt="Figure 3 Software Flow Diagram" width="600" height="400" loading="lazy"></p>
<h4 id="heading-category-label-based-filtering-component"><strong>Category Label-Based Filtering Component</strong></h4>
<p>The Category Label-Based Filtering Component classifies transactions by matching their "Category Label" with predefined expense categories from a JSON file. Transactions with valid category labels are stored in the finance registry, while unmatched ones remain for further processing.</p>
<ul>
<li><p>Input: DataFrame of time-filtered transactions, expense categories from JSON.</p>
</li>
<li><p>Libraries used: Pandas DataFrame.</p>
</li>
<li><p>Software design: Filters transactions based on the "Category Label" column and assigns them to corresponding categories. Transactions that cannot be categorized remain for further processing.</p>
</li>
<li><p>Output: DataFrame of remaining transactions with empty values in the "Category Label" field.</p>
</li>
<li><p>Component tests: Validate handling of valid, invalid, and missing category labels.</p>
</li>
</ul>
<h4 id="heading-finance-registry-component"><strong>Finance Registry Component</strong></h4>
<p>The Finance Registry Component manages categorized transactions by storing them as datasets for each expense category. It maintains a structured collection of DataFrames, each containing transactions and summary statistics such as total count, max amount, and mean amount.</p>
<ul>
<li><p>Input: Expense categories from JSON.</p>
</li>
<li><p>Libraries used: Pandas DataFrame.</p>
</li>
<li><p>Software design: Implements a class that organizes datasets for all expense categories, providing methods to set and retrieve DataFrames.</p>
</li>
<li><p>Component tests: Validate dataset creation, ensuring correct storage and retrieval of categorized transactions.</p>
</li>
</ul>
<p>Here’s a simple and efficient Finance Registry implementation in Python for managing categorized financial datasets:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> Dataset <span class="hljs-keyword">import</span> Dataset
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd  <span class="hljs-comment"># Ensure Pandas is imported if used elsewhere</span>

<span class="hljs-comment"># Define column structure for datasets</span>
KEYS = (<span class="hljs-string">"Date"</span>, <span class="hljs-string">"Description"</span>, <span class="hljs-string">"Amount"</span>, <span class="hljs-string">"Transaction Type"</span>, <span class="hljs-string">"Category"</span>, <span class="hljs-string">"Account Name"</span>, <span class="hljs-string">"Labels"</span>, <span class="hljs-string">"Notes"</span>)

<span class="hljs-comment"># Define dataset names for different financial categories</span>
EXAMPLE_DATASET_NAMES = (<span class="hljs-string">"Investment"</span>, <span class="hljs-string">"Expense"</span>, <span class="hljs-string">"Savings"</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FinanceRegistry</span>:</span>
    <span class="hljs-string">"""
    A class to manage categorized financial datasets, including investment, expense, and savings datasets.
    This registry allows structured access to transaction data and maintains aggregated financial metrics.
    """</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        Initializes the FinanceRegistry object.

        Attributes:
        self.example_dataset (dict): A dictionary storing Dataset objects for financial datasets.
        """</span>
        self.example_dataset = {name: Dataset(name, KEYS) <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> EXAMPLE_DATASET_NAMES}  <span class="hljs-comment"># Create datasets for categories</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setExampleDatasetToRegistry</span>(<span class="hljs-params">self, name, dataframe</span>):</span>
        <span class="hljs-string">"""
        Merges a new dataframe into the existing dataset for a given financial category.

        Parameters:
        name (str): The category name (e.g., "Investment", "Expense", or "Savings").
        dataframe (pd.DataFrame): The new data to be added.

        If the dataset already contains data, it concatenates the new dataframe to the existing one.

        Raises:
        ValueError: If the provided name is not a valid dataset category.
        """</span>
        <span class="hljs-keyword">if</span> name <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.example_dataset:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">f"Invalid dataset name: '<span class="hljs-subst">{name}</span>'. Expected one of <span class="hljs-subst">{EXAMPLE_DATASET_NAMES}</span>"</span>)

        df = self.example_dataset[name].getDataFrame()  <span class="hljs-comment"># Get existing dataset</span>

        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> dataframe.empty:  <span class="hljs-comment"># Ensure the new dataframe is not empty</span>
            dataframe = pd.concat([df, dataframe], axis=<span class="hljs-number">0</span>, ignore_index=<span class="hljs-literal">True</span>)  <span class="hljs-comment"># Append new data</span>

        self.example_dataset[name].setDataFrame(dataframe)  <span class="hljs-comment"># Update dataset in registry</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getExampleDatasetFromRegistry</span>(<span class="hljs-params">self, name</span>):</span>
        <span class="hljs-string">"""
        Retrieves the dataset for a given financial category.

        Parameters:
        name (str): The category name (e.g., "Investment", "Expense", or "Savings").

        Returns:
        Dataset: The dataset corresponding to the given name.

        Raises:
        ValueError: If the provided name is not a valid dataset category.
        """</span>
        <span class="hljs-keyword">if</span> name <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> self.example_dataset:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">f"Invalid dataset name: '<span class="hljs-subst">{name}</span>'. Expected one of <span class="hljs-subst">{EXAMPLE_DATASET_NAMES}</span>"</span>)

        <span class="hljs-keyword">return</span> self.example_dataset[name]
</code></pre>
<p>The diagram below illustrates how the Finance Registry organizes these datasets for further processing in the Report Generation component.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739209411075/7a772e4f-9687-4c96-8995-10a70e27a36d.png?auto=compress,format&amp;format=webp" alt="Figure 4 Finance Registry datasets for expense category" width="600" height="400" loading="lazy"></p>
<h4 id="heading-report-generation-component"><strong>Report Generation Component</strong></h4>
<p>The Report Generation Component processes categorized transaction datasets from the finance registry and generates summary statistics. It calculates key financial metrics such as maximum amount, mean amount, and total transaction count. It also provides functionality to display categorized transactions in a structured format within the shell.</p>
<ul>
<li><p>Input: Datasets of categorized transactions from the finance registry.</p>
</li>
<li><p>Libraries used: Numpy for calculations, Tabulate for formatted shell output (if needed).</p>
</li>
<li><p>Software design: Implements a class with methods to compute financial statistics and display transaction summaries per expense category.</p>
</li>
<li><p>Component tests: Validate correct calculation of mean, max, and total transactions, and ensure accurate display of categorized datasets in the shell.</p>
</li>
</ul>
<p>Here’s a function to compute transaction statistics, including mean, max, and count, from a dataset in the report generation component:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> Dataset <span class="hljs-keyword">import</span> Dataset
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculateStats</span>(<span class="hljs-params">dataset</span>):</span>
    <span class="hljs-string">"""
    Computes statistical metrics for a given dataset.

    Parameters:
    dataset: The dataset containing transaction data.

    Updates:
    - dataset.mean: Mean transaction amount.
    - dataset.max: Maximum transaction amount.
    - dataset.count: Number of transactions.
    """</span>

    <span class="hljs-comment"># Return early if the dataset has no transactions</span>
    <span class="hljs-keyword">if</span> dataset.dataframe.empty:
        <span class="hljs-keyword">return</span>

    <span class="hljs-comment"># Extract transaction amounts as a list</span>
    tx_amount_list = dataset.dataframe[<span class="hljs-string">'Amount'</span>].astype(float).round(<span class="hljs-number">2</span>).tolist()

    <span class="hljs-comment"># Adjust transaction amounts based on "Transaction Type"</span>
    <span class="hljs-keyword">for</span> i, tx_type <span class="hljs-keyword">in</span> enumerate(dataset.dataframe[<span class="hljs-string">'Transaction Type'</span>]):
        <span class="hljs-keyword">if</span> tx_type == <span class="hljs-string">'debit'</span>:
            tx_amount_list[i] *= <span class="hljs-number">-1</span>  <span class="hljs-comment"># Convert debit transactions to negative values</span>

    <span class="hljs-comment"># Compute statistical metrics</span>
    dataset.mean = round(np.mean(tx_amount_list), <span class="hljs-number">2</span>)
    dataset.max = max(tx_amount_list)
    dataset.count = len(tx_amount_list)
</code></pre>
<p>This concludes the design section, where we explored key software design elements with a practical example. The next step, implementation, is beyond the scope of this article. But it's crucial to recognize that new challenges often emerge during development, requiring updates to requirements, architecture, and specifications.</p>
<p>The purpose of this article is not to provide a full implementation, but to teach you some basic software design principles through an example. The focus is on understanding how to structure software, define clear requirements, and create scalable architectures, all before writing code.</p>
<p>By following a structured design process, you can shift complex problem-solving from implementation to the architecture phase, where you can explore solutions more effectively using flowcharts, block diagrams, and documentation. This makes the development process more organized, efficient, and maintainable, a crucial skill for real-world software engineering.</p>
<p>If you're learning to code, remember that good design is just as important as writing code itself!</p>
<h2 id="heading-conclusion-the-value-of-thoughtful-software-design"><strong>Conclusion: The Value of Thoughtful Software Design</strong></h2>
<p>With well-defined problem statements, scope, requirements, specifications, and design, even complex problems can be solved and maintained in a sustainable way.</p>
<p>The steps we went through in this article can help you break down any problem, regardless of its complexity, into smaller, actionable tasks that you and your team can efficiently tackle.</p>
<p>Without proper planning, projects are often plagued by scope creep, wasted time and resources, miscommunication between teams, overly complicated designs, technical debt, and frequent redesigns.<br>Good design is often simple design, but achieving simplicity is difficult without thorough planning.</p>
<p>Approaching each problem with the mindset of defining a Problem Statement, Scope, Use Cases, Requirements, Architecture, and Specifications helps cultivate a strong software design mindset. This mindset is crucial for developing software that is scalable, maintainable, and high quality.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Server-Sent Events vs WebSockets – How to Choose a Real-Time Data Exchange Protocol ]]>
                </title>
                <description>
                    <![CDATA[ In our fast-paced digital era, real-time data exchange has become critical in creating responsive and dynamic user experiences. It’s especially important in applications like live news updates, chat systems, AI generative platforms, and so on. In thi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/server-sent-events-vs-websockets/</link>
                <guid isPermaLink="false">677835cd5280589b2bc82110</guid>
                
                    <category>
                        <![CDATA[ development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ websockets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Devops ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Svitlana Lorman ]]>
                </dc:creator>
                <pubDate>Fri, 03 Jan 2025 19:09:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1734440242816/4ba6ef33-386a-45f7-872b-5974742855e2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In our fast-paced digital era, real-time data exchange has become critical in creating responsive and dynamic user experiences. It’s especially important in applications like live news updates, chat systems, AI generative platforms, and so on.</p>
<p>In this article, you’ll learn about <strong>WebSockets</strong> and <strong>Server-Sent Events (SSE)</strong>, two powerful communication protocols that ensure seamless, real-time interactions in modern web applications.</p>
<p>By examining their differences, advantages, and use cases, you’ll gain a clear understanding of how to choose the right protocol to optimize scalability and performance. This article also includes simple example implementations using <strong>Node.js</strong>, allowing you to see these technologies in action.</p>
<p>To help you solidify your knowledge further, we’ll conclude with practical project recommendations, offering hands-on opportunities to apply what you’ve learned.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-websocket">What is a WebSocket?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-advantages-of-websockets">Advantages and Disadvantages of WebSockets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-cases-for-websockets">Use Cases for WebSockets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-websocket-server-with-nodejs">How to Create a WebSocket Server with Node.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-server-sent-events-sse">What are Server-Sent Events (SSE)?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-advantages-of-server-sent-events">Advantages and Disadvantages of Server-Sent Events</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-cases-for-sse">Use Cases for SSE</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-server-sent-events-using-node-js">How to Implement Server-Sent Events using Node.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-websockets-vs-server-sent-events">WebSockets vs Server-Sent Events</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-which-is-better-server-sent-events-or-websockets">Which is Better: Server-Sent Events or WebSockets?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-websocket"><strong>What is a WebSocket?</strong></h2>
<p>In short, a WebSocket is a communication protocol that enables full-duplex, low-latency, event-driven connections between the server and the browser. In case you’re not familiar, full-duplex refers to the ability to send and receive data simultaneously between a client (like a web browser) and a server over a single connection.</p>
<p>Unlike <a target="_blank" href="https://www.freecodecamp.org/news/what-is-http/">HTTP</a>, which operates in a request-response model, WebSockets enable persistent and continuous data exchange. This means that the data is exchanged in real-time, and pulling it from the server is unnecessary each time.</p>
<p>The WebSockets protocol was formalized in 2011 by the IETF through RFC 6455 and is now supported by all major browsers (Chrome, Edge, Safari, and so on).</p>
<p>Although WebSockets differ from HTTP, both protocols operate on the <a target="_blank" href="https://www.freecodecamp.org/news/osi-model-networking-layers-explained-in-plain-english/">OSI model’</a>s Application Layer (layer 7) and rely on <a target="_blank" href="https://www.freecodecamp.org/news/what-is-tcp-ip-layers-and-protocols-explained/">TCP/IP</a> at the Transport Layer (layer 4). The OSI (Open Systems Interconnection) model is a conceptual framework used to understand network communication. It divides the network into 7 layers, each responsible for a specific function, from physical data transmission to application-level interactions.</p>
<p>Similar to HTTP and HTTPS<em>,</em> WebSockets have a unique set of prefixes:</p>
<ul>
<li><p><strong>ws</strong>: indicates an unencrypted connection without TLS and should not be opened from HTTPS-secured sites.</p>
</li>
<li><p><strong>wss</strong>: indicates an encrypted connection secured by TLS and shouldn’t be opened from HTTP (non-secure) sites.</p>
</li>
</ul>
<h3 id="heading-how-do-websockets-work"><strong>How Do WebSockets Work?</strong></h3>
<p>As I mentioned earlier, WebSockets establish a persistent, bidirectional connection between the client and the server. The process begins with an HTTP handshake initiated by the client, where the client requests a WebSocket connection by sending a specific header to the server. If the server accepts the request, it responds with a status code 101 confirming the upgrade to a WebSocket connection.</p>
<p>Once the connection is established, the WebSocket protocol takes over, and both the client and the server can send and receive data at any time without the need for repeated handshakes. This continuous connection allows real-time communication with minimal latency, as data is exchanged immediately without waiting for additional requests.</p>
<p>The WebSocket connection remains open until either the client or server decides to close it. This ensures efficient and fast data exchange, making it ideal for real-time applications like chat systems, online gaming, or live data feeds.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735898910124/24538662-d00f-4457-a8a4-9da16f618046.png" alt="WebSocket full-duplex client-server connection " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-advantages-of-websockets"><strong>Advantages of WebSockets</strong></h3>
<ul>
<li><p><strong>Full-duplex connection</strong>: both client and server can send and receive data simultaneously.</p>
</li>
<li><p><strong>Low latency:</strong> since WebSockets maintain an open connection, they ensure minimal delay in data transfer by eliminating the overhead of repeatedly establishing and tearing down connections, ensuring minimal delay in data transfer.</p>
</li>
<li><p><strong>Reduced bandwidth usage:</strong> unlike HTTP requests, which include headers for every request, WebSockets only require a single handshake, resulting in smaller data packets and reduced bandwidth consumption.</p>
</li>
<li><p><strong>Cross-Platform Compatibility:</strong> as stated earlier, WebSockets are supported by most modern browsers and programming frameworks, which ensures broad applicability.</p>
</li>
</ul>
<h3 id="heading-disadvantages-of-websockets"><strong>Disadvantages of WebSockets</strong></h3>
<ul>
<li><p><strong>Complexity in implementation</strong>: WebSockets require a dedicated server and a special protocol.</p>
</li>
<li><p><strong>Vulnerability to attacks</strong>: Without proper security (wss prefix) and authentication mechanisms, WebSockets are susceptible to <a target="_blank" href="https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking">cross-site WebSocket hijacking</a> (CSWSH) and <a target="_blank" href="https://www.ibm.com/think/topics/man-in-the-middle">man-in-the-middle (MITM)</a> attacks.</p>
</li>
<li><p><strong>No built-in security</strong>: Unlike HTTP, WebSockets do not inherently support request-response headers for additional security. Thus, it’s necessary to implement token-based authentication or other secure methods manually.</p>
</li>
</ul>
<h2 id="heading-use-cases-for-websockets"><strong>Use Cases for WebSockets</strong></h2>
<p>WebSockets have revolutionized how applications deliver real-time communication. This protocol powers various industries by enabling low-latency, bidirectional data flow. Let’s talk about some good use cases for WebSockets:</p>
<h3 id="heading-1-chat-applications">1. Chat Applications</h3>
<p>WebSockets’ full-duplex connection ensures that messages are delivered instantly and without interruptions, making them the perfect choice for real-time communication. This technology powers platforms like Slack, Discord, and various live customer support chat systems, providing seamless and efficient interactions.</p>
<h3 id="heading-2-online-gaming">2. Online Gaming</h3>
<p>WebSockets are essential for fast-paced online games like Clash Royal, where real-time communication between players and servers is crucial. By maintaining a persistent, two-way connection, WebSockets allow immediate transmission of actions, such as moves or attacks, ensuring that all players experience seamless gameplay without lag. </p>
<h3 id="heading-3-real-time-dashboards">3. Real-Time Dashboards</h3>
<p>Tools like Datadog and e-commerce platforms use WebSockets to ensure system metrics, sales, and inventory data are always current, eliminating manual refreshes and enhancing user experience.</p>
<p>WebSockets also excel at handling big data, streaming, and visualizing large volumes of information with low latency. This makes them the perfect choice for industries such as finance, healthcare, and logistics, where real-time insights are essential for effective decision-making. </p>
<p>An example is DataTableDev, a grid prototype capable of working with massive data volumes, demonstrating WebSockets’ potential in real-time data processing.</p>
<h2 id="heading-how-to-create-a-websocket-server-with-nodejs"><strong>How to Create a WebSocket Server with Node.js</strong></h2>
<p>Before setting up a simple WebSocket server with Node.js to handle secure connections, you’ll need a <a target="_blank" href="https://www.freecodecamp.org/news/what-is-tls-transport-layer-security-encryption-explained-in-plain-english/">TLS certificate</a> to ensure the communication is encrypted. You can acquire one from a trusted Certificate Authority (CA) like <a target="_blank" href="https://letsencrypt.org/">Let's Encrypt</a> or use a self-signed certificate for testing.</p>
<p>Below is the complete implementation of a WebSocket Secure (WSS) server using Node.js:</p>
<p>We’ll start on the server-side. Firstly, let’s import the required modules:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>);  <span class="hljs-comment">// Module for creating an HTTPS server</span>
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);        <span class="hljs-comment">// Module to read files (used to load TLS certificates)</span>
<span class="hljs-keyword">const</span> WebSocket = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ws'</span>); <span class="hljs-comment">// WebSocket library to handle WebSocket connections</span>
</code></pre>
<p>Next, we’ll load TLS certificates for secure communication (wss://).</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> serverOptions = {
  <span class="hljs-attr">cert</span>: fs.readFileSync(<span class="hljs-string">'cert.pem'</span>), <span class="hljs-comment">// Load the TLS certificate for HTTPS encryption</span>
  <span class="hljs-attr">key</span>: fs.readFileSync(<span class="hljs-string">'key.pem'</span>),   <span class="hljs-comment">// Load the private key associated with the certificate</span>
};
</code></pre>
<p><code>serverOptions</code> reads the TLS certificate and private key from files (<code>cert.pem</code> and <code>key.pem</code>) and holds them. These are essential for establishing secure communication using the <code>wss://</code> protocol since they enable <strong>encryption</strong> for data transmitted between the server and the client.</p>
<p>Since the WebSocket server runs on top of the HTTPS server, we first create and initialize the HTTPS server using the <code>serverOptions</code>, and then set up the WebSocket server.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Create the HTTPS server with the loaded certificates and initialize it with TLS options</span>
<span class="hljs-keyword">const</span> httpsServer = https.createServer(serverOptions); 
<span class="hljs-comment">// Create a WebSocket server that runs on top of the HTTPS server</span>
<span class="hljs-keyword">const</span> wss = <span class="hljs-keyword">new</span> WebSocket.Server({ <span class="hljs-attr">server</span>: httpsServer });
</code></pre>
<p>Now it's time to define the behavior when a new WebSocket connection is established. You'll need to handle incoming messages from the WebSocket client, send a response back, and manage the disconnection process. In this tutorial, we'll keep it simple by printing the received data to the console.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Define the behavior when a new WebSocket connection is established</span>
wss.on(<span class="hljs-string">'connection'</span>, <span class="hljs-function">(<span class="hljs-params">ws</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Client connected'</span>);

  <span class="hljs-comment">// Handle incoming messages from the WebSocket client</span>
  ws.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Received: <span class="hljs-subst">${message}</span>`</span>); 
    ws.send(<span class="hljs-string">`Server received: <span class="hljs-subst">${message}</span>`</span>); <span class="hljs-comment">// Send a response back to the client</span>
  });

  <span class="hljs-comment">// Handle when a client disconnects</span>
  ws.on(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Client disconnected'</span>);

  <span class="hljs-comment">// Send an initial message to the client when the connection is established</span>
  ws.send(<span class="hljs-string">'Welcome to the secure WebSocket server!'</span>);
});
</code></pre>
<p>Last but not least, you need to define the port where the HTTPS WebSocket server will listen for incoming connections. In this example, we use a port <code>8080</code>. After that, we start the HTTPS server and make it listen on the specified port. Once the server is up and running a log message will be printed to confirm that the secure WebSocket server is ready.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Define the port where the HTTPS WebSocket server will listen for incoming connections</span>
<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">8080</span>;

<span class="hljs-comment">// Start the HTTPS server and begin listening on the specified port</span>
httpsServer.listen(PORT, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Secure WebSocket server running at wss://localhost:<span class="hljs-subst">${PORT}</span>`</span>); <span class="hljs-comment">// Log a message when the server starts</span>
});
</code></pre>
<p>And that’s it for the server-side part. Your full code should look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Import required modules</span>
<span class="hljs-keyword">const</span> https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>);  <span class="hljs-comment">// Module for creating an HTTPS server</span>
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);        <span class="hljs-comment">// Module to read files (used to load TLS certificates)</span>
<span class="hljs-keyword">const</span> WebSocket = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ws'</span>); <span class="hljs-comment">// WebSocket library to handle WebSocket connections</span>

<span class="hljs-comment">// Load TLS certificates for secure communication (wss://)</span>
<span class="hljs-keyword">const</span> serverOptions = {
  <span class="hljs-attr">cert</span>: fs.readFileSync(<span class="hljs-string">'cert.pem'</span>), <span class="hljs-comment">// Load the TLS certificate for HTTPS encryption</span>
  <span class="hljs-attr">key</span>: fs.readFileSync(<span class="hljs-string">'key.pem'</span>),   <span class="hljs-comment">// Load the private key associated with the certificate</span>
};

<span class="hljs-comment">// Create the HTTPS server with the loaded certificates and initialize it with TLS options</span>
<span class="hljs-keyword">const</span> httpsServer = https.createServer(serverOptions); 
<span class="hljs-comment">// Create a WebSocket server that runs on top of the HTTPS server</span>
<span class="hljs-keyword">const</span> wss = <span class="hljs-keyword">new</span> WebSocket.Server({ <span class="hljs-attr">server</span>: httpsServer }); 

<span class="hljs-comment">// Define the behavior when a new WebSocket connection is established</span>
wss.on(<span class="hljs-string">'connection'</span>, <span class="hljs-function">(<span class="hljs-params">ws</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Client connected'</span>); 

  <span class="hljs-comment">// Handle incoming messages from the WebSocket client</span>
  ws.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Received: <span class="hljs-subst">${message}</span>`</span>); 
    ws.send(<span class="hljs-string">`Server received: <span class="hljs-subst">${message}</span>`</span>); <span class="hljs-comment">// Send a response back to the client</span>
  });

  <span class="hljs-comment">// Handle when a client disconnects</span>
  ws.on(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Client disconnected'</span>); 
  });
  <span class="hljs-comment">// Send an initial message to the client when the connection is established</span>
  ws.send(<span class="hljs-string">'Welcome to the secure WebSocket server!'</span>);
});

<span class="hljs-comment">// Define the port where the HTTPS WebSocket server will listen for incoming connections</span>
<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">8080</span>;

<span class="hljs-comment">// Start the HTTPS server and begin listening on the specified port</span>
httpsServer.listen(PORT, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Secure WebSocket server running at wss://localhost:<span class="hljs-subst">${PORT}</span>`</span>); <span class="hljs-comment">// Log a message when the server starts</span>
});
</code></pre>
<p>To run the created server with Node.js, type the following line into Command Prompt / Terminal:</p>
<p> <code>node wss-server.js</code></p>
<p>Connect to the server using a WebSocket client or browser console at <code>wss://</code><a target="_blank" href="http://localhost:8080"><code>localhost:8080</code></a>.</p>
<p>Once the connection is established, the client can send and receive messages. Now well look at a simple example of how to receive and send messages on the client side.</p>
<p>To start, let’s define a basic HTML structure:</p>
<pre><code class="lang-javascript">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;WebSocket Client&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;WebSocket Client&lt;/h1&gt;
  &lt;div id="messages"&gt;&lt;/div&gt;
  &lt;input type="text" id="messageInput" placeholder="Type a message"&gt;
  &lt;button onclick="sendMessage()"&gt;Send Message&lt;/button&gt;

  &lt;script&gt;
    &lt;!-- JS code goes here --&gt;
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>The <code>&lt;button&gt;</code> element has an <code>onclick</code> event that triggers the <code>sendMessage()</code> function when clicked. Before we dive into the function, let's first establish a WebSocket connection to the server. We'll also define event listeners to handle the following:</p>
<ol>
<li><p>When the WebSocket connection is successfully established.</p>
</li>
<li><p>When a message is received from the server.</p>
</li>
</ol>
<p>These event listeners will ensure that we can interact with the server and handle incoming data in real time.</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// Establish a WebSocket connection to the server</span>
    <span class="hljs-keyword">const</span> socket = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">'wss://localhost:8080'</span>); 

    <span class="hljs-comment">// Event listener for when the WebSocket connection is established</span>
    socket.addEventListener(<span class="hljs-string">'open'</span>, <span class="hljs-function">() =&gt;</span> {
      displayMessage(<span class="hljs-string">'Connected to the WebSocket server'</span>);

    <span class="hljs-comment">// Event listener for when a message is received from the server</span>
    socket.addEventListener(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      displayMessage(<span class="hljs-string">`Server: <span class="hljs-subst">${event.data}</span>`</span>); <span class="hljs-comment">// Display the message received from the server</span>
    });
</code></pre>
<p>To display the message on the user interface, we've created a function called <code>displayMessage</code>. Here's how it's defined:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Function to display messages in the message container</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayMessage</span>(<span class="hljs-params">message</span>) </span>{
      <span class="hljs-keyword">const</span> messageDiv = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'messages'</span>); <span class="hljs-comment">// Get the div where messages will be displayed</span>
      <span class="hljs-keyword">const</span> newMessage = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'p'</span>); <span class="hljs-comment">// Create a new paragraph element for the new message</span>
      newMessage.textContent = message; <span class="hljs-comment">// Set the text content of the paragraph to the message</span>
      messageDiv.appendChild(newMessage); <span class="hljs-comment">// Add the new paragraph to the message container</span>
}
</code></pre>
<p>Now, it’s time to define the <code>sendMessage()</code> function. Firstly, we retrieve a message and then send it to the WebSocket server using the <code>socket.send()</code> method. This transmits the message over the WebSocket connection established earlier, allowing the server to receive it. Next, on the UI, we display the message and clear the input field.</p>
<p>Thus, the code looks the following way:</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// Function to send a message to the server</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> message = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'messageInput'</span>).value; <span class="hljs-comment">// Get the message from the input field</span>
      socket.send(message); <span class="hljs-comment">// Send the message over the WebSocket connection</span>
      displayMessage(<span class="hljs-string">`You: <span class="hljs-subst">${message}</span>`</span>); <span class="hljs-comment">// Display the message in the UI as sent by the user</span>
      <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'messageInput'</span>).value = <span class="hljs-string">''</span>; <span class="hljs-comment">// Clear the input field after sending the message</span>
    }
</code></pre>
<p>The final step is to set the event listener for when the WebSocket connection closes. To keep it simple, we will log a message to the console.</p>
<pre><code class="lang-javascript"> socket.addEventListener(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Disconnected from the WebSocket server'</span>); 
 });
</code></pre>
<p>This is what the client-side part looks like:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>WebSocket Client<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>WebSocket Client<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"messages"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"messageInput"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type a message"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"sendMessage()"</span>&gt;</span>Send Message<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-comment">// Establish a WebSocket connection to the server</span>
    <span class="hljs-keyword">const</span> socket = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">'wss://localhost:8080'</span>); <span class="hljs-comment">// Connect to WebSocket server </span>

    <span class="hljs-comment">// Event listener for when the WebSocket connection is established</span>
    socket.addEventListener(<span class="hljs-string">'open'</span>, <span class="hljs-function">() =&gt;</span> {
      displayMessage(<span class="hljs-string">'Connected to the WebSocket server'</span>);

    <span class="hljs-comment">// Event listener for when a message is received from the server</span>
    socket.addEventListener(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      displayMessage(<span class="hljs-string">`Server: <span class="hljs-subst">${event.data}</span>`</span>); <span class="hljs-comment">// Display the message received from the server</span>
    });

    <span class="hljs-comment">// Function to send a message to the server</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> message = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'messageInput'</span>).value; <span class="hljs-comment">// Get the message from the input field</span>
      socket.send(message); <span class="hljs-comment">// Send the message over the WebSocket connection</span>
      displayMessage(<span class="hljs-string">`You: <span class="hljs-subst">${message}</span>`</span>); <span class="hljs-comment">// Display the message in the UI as sent by the user</span>
      <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'messageInput'</span>).value = <span class="hljs-string">''</span>; <span class="hljs-comment">// Clear the input field after sending the message</span>
    }

    <span class="hljs-comment">// Function to display messages in the message container</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayMessage</span>(<span class="hljs-params">message</span>) </span>{
      <span class="hljs-keyword">const</span> messageDiv = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'messages'</span>); <span class="hljs-comment">// Get the div where messages will be displayed</span>
      <span class="hljs-keyword">const</span> newMessage = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'p'</span>); <span class="hljs-comment">// Create a new paragraph element for the new message</span>
      newMessage.textContent = message; <span class="hljs-comment">// Set the text content of the paragraph to the message</span>
      messageDiv.appendChild(newMessage); <span class="hljs-comment">// Add the new paragraph to the message container</span>
    }

    <span class="hljs-comment">// Event listener for when the WebSocket connection is closed</span>
    socket.addEventListener(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Disconnected from the WebSocket server'</span>); 
    });
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-what-are-server-sent-events-sse"><strong>What are Server-Sent Events (SSE)?</strong></h2>
<p>Server-Sent Events (SSE) is a technology that enables a web server to push updates to a web page. As part of the HTML5 specification, it functions similarly to WebSockets by using a single, long-lived HTTP connection to deliver data in real-time.</p>
<p>The concept of SSE originated in 2004, with the <a target="_blank" href="https://blogs.opera.com/news/">Opera team</a> taking the first steps towards implementation in 2006. One of the main limitations of SSE in the early stages was the connection cap imposed by HTTP/1.1, which restricted the number of simultaneous connections a client could establish with a server. But with the introduction of HTTP/2, this limitation was removed. HTTP/2 allows multiple data streams to flow over a single connection through multiplexing, enabling more efficient and scalable communication for SSE.</p>
<p>Server-sent events (SSE) rely on two fundamental components:</p>
<ul>
<li><strong>EventSource</strong>: An interface defined by the WHATWG specification and implemented by modern browsers. It enables the client (typically a browser) to subscribe to server-sent events.  </li>
</ul>
<ul>
<li><strong>EventStream</strong>: A protocol that specifies the plain-text format servers must use to send events, ensuring compatibility with the EventSource client for seamless communication.  </li>
</ul>
<p>As the specification outlines, events can include arbitrary text data and an optional ID and are separated by newlines. Also, SSE events have a dedicated <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types">MIME type</a>: <code>text/event-stream.</code> A MIME type (Multipurpose Internet Mail Extensions type) is a standard that indicates the nature and format of a file or data, allowing the browser or server to properly interpret and handle it.</p>
<h3 id="heading-how-do-server-sent-events-work"><strong>How do Server-Sent Events Work?</strong></h3>
<p>Server-sent events (SSE) work by establishing a persistent, one-way communication channel from the server to the client over a standard HTTP connection. The client initiates the connection by creating an <code>EventSource</code> object, which sends a request to the server to start streaming data. Once the server receives this request, it responds by sending a continuous stream of updates in a specific <code>text/event-stream</code> format. The client listens for these events, automatically handling any reconnections if the connection is lost.</p>
<p>SSE is ideal for applications that require real-time updates from the server, such as live news feeds or notifications, as it ensures a constant flow of information with minimal overhead.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735897258671/eec0599a-f5b5-43f2-8552-7f84ac265c3e.png" alt="This picture outlines how SSE works" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-advantages-of-server-sent-events"><strong>Advantages of Server-Sent Events</strong></h3>
<ul>
<li><p><strong>Polyfill capability</strong>: Server-sent events (SSE) can be implemented using JavaScript in browsers that don’t natively support them. This ensures backward compatibility by leveraging the standard SSE interface instead of creating a custom alternative.  </p>
</li>
<li><p><strong>Automatic reconnection</strong>: SSE connections are designed to reconnect automatically after interruption. Thus, they reduce the need for extra code to handle this essential functionality.  </p>
</li>
<li><p><strong>Firewall-friendly</strong>: SSEs work seamlessly with corporate firewalls that perform packet inspection, making them a reliable choice for enterprise applications.</p>
</li>
</ul>
<h3 id="heading-disadvantages-of-server-sent-events"><strong>Disadvantages of Server-Sent Events</strong></h3>
<ul>
<li><p><strong>Data format restrictions</strong>: SSE is restricted to transmitting messages in UTF-8 format, as it does not support binary data.  </p>
</li>
<li><p><strong>Connection limits</strong>: Browsers cap the number of simultaneous SSE connections to six per client. This limitation becomes problematic when multiple tabs require active SSE connections. For more details and potential workarounds, refer to this StackOverflow thread: <a target="_blank" href="https://stackoverflow.com/questions/18584525/server-sent-events-and-browser-limits">Server-Sent Events and browser limits</a>.</p>
</li>
<li><p><strong>One-way communication</strong>: SSE supports only server-to-client messaging, making it ideal for read-only real-time applications like stock tickers. However, this unidirectional nature can be a constraint for more interactive real-time applications.</p>
</li>
</ul>
<h2 id="heading-use-cases-for-sse"><strong>Use Cases for SSE</strong></h2>
<p>Server-sent events are widely used in applications where real-time data delivery is crucial. SSE enables the server to push updates to the client automatically, making it ideal for applications that require live information streams. From news feeds to financial dashboards, SSE ensures that users receive the latest content without constant page refreshes.</p>
<p>Here are some common use cases for using SSE:</p>
<h3 id="heading-1-social-media-feeds">1. Social Media Feeds</h3>
<p>Social media platforms leverage SSE to push new posts instantly, likes, and comments to users’ feeds, providing a more dynamic and engaging user experience. A great example is Twitter’s (X’s) real-time feed implementation, which allows them to push real-time updates to the browser.</p>
<h3 id="heading-2-enterprise-monitoring-system">2. Enterprise Monitoring System</h3>
<p>SSE enables financial monitoring systems and other real-time applications to deliver live data updates efficiently. For instance, Netflix’s open-source Hystrix, a well-known component for microservice monitoring and circuit breaking, includes a web dashboard that displays real-time performance metrics and circuit status. This dashboard uses SSE to push performance data in real-time, ensuring that users can monitor the health and performance of microservices as they happen. The dashboard leveraging SSE provides an efficient, low-latency solution for updating performance data without needing constant manual refreshing or polling.</p>
<h3 id="heading-3-generative-ai">3. Generative AI</h3>
<p>SSE technology plays a key role behind the scenes when interacting with Generative AI chatbots like ChatGPT and Gemini. For instance, when a user requests ChatGPT to write an article on a specific topic, the server starts processing the request and generates the article progressively, often in chunks rather than all at once.</p>
<p>During this process, ChatGPT’s server utilizes SSE to push each part of the article to the client in real-time, allowing the user to see the content appear as it is being generated. </p>
<h2 id="heading-how-to-implement-server-sent-events-using-nodejs"><strong>How to Implement Server-Sent Events using Node.js</strong></h2>
<p>In this section, we’ll explore how to implement SSE using Node.js, a popular JavaScript runtime, to push updates to the client in real-time. We’ll set up a basic server and send live data to the browser using SSE.</p>
<p>We’ll start with the client-side (HTML/JavaScript). First, we’ll create a new <code>EventSource</code> object to listen for events from the server.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> evtSource = <span class="hljs-keyword">new</span> EventSource(<span class="hljs-string">"sse-demo.js"</span>);
</code></pre>
<p>The URL <code>"sse-demo.js"</code> is the path to the server-side script that will generate the events. But if the event generator script were hosted on a different origin, we would need to provide an additional configuration for cross-origin requests.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// If the event generator script is hosted on a different origin (cross-origin request):</span>
<span class="hljs-keyword">const</span> evtSource = <span class="hljs-keyword">new</span> EventSource(<span class="hljs-string">"//api.example.com/sse-demo.js"</span>, {
  <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span>,  <span class="hljs-comment">// Sends cookies, authorization headers with the request to the server</span>
});
</code></pre>
<p>This version ensures that cookies and authorization headers are sent with the request, enabling secure communication and making sure that credentials can be included in cross-origin requests. <code>withCredentials: true</code> ensures that authentication is handled correctly if needed.</p>
<p>Next, let’s set up an event listener to handle the message when it is received. To keep things simple, we will display the message on the user interface by adding it as a new list item.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// When a message event is received</span>
evtSource.onmessage = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-comment">// Create a new list item element to display the message</span>
  <span class="hljs-keyword">const</span> newElement = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"li"</span>);

  <span class="hljs-comment">// Get the reference to the unordered list element where messages will be displayed</span>
  <span class="hljs-keyword">const</span> eventList = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"list"</span>);

  <span class="hljs-comment">// Set the text content of the new list item to the message received</span>
  newElement.textContent = <span class="hljs-string">`message: <span class="hljs-subst">${event.data}</span>`</span>;

  <span class="hljs-comment">// Append the new list item to the event list (ul) in the HTML</span>
  eventList.appendChild(newElement);
};
</code></pre>
<p>Let's also add an event listener for a custom "ping" event. Again, we will simply add new data to the list and display it on the page. Thus, when the custom event is received, a new list item (<code>&lt;li&gt;</code>) is created.</p>
<p>The event data, which contains a <code>time</code> property, is parsed from JSON, and the time is displayed in the list item. This new list item is then appended to an unordered list (<code>&lt;ul&gt;</code>) in the HTML, allowing the "ping" event data to be shown on the user interface.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Add an event listener for a custom event type, "ping"</span>
evtSource.addEventListener(<span class="hljs-string">"ping"</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-comment">// Create a new list item element to display the ping event</span>
  <span class="hljs-keyword">const</span> newElement = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"li"</span>);

  <span class="hljs-comment">// Get the reference to the unordered list element where ping events will be displayed</span>
  <span class="hljs-keyword">const</span> eventList = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"list"</span>);

  <span class="hljs-comment">// Parse the event data as JSON (assuming it contains a time property)</span>
  <span class="hljs-keyword">const</span> time = <span class="hljs-built_in">JSON</span>.parse(event.data).time;

  <span class="hljs-comment">// Set the text content of the new list item to display the ping time</span>
  newElement.textContent = <span class="hljs-string">`ping at <span class="hljs-subst">${time}</span>`</span>;

  <span class="hljs-comment">// Append the new list item to the event list (ul) in the HTML</span>
  eventList.appendChild(newElement);
});
</code></pre>
<p>Make sure that your code for the client-side part looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Create a new EventSource to listen for events from the server</span>
<span class="hljs-keyword">const</span> evtSource = <span class="hljs-keyword">new</span> EventSource(<span class="hljs-string">"sse-demo.js"</span>);

<span class="hljs-comment">/* If the event generator script is hosted on a different origin (cross-origin request):
const evtSource = new EventSource("//api.example.com/sse-demo.js", {
  withCredentials: true,  // Sends cookies, authorization headers with the request to the server
});
*/</span>
<span class="hljs-comment">// When a message event is received</span>
evtSource.onmessage = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-comment">// Create a new list item element to display the message</span>
  <span class="hljs-keyword">const</span> newElement = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"li"</span>);

  <span class="hljs-comment">// Get the reference to the unordered list element where messages will be displayed</span>
  <span class="hljs-keyword">const</span> eventList = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"list"</span>);

  <span class="hljs-comment">// Set the text content of the new list item to the message received</span>
  newElement.textContent = <span class="hljs-string">`message: <span class="hljs-subst">${event.data}</span>`</span>;

  <span class="hljs-comment">// Append the new list item to the event list (ul) in the HTML</span>
  eventList.appendChild(newElement);
};

<span class="hljs-comment">// Add an event listener for a custom event type, "ping"</span>
evtSource.addEventListener(<span class="hljs-string">"ping"</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-comment">// Create a new list item element to display the ping event</span>
  <span class="hljs-keyword">const</span> newElement = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"li"</span>);

  <span class="hljs-comment">// Get the reference to the unordered list element where ping events will be displayed</span>
  <span class="hljs-keyword">const</span> eventList = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"list"</span>);

  <span class="hljs-comment">// Parse the event data as JSON (assuming it contains a time property)</span>
  <span class="hljs-keyword">const</span> time = <span class="hljs-built_in">JSON</span>.parse(event.data).time;

  <span class="hljs-comment">// Set the text content of the new list item to display the ping time</span>
  newElement.textContent = <span class="hljs-string">`ping at <span class="hljs-subst">${time}</span>`</span>;

  <span class="hljs-comment">// Append the new list item to the event list (ul) in the HTML</span>
  eventList.appendChild(newElement);
});
</code></pre>
<p>Now, let’s code the server-side part with Node.js and Express.js. Express is a minimal and flexible web application framework for Node.js. It simplifies the creation of server-side applications by providing robust features like routing, middleware support, and handling HTTP requests and responses. It helps streamline the development of web APIs and websites, making it perfect for our tutorial.</p>
<p>Note that you’ll need to go to the <a target="_blank" href="https://expressjs.com">official Express.js documentation</a> and install it on your machine if you don’t have it installed already.</p>
<p>Then, head over to the IDE and import the Express module, which allows us to create an instance of the Express application.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Import the Express module</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-comment">// Create an instance of the Express application</span>
<span class="hljs-keyword">const</span> app = express();
</code></pre>
<p>It is considered good practice to specify the port number at the top of the file to make it easy to configure and modify later. This approach improves code readability and maintainability, allowing you to quickly change the port number without searching through the entire file. It also enables better flexibility when deploying the application in different environments (for example, development, staging, production).</p>
<p>For this tutorial, we have set the port number to <code>3000</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Define the port number for the server to listen on</span>
<span class="hljs-keyword">const</span> port = <span class="hljs-number">3000</span>;
</code></pre>
<p>Now, let's set up the server-side part with Node.js and Express to handle SSE requests. We define a route (<code>/sse</code>) that will send a continuous stream of events to the client.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Define a route that handles requests to /sse endpoint</span>
app.get(<span class="hljs-string">'/sse'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
<span class="hljs-comment">//....</span>
});
</code></pre>
<p>For the server to communicate with the client using SSE, we need to set specific HTTP headers:</p>
<ul>
<li><p><strong>Content-Type</strong>: We specify <code>'text/event-stream'</code> to let the client know that the response is an SSE stream.</p>
</li>
<li><p><strong>Cache-Control</strong>: Setting it to <code>'no-cache'</code> ensures the client gets fresh data each time, without caching.</p>
</li>
<li><p><strong>Connection</strong>: This is set to <code>'keep-alive'</code> to maintain the connection open for continuous data transmission.</p>
</li>
</ul>
<pre><code class="lang-javascript">app.get(<span class="hljs-string">'/sse'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-comment">// Set the Content-Type header to 'text/event-stream' to indicate that </span>
  <span class="hljs-comment">// the response will be an SSE stream</span>
  res.setHeader(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'text/event-stream'</span>);

  <span class="hljs-comment">// Prevent caching of the stream (important to ensure real-time updates)</span>
  res.setHeader(<span class="hljs-string">'Cache-Control'</span>, <span class="hljs-string">'no-cache'</span>);

  <span class="hljs-comment">// Keep the connection alive to continuously send events</span>
  res.setHeader(<span class="hljs-string">'Connection'</span>, <span class="hljs-string">'keep-alive'</span>);
});
</code></pre>
<p>You can use <code>res.flushHeaders()</code> to send the headers immediately. Thus, the client can begin listening for events without delay.</p>
<p>To add a bit of flair, let's send a new SSE message every second, including the number of the message being sent. For this, we will initialize a variable <code>counter</code> , as well as to use <code>setInterval</code> to send a new message every second (1000ms).</p>
<pre><code class="lang-javascript">app.get(<span class="hljs-string">'/sse'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-comment">// Set the Content-Type header to 'text/event-stream' to indicate that </span>
  <span class="hljs-comment">// the response will be an SSE stream</span>
  res.setHeader(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'text/event-stream'</span>);

  <span class="hljs-comment">// Prevent caching of the stream (important to ensure real-time updates)</span>
  res.setHeader(<span class="hljs-string">'Cache-Control'</span>, <span class="hljs-string">'no-cache'</span>);

  <span class="hljs-comment">// Keep the connection alive to continuously send events</span>
  res.setHeader(<span class="hljs-string">'Connection'</span>, <span class="hljs-string">'keep-alive'</span>);

  <span class="hljs-comment">// Send the headers immediately, so the client starts listening for events</span>
  res.flushHeaders();

  <span class="hljs-comment">// Initialize a counter variable for the messages</span>
  <span class="hljs-keyword">let</span> counter = <span class="hljs-number">0</span>;

  <span class="hljs-comment">// Use setInterval to send a new message every second (1000ms)</span>
  <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Send a new SSE message, incrementing the counter each time</span>
    <span class="hljs-comment">// Each message is prefixed with 'data: ' and followed by the message content</span>
    res.write(<span class="hljs-string">`data: This is message <span class="hljs-subst">${counter++}</span>\n\n`</span>);
  }, <span class="hljs-number">1000</span>); <span class="hljs-comment">// This interval runs every 1000 milliseconds (1 second)</span>
});
</code></pre>
<p>The last step is to start the Express server the following way:</p>
<pre><code class="lang-javascript">app.listen(port, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running at http://localhost:<span class="hljs-subst">${port}</span>`</span>);
});
</code></pre>
<p>And that’s it! Make sure your server-sent code looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Import the Express module</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-comment">// Create an instance of the Express application</span>
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Define the port number for the server to listen on</span>
<span class="hljs-keyword">const</span> port = <span class="hljs-number">3000</span>;

<span class="hljs-comment">// Define a route that handles requests to /sse endpoint</span>
app.get(<span class="hljs-string">'/sse'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-comment">// Set the Content-Type header to 'text/event-stream' to indicate that </span>
  <span class="hljs-comment">// the response will be an SSE stream</span>
  res.setHeader(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'text/event-stream'</span>);

  <span class="hljs-comment">// Prevent caching of the stream (important to ensure real-time updates)</span>
  res.setHeader(<span class="hljs-string">'Cache-Control'</span>, <span class="hljs-string">'no-cache'</span>);

  <span class="hljs-comment">// Keep the connection alive to continuously send events</span>
  res.setHeader(<span class="hljs-string">'Connection'</span>, <span class="hljs-string">'keep-alive'</span>);

  <span class="hljs-comment">// Send the headers immediately, so the client starts listening for events</span>
  res.flushHeaders();

  <span class="hljs-comment">// Initialize a counter variable for the messages</span>
  <span class="hljs-keyword">let</span> counter = <span class="hljs-number">0</span>;

  <span class="hljs-comment">// Use setInterval to send a new message every second (1000ms)</span>
  <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Send a new SSE message, incrementing the counter each time</span>
    <span class="hljs-comment">// Each message is prefixed with 'data: ' and followed by the message content</span>
    res.write(<span class="hljs-string">`data: This is message <span class="hljs-subst">${counter++}</span>\n\n`</span>);
  }, <span class="hljs-number">1000</span>); <span class="hljs-comment">// This interval runs every 1000 milliseconds (1 second)</span>
});

<span class="hljs-comment">// Start the Express server and listen on the specified port</span>
app.listen(port, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running at http://localhost:<span class="hljs-subst">${port}</span>`</span>);
});
</code></pre>
<h2 id="heading-websockets-vs-server-sent-events"><strong>WebSockets vs Server-Sent Events</strong></h2>
<p>The goal of data transfer methods is to load and display large datasets as quickly as possible. This ensures that the user perceives the response as instant and provides smooth navigation and a pleasant user experience.</p>
<p><a target="_blank" href="https://www.nngroup.com/articles/author/jakob-nielsen/">Jakob Nielsen</a>, a retired principal and co-founder of the Nielsen Norman Group, outlined three key time limits that developers should consider when optimizing web and application performance in his book <a target="_blank" href="https://www.nngroup.com/books/usability-engineering/">Usability Engineering</a>. In short, 0.1 seconds is the threshold for users to feel that the system is responding instantaneously, meaning that no special feedback is required other than simply displaying the result.</p>
<p><a target="_blank" href="https://www.linkedin.com/in/vera-didenko/">Vera Didenko</a>, Software Architect and Developer at Flexmonster conducted research to identify the most efficient data transfer protocol and, based on the 100-millisecond constraint, calculated the time budget for each process, ultimately choosing WebSockets as the optimal method for loading and updating the data.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe5vtbDVh_QdPm4ajDMJ3Gc2l6sF-TZs4YhzZEXLbj0fbsm1iW71lNu7X7TGuu6uUnXZSUPsPWZPjviWFcYnSZFALba9qoGgbHICv6z635gn2Ie9pvYjsv3-n0M7aZCe6Hy7kXNpC5I4P6k0YBqBcg?key=p_cDJW9Yx9AjWig3CS4ijdeZ" alt="  Extended tolerable response time from Jakob Nielsen’s “Usability Engineering”." width="600" height="400" loading="lazy"></p>
<p>For research purposes, Vera created an application using .NET Core and <a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/introduction-to-signalr">SignalR</a> to test and visually compare the performance of WebSockets and Server-Sent Events to discover which data transfer approach is the most performance-efficient. SignalR is an open-source library that simplifies real-time web functionality.</p>
<p>After running several tests for all methods simultaneously while increasing the number of calls each time, the test results were gathered in JSON format and fed to the <a target="_blank" href="https://www.amcharts.com/">amCharts library</a>. Below are the test results for 100, 1000, and 10000 calls:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735051327581/c940c14c-636b-4cfc-b55f-5e1fd4f11370.png" alt="The performance of WebSockets and Server-Sent Events" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The experiment results show that WebSockets perform best for this task, emerging as the most performance-efficient data transfer technology in the simulated scenarios.</p>
<h3 id="heading-which-is-better-server-sent-events-or-websockets"><strong>Which is Better: Server-Sent Events or WebSockets?</strong></h3>
<p>SSE is a simpler solution, but it isn't extensible: if your web application <a target="_blank" href="https://www.amcharts.com/">r</a>equirements were to change, it would likely need to be refactored using WebSockets. Also, with AI integration SSE becomes even more powerful and secure.</p>
<p>Although WebSocket technology presents more upfront work, it's a more versatile and extensible framework, so it’s a better option for complex applications that are likely to add new features over time.</p>
<table><tbody><tr><td><p>Feature</p></td><td><p>WebSockets</p></td><td><p>Server-Sent Events&nbsp;</p></td></tr><tr><td><p>Communication</p></td><td><p>Full-duplex (two-way)</p></td><td><p>One-way (server-to-client)</p></td></tr><tr><td><p>Data Type Support</p></td><td><p>Binary and text</p></td><td><p>Text (UTF-8 encoded only)</p></td></tr><tr><td><p>Connection Limits</p></td><td><p>Limited by server resources</p></td><td><p>Limited by browser (e.g. 6 tabs)</p></td></tr><tr><td><p>Reconnection</p></td><td><p>Requires manual handling</p></td><td><p>Automatic</p></td></tr><tr><td><p>Protocol</p></td><td><p>Custom, low-level protocol</p></td><td><p>Built on HTTP</p></td></tr><tr><td><p>Firewall Handling</p></td><td><p>May face problems</p></td><td><p>Work seamlessly</p></td></tr><tr><td><p>Use Case Examples</p></td><td><p>real-time, event-driven communication between clients and servers, such as online games, chats, etc</p></td><td><p>streaming data uni-directionally (i.e., “one direction”) from server to client for streaming data like stock quotes, bitcoin prices, etc</p></td></tr></tbody></table>

<p>In practice, many developers prefer WebSockets even for scenarios requiring receiving information rather than opting for SSE. This preference is not solely due to the limitations of SSE—such as its reliance on keeping a connection open for continuous data flow—but also because WebSockets offer greater versatility and are often considered more future-proof.</p>
<p>For instance, popular platforms like Reddit and Trello choose WebSockets to receive data (Reddit and Trello only send information to users when they are offered to subscribe to another person).</p>
<p>From personal experience, I can point out that SSE data often doesn’t appear in the developer tools, making it harder to debug and inspect. You can verify this by checking a web application like ChatGPT, where no SSE data sent by the server is visible in the developer tools network tab. This lack of transparency can make working with SSE more challenging than the more straightforward, visible data flow provided by WebSockets.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>I hope this article was both interesting and useful to you! If you want to further strengthen your knowledge and take your skills to the next level, I highly recommend diving into real-life projects.</p>
<p>Personally, I found these on freeCodeCamp to be really useful and even a bit challenging: <a target="_blank" href="https://www.freecodecamp.org/news/build-a-logging-web-app-with-server-sent-events-rxjs-and-express/">How to Build a Logging Web App with Server-Sent Events, RxJS, and Express and Learn WebSockets with Socket.IO</a>. Not only will these projects give you hands-on experience, but they will also provide you with valuable new insights and skills that you can apply to future development challenges.</p>
<p>Happy coding, and keep learning!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Understanding Modern Development Frameworks: A Guide for Developers and Technical Decision-makers ]]>
                </title>
                <description>
                    <![CDATA[ As a developer for over 20 years, I've seen firsthand how choosing the right framework can make or break a project. The term "framework" has become so broad that it's often misunderstood. Let's clear up the confusion and help you make better technica... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/understanding-modern-development-frameworks-guide-for-devs/</link>
                <guid isPermaLink="false">673cc307f6df251b434f7f90</guid>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jesse Hall ]]>
                </dc:creator>
                <pubDate>Tue, 19 Nov 2024 16:55:35 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731968979425/412c6bc7-e717-481b-aa9e-4962c9687115.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a developer for over 20 years, I've seen firsthand how choosing the right framework can make or break a project. The term "framework" has become so broad that it's often misunderstood. Let's clear up the confusion and help you make better technical decisions.</p>
<h2 id="heading-what-is-a-framework">What is a Framework?</h2>
<p>In terms of software development, a framework is a structured set of tools, libraries, and conventions that provides a foundation for building applications more efficiently by handling common functionalities so developers can focus on unique features.</p>
<p>A modern web application can combine multiple frameworks to handle different aspects of development efficiently:</p>
<ul>
<li><p>React with Tailwind CSS manages the user interface and styling.</p>
</li>
<li><p>FastAPI or Django with LangChain handle backend operations and AI functionality, while MongoDB acts as a memory store.</p>
</li>
</ul>
<p>These frameworks communicate through APIs and defined interfaces to work together—for example, a user interaction in the React front end can trigger an AI process through LangChain in the Python back end, which uses MongoDB Atlas Vector Search to retrieve relevant data and then display it back to the user with Tailwind CSS styles.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-framework-landscape-in-2024">The framework landscape in 2024</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-application-frameworks">Application frameworks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ai-frameworks">AI frameworks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-web-frameworks">Web frameworks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-cssui-frameworks">CSS/UI frameworks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-amp-infrastructure">Testing &amp; infrastructure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-making-the-right-choice">Making the right choice</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-bottom-line">The bottom line</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-resources">Additional resources</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frequently-asked-questions-faq">Frequently asked questions (FAQ)</a></p>
</li>
</ul>
<h2 id="heading-the-framework-landscape-in-2024">The Framework Landscape in 2024</h2>
<p>Think of frameworks as tools in a technical toolbox. Understanding what each tool is designed to do—and what it isn't—ensures you use the right solution for the task at hand.</p>
<h3 id="heading-the-evolution-of-development-frameworks">The Evolution of Development Frameworks</h3>
<p>The framework landscape has transformed dramatically over the past decade. What started as simple libraries for rendering web pages has evolved into sophisticated ecosystems that can:</p>
<ul>
<li><p>Handle complex state management.</p>
</li>
<li><p>Process real-time data streams.</p>
</li>
<li><p>Integrate AI capabilities.</p>
</li>
<li><p>Scale automatically based on demand.</p>
</li>
<li><p>Deploy across multiple platforms from a single codebase.</p>
</li>
</ul>
<h3 id="heading-why-framework-choice-matters">Why Framework Choice Matters</h3>
<p>Frameworks are puzzle pieces: each has a unique shape and function. When chosen wisely, they fit together seamlessly to create a cohesive application. But forcing incompatible pieces together can lead to inefficiencies and broken functionality.</p>
<p>Here's why your choice matters:</p>
<h4 id="heading-technical-impact">Technical impact</h4>
<ul>
<li><p><strong>Performance</strong>: Different frameworks have different performance characteristics. Instagram chose React for its virtual DOM, which handles frequent updates efficiently.</p>
</li>
<li><p><strong>Scalability</strong>: Uber's back end uses Node.js because it excels at handling numerous concurrent connections.</p>
</li>
<li><p><strong>Maintenance</strong>: Shopify standardized on React Native to maintain a single codebase for mobile applications.</p>
</li>
</ul>
<h4 id="heading-business-impact">Business impact</h4>
<ul>
<li><p><strong>Development speed</strong>: The right framework can accelerate development by 2-3x.</p>
</li>
<li><p><strong>Team productivity</strong>: Familiar frameworks reduce onboarding time from months to weeks.</p>
</li>
<li><p><strong>Cost efficiency</strong>: Proper framework selection can significantly reduce hosting and maintenance costs.</p>
</li>
</ul>
<h4 id="heading-common-pitfalls">Common pitfalls</h4>
<ul>
<li><p><strong>Over-engineering</strong>: Using Next.js when a simple HTML page would suffice</p>
</li>
<li><p><strong>Under-engineering</strong>: Using vanilla JavaScript for a complex, state-heavy application</p>
</li>
<li><p><strong>Misaligned tools</strong>: Using Electron (a desktop app framework) to build a simple website</p>
</li>
<li><p><strong>Trend-chasing</strong>: Adopting the newest framework without considering maintenance implications</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731967899960/8c8b60fb-4370-4bb1-91fd-5b8b18db22e9.png" alt="A diagram of frameworks and their categorizations" width="600" height="400" loading="lazy"></p>
<p>Let’s dive deeper into the various categories of development frameworks and how they can help you build better applications.</p>
<p><strong>Note</strong>: I give framework examples throughout this article, but these are not exhaustive lists and new frameworks are created <code>daily|weekly|monthly</code>.</p>
<h2 id="heading-application-frameworks">Application Frameworks</h2>
<p>These are your Swiss Army knives of development—comprehensive toolkits that handle the entire application lifecycle. While each framework has its specialties, they typically provide:</p>
<ul>
<li><p>Database integration and ORM support.</p>
</li>
<li><p>Authentication and authorization.</p>
</li>
<li><p>API routing and middleware.</p>
</li>
<li><p>Template engines or component systems.</p>
</li>
<li><p>Asset management.</p>
</li>
<li><p>Security features.</p>
</li>
<li><p>Development tools and debugging support.</p>
</li>
</ul>
<p><strong>What is an application?</strong> An application is the combination of individual components working together, including a user interface and backend services, to perform specific functions or a set of functions for users. It’s designed to be fully deployable and operate in production environments.</p>
<p>You'll encounter them in three main flavors:</p>
<h3 id="heading-full-stack-web-application-frameworks">Full-Stack Web Application Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://www.djangoproject.com/"><strong>Django</strong></a> <strong>and</strong> <a target="_blank" href="https://rubyonrails.org/"><strong>Rails</strong></a>: Perfect for data-heavy applications with complex business logic. They follow the "batteries included" philosophy, providing everything you need out of the box.</p>
</li>
<li><p><a target="_blank" href="https://nextjs.org/"><strong>Next.js</strong></a> <strong>and</strong> <a target="_blank" href="https://nuxtjs.org/"><strong>Nuxt.js</strong></a>: Modern full-stack frameworks optimized for React and Vue.js, respectively. They excel at building performant applications with capabilities like server-side rendering, static site generation, and API integration.</p>
</li>
<li><p><a target="_blank" href="https://spring.io/projects/spring-boot"><strong>Spring Boot</strong></a>: Enterprise-grade framework favored for large-scale Java applications, particularly in financial and banking sectors.</p>
</li>
</ul>
<h3 id="heading-mobile-application-frameworks">Mobile Application Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://flutter.dev/"><strong>Flutter</strong></a>: Google's toolkit for building natively compiled apps for mobile, web, and desktop from a single codebase. Known for smooth animations and native performance.</p>
</li>
<li><p><a target="_blank" href="https://reactnative.dev/"><strong>React Native</strong></a>: Ideal when you want to leverage your team's React knowledge for mobile development. Great for apps that need to feel native while maintaining code sharing between platforms.</p>
</li>
<li><p><a target="_blank" href="https://developer.apple.com/xcode/swiftui/"><strong>SwiftUI</strong></a> <strong>and</strong> <a target="_blank" href="https://developer.android.com/jetpack/compose"><strong>Jetpack Compose</strong></a>: Native frameworks for iOS and Android, respectively. Ideal when platform-specific features and optimal performance are crucial.</p>
</li>
</ul>
<h3 id="heading-desktop-application-frameworks">Desktop Application Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://www.electronjs.org/"><strong>Electron</strong></a>: Powers apps like VS Code and Slack. Ideal for leveraging existing web development knowledge without having to learn OS-specific languages to build cross-platform desktop applications.</p>
</li>
<li><p><a target="_blank" href="https://tauri.app/"><strong>Tauri</strong></a>: A modern alternative to Electron with smaller bundle sizes and better performance. Uses native system webviews to run apps more efficiently, with less memory and faster startup times. Developers can use their existing web development skills without learning new programming languages for each OS.</p>
</li>
<li><p><a target="_blank" href="https://wiki.python.org/moin/PyQt"><strong>PyQt</strong></a>: A good option for building GUI applications in Python, especially for data science projects. It has a rich set of libraries and widgets, suitable for both small tools and complex apps.</p>
</li>
</ul>
<h3 id="heading-gaming-frameworks">Gaming Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://unity.com/"><strong>Unity</strong></a>: A popular framework used for creating 2D and 3D games. It supports multiple platforms, making it a versatile choice for game developers. Unity is known for its user-friendly interface and extensive asset store.</p>
</li>
<li><p><a target="_blank" href="https://www.unrealengine.com/"><strong>Unreal Engine</strong></a>: Known for its high-quality graphics, Unreal Engine is a powerful framework used for both AAA games and indie projects. It provides advanced visual tools and real-time rendering capabilities.</p>
</li>
<li><p><a target="_blank" href="https://godotengine.org/"><strong>Godot</strong></a>: An open-source game engine that's lightweight and flexible. Godot is often used for smaller or indie game projects and features an intuitive scene system that makes development straightforward.</p>
</li>
</ul>
<h2 id="heading-ai-frameworks">AI Frameworks</h2>
<p>Here's a crucial point many miss: AI frameworks like TensorFlow or LangChain are powerful, but they're not standalone solutions. These frameworks require integration with other tools and frameworks for data handling, user interface, and deployment to create a complete, production-ready application. These are just another piece of the puzzle.</p>
<p><strong>The exception?</strong> Data scientists can use these tools directly in Jupyter notebooks for research and prototyping. But for production applications, you'll need more.</p>
<p>Let's look at the major players and their sweet spots:</p>
<h3 id="heading-ai-model-development-frameworks">AI Model Development Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://www.tensorflow.org/"><strong>TensorFlow</strong></a>: Google's powerhouse for deep learning, TensorFlow is perfect for applications involving computer vision, neural networks, and production-grade ML. Pinterest uses it for image recognition and recommendations, highlighting its strength in processing large amounts of image data efficiently.</p>
</li>
<li><p><a target="_blank" href="https://pytorch.org/"><strong>PyTorch</strong></a>: Developed by Facebook, PyTorch is a flexible framework ideal for research, natural language processing, and quick prototyping. Tesla has utilized PyTorch for various machine learning tasks, including research related to autonomous driving vision systems, demonstrating its versatility in cutting-edge applications.</p>
</li>
<li><p><a target="_blank" href="https://github.com/google/jax"><strong>JAX</strong></a>: A high-performance numerical computing framework by Google, JAX is well-suited for scientific computing and large-scale transformers. DeepMind has used JAX for advanced AI research, including projects like AlphaFold for protein structure prediction, showcasing its effectiveness in large-scale computational problems.</p>
</li>
</ul>
<h3 id="heading-ai-model-deployment-and-serving-frameworks">AI Model Deployment and Serving Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://github.com/tensorflow/serving"><strong>TensorFlow Serving</strong></a>: A deployment tool for TensorFlow models, perfect for serving high-performance ML models in production environments. For example, it has been used to serve image classification models for e-commerce platforms, ensuring rapid and scalable response times.</p>
</li>
<li><p><a target="_blank" href="https://pytorch.org/serve/"><strong>TorchServe</strong></a>: A robust tool for deploying PyTorch models, perfect for scalable PyTorch model serving. It has been used for deploying chatbot models for real-time customer support, providing flexibility and efficiency in managing conversational AI.</p>
</li>
<li><p><a target="_blank" href="https://developer.nvidia.com/triton-inference-server"><strong>NVIDIA Triton Inference Server</strong></a>: A multi-framework model serving tool, NVIDIA Triton Inference Server is capable of handling models from TensorFlow, PyTorch, ONNX, and more. It is ideal for managing inference requests for multi-modal AI applications, making it highly suitable for complex AI deployments.</p>
</li>
</ul>
<h3 id="heading-llm-integration-frameworks">LLM Integration Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://langchain.io/"><strong>LangChain</strong></a>: The Swiss Army knife for LLM applications. Ideal for building chatbots and document Q&amp;A systems. It has been employed to create customer service bots capable of accessing company knowledge bases, demonstrating its usefulness in enhancing customer interactions.</p>
</li>
<li><p><a target="_blank" href="https://www.llamaindex.ai/"><strong>LlamaIndex</strong></a>: Specializing in data connection, LlamaIndex is perfect for building search engines over private data. It has been used to create semantic search systems for internal documents, facilitating more effective data retrieval and organizational knowledge management.</p>
</li>
<li><p><a target="_blank" href="https://huggingface.co/docs/transformers/en/index"><strong>Hugging Face Transformers</strong></a>: A pre-trained model hub, Hugging Face Transformers allows for the quick deployment of state-of-the-art models. It has been used to add sentiment analysis to customer feedback systems, highlighting its capability in natural language understanding.</p>
</li>
</ul>
<h3 id="heading-ai-data-processing-frameworks">AI Data Processing Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://spark.apache.org/mllib/"><strong>Apache Spark (MLlib)</strong></a>: Ideal for large-scale data transformation and ML, used for processing millions of user interactions in recommendation systems. Its scalability and efficiency make it a popular choice for big data ML tasks.</p>
</li>
<li><p><a target="_blank" href="https://pandas.pydata.org/"><strong>Pandas</strong></a>: A widely-used data manipulation and analysis tool that is perfect for data cleaning, analysis, and feature engineering. It is often employed in preparing customer data for churn prediction models, owing to its intuitive data handling capabilities.</p>
</li>
<li><p><a target="_blank" href="https://www.pola.rs/"><strong>Polars</strong></a>: A high-performance data manipulation framework, used when Pandas is not fast enough for processing requirements. It has been applied in real-time financial data analysis, delivering faster data processing and efficiency.</p>
</li>
</ul>
<h3 id="heading-ai-automation-and-orchestration-frameworks">AI Automation and Orchestration Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://crewai.com/"><strong>CrewAI</strong></a>: Used to orchestrate multiple AI agents, making it perfect for complex workflows requiring multiple AI models. It has been used to create a content creation pipeline that plans, writes, and edits, showcasing its ability to automate creative processes.</p>
</li>
<li><p><a target="_blank" href="https://github.com/Torantulino/Auto-GPT"><strong>Auto-GPT</strong></a>: Develops autonomous AI agents, ideal for self-directed task completion. It has been utilized for automated research and data gathering, highlighting its potential for automating repetitive knowledge tasks.</p>
</li>
<li><p><a target="_blank" href="https://github.com/microsoft/semantic-kernel"><strong>Microsoft Semantic Kernel</strong></a>: An AI orchestration tool perfect for integrating AI into .NET applications. It has been used to add AI capabilities to existing enterprise applications, providing a seamless integration of AI functions into established workflows.</p>
</li>
</ul>
<h3 id="heading-ai-data-ingestion-and-document-processing-frameworks">AI Data Ingestion and Document Processing Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://nifi.apache.org/"><strong>Apache NiFi</strong></a>: A powerful tool for data flow automation, well-suited for real-time data ingestion and processing. It has been used to extract and transform log data before analysis, ensuring efficient data flow for various use cases.</p>
</li>
<li><p><a target="_blank" href="https://haystack.deepset.ai/"><strong>Haystack</strong></a>: Specialized in document processing for search and QA systems. It has been utilized to create pipelines for indexing documents and answering questions, making it ideal for building internal knowledge base searches.</p>
</li>
<li><p><a target="_blank" href="https://unstructured.io/"><strong>Unstructured</strong></a>: Designed for extracting data from a variety of formats, including PDFs, HTML, and images. It’s perfect for handling unstructured content in document processing workflows and has been used to extract relevant information from scanned documents for data analysis.</p>
</li>
<li><p><a target="_blank" href="https://airbyte.com/"><strong>Airbyte</strong></a>: An open-source data integration tool that is ideal for connecting and syncing data across multiple sources. It has been used to ingest data from third-party APIs into analytics systems, enabling effective data consolidation.</p>
</li>
</ul>
<h3 id="heading-interactive-ai-web-frameworks">Interactive AI Web Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://gradio.app/"><strong>Gradio</strong></a>: Simplifies the process of building web UIs for machine learning models, making it perfect for creating quick demos for ML models. It has been used to create interactive image classifiers for end users, providing an accessible interface for testing ML capabilities.</p>
</li>
<li><p><a target="_blank" href="https://streamlit.io/"><strong>Streamlit</strong></a>: A Python-based web app framework for ML and data science, ideal for turning data scripts into shareable web apps. It has been used to build user-friendly dashboards for exploring model predictions, enhancing the accessibility of ML models.</p>
</li>
</ul>
<h3 id="heading-mlops-and-ai-monitoring-frameworks">MLOps and AI Monitoring Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://mlflow.org/"><strong>MLflow</strong></a>: Used for experiment tracking and model lifecycle management, perfect for keeping track of experiments and model versions. It has been applied to manage multiple iterations of predictive models, supporting organized development workflows.</p>
</li>
<li><p><a target="_blank" href="https://www.kubeflow.org/"><strong>Kubeflow</strong></a>: A Kubernetes-native platform for MLOps, ideal for deploying, scaling, and managing machine learning models on Kubernetes. It has been used to run end-to-end ML workflows in production environments, ensuring scalability and consistency.</p>
</li>
<li><p><a target="_blank" href="https://prometheus.io/"><strong>Prometheus</strong></a> &amp; <a target="_blank" href="https://grafana.com/"><strong>Grafana</strong></a>: Monitoring and alerting tools for ML infrastructure, perfect for tracking model inference performance and system metrics. They have been used to monitor latency and resource usage of deployed ML services, ensuring optimal operational performance.</p>
</li>
</ul>
<h2 id="heading-web-frameworks">Web frameworks</h2>
<p>Web development has evolved into two distinct camps—think of them as the front-of-house and kitchen staff in a restaurant. Both essential, both specialized, but with very different responsibilities.</p>
<p><strong>Note</strong>: We already discussed full-stack web application frameworks above, which marry these two together.</p>
<h3 id="heading-frontend-frameworks">Frontend Frameworks</h3>
<p>Frontend frameworks handle what users see and interact with, managing everything from data display to user interactions, user input, and how the overall user experience is structured. These frameworks ensure that the interface is visually appealing, intuitive, and responsive to user actions.</p>
<p>They play a critical role in how smoothly data is presented, processed, and updated in real time, providing dynamic elements like animations, form validation, and client-side routing to enhance usability.</p>
<p>By using frontend frameworks, developers can create highly interactive and cohesive user experiences that feel natural and engaging.</p>
<ul>
<li><p><a target="_blank" href="https://reactjs.org/"><strong>React</strong></a>: Ideal for large-scale applications with complex state management. It features a virtual DOM for optimal performance, making it suitable for highly interactive user interfaces.</p>
</li>
<li><p><a target="_blank" href="https://vuejs.org/"><strong>Vue.js</strong></a>: Perfect for both small projects and enterprise applications. It has a gentle learning curve combined with powerful scalability, making it an approachable yet robust frontend solution.</p>
</li>
<li><p><a target="_blank" href="https://svelte.dev/"><strong>Svelte</strong></a>: Ideal for when you have performance-critical applications and want smaller bundles. It compiles away framework code for lighter applications, providing better performance and a smaller footprint.</p>
</li>
</ul>
<h3 id="heading-backend-frameworks">Backend Frameworks</h3>
<p>Backend frameworks manage server-side logic, data processing, and system integration, handling everything from receiving and processing client requests to interacting with databases and external APIs. These frameworks ensure that the server processes are efficient, scalable, and secure, supporting high concurrency and maintaining consistent data flows.</p>
<p>They provide the essential tools for developers to build, maintain, and optimize the server-side of applications, including tasks such as handling authentication, managing business logic, and ensuring data consistency.</p>
<p>A well-chosen backend framework allows developers to focus more on creating features rather than dealing with low-level server management.</p>
<ul>
<li><p><a target="_blank" href="https://expressjs.com/"><strong>Express.js</strong></a>: Perfect for APIs and microservices, offering minimal structure with maximum flexibility. It is highly popular in Node.js environments for building efficient server-side logic.</p>
</li>
<li><p><a target="_blank" href="https://fastapi.tiangolo.com/"><strong>FastAPI</strong></a>: Designed for high-performance APIs, with automatic API documentation and type checking. It is commonly used for fast and secure backend implementations in Python.</p>
</li>
<li><p><a target="_blank" href="https://nestjs.com/"><strong>NestJS</strong></a>: For large-scale Node.js applications, featuring an Angular-inspired architecture that enhances scalability. It provides a well-structured framework for enterprise-level backends.</p>
</li>
</ul>
<h2 id="heading-cssui-frameworks">CSS/UI Frameworks</h2>
<p>Modern CSS frameworks have evolved beyond simple styling to become complete design systems. Gone are the days when CSS frameworks just provided basic grid systems and button styles.</p>
<p>Today's frameworks are sophisticated tools that enable consistent design at scale. They offer features such as responsive layouts, dark mode support, accessibility enhancements, and interactive components.</p>
<p>They've become essential for maintaining design consistency across large applications and teams, while significantly reducing development time and technical debt. Some frameworks even include built-in performance optimization, design tokens for brand customization, and tools for managing design systems across multiple platforms.</p>
<p>They fall into two main categories:</p>
<h3 id="heading-utility-first-frameworks">Utility-first Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://tailwindcss.com/"><strong>Tailwind CSS</strong></a>: Custom designs with consistent systems. It features rapid prototyping capabilities, highly customizable design tokens, and small production bundles through PurgeCSS.</p>
</li>
<li><p><a target="_blank" href="https://unocss.dev/"><strong>UnoCSS</strong></a>: A customizable, efficient, utility-first CSS solution. It provides on-demand CSS for optimal performance and minimal bundle size, making it a modern tool for design system management.</p>
</li>
</ul>
<h3 id="heading-component-based-frameworks">Component-based Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://getbootstrap.com/"><strong>Bootstrap</strong></a>: Rapid prototyping and traditional web applications. It offers an extensive library of pre-built components, a responsive grid system, and a rich ecosystem of themes and plugins.</p>
</li>
<li><p><a target="_blank" href="https://mui.com/"><strong>Material UI</strong></a>: For applications following Material Design guidelines. It includes a comprehensive component library, a theming system, and accessibility compliance features.</p>
</li>
</ul>
<h2 id="heading-testing-and-infrastructure">Testing and Infrastructure</h2>
<p>These frameworks form the backbone of reliable, scalable applications. While they might not get as much attention as flashy frontend frameworks or AI tools, they're the critical infrastructure that keeps modern applications running smoothly at scale.</p>
<p>Testing frameworks ensure code quality and prevent regressions, while containerization and orchestration frameworks handle the increasingly complex world of cloud deployment and scaling.</p>
<p>In an era where a single code change can affect millions of users instantly, or where an application might need to scale from hundreds to millions of requests in minutes, these frameworks aren't just nice-to-have—they're essential for survival. Major tech companies like Netflix, Amazon, and Google rely on these tools to maintain their rapid development pace while ensuring reliability and performance at massive scale.</p>
<h3 id="heading-testing-frameworks">Testing Frameworks</h3>
<ul>
<li><p><a target="_blank" href="https://jestjs.io/"><strong>Jest</strong></a>: Features snapshot testing, code coverage, and mocking capabilities, making it a popular choice for ensuring the quality of JavaScript codebases.</p>
</li>
<li><p><a target="_blank" href="https://www.cypress.io/"><strong>Cypress</strong></a>: Provides real browser testing and time-travel debugging, ideal for end-to-end testing of web applications.</p>
</li>
<li><p><a target="_blank" href="https://docs.pytest.org/en/stable/"><strong>PyTest</strong></a>: Known for its simple syntax, powerful extensions, and easy fixture management, making it a go-to framework for testing Python applications.</p>
</li>
</ul>
<h3 id="heading-containerization-and-orchestration">Containerization and Orchestration</h3>
<ul>
<li><p><a target="_blank" href="https://www.docker.com/"><strong>Docker</strong></a>: Used for application containerization, providing consistent development and deployment environments with isolated dependencies and efficient resource usage.</p>
</li>
<li><p><a target="_blank" href="https://kubernetes.io/"><strong>Kubernetes</strong></a>: Orchestration of large-scale distributed applications. It provides automated scaling, self-healing deployments, and rolling updates, ensuring that containerized applications can grow as needed.</p>
</li>
</ul>
<h2 id="heading-making-the-right-choice">Making the Right Choice</h2>
<p>Selecting the right framework can determine the success of your entire project. Consider these critical points to guide your decision-making process:</p>
<h3 id="heading-1-application-type-and-scale">1. Application Type and Scale</h3>
<ul>
<li><p>Small site? Consider React or Vue.js.</p>
</li>
<li><p>Large application? Next.js or Django might be better.</p>
</li>
<li><p>Need SEO? Look for SSR capabilities.</p>
</li>
</ul>
<h3 id="heading-2-team-capabilities">2. Team Capabilities</h3>
<ul>
<li><p>Strong JavaScript? Consider Node.js ecosystem.</p>
</li>
<li><p>Python experts? Django or FastAPI might be better.</p>
</li>
<li><p>Need quick ramp-up? Combine key frameworks like Vue.js and Bootstrap.</p>
</li>
</ul>
<h3 id="heading-3-technical-requirements">3. Technical Requirements</h3>
<ul>
<li><p>High-performance computing? Consider Rust frameworks.</p>
</li>
<li><p>Real-time updates? Look at WebSocket support.</p>
</li>
<li><p>AI requirements? Integration with platforms like Hugging Face and frameworks like LangChain might be essential.</p>
</li>
</ul>
<h3 id="heading-4-scaling-strategy">4. Scaling Strategy</h3>
<ul>
<li><p>Vertical scaling? Simpler frameworks might suffice.</p>
</li>
<li><p>Horizontal scaling? You need frameworks with microservices support.</p>
</li>
<li><p>Global distribution? Consider edge computing capabilities.</p>
</li>
</ul>
<h3 id="heading-5-long-term-maintenance">5. Long-term Maintenance</h3>
<ul>
<li><p>Community size and activity</p>
</li>
<li><p>Available talent pool</p>
</li>
<li><p>Corporate backing and stability</p>
</li>
<li><p>Documentation quality</p>
</li>
<li><p>Upgrade path complexity</p>
</li>
</ul>
<h2 id="heading-the-bottom-line">The Bottom Line</h2>
<p>Framework selection isn't just a technical decision—it's a strategic one that affects your project's success, team productivity, and maintenance costs. So take the time to understand your options.</p>
<p>Now you should have all of the puzzle pieces, but it's up to you to put them together thoughtfully to create the perfect technology stack that meets both your current and future needs.</p>
<h2 id="heading-additional-resources">Additional Resources</h2>
<p>If you'd like to learn how <a target="_blank" href="https://mdb.link/register-frameworks">MongoDB</a> integrates seamlessly with many of the frameworks mentioned in this guide, check out the resources below. You'll find that it offers a flexible and scalable database solution that adapts to different use cases.</p>
<ul>
<li><p><a target="_blank" href="https://mdb.link/frameworks-nextjs">How to Integrate MongoDB Into Your Next.js App</a></p>
</li>
<li><p><a target="_blank" href="https://mdb.link/frameworks-farm">Introducing FARM Stack - FastAPI, React, and MongoDB</a></p>
</li>
<li><p><a target="_blank" href="https://mdb.link/frameworks-mern">How to Use MERN Stack: A Complete Guide</a></p>
</li>
<li><p><a target="_blank" href="https://mdb.link/frameworks-langchainjs">Build a JavaScript AI Agent With LangGraph.js and MongoDB</a></p>
</li>
<li><p><a target="_blank" href="https://mdb.link/frameworks-langchain">RAG with Atlas Vector Search, LangChain, and OpenAI</a></p>
</li>
</ul>
<h2 id="heading-frequently-asked-questions-faq"><strong>Frequently Asked Questions (FAQ)</strong></h2>
<h3 id="heading-what-is-a-development-framework">What is a development framework?</h3>
<p>A development framework is a set of tools, libraries, and conventions that provide a foundation for building applications efficiently. Frameworks handle common tasks so developers can focus on building unique features.</p>
<h3 id="heading-how-do-ai-and-development-frameworks-work-together">How do AI and development frameworks work together?</h3>
<p>AI frameworks can be combined with traditional development frameworks to create intelligent, data-driven applications. For instance, a backend framework like FastAPI can handle incoming requests, while an AI framework like LangChain processes natural language data, providing users with enhanced functionality like chatbots or recommendation systems.</p>
<h3 id="heading-why-is-choosing-the-right-framework-important">Why is choosing the right framework important?</h3>
<p>Choosing the right framework can impact your project's performance, scalability, and maintenance. It ensures that your application meets user expectations, is easy to manage, and can grow as needed.</p>
<h3 id="heading-how-do-i-decide-which-framework-to-use-for-my-project">How do I decide which framework to use for my project?</h3>
<p>Consider factors like application type, team expertise, performance needs, scalability, and long-term maintenance. Each of these can guide you in selecting a framework that matches your specific requirements.</p>
<h3 id="heading-can-i-use-multiple-frameworks-in-one-project">Can I use multiple frameworks in one project?</h3>
<p>Yes, combining multiple frameworks can be very effective. You might use one framework for the front end, another for backend services, and a third for AI integrations, ensuring that each part of your application is handled by the best-suited tool.</p>
<h3 id="heading-how-does-mongodb-fit-into-development-frameworks">How does MongoDB fit into development frameworks?</h3>
<p>MongoDB integrates with many frameworks, acting as the data layer for your applications. It provides a flexible, scalable solution that supports full-stack, backend, and AI frameworks to store and retrieve data efficiently.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Cloud Computing? A Guide for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ When I was a kid, I loved looking at clouds and imagining funny shapes. Sometimes, I even wondered if someone was up there! Now that I’m an adult, I still ask, “What’s in the cloud?” When we talk about "the cloud" in technology, we’re not referring t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/cloud-computing-guide-for-beginners/</link>
                <guid isPermaLink="false">6732b0dbe6dfc6edf3fe9c72</guid>
                
                    <category>
                        <![CDATA[ Cloud Computing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Tue, 12 Nov 2024 01:35:23 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730228320580/871eed36-be9c-4ca8-a92d-b0329ad91ffe.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When I was a kid, I loved looking at clouds and imagining funny shapes. Sometimes, I even wondered if someone was up there! Now that I’m an adult, I still ask, “What’s in the cloud?”</p>
<p>When we talk about "the cloud" in technology, we’re not referring to those fluffy clouds in the sky. Instead, the cloud represents a network of remote servers connected by wires and cables.</p>
<p>In the past, businesses used large servers in their offices to store data, which took up a lot of space. While that still works, imagine having powerful software, lots of storage, and computing resources, without needing a room full of machines. That sounds great! Having an organized space can make you feel calm and focused, and that’s what cloud computing offers.</p>
<p>Today, we can store our pictures, videos, emails, and data in the cloud instead of using boxes and drives like we used to. Major cloud providers like AWS, Microsoft Azure, and Google Cloud allow us to store and access our data from anywhere.</p>
<p>In this article, I’ll explain cloud computing, how it works, and why it’s important for businesses and everyday people.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-cloud-computing-and-how-does-it-work">What is Cloud Computing and How Does It Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-who-are-the-leading-cloud-providers">Who Are the Leading Cloud Providers?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-types-and-models-of-cloud-services">Types and Models of Cloud Services</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-uses-of-cloud-services">Real-World Uses of Cloud Services</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-do-developers-use-the-cloud">How Do Developers Use the Cloud?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-is-cloud-computing-important">Why is Cloud Computing Important?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-do-you-need-to-know-to-use-the-cloud">What Do You Need to Know to Use the Cloud?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-cloud-computing-and-how-does-it-work">What is Cloud Computing and How Does It Work?</h2>
<p>Cloud computing is a process where technology services like storage, databases, computing power, and software are delivered over the Internet. In simple terms, it means using the internet to access storage, apps, or tools on powerful computers that aren’t in your organization. Instead of needing large storage or high-powered equipment yourself, you can connect online to store files, watch movies, or work on projects.</p>
<p>In cloud computing, the three basic functions are:</p>
<ol>
<li><p><strong>Storage:</strong> This lets you save and keep your data online, like using Google Drive or Dropbox for your files.</p>
</li>
<li><p><strong>Computing:</strong> This provides the power to process tasks, similar to how a computer's CPU works. It helps run applications smoothly.</p>
</li>
<li><p><strong>Database:</strong> This stores organized data. For example, services like Amazon RDS or Google Cloud SQL manage information for apps.</p>
</li>
</ol>
<h2 id="heading-who-are-the-leading-cloud-providers">Who Are the Leading Cloud Providers?</h2>
<p>Cloud providers offer the infrastructure and services needed to deploy and scale applications.</p>
<p>Big companies like Amazon Web Service (AWS), Google (Google Cloud), and Microsoft (Azure) are leading providers in the cloud industry.</p>
<p>Below is a summary of each provider:</p>
<ul>
<li><p><strong>Amazon Web Services (AWS):</strong> AWS is a leading cloud provider, offering a wide range of services including cloud storage (S3), databases (RDS), and machine learning tools. It’s known for its scalability, flexibility, and reliability, making it a popular choice for developers and businesses.</p>
</li>
<li><p><strong>Microsoft (Azure):</strong> Microsoft has been around for 45 years, and over time, they've adapted their software like Microsoft Office and Windows, seamlessly integrating these services with the cloud. They provide services like Azure Blob Storage and Azure SQL Database. As a result, Microsoft is considered one of the top cloud providers.</p>
</li>
<li><p><strong>Google (Google Cloud):</strong> Google Cloud offers powerful services like Google BigQuery for data analytics and Google Anthos for managing hybrid applications. Google Cloud is known for its speed and reliability, and provides tools for storage, computing, and database management, making it a solid choice for businesses.</p>
</li>
</ul>
<p>All these cloud providers rent out powerful computers to individuals and businesses, allowing you to store files, use apps, or run a business without needing your own servers and equipment.</p>
<h2 id="heading-types-and-models-of-cloud-services">Types and Models of Cloud Services</h2>
<p>Due to the powerful features of cloud services, some companies prefer to control certain parts themselves. This brings us to three types of service control in cloud computing:</p>
<ol>
<li><p><strong>Infrastructure as a Service (IaaS):</strong><br> Think of IaaS as renting a computer online. You can practice coding or run a website without buying any hardware. For example, you can rent a powerful server from AWS. With IaaS, you have full control over everything. You can choose the operating system and install the software you need.</p>
</li>
<li><p><strong>Platform as a Service (PaaS):</strong><br> PaaS is like having a complete workshop online. It gives you the tools to build and launch projects, like a mobile app. You can create your applications, but the provider handles the servers and storage. This way, you can focus on building your app without worrying about the technical details.</p>
</li>
<li><p><strong>Software as a Service (SaaS):</strong><br> SaaS lets you use software directly on the internet. For example, you can write documents using Google Docs, or practice coding with Replit. With SaaS, you have limited control. You can change some settings, but the provider handles everything else, like maintenance and updates.</p>
</li>
</ol>
<p>These options help businesses decide how much control they want over cloud services.</p>
<h2 id="heading-real-world-uses-of-cloud-services">Real-World Uses of Cloud Services</h2>
<p>Here are some examples of using cloud services in real life:</p>
<ul>
<li><p>When you watch Netflix, you’re using the cloud. Netflix keeps movies on its cloud servers and streams them to you online, so there’s no need to download anything.</p>
</li>
<li><p>Services like Google Drive and Dropbox let you store files in the cloud instead of on your computer. This way, you can access your files from any device with internet access.</p>
</li>
<li><p>With Google Docs, you can create and edit documents in the cloud. You don’t need to install anything on your computer. You can even collaborate with others in real-time.</p>
</li>
</ul>
<h2 id="heading-how-do-developers-use-the-cloud">How Do Developers Use the Cloud?</h2>
<p>Cloud services play a key role in development:</p>
<ul>
<li><p>Cloud services like Amazon Web Service (AWS) and Google Cloud provide development tools, virtual environments, and analytics services which developers can use to test their application.</p>
</li>
<li><p>Getting applications online is made easy with services like <a target="_blank" href="https://aws.amazon.com/amplify/?gclid=Cj0KCQiArby5BhCDARIsAIJvjIQhZ0XF6IF-Pb0N8FNn76tRMfP2CfP_X_fC9xyUgegvLSmLQUhPfFsaApkrEALw_wcB&amp;trk=e37f908f-322e-4ebc-9def-9eafa78141b8&amp;sc_channel=ps&amp;ef_id=Cj0KCQiArby5BhCDARIsAIJvjIQhZ0XF6IF-Pb0N8FNn76tRMfP2CfP_X_fC9xyUgegvLSmLQUhPfFsaApkrEALw_wcB:G:s&amp;s_kwcid=AL!4422!3!647301987538!e!!g!!aws%20amplify!19613610159!148358959849"><strong>AWS Amplify</strong></a>, which allow developers to host their apps without writing the backend code.</p>
</li>
<li><p>Cloud storage allows developers to easily add extra storage as needed while keeping data safe and accessible from any location.</p>
</li>
<li><p>Services like Google TensorFlow and AWS SageMaker offer resources for quickly developing AI and machine learning projects.</p>
</li>
</ul>
<h2 id="heading-why-is-cloud-computing-important">Why is Cloud Computing Important?</h2>
<p>Cloud computing offers several key benefits:</p>
<ul>
<li><p>For businesses that want to save money, cloud computing helps cut out expensive hardware and maintenance. You only pay for what you use, like creating virtual servers or storing files.</p>
</li>
<li><p>Storing data or files in the cloud can help you easily increase or decrease your resources based on your needs. This flexibility lets businesses adapt quickly to changes—for example, an increase in Black Friday sales or Boxing Day.</p>
</li>
<li><p>In the event of a disaster, such as a fire, storing files in the cloud serves as a reliable backup, ensuring that important information is not lost. This is especially beneficial for hospitals and government agencies.</p>
</li>
<li><p>Using cloud service enhances collaboration among workers and ease of getting a file since it is remote.</p>
</li>
<li><p>Most cloud providers offer fast services, which leads to quicker load times.</p>
</li>
<li><p>Cloud services are secure.</p>
</li>
</ul>
<h2 id="heading-what-do-you-need-to-know-to-use-the-cloud">What Do You Need to Know to Use the Cloud?</h2>
<ul>
<li><p>To start using the cloud, you should learn basics like virtual machines, storing data, networking, and security.</p>
</li>
<li><p>Understand how to back up your data and recover it in case of any issues.</p>
</li>
<li><p>Learn how pricing works in the cloud so you can monitor and manage your costs effectively.</p>
</li>
<li><p>Most cloud platforms offer tutorials, tools, and ready-made services to make them easier to understand and speed up development.</p>
</li>
</ul>
<p>It can be overwhelming at first, but just start with the basic services, and everything else will fall into place.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, cloud computing is changing the way businesses work and how we store and manage data. It offers flexibility, minimizes cost, and leads to easy collaboration, while improving backup and recovery.</p>
<p>As cloud technology continues to grow, it will become even more important for both individuals and businesses. Whether you're storing personal files or managing a big company, the cloud makes it simpler, safer, and more affordable.</p>
<p>If you found this article helpful, share it with others who may find it interesting.</p>
<p>Stay updated with my projects by following me on <a target="_blank" href="https://https//twitter.com/ijaydimples">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/ijeoma-igboagu/">LinkedIn</a> and <a target="_blank" href="https://github.com/ijayhub">GitHub</a>.</p>
<p>Thank you for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Fine-Grained Authorization in Java and SpringBoot ]]>
                </title>
                <description>
                    <![CDATA[ Securing your application goes beyond simply granting or denying access at the surface level. As a developer, you need to implement fine-grained authorization (FGA) to manage permissions at a more detailed, granular level. FGA allows you to set up de... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/fine-grained-authorization-in-java-and-springboot/</link>
                <guid isPermaLink="false">671a85db0db570158155ec00</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ankur Tyagi ]]>
                </dc:creator>
                <pubDate>Thu, 24 Oct 2024 17:37:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729783227124/9725e8cf-553d-42c3-a823-5215e8d4d0e9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Securing your application goes beyond simply granting or denying access at the surface level. As a developer, you need to implement <code>fine-grained authorization</code> (FGA) to manage permissions at a more detailed, granular level.</p>
<p>FGA allows you to set up detailed access controls that specify who can do what and under which conditions.</p>
<p>In this tutorial, you will learn how to implement <code>fine-grained authorization</code> in Java and Spring Boot using <a target="_blank" href="https://permit.io/">Permit.io</a>.</p>
<p>Here is the <a target="_blank" href="https://github.com/tyaga001/java-spring-fine-grained-auth">source code</a> (remember to give it a star ⭐).</p>
<p>I hope you enjoyed my previous <a target="_blank" href="https://www.freecodecamp.org/news/how-i-built-a-custom-video-conferencing-app-with-stream-and-nextjs/">blog</a> about building a custom video conferencing app with Stream and Next.js. These blogs reflect my journey in creating DevTools Academy, a platform designed to help developers discover amazing developer tools.</p>
<p>This tutorial is another effort to introduce you to a super helpful developer tool that I recently explored.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents:</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-permit">What is Permit</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-fine-grained-authorization">What is Fine-Grained Authorization</a>?</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-role-based-access-control-rbac">Role-Based Access Control (RBAC)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-attribute-based-access-control-abac">Attribute-Based Access Control (ABAC)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-relationship-based-access-control-rebac">Relationship-Based Access Control (ReBAC)</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-fine-grained-authorization">How to Implement Fine-Grained Authorization</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-implementing-role-based-access-control">Implementing Role-Based Access Control</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-implementing-attribute-based-access-control">Implementing Attribute-Based Access Control</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-implementing-relationship-based-access-control">Implementing Relationship-Based Access Control</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-fga-in-java-and-springboot">How to Implement FGA in Java and SpringBoot</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-setting-up-the-e-commerce-application">Step 1: Setting Up the E-commerce Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-get-your-environment-api-key">Step 2: Get your Environment API Key</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-deploy-policy-decision-point-pdp">Step 3: Deploy Policy Decision Point (PDP)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-running-the-app">Step 4: Running the App</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-next-steps">Next Steps</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></li>
</ul>
</li>
</ul>
<h2 id="heading-what-is-permit"><strong>What is</strong> Permit?</h2>
<blockquote>
<p><a target="_blank" href="https://www.permit.io">Permit.io</a> is a full stack, plug-and-play application-level authorization solution that allows you to implement a <code>secure</code>, <code>flexible</code>, <code>authorization</code> layer within minutes, so you can focus on what matters most.</p>
</blockquote>
<p><a target="_blank" href="https://www.permit.io"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729499767197/6e2b4312-8986-493e-9453-3b67e6aad155.png" alt="what is permit - screenshot of homepage" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To fully understand the tutorial, you need to have a basic understanding of <code>Java</code> and <code>Spring Boot</code>. You’ll also need the following:</p>
<ul>
<li><p><a target="_blank" href="http://Permit.io"><strong>Permit.io</strong></a>: A developer tool that simplifies the implementation of FGA.</p>
</li>
<li><p><strong>Spring Boot Starter Web</strong>: Provides essential components for building web applications, including RESTful APIs.</p>
</li>
<li><p><strong>Gradle</strong>: A build tool for managing dependencies.</p>
</li>
<li><p><strong>JDK 11 or later</strong>: The Java Development Kit version required to compile and run your Spring Boot app.</p>
</li>
<li><p><strong>Postman or cURL</strong>: Tools for testing your <code>API</code> endpoints.</p>
</li>
</ul>
<h2 id="heading-what-is-fine-grained-authorization"><strong>What is Fine-Grained Authorization?</strong></h2>
<p><a target="_blank" href="https://www.permit.io/blog/what-is-fine-grained-authorization-fga">Fine-grained authorization</a> offers access control to resources by determining who can access them, to what extent, and under specified conditions.</p>
<p>Contrary to coarse-grained authorization (that handles access based on categories like <code>user roles</code> such as "<code>admin</code>" or "<code>user</code>"), fine-grained authorization gives you the flexibility to define access at a granular level, for specific resources or actions and even attributes. </p>
<p>In <code>Fine Grained Authorization</code> there exist 3 types of policy models for managing authorization; <strong>Role Based Access Control (RBAC)</strong>, <strong>Attribute Based Access Control (ABAC)</strong>, and <strong>Relationship-Based Access Control (ReBAC)</strong>.</p>
<p>Let's take a look, at each of these approaches and see how you can implement them in your application.</p>
<h3 id="heading-role-based-access-control-rbac"><strong>Role-Based Access Control (RBAC)</strong></h3>
<p><a target="_blank" href="https://www.permit.io/blog/what-is-rebac">RBAC</a> is a security approach that controls resource access based on the roles of users within an organization. This model streamlines permissions by organizing users into roles and managing access control according to these defined roles.</p>
<p><strong>Key Concepts in RBAC:</strong></p>
<p><strong>Users:</strong> People who use the system such as employees or customers.</p>
<p><strong>Roles:</strong> A set of permissions or access privileges assigned to a group of users based on their responsibilities or tasks such as admin, manager, or customer.</p>
<p><strong>Permissions:</strong> The rights granted to users for interacting with resources, such as read, write, or delete.</p>
<h3 id="heading-attribute-based-access-control-abac"><strong>Attribute-Based Access Control (ABAC)</strong></h3>
<p><a target="_blank" href="https://www.permit.io/blog/what-is-abac">ABAC</a> is a versatile and adaptive access control model that decides who can or cannot access resources based on attributes, like user details. The ABAC model allows you to define fine-grained authorization based on user attributes.</p>
<p><strong>Key Concepts in ABAC:</strong></p>
<p><strong>Attributes:</strong> Characteristics or properties used to make access control decisions. Attributes are typically categorized into:</p>
<ul>
<li><p><strong>User Attributes:</strong> Information about the user (for example, role, department, job title, age, and so on).</p>
</li>
<li><p><strong>Resource Attributes:</strong> Characteristics of the resource (for example, file type, data classification level, creation date, owner).</p>
</li>
<li><p><strong>Action Attributes:</strong> The action the user is trying to perform (for example, read, write, delete, approve).</p>
</li>
<li><p><strong>Environmental Attributes:</strong> Contextual information about the access request (for example, time of day, location, device type, IP address).</p>
</li>
</ul>
<h3 id="heading-relationship-based-access-control-rebac"><strong>Relationship-Based Access Control (ReBAC)</strong></h3>
<p>ReBAC is an access control system that grants permissions to access resources based on the relationship between entities within a system. The approach emphasizes defining and managing access control by mapping out how users relate to resources and other entities such as organizations or groups.</p>
<p><strong>Key Concepts of ReBAC:</strong></p>
<p><strong>Entities:</strong> Users, resources (such as files and documents), and other entities, such as groups or organizational units.</p>
<p><strong>Relationships:</strong> The connections that specify the relationship between two entities. A user might be the "owner" of a document or a "member" of a team, for instance.</p>
<p><strong>Policies:</strong> Rules that use relationships to determine access rights. A user can access a resource or execute an action on it if they have a particular relationship with it.</p>
<h2 id="heading-how-to-implement-fine-grained-authorization"><strong>How to Implement Fine-Grained Authorization</strong></h2>
<p>Now that you have a basic understanding of <code>RBAC</code>, <code>ABAC</code>, and <code>ReBAC</code>, let’s see how we can implement these models in an e-commerce app.</p>
<h3 id="heading-implementing-role-based-access-control"><strong>Implementing Role-Based Access Control</strong></h3>
<p><strong>Step 1:</strong> Navigate to <a target="_blank" href="http://Permit.io">Permit.io</a>, and then create an account and your workspace.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729494514537/a49035e8-1eb2-495f-acee-6ac212d0076e.png" alt="Permit.io - create your workspace page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>By default, you should see a project that includes two environments: <code>Development</code> and <code>Production</code>. </p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong><em>Note:</em></strong><em> You need to define and test your policies in the development environment before deploying them to production.</em></div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729494835226/8d0e6841-09e7-44e2-89fb-1ec3bacb316d.png" alt="Permit.io - project dashboard" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2:</strong> Create a resource named <strong>Products</strong>. To create the resource, open the <strong>Policy</strong> tab on the left sidebar and then open the <strong>Resources</strong> tab at the top. After that, click the <strong>Create a Resource</strong> button and then create a resource called <strong>Products</strong> with actions <code>read</code>, <code>create</code>, <code>update</code>, and <code>delete</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495042599/91660d3d-eafe-4874-aeb2-50bf88c5a291.png" alt="Permit.io - how to add a new resource" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3:</strong> Create another resource called <strong>Reviews</strong> with actions <code>read</code>, <code>create</code>, <code>update</code>, and <code>delete</code>.</p>
<p><strong>Step 4:</strong> Open the <strong>Policy Editor</strong> tab. You’ll see that 3 roles named <code>admin</code>, <code>editor</code>, and <code>viewer</code> were created.</p>
<ul>
<li><p>Role admin has permission to <code>create</code>, <code>delete</code>, <code>read</code>, or <code>update</code> a product or a review.</p>
</li>
<li><p>Role <code>editor</code> has permission to <code>create</code>, <code>read</code>, or <code>update</code> a <code>product</code> or a <code>review</code> but not <code>delete</code> any.</p>
</li>
<li><p>Role <code>viewer</code> has permission to <code>create</code> and <code>read</code> a product or a <code>review</code> but not <code>delete</code> or <code>update</code> any.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495227714/38553c90-5cc0-4fa0-a116-2f5051b5ebb8.png" alt="Permit.io - Policy editor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-implementing-attribute-based-access-control"><strong>Implementing Attribute-Based Access Control</strong></h3>
<p><strong>Step 1:</strong> Open the <strong>Resources</strong> tab, then click the <strong>Add Attributes</strong> button.</p>
<ul>
<li><p>Add an attribute called <strong>vendor</strong></p>
</li>
<li><p>Add an attribute called the <strong>customer</strong></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495417262/94a09532-83b3-496c-8fef-6ee7c836a211.png" alt="Permit.io - edit resource" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2:</strong> Open the ABAC Rules tab, then create a new ABAC Resource Set called <strong>Own Products</strong> that depends on the Products resource. After that, add a condition that gives permissions only to the user who created a product based on the vendor attribute.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495597939/d528f47f-710a-4bd6-b13a-1cf3a3c49031.png" alt="Permit.io - create your resource set page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3:</strong> Create another ABAC Resource Set called <strong>Own Reviews</strong> that depends on the Reviews resource.</p>
<h3 id="heading-implementing-relationship-based-access-control"><strong>Implementing Relationship-Based Access Control</strong></h3>
<p><strong>Step 1:</strong> Open the Resources tab and edit the Products resource. Add role <code>vendor</code> in the <code>ReBAC</code> options section. Then set products as parent of reviews in the relations section.</p>
<p><strong>Step 2:</strong> Edit the Reviews resource by adding role customer in the <code>ReBAC</code> options section, as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729497355241/4f1a6235-7181-468a-82ce-c727df517604.png" alt="Permit.io - ABAC edit resource" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3:</strong> Go to <code>Policy</code> <code>Editor</code> tab and add:</p>
<ul>
<li><p>role <code>vendor</code> permission to update and delete own products.</p>
</li>
<li><p>role <code>customer</code> permission to update and delete their own reviews on products.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729497438508/935f79b7-3789-4047-b7b5-73e82654b617.png" alt="Permit.io - Policy editor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-implement-fga-in-java-and-springboot"><strong>How to Implement FGA in Java and SpringBoot</strong></h2>
<p>Now that we have defined <code>RBAC</code>, <code>ABAC</code>, and <code>ReBAC</code> policies in the Permit.io web interface, let’s learn how to enforce them in an E-Commerce Management System application using the Permit.io API.</p>
<p>There’s a lot of code coming up, so make sure you read through the extensive comments I’ve left throughout each code block. These will help you understand more fully what’s going on in this code.</p>
<h3 id="heading-step-1-setting-up-the-e-commerce-application"><strong>Step 1: Setting Up the E-commerce Application</strong></h3>
<p>To set up the e-commerce application and git clone the source code.</p>
<pre><code class="lang-powershell">git clone https://github.com/tyaga001/java<span class="hljs-literal">-spring</span><span class="hljs-literal">-fine</span><span class="hljs-literal">-grained</span><span class="hljs-literal">-auth</span>.git
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Then open the code in your Java IDE.&nbsp;I used <a target="_blank" href="https://www.jetbrains.com/idea/">JetBrains</a> for all my work.</div>
</div>

<h4 id="heading-installing-permit-package-sdk"><strong>Installing Permit package SDK</strong></h4>
<p>To install the Permit package SDK, you add the SDK under the dependencies block in the <code>build.graddle</code> file.</p>
<pre><code class="lang-java">## Dependencies

To set up the necessary dependencies <span class="hljs-keyword">for</span> your Spring Boot project, include the following in your `build.gradle` file:

```groovy
dependencies {
    implementation <span class="hljs-string">'org.springframework.boot:spring-boot-starter-web'</span>
    implementation <span class="hljs-string">'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'</span>
    developmentOnly <span class="hljs-string">'org.springframework.boot:spring-boot-devtools'</span>
    testImplementation <span class="hljs-string">'org.springframework.boot:spring-boot-starter-test'</span>
    testRuntimeOnly <span class="hljs-string">'org.junit.platform:junit-platform-launcher'</span>

    <span class="hljs-comment">// Add this line to install the Permit.io Java SDK in your project</span>
    implementation <span class="hljs-string">'io.permit:permit-sdk-java:2.0.0'</span>
}
</code></pre>
<h4 id="heading-initializing-the-permit-sdk"><strong>Initializing the Permit SDK</strong></h4>
<p>You can initialize the Permit <code>SDK</code> Client using the code below:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.config;

<span class="hljs-keyword">import</span> io.permit.sdk.Permit;
<span class="hljs-keyword">import</span> io.permit.sdk.PermitConfig;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Value;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;

<span class="hljs-meta">@Configuration</span>  <span class="hljs-comment">// Marks this class as a configuration class for Spring IoC</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PermitClientConfig</span> </span>{

    <span class="hljs-meta">@Value("${permit.api-key}")</span>  <span class="hljs-comment">// Inject Permit API key from application properties</span>
    <span class="hljs-keyword">private</span> String apiKey;

    <span class="hljs-meta">@Value("${permit.pdp-url}")</span>  <span class="hljs-comment">// Inject Permit PDP (Policy Decision Point) URL from application properties</span>
    <span class="hljs-keyword">private</span> String pdpUrl;

    <span class="hljs-comment">/**
     * Creates a Permit client bean with custom configuration
     * <span class="hljs-doctag">@return</span> Permit client instance
     */</span>
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Permit <span class="hljs-title">permit</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Permit(
                <span class="hljs-keyword">new</span> PermitConfig.Builder(apiKey)  <span class="hljs-comment">// Initialize PermitConfig with API key</span>
                        .withPdpAddress(pdpUrl)   <span class="hljs-comment">// Set the PDP address</span>
                        .withDebugMode(<span class="hljs-keyword">true</span>)      <span class="hljs-comment">// Enable debug mode for detailed logging</span>
                        .build()                  <span class="hljs-comment">// Build the PermitConfig object</span>
        );
    }
}
</code></pre>
<h4 id="heading-syncing-users-with-sdk"><strong>Syncing Users with SDK</strong></h4>
<p>To start enforcing permissions, you should first sync a user to Permit, and then assign them a role.</p>
<p>In the code below, the <strong>UserService</strong> class provides methods for user login, signup, role assignment, and authorization, with exception handling for possible errors when interacting with the Permit API.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.service;

<span class="hljs-keyword">import</span> com.boostmytool.store.exception.ForbiddenAccessException;
<span class="hljs-keyword">import</span> com.boostmytool.store.exception.UnauthorizedException;
<span class="hljs-keyword">import</span> io.permit.sdk.Permit;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitApiError;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitContextError;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.Resource;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-meta">@Service</span>  <span class="hljs-comment">// Marks this class as a Spring service, making it a candidate for component scanning</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Permit permit;

    <span class="hljs-comment">// Constructor injection for the Permit SDK</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserService</span><span class="hljs-params">(Permit permit)</span> </span>{
        <span class="hljs-keyword">this</span>.permit = permit;
    }

    <span class="hljs-comment">/**
     * Simulates user login by creating and returning a Permit User object.
     * 
     * <span class="hljs-doctag">@param</span> key User's unique key
     * <span class="hljs-doctag">@return</span> User object
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">login</span><span class="hljs-params">(String key)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> User.Builder(key).build();
    }

    <span class="hljs-comment">/**
     * Handles user signup by creating and syncing a new Permit User.
     * 
     * <span class="hljs-doctag">@param</span> key User's unique key
     * <span class="hljs-doctag">@return</span> Created and synced User object
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">signup</span><span class="hljs-params">(String key)</span> </span>{
        <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> User.Builder(key).build();
        <span class="hljs-keyword">try</span> {
            permit.api.users.sync(user);  <span class="hljs-comment">// Syncs the new user with the Permit service</span>
        } <span class="hljs-keyword">catch</span> (PermitContextError | PermitApiError | IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to create user"</span>, e);  <span class="hljs-comment">// Handles exceptions during user creation</span>
        }
        <span class="hljs-keyword">return</span> user;
    }

    <span class="hljs-comment">/**
     * Assigns a role to the user within the "default" environment.
     * 
     * <span class="hljs-doctag">@param</span> user User object to assign the role to
     * <span class="hljs-doctag">@param</span> role Role to be assigned
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">assignRole</span><span class="hljs-params">(User user, String role)</span> </span>{
        <span class="hljs-keyword">try</span> {
            permit.api.users.assignRole(user.getKey(), role, <span class="hljs-string">"default"</span>);  <span class="hljs-comment">// Assigns role in the "default" environment</span>
        } <span class="hljs-keyword">catch</span> (PermitApiError | PermitContextError | IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to assign role to user"</span>, e);  <span class="hljs-comment">// Handles exceptions during role assignment</span>
        }
    }

    <span class="hljs-comment">/**
     * Checks if the user is authorized to perform a specific action on a resource.
     * 
     * <span class="hljs-doctag">@param</span> user User object requesting authorization
     * <span class="hljs-doctag">@param</span> action Action to be authorized
     * <span class="hljs-doctag">@param</span> resource Resource on which the action will be performed
     * <span class="hljs-doctag">@throws</span> UnauthorizedException if user is not logged in
     * <span class="hljs-doctag">@throws</span> ForbiddenAccessException if user is denied access
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Resource resource)</span> </span>{
        <span class="hljs-keyword">if</span> (user == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">"Not logged in"</span>);  <span class="hljs-comment">// Throws exception if user is not logged in</span>
        }
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">var</span> permitted = permit.check(user, action, resource);  <span class="hljs-comment">// Performs authorization check</span>
            <span class="hljs-keyword">if</span> (!permitted) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ForbiddenAccessException(<span class="hljs-string">"Access denied"</span>);  <span class="hljs-comment">// Throws exception if access is denied</span>
            }
        } <span class="hljs-keyword">catch</span> (PermitApiError | IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to authorize user"</span>, e);  <span class="hljs-comment">// Handles exceptions during authorization</span>
        }
    }
}
</code></pre>
<p>Then in the code below, the <strong>UserController</strong> class exposes REST API endpoints for user signup and role assignment. It interacts with the UserService class to handle user-related business logic and provides appropriate HTTP responses.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.controllers;

<span class="hljs-keyword">import</span> com.boostmytool.store.exception.UnauthorizedException;
<span class="hljs-keyword">import</span> com.boostmytool.store.service.UserService;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> jakarta.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.PostMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestBody;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RestController;

<span class="hljs-meta">@RestController</span>  <span class="hljs-comment">// Indicates that this class handles HTTP requests and returns JSON responses</span>
<span class="hljs-meta">@RequestMapping("/api/users")</span>  <span class="hljs-comment">// Base URL path for all user-related operations</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserService userService;

    <span class="hljs-comment">// Constructor injection of UserService, containing business logic for user operations</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserController</span><span class="hljs-params">(UserService userService)</span> </span>{
        <span class="hljs-keyword">this</span>.userService = userService;
    }

    <span class="hljs-comment">/**
     * Handles user signup requests.
     * Endpoint: POST /api/users/signup
     * 
     * <span class="hljs-doctag">@param</span> key Unique key for the new user
     * <span class="hljs-doctag">@return</span> Created User object
     */</span>
    <span class="hljs-meta">@PostMapping("/signup")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">signup</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> String key)</span> </span>{
        <span class="hljs-keyword">return</span> userService.signup(key);  <span class="hljs-comment">// Calls the signup method in UserService to create a new user</span>
    }

    <span class="hljs-comment">/**
     * Handles assigning a role to the logged-in user.
     * Endpoint: POST /api/users/assign-role
     * 
     * <span class="hljs-doctag">@param</span> request HTTP request, used to retrieve the current user
     * <span class="hljs-doctag">@param</span> role Role to be assigned to the current user
     */</span>
    <span class="hljs-meta">@PostMapping("/assign-role")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">assignRole</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@RequestBody</span> String role)</span> </span>{
        <span class="hljs-comment">// Retrieves the current user from the request attributes</span>
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);

        <span class="hljs-comment">// Throws an exception if the user is not logged in</span>
        <span class="hljs-keyword">if</span> (currentUser == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">"Not logged in"</span>);
        }

        <span class="hljs-comment">// Assigns the specified role to the current user</span>
        userService.assignRole(currentUser, role);
    }
}
</code></pre>
<h4 id="heading-creating-rbac-abac-and-rebac-policy-enforcement-point"><strong>Creating RBAC, ABAC, and ReBAC Policy Enforcement Point</strong></h4>
<p>In the code below, the <strong>ProductService</strong> class manages CRUD operations for products and reviews, handling permissions and roles via the Permit API.</p>
<p>Each operation includes user <code>authorization</code> checks, with appropriate exception handling for Permit API errors and resource not found scenarios.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.service;

<span class="hljs-keyword">import</span> com.boostmytool.store.exception.ResourceNotFoundException;
<span class="hljs-keyword">import</span> com.boostmytool.store.model.Product;
<span class="hljs-keyword">import</span> com.boostmytool.store.model.Review;
<span class="hljs-keyword">import</span> io.permit.sdk.Permit;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitApiError;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitContextError;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.Resource;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> io.permit.sdk.openapi.models.RelationshipTupleCreate;
<span class="hljs-keyword">import</span> io.permit.sdk.openapi.models.ResourceInstanceCreate;
<span class="hljs-keyword">import</span> io.permit.sdk.openapi.models.RoleAssignmentCreate;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.concurrent.atomic.AtomicInteger;

<span class="hljs-meta">@Service</span>  <span class="hljs-comment">// Marks this class as a Spring service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductService</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;Product&gt; products = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();  <span class="hljs-comment">// In-memory list to store products</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger productIdCounter = <span class="hljs-keyword">new</span> AtomicInteger();  <span class="hljs-comment">// Counter to generate unique product IDs</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger reviewIdCounter = <span class="hljs-keyword">new</span> AtomicInteger();   <span class="hljs-comment">// Counter to generate unique review IDs</span>

    <span class="hljs-comment">// Builders for Permit resource instances (product and review)</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Resource.Builder productResourceBuilder = <span class="hljs-keyword">new</span> Resource.Builder(<span class="hljs-string">"product"</span>);
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Resource.Builder reviewResourceBuilder = <span class="hljs-keyword">new</span> Resource.Builder(<span class="hljs-string">"review"</span>);

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserService userService;  <span class="hljs-comment">// Service for handling user-related operations</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Permit permit;  <span class="hljs-comment">// Permit SDK instance for handling authorization and resource management</span>

    <span class="hljs-comment">// Constructor for injecting dependencies</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProductService</span><span class="hljs-params">(UserService userService, Permit permit)</span> </span>{
        <span class="hljs-keyword">this</span>.userService = userService;
        <span class="hljs-keyword">this</span>.permit = permit;
    }

    <span class="hljs-comment">// Method to authorize a user for a given action on a resource</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Resource resource)</span> </span>{
        userService.authorize(user, action, resource);
    }

    <span class="hljs-comment">// Authorizes a user to perform an action on a specific product</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Product product)</span> </span>{
        <span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">new</span> HashMap&lt;String, Object&gt;();
        attributes.put(<span class="hljs-string">"vendor"</span>, product.getVendor());  <span class="hljs-comment">// Add vendor attribute to the product</span>
        userService.authorize(user, action, productResourceBuilder.withKey(product.getId().toString()).withAttributes(attributes).build());
    }

    <span class="hljs-comment">// Authorizes a user to perform an action on a specific review</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Review review)</span> </span>{
        <span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">new</span> HashMap&lt;String, Object&gt;();
        attributes.put(<span class="hljs-string">"customer"</span>, review.getCustomer());  <span class="hljs-comment">// Add customer attribute to the review</span>
        userService.authorize(user, action, reviewResourceBuilder.withKey(review.getId().toString()).withAttributes(attributes).build());
    }

    <span class="hljs-comment">// Retrieves a product by its ID, throws an exception if not found</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> Product <span class="hljs-title">getProductById</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{
        <span class="hljs-keyword">return</span> products.stream().filter(product -&gt; product.getId().equals(id))
                .findFirst().orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Product with id "</span> + id + <span class="hljs-string">" not found"</span>));
    }

    <span class="hljs-comment">// Retrieves all products, checks if the user is authorized to "read" products</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Product&gt; <span class="hljs-title">getAllProducts</span><span class="hljs-params">(User user)</span> </span>{
        authorize(user, <span class="hljs-string">"read"</span>, productResourceBuilder.build());  <span class="hljs-comment">// User must have "read" permission</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(products);  <span class="hljs-comment">// Return a copy of the products list</span>
    }

    <span class="hljs-comment">// Retrieves a product by its ID, checks if the user is authorized to "read" the product</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">getProduct</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> id)</span> </span>{
        authorize(user, <span class="hljs-string">"read"</span>, productResourceBuilder.build());
        <span class="hljs-keyword">return</span> getProductById(id);
    }

    <span class="hljs-comment">// Adds a new product, authorizes the user and creates resource instances and role assignments in Permit</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">addProduct</span><span class="hljs-params">(User user, String content)</span> </span>{
        authorize(user, <span class="hljs-string">"create"</span>, productResourceBuilder.build());  <span class="hljs-comment">// Check if user can create a product</span>
        Product product = <span class="hljs-keyword">new</span> Product(productIdCounter.incrementAndGet(), user.getKey(), content);  <span class="hljs-comment">// Create new product</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Create resource instance in Permit and assign "vendor" role to the user for this product</span>
            permit.api.resourceInstances.create(<span class="hljs-keyword">new</span> ResourceInstanceCreate(product.getId().toString(), <span class="hljs-string">"product"</span>).withTenant(<span class="hljs-string">"default"</span>));
            permit.api.roleAssignments.assign(<span class="hljs-keyword">new</span> RoleAssignmentCreate(<span class="hljs-string">"vendor"</span>, user.getKey()).withResourceInstance(<span class="hljs-string">"product:"</span> + product.getId()).withTenant(<span class="hljs-string">"default"</span>));
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to create resource instance or role assignment: "</span> + e.getMessage());
        }

        products.add(product);  <span class="hljs-comment">// Add product to in-memory list</span>
        <span class="hljs-keyword">return</span> product;
    }

    <span class="hljs-comment">// Updates a product's content, checks if the user is authorized to "update" the product</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">updateProduct</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> id, String content)</span> </span>{
        Product product = getProductById(id);  <span class="hljs-comment">// Get the product by its ID</span>
        authorize(user, <span class="hljs-string">"update"</span>, product);  <span class="hljs-comment">// Check if user can update the product</span>
        product.setContent(content);  <span class="hljs-comment">// Update product content</span>
        <span class="hljs-keyword">return</span> product;
    }

    <span class="hljs-comment">// Deletes a product, checks if the user is authorized to "delete" the product</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteProduct</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> id)</span> </span>{
        <span class="hljs-keyword">boolean</span> isDeleted = products.removeIf(product -&gt; {
            <span class="hljs-keyword">if</span> (product.getId().equals(id)) {
                authorize(user, <span class="hljs-string">"delete"</span>, product);  <span class="hljs-comment">// Check if user can delete the product</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            }
        });

        <span class="hljs-keyword">if</span> (!isDeleted) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Product with id "</span> + id + <span class="hljs-string">" not found"</span>);
        }

        <span class="hljs-keyword">try</span> {
            permit.api.resourceInstances.delete(<span class="hljs-string">"product:"</span> + id);  <span class="hljs-comment">// Remove product resource instance from Permit</span>
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }
    }

    <span class="hljs-comment">// Adds a review to a product, creates a resource instance and relationship in Permit</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">addReview</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> productId, String content)</span> </span>{
        authorize(user, <span class="hljs-string">"create"</span>, reviewResourceBuilder.build());  <span class="hljs-comment">// Check if user can create a review</span>
        Product product = getProductById(productId);  <span class="hljs-comment">// Get the product by its ID</span>
        Review review = <span class="hljs-keyword">new</span> Review(reviewIdCounter.incrementAndGet(), user.getKey(), content);  <span class="hljs-comment">// Create new review</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Create a resource instance for the review and set relationship with the product</span>
            permit.api.resourceInstances.create(<span class="hljs-keyword">new</span> ResourceInstanceCreate(review.getId().toString(), <span class="hljs-string">"review"</span>).withTenant(<span class="hljs-string">"default"</span>));
            permit.api.relationshipTuples.create(<span class="hljs-keyword">new</span> RelationshipTupleCreate(<span class="hljs-string">"product:"</span> + productId, <span class="hljs-string">"parent"</span>, <span class="hljs-string">"review:"</span> + review.getId()));
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }

        product.addReview(review);  <span class="hljs-comment">// Add the review to the product</span>
        <span class="hljs-keyword">return</span> review;
    }

    <span class="hljs-comment">// Updates a review's content, checks if the user is authorized to "update" the review</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">updateReview</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> productId, <span class="hljs-keyword">int</span> reviewId, String content)</span> </span>{
        Product product = getProductById(productId);  <span class="hljs-comment">// Get the product by its ID</span>
        Review review = product.getReviews().stream().filter(c -&gt; c.getId().equals(reviewId))
                .findFirst().orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Review with id "</span> + reviewId + <span class="hljs-string">" not found"</span>));

        authorize(user, <span class="hljs-string">"update"</span>, review);  <span class="hljs-comment">// Check if user can update the review</span>
        review.setContent(content);  <span class="hljs-comment">// Update review content</span>
        <span class="hljs-keyword">return</span> review;
    }

    <span class="hljs-comment">// Deletes a review, checks if the user is authorized to "delete" the review</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteReview</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> productId, <span class="hljs-keyword">int</span> reviewId)</span> </span>{
        Product product = getProductById(productId);  <span class="hljs-comment">// Get the product by its ID</span>
        <span class="hljs-keyword">boolean</span> isDeleted = product.getReviews().removeIf(review -&gt; {
            <span class="hljs-keyword">if</span> (review.getId().equals(reviewId)) {
                authorize(user, <span class="hljs-string">"delete"</span>, review);  <span class="hljs-comment">// Check if user can delete the review</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            }
        });

        <span class="hljs-keyword">if</span> (!isDeleted) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Review with id "</span> + reviewId + <span class="hljs-string">" not found"</span>);
        }

        <span class="hljs-keyword">try</span> {
            permit.api.resourceInstances.delete(<span class="hljs-string">"review:"</span> + reviewId);  <span class="hljs-comment">// Remove review resource instance from Permit</span>
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }
    }
}
</code></pre>
<p>Then in the code below, the <strong>ProductController</strong> class handles HTTP requests related to products and their reviews. It exposes endpoints for managing products (like <code>creating</code>, <code>updating</code>, <code>deleting</code>, and <code>retrieving</code>) and for managing product reviews.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.controllers;

<span class="hljs-keyword">import</span> com.boostmytool.store.model.Product;
<span class="hljs-keyword">import</span> com.boostmytool.store.model.Review;
<span class="hljs-keyword">import</span> com.boostmytool.store.service.ProductService;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> jakarta.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.http.HttpStatus;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.*;

<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-meta">@RestController</span>  <span class="hljs-comment">// Indicates that this class is a Spring REST controller</span>
<span class="hljs-meta">@RequestMapping("/api/products")</span>  <span class="hljs-comment">// Base URL for all endpoints in this controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductController</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ProductService productService;  <span class="hljs-comment">// ProductService instance to handle product-related operations</span>

    <span class="hljs-meta">@Autowired</span>  <span class="hljs-comment">// Autowires ProductService bean automatically</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProductController</span><span class="hljs-params">(ProductService productService)</span> </span>{
        <span class="hljs-keyword">this</span>.productService = productService;
    }

    <span class="hljs-comment">// GET request to retrieve all products</span>
    <span class="hljs-meta">@GetMapping</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Product&gt; <span class="hljs-title">getAllProducts</span><span class="hljs-params">(HttpServletRequest request)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.getAllProducts(currentUser);  <span class="hljs-comment">// Calls ProductService to get all products for the user</span>
    }

    <span class="hljs-comment">// GET request to retrieve a product by its ID</span>
    <span class="hljs-meta">@GetMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">getProductById</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.getProduct(currentUser, id);  <span class="hljs-comment">// Calls ProductService to get the product by ID for the user</span>
    }

    <span class="hljs-comment">// POST request to add a new product</span>
    <span class="hljs-meta">@PostMapping</span>
    <span class="hljs-meta">@ResponseStatus(HttpStatus.CREATED)</span>  <span class="hljs-comment">// Sets the response status to 201 (Created)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">addProduct</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.addProduct(currentUser, content);  <span class="hljs-comment">// Calls ProductService to add a new product</span>
    }

    <span class="hljs-comment">// PUT request to update an existing product by its ID</span>
    <span class="hljs-meta">@PutMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">updateProduct</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.updateProduct(currentUser, id, content);  <span class="hljs-comment">// Calls ProductService to update the product by ID</span>
    }

    <span class="hljs-comment">// DELETE request to delete a product by its ID</span>
    <span class="hljs-meta">@DeleteMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">deleteProduct</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        productService.deleteProduct(currentUser, id);  <span class="hljs-comment">// Calls ProductService to delete the product by ID</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Deleted product with id "</span> + id;  <span class="hljs-comment">// Returns a success message after deletion</span>
    }

    <span class="hljs-comment">// POST request to add a new review to a product by product ID</span>
    <span class="hljs-meta">@PostMapping("/{id}/review")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">addReview</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.addReview(currentUser, id, content);  <span class="hljs-comment">// Calls ProductService to add a review to the product</span>
    }

    <span class="hljs-comment">// PUT request to update an existing review by product and review ID</span>
    <span class="hljs-meta">@PutMapping("/{id}/review/{reviewId}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">updateReview</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@PathVariable("reviewId")</span> <span class="hljs-keyword">int</span> reviewId, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.updateReview(currentUser, id, reviewId, content);  <span class="hljs-comment">// Calls ProductService to update the review</span>
    }

    <span class="hljs-comment">// DELETE request to delete a review by product and review ID</span>
    <span class="hljs-meta">@DeleteMapping("/{id}/review/{reviewId}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">deleteReview</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@PathVariable("reviewId")</span> <span class="hljs-keyword">int</span> reviewId)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        productService.deleteReview(currentUser, id, reviewId);  <span class="hljs-comment">// Calls ProductService to delete the review</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Deleted review with id "</span> + reviewId + <span class="hljs-string">" from product "</span> + id;  <span class="hljs-comment">// Returns a success message after deletion</span>
    }
}
</code></pre>
<h3 id="heading-step-2-get-your-environment-api-key"><strong>Step 2: Get your Environment API Key</strong></h3>
<p>In the UI Dashboard, copy the Environment <code>API Key</code> of the active environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498343969/2bbbd4a0-512f-4b46-a82a-ca41ecb67a4c.png" alt="Permit.io - copy env key" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Then add the env <code>API key</code> and <code>PDP URL</code> in the <code>application.yaml</code> file.</p>
<pre><code class="lang-plaintext">permit:
  pdpUrl: 'http://localhost:7766'
  apiKey: "Your Permit environment API Key"
</code></pre>
<h3 id="heading-step-3-deploy-policy-decision-point-pdp"><strong>Step 3: Deploy Policy Decision Point (PDP)</strong></h3>
<p>The Policy Decision Point (PDP) is deployed in your VPC and is in charge of evaluating your authorization requests. The PDP will ensure zero latency, great performance, high availability, and improved security.</p>
<p>Use the command below to pull the <a target="_blank" href="http://Permit.io">Permit.io</a> PDP container from <code>Docker</code> Hub.</p>
<pre><code class="lang-dockerfile">docker pull permitio/pdp-v2:latest
</code></pre>
<p>Then run the container.</p>
<pre><code class="lang-dockerfile">docker <span class="hljs-keyword">run</span><span class="bash"> -it -p 7766:7000 --env PDP_DEBUG=True --env PDP_API_KEY=&lt;YOUR_API_KEY&gt; permitio/pdp-v2:latest</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729515246656/6bed08e3-6109-4643-a724-f55641d7c974.png" alt="Permit.io - local testing" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-4-running-the-app"><strong>Step 4: Running the App</strong></h3>
<p>You can run the application using the following <code>Gradle</code> command:</p>
<pre><code class="lang-dockerfile">./gradlew bootRun
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729515837209/41556843-b8d5-4433-a2f3-93371562d27d.png" alt="Permit.io - how to run the app in local" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-viewing-and-creating-products"><strong>Viewing and Creating Products</strong></h4>
<p>Let’s now interact with the application endpoints using <a target="_blank" href="https://reqbin.com/curl">REQBIN</a>.</p>
<p>First, create a new user using the <code>/api/users/signup</code> endpoint.</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/signup"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'johndoe'</span>
</code></pre>
<p>You should be able to view the user in your Permit project, under Directory &gt; All Tenants.</p>
<p>Initially, the user has no roles, so it cannot do much. For example, trying to list the products will result in a 403 Forbidden response, as shown below. The 403 error code means the user doesn’t have permissions to access the requested resource, which is products in this case. You can learn more about <a target="_blank" href="https://www.permit.io/blog/401-vs-403-error-whats-the-difference">the difference between 401 and 403 error codes here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498632123/aaf26b76-a89f-4e6b-9324-85d082b8061d.png" alt="Permit.io - endpoints" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>For the user to view a list of products, assign them a viewer role using the command below:</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/assign-role"</span> \
-H <span class="hljs-string">"Authorization: Bearer johndoe"</span> \
-H <span class="hljs-string">"Content-Type: application/json"</span> \
-d <span class="hljs-string">'viewer'</span>
</code></pre>
<p>You should see that user <code>johndoe</code> was assigned role viewer, as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498710784/ebd789fd-ec52-4146-bb94-6f300edb9d7e.png" alt="Permit.io - users" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Since a viewer can create a product, use the command below to create a product with user <code>johndoe</code>.</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/products"</span> -H <span class="hljs-string">"Authorization: Bearer johndoe"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'MacBook'</span>
</code></pre>
<p>You should see that a new product is created with ID 1 and that the user <code>johndoe</code> has been added as the vendor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498758160/c14169f0-d720-465e-9bc1-f7096e6da31a.png" alt="Permit.io - API end points " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-adding-reviews-to-products"><strong>Adding Reviews To Products</strong></h4>
<p>To add reviews to products, create another user called <code>jane</code>.</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/signup"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'jane'</span>
</code></pre>
<p>For the user to add a review to products, assign them a <code>viewer</code> role using the command below:</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/assign-role"</span> \
-H <span class="hljs-string">"Authorization: Bearer jane"</span> \
-H <span class="hljs-string">"Content-Type: application/json"</span> \
-d <span class="hljs-string">'viewer'</span>
</code></pre>
<p>Then you can add a review to the product added by <code>johndoe</code> using the command below:</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/products/1/review"</span> -H <span class="hljs-string">"Authorization: Bearer jane"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'The product was in good quality'</span>
</code></pre>
<p>Congratulations! You’ve completed the project for this tutorial.</p>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that you've learned how to implement fine-grained authorization in your Java and Spring Boot applications using <a target="_blank" href="http://Permit.io">Permit.io</a>, you might want to explore further.</p>
<p>Here are some valuable resources:</p>
<ul>
<li><p><a target="_blank" href="https://docs.permit.io/">Permit.io docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.permit.io/blog/rbac-vs-abac">RBAC VS ABAC: Choosing the Right Authorization Policy Model</a></p>
</li>
</ul>
<h3 id="heading-before-we-end">Before We End</h3>
<p>I hope you found this tutorial insightful.</p>
<p>Here are some of my other recent blog posts that you might enjoy:</p>
<ul>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/learn-react-key-concepts/">Learn React – A Guide to the Key Concepts</a></p>
</li>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/neon-vs-supabase"><strong>Neon Postgres vs Supabase</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/nextjs-clerk-neon-fullstack-development/">Full Stack Development with Next.js, Clerk, and Neon Postgres</a></p>
</li>
</ul>
<p>For more tutorials on amazing developer tools, be sure to check out my blog <a target="_blank" href="https://www.devtoolsacademy.com/">DTA</a>.</p>
<p>Follow me on <a target="_blank" href="https://x.com/TheAnkurTyagi">Twitter</a> to get live updates on my other projects.</p>
<p>Happy coding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get Your MongoDB URL to Connect to Your Node.js Application – A Step-by-Step Guide ]]>
                </title>
                <description>
                    <![CDATA[ In my previous article about building a Node.js application, I didn’t fully explain how to obtain the MongoDB URL, as I wanted to keep the article concise. However, I realized that this information is essential for saving data to MongoDB. In this art... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/get-mongodb-url-to-connect-to-a-nodejs-application/</link>
                <guid isPermaLink="false">66ba7ce339eb4776cdcacc56</guid>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Mon, 12 Aug 2024 21:21:39 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723497228942/b766b557-8230-4bef-8392-d3f4f020c1f4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-an-event-app-with-node-js/">previous article about building a Node.js application</a>, I didn’t fully explain how to obtain the MongoDB URL, as I wanted to keep the article concise. However, I realized that this information is essential for saving data to MongoDB.</p>
<p>In this article, I will guide you through the process of getting your MongoDB URL so you can connect your application effectively. By the end of this tutorial, you’ll have a clear understanding of how to retrieve your MongoDB URL.</p>
<h2 id="heading-lets-get-started">Let's get started! 🚀</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/drum-roll-3.gif" alt="A drum indicating let's get started" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-1-search-for-mongodb-or-visit-their-website">Step 1:  Search for MongoDB or Visit their Website</h2>
<p>To begin, head to the <a target="_blank" href="https://www.mongodb.com">MongoDB</a> website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/mongodb-website.png" alt="Mongodb website" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-2-click-on-the-sign-in-button-on-their-website">Step 2: Click on the Sign In button on their website.</h2>
<p>This will redirect you to the MongoDB login page. If you don’t have an account yet, you can create one by selecting the <strong>Sign Up</strong> option instead. Since I already have an account, I will log in to access my MongoDB dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/sigin-mongodb.gif" alt="Redirection to login or signup page of mongodb" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-3-access-the-dashboard">Step 3: Access the Dashboard</h2>
<p>Once you log in, you'll have access to the dashboard. But first, you need to create a project folder.</p>
<h3 id="heading-why-do-you-need-a-project-folder">Why Do You Need a Project Folder?</h3>
<p>This is for organizational purposes, helping you keep track of which projects you are working on.</p>
<p><strong>To create a project folder</strong></p>
<ul>
<li><p>Click on the <strong>Projects</strong> section at the top, indicated by a folder icon. This will reveal a dropdown menu.</p>
</li>
<li><p>From the dropdown, click on <strong>New Project</strong>. This will redirect you to a page where you can create your new project.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/use-mongodb.gif" alt="Create a new project" width="600" height="400" loading="lazy"></p>
<ul>
<li>Click the <strong>Next</strong> button to proceed to the project creation page.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/create-project.png" alt="Creating a project continues" width="600" height="400" loading="lazy"></p>
<p>After creating your project, you will be redirected back to your dashboard, where you will see your newly created project folder. You can now start working on this specific project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/project-created-mongodb-1.png" alt="Going back to the dashboard" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-4-creating-a-cluster">Step 4: Creating a Cluster</h2>
<p>To obtain the MongoDB connection URL, it is essential to create a <strong>Cluster</strong>.</p>
<h3 id="heading-what-is-a-cluster">What is a cluster?</h3>
<p>A cluster in MongoDB is a group of servers that work together to store and manage your data, providing high availability and scalability.</p>
<p><strong>To create a cluster:</strong></p>
<ol>
<li><p>On your dashboard, click on the <strong>Clusters</strong> button as shown in the picture of <strong>Step 3</strong> above.</p>
</li>
<li><p>Next, this will direct you to a page called "<strong>Deploy your cluster</strong>" where you get to create your cluster.</p>
</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/cluster-mongoDB.gif" alt="Creating a cluster" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-5-create-a-username-for-your-connection-url">Step 5: Create a Username for Your Connection URL</h2>
<p>After creating a cluster, you will be taken to a page where you need to create a username and password for the connection URL. The password can be autogenerated, or you can create your own.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/creating-a-username-for-mongodb.png" alt="Creating Username and password" width="600" height="400" loading="lazy"></p>
<h3 id="heading-why-do-i-have-to-create-a-username">Why Do I Have to Create a Username?</h3>
<p>Creating a username is essential for managing access to your MongoDB cluster. A username, along with a password, ensures that only authorized users can access your database. This adds a layer of security, protecting your data from unauthorized access.</p>
<h3 id="heading-benefits-of-creating-a-username">Benefits of creating a username:</h3>
<ul>
<li><p><strong>Security:</strong> Ensures that your database is only accessible to those with the correct credentials.</p>
</li>
<li><p><strong>Management:</strong> You can track who is accessing your database and manage permissions.</p>
</li>
<li><p><strong>Accountability:</strong> Helps in auditing and monitoring activities within your database.</p>
</li>
</ul>
<h2 id="heading-step-6-auto-generation-of-the-mongodb-connection-url">Step 6: Auto Generation  of The MongoDB Connection URL</h2>
<p>Once you click the <strong>Create User</strong> button, you will be redirected to a page where your connection URL is automatically generated. Copy this URL and paste it into your <code>.env</code> file to establish a connection to your database. Alternatively, you can paste it directly into your <code>app.js</code> or <code>server.js</code> file, as I <a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-an-event-app-with-node-js/">explained in my previous article</a>.</p>
<p>Feel free to let me know if you need assistance!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/getting-the-strringt-fot-conn.png" alt="Automatic generation of the URL" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By following the steps outlined in this article, you should now understand how to obtain your MongoDB connection URL. Remember, creating a username and password for your database access is crucial for ensuring the security and management of your data.</p>
<p>If you encounter any challenges along the way, don't hesitate to refer back to this guide, ask questions or better still consult the official <a target="_blank" href="https://www.mongodb.com/resources/products/fundamentals/basics">MongoDB documentation</a> for further assistance.</p>
<p>If you found this article helpful, share it with others who may also find it interesting.</p>
<p>Stay updated with my projects by following me on <a target="_blank" href="https://https//twitter.com/ijaydimples">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/ijeoma-igboagu/">LinkedIn</a> and <a target="_blank" href="https://github.com/ijayhub">GitHub</a>.</p>
<p>Thank you for reading💖.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ SEO Tips for Developers ]]>
                </title>
                <description>
                    <![CDATA[ SEO (Search Engine Optimization) is essential for your online marketing strategy. It's the process of optimizing your site and content to help you get as much traffic as you can from search engines. Reaching top positions in the search engine results... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tips-to-boost-your-seo/</link>
                <guid isPermaLink="false">66d45e4a052ad259f07e4aa9</guid>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Edan Ben-Atar ]]>
                </dc:creator>
                <pubDate>Sat, 29 Oct 2022 00:09:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/10-Tips-to-Boost-Your-SEO.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>SEO (Search Engine Optimization) is essential for your online marketing strategy. It's the process of optimizing your site and content to help you get as much traffic as you can from search engines.</p>
<p>Reaching top positions in the search engine results pages (SERPs) with your website is one of the fastest ways to drive traffic to your site and boost conversions.</p>
<p>This article will go over the top 10 tips to boost your SEO and grow your website.</p>
<h2 id="heading-how-to-create-a-content-marketing-strategy">How to Create a Content Marketing Strategy</h2>
<p>You’ll want to create a content <a target="_blank" href="https://en.wikipedia.org/wiki/Marketing_strategy">marketing strategy</a> that will help you increase your rankings and reach your target audience.</p>
<p>But what’s a content marketing strategy? Content marketing will keep your business top of mind and help you establish yourself as an expert in your field, but it requires a lot of work.</p>
<p>For example, the company's content marketing manager would usually have to post a minimum of one article per week, taking into consideration keywords and the searcher’s intent.</p>
<p>It sounds like a lot, but it pays off. The content you're posting is relevant to the audience and shows that the company cares about them. It builds trust with consumers and helps them stay connected with the brand.</p>
<p>The best way to do this is to create content specific to your business, targeted toward your prospects, optimized for SEO, and distributed through social media. But don’t forget – consistency is key.</p>
<p>Create a plan for the kind of content you want to put out there and how often you wish to publish it. Track what works and what doesn’t so you can make adjustments as necessary.</p>
<p>Here are a few initial steps to follow during your content strategy process:</p>
<ol>
<li><p>Understand your goals. Do you want to get more traffic or more conversions? Do you want to let your audience know about new features, or do you want to educate them?</p>
</li>
<li><p>Figure out which content channels are best for your business. Creating content is not just about publishing a few articles. It’s also about distributing them. Share your content on websites such as LinkedIn, Reddit, or Hacker News.</p>
</li>
<li><p>Research the keywords people search for when browsing for your solution. Address those keywords in your content and appeal to your audience’s pain points.</p>
</li>
</ol>
<h2 id="heading-how-to-make-your-website-mobile-friendly">How to Make Your Website Mobile Friendly</h2>
<p>How can you know if your website is mobile-friendly?</p>
<p>Mobile-friendliness isn’t the only thing that matters. It’s also essential to have a fast website, responsive design, mobile-friendly content, and navigation.</p>
<p>Google has tools that you can use to check if your site is mobile-friendly, as well as other tools for testing speed.</p>
<p>If your website isn’t optimized for mobile, you should start doing this:</p>
<ol>
<li><p>Make sure your website is not overloaded with plugins. If you’re using WordPress, too many plugins can slow down your website.</p>
</li>
<li><p>Use appropriate sizes and formats for your pictures and media. Images that are too large will slow your pages down and will have an undesirable effect on customer experience.</p>
</li>
<li><p>Check your Core Web Vitals periodically. Make sure that your website loads under 2 seconds and your CWV metrics are within limits.</p>
</li>
</ol>
<p>Your customers and Google will thank you, and it will pay dividends in both traffic and conversions.</p>
<h2 id="heading-how-to-create-evergreen-content">How to Create Evergreen Content</h2>
<p>Another tip to boost your SEO is creating evergreen content. Evergreen content is any type of information that has long-term relevance, meaning it's both timeless and timely (that is, not outdated). It's also search engine optimized, readable on mobile devices, and can be repurposed in multiple formats.</p>
<p>Evergreen content can be an excellent tool to help with SEO because it tends to rank well in search engines and can help your website gain traction when posted on other sites.</p>
<p>When done correctly, evergreen content provides an opportunity for your business to market itself without having to rely on time-sensitive events or news items to draw traffic to your site. Evergreen posts are updated frequently but are always focused on something new or something old that has been updated.</p>
<p>Examples of evergreen content include "How to Start a Business," "The Importance of Being Organized at Work", and "5 Things You Can Do With Leftover Pasta".</p>
<p>Content like this won’t ever lose its value because it doesn’t rely on current events or trends to stay relevant. Because of this, you can build a library of evergreen content that will continue to drive traffic over time.</p>
<h2 id="heading-how-to-reduce-your-bounce-rate">How to Reduce Your Bounce Rate</h2>
<p>Once you have people arriving on your site, you need to keep them there. A low bounce rate signals to Google that your content is valuable and will rank you higher in search results.</p>
<p>Remember, it’s not just about bringing more traffic to your site but keeping the traffic that comes from a good SEO strategy.</p>
<p>We know what you’re thinking: how do I reduce my bounce rate?</p>
<p>Here are some ways:</p>
<ul>
<li><p>Reduce friction for users. Make it easy for them to read your content by making it readable and entertaining enough to stay on the page. Improve your navigation, so readers don’t get lost or stuck trying to find what they came for. Remove annoying pop-ups that distract users from reading your content or even prevent them from accessing it altogether.</p>
</li>
<li><p>Use visual elements such as images and videos where appropriate. They can make reading text easier and more enjoyable by breaking up chunks of text and making long articles seem shorter.</p>
</li>
<li><p>Use short paragraphs and bullet points so readers can skim through the page quickly without losing their place or interest in the material.</p>
</li>
<li><p>Use headings and subheadings throughout long articles so readers can get an idea of what each paragraph is about before reading it all word by word.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/Screen-Shot-2022-04-21-at-3.41.52-PM.png" alt="GTmetrix report for limey.io showing A score and 552ms of load time" width="600" height="400" loading="lazy"></p>
<p><em>GTmetrix report for</em> <a target="_blank" href="https://limey.io/"><em>Limey</em></a></p>
<h2 id="heading-how-to-optimize-page-speed">How to Optimize Page Speed</h2>
<p>As you might know, optimizing your page speed is no small task. It requires several steps and can be challenging. If this seems like too much to take on, consider hiring an SEO to help you identify page speed issues on your WordPress or Shopify website.</p>
<p>Some actionable steps you could take are:</p>
<ul>
<li><p>Reduce unused JavaScript.</p>
</li>
<li><p>Eliminate render-blocking resources.</p>
</li>
<li><p>Reduce initial server response time.</p>
</li>
</ul>
<h2 id="heading-how-to-start-guest-blogging">How to Start Guest Blogging</h2>
<p>Guest blogging is a great tool to keep your site fresh and relevant. Having other bloggers accept articles you submitted can help bring new traffic to your website, and encourage back-links that increase your search engine ranking.</p>
<p>This could lead to more traffic, sign-ups, and sales for you.</p>
<p>Guest posting also helps with branding and reaching new audiences.</p>
<p>In the end, you will want to find blogs in your niche that accept contributions or have a "write for us" section where you can submit your content.</p>
<p>It's not easy to get accepted, so make sure you write something great when pitching yourself as a guest blogger!</p>
<p>Guest blogs aren't just for large businesses—if you're just starting out, there are a variety of ways you can use guest blogging to your advantage.</p>
<p>First, if you're just starting out and don't have a huge following yet, guest blogging is a great way to build up your audience. The big companies that have been guest blogging for years have thousands of new readers coming in each time they publish something new.</p>
<p>If you've got some good ideas on your blog, and you have the drive to pitch yourself to other blogs and websites as well, then why not give it a shot?</p>
<p>Also, if you've got any interesting story behind your company or products, this is another great way to show off what makes you unique. Who knows—your story could be the thing that makes your blog post stand out and draw people in.</p>
<h2 id="heading-how-to-optimize-on-page-seo">How to Optimize On-Page SEO</h2>
<p>Now that you have the basics down, let’s look at how to optimize on-page SEO.</p>
<ul>
<li><p>Content relevance: Ensure your content is relevant and up to date. A key element of on-page SEO is having a page that covers the query in question and any related queries a user may have.</p>
</li>
<li><p>Title Tag: Make sure your title tag is relevant and accurate. Your title tag should give users an idea of what they’re clicking on before they visit your site, so make sure it accurately reflects the topic of the page and makes sense for searchers (it doesn’t need to be precisely the same as what you searched for).</p>
</li>
<li><p>Meta description: Don’t forget about meta descriptions! While it won’t directly affect rankings, meta descriptions are still important because they show up in SERPs and can encourage clicks from users if optimized correctly.</p>
</li>
<li><p>Headings: Use headers appropriately by breaking up content into sections with clear titles, including keywords when possible.</p>
</li>
<li><p>Links: Link out to other relevant websites and make sure you link internally when possible to help users navigate your site (and include anchor text with contextual keywords). This can also help boost page authority.</p>
</li>
<li><p>Images &amp; Videos: Use images and videos strategically to make your content more compelling for visitors who don't want to read through long blocks of text or who like visuals better than reading text. You can also use image alt tags or video subtitles/transcripts (not automated) to optimize content since Google crawls these types of media as well.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/ahrefs-wordpress-tips.png" alt="Ahrefs Keyword Explorer showing results for the search &quot;WordPress tips&quot;" width="600" height="400" loading="lazy"></p>
<p><em>Ahrefs Keyword Explorer</em></p>
<h2 id="heading-how-to-find-the-right-keywords-for-your-content-opportunities">How to Find the Right Keywords for Your Content Opportunities</h2>
<p>Keyword research is arguably the most important part of SEO. The right keywords can make the difference between a high-ranking article and one that doesn’t get noticed at all.</p>
<p>When you are starting, it’s important to understand your goals in terms of organic search traffic. From there, you can choose a keyword strategy that will help you reach those goals.</p>
<p>There are several factors to consider when choosing keywords for your content opportunities:</p>
<ul>
<li><p>Relevancy: What is the keyword relevant to? Choose a keyword that corresponds with your content or product offering.</p>
</li>
<li><p>Search Volume: If you want people to see your content, choose a keyword with high search volume (that is, many people have searched for it).</p>
</li>
<li><p>Unique: A unique keyword may be more difficult for your competition to target and rank for in organic search results than a more general, common phrase.</p>
</li>
</ul>
<h2 id="heading-how-to-leverage-social-media-for-seo-traffic-and-sales">How to Leverage Social Media for SEO, Traffic, and Sales</h2>
<p>Social media plays an important role in gaining organic traffic in today's SEO landscape. The reason is simple: social media sites are some of the most visited websites.</p>
<p>More importantly, Google and other search engines use social signals to determine a site's relevance for a given keyword. That’s why having your content shared on Facebook, Pinterest, Twitter, and other social media sites can help you rank higher in search results.</p>
<p>It’s important to note that not all social signals have the same influence on SEO. Some signals give a site more authority than others, so it would be wise for you to determine which ones are worth pursuing for your business goals.</p>
<h2 id="heading-how-to-encourage-quality-backlinks-to-your-site">How to Encourage Quality Backlinks to Your Site.</h2>
<p>One of the most effective ways to boost your SEO is to encourage quality backlinks to your site by sharing your blog posts on social networks and encouraging influencers to share your content.</p>
<p>But what is a “backlink”?</p>
<p>A backlink is simply a link from another website that points back to yours.</p>
<p>For example, if this page had a link pointing to Social Media Examiner's homepage, that would be considered a backlink. Backlinks are vital because they show Google that other people or businesses see your site as important and valuable enough to include in their pages.</p>
<p>The more high-quality (important) links you have pointing toward your website, the higher you will rank on search engine results.</p>
<p>Some good strategies for obtaining high-quality links include guest blogging on industry websites, conducting interviews with influencers in your industry, and asking customers/clients if they would be willing to post reviews of your services online.</p>
<p>Once you have some high-quality links coming in, it's important to keep track of them to determine how effective they are at boosting traffic and ranking. You can use tools like Ahrefs or Semrush to do this.</p>
<h2 id="heading-if-you-want-your-website-to-be-searchable-these-tips-will-help-you">If you want your website to be searchable, these tips will help you</h2>
<p>The best way to achieve higher visibility is to make sure your website appears on the first page of search results (better yet, the first three positions).</p>
<p>If your site doesn't show up on that first page, there's a good chance potential customers will never see it. In fact, you can increase traffic to your website significantly if you move from the second page to the first. To do this, you need a strong SEO strategy.</p>
<p>SEO can seem like a daunting topic, but it doesn't have to be. Whether you're already familiar with SEO or not, there's likely something in the above guide you can start implementing right away to better optimize your website for search engines and improve the user experience for potential clients. All you have to do is get started, and the sooner, the better!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Let's Talk Design – How to Speak to a Designer as a Developer ]]>
                </title>
                <description>
                    <![CDATA[ In this conference talk, Magdalena Ostoja-Chyżyńska will not talk about the differences between developers and designers.  Instead of focusing on the differences between the roles and how that might cause friction, she will approach the subject with ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-speak-to-a-designer-as-a-developer-tech-talk/</link>
                <guid isPermaLink="false">66b0a8af5e73cf343a5cc04b</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ designer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ ania kubow ]]>
                </dc:creator>
                <pubDate>Mon, 22 Nov 2021 17:07:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/11/deisgner-dev.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this conference talk, Magdalena Ostoja-Chyżyńska will <strong>not</strong> talk about the differences between developers and designers. </p>
<p>Instead of focusing on the differences between the roles and how that might cause friction, she will approach the subject with a problem-solving attitude, and expand on how to make the relationship work.</p>
<p>And she should know.</p>
<p>Magdalena Ostoja-Chyżyńska is a former frontend developer with 10 years experience in design. During her career she has worked with over 70 developers and enjoyed every second of it.</p>
<p>If you are struggling to get on the same page as a Designer friend, here are some tips she will cover:</p>
<h2 id="heading-how-to-set-up-your-desks">How to Set-up Your Desks</h2>
<p>The desk set up is pretty powerful. Where the Designer sits in relationship to you is imperative for good and strong communication. </p>
<p>Magdalena suggests sitting in a triangulated format, with the Product Owner being the third piece of the puzzle. This way, any dialogue that is shared can be picked up by all parties at all times.</p>
<p>Another suggestion is to form an L shape, where the Analyst is an information broker between the Designer and Developer, keeping both separate from each other and solving any issues that may arise. This formation is very popular in the banking or finance industries.</p>
<p>'The Bridge' is the third set-up. This set-up works for smaller scale startups where the dev team is not so large. It essentially has the Product Owner as the information broker, whilst perhaps taking on some of the traditional roles an Analyst may have. Again, in this situation, the Developer and Designer have limited contact with each other.</p>
<p>Each set-up is powerful, but very unique to your team. Make sure to watch the video to see which is right for you.</p>
<h2 id="heading-how-to-manage-access-between-designers-and-developers">How to Manage Access Between Designers and Developers</h2>
<p>Even if it's in a limited capacity, Magdalena recommends encouraging developers and designers to have a direct form of access to each other. If you hear any of the following, this is a major red flag.</p>
<blockquote>
<p>"You don't need to speak to the designers/developers, you can speak to me."</p>
<p>"Just focus on your code."</p>
</blockquote>
<p>You should always encourage open communication on any team, as gatekeeping can cause toxic workplaces for all involved. If you are in a situation where this is happening, Magdalena suggests taking on the responsibility to fix this.</p>
<h2 id="heading-how-to-handle-developer-designer-meetings">How to Handle Developer-Designer Meetings</h2>
<p>An exemplary developer-designer meeting is a presentation consisting of showing visuals and storytelling. </p>
<p>Designers should not only show what they have designed, but also explain why. By explaining why, the Developer can understand the decisions the designer made in the design process, and buy into the final idea with the same amount of conviction. </p>
<h2 id="heading-respect-between-developers-and-designers">Respect Between Developers and Designers</h2>
<p>Both designer and developer need to respect each other's work. This means that the designer does the design work, and the developer does the development work, not the other way around. This might sound obvious, but the opposite happens more often than you think!</p>
<p>To learn more and dive into each section in more detail, make sure to watch the talk from Magdalena right here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/V-f5e_HP0pY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>This article was written by Ania Kubow in support of the conference talk made by Magdalena Ostoja-Chyżyńska.</p>
<figure><a class="kg-bookmark-container" href="https://www.youtube.com/channel/UC5DNytAJ6_FISueUfzZCVsw"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Code with Ania Kubów</div><div class="kg-bookmark-description">Hello everyone. This channel is run by Ania Kubow. In this channel, I will be teaching you JavaScript,React, HTML, CSS, React-native, Node.js and so much more! A little bit about me:My background is in the financial markets, where I worked as a derivates broker our of University. After starting m…</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.youtube.com/s/desktop/6b151e52/img/favicon_144.png" width="144" height="144" alt="favicon_144" loading="lazy"><span class="kg-bookmark-publisher">YouTube</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://yt3.ggpht.com/ytc/AAUvwnjSRt8sIbeM7P--pHoUDh67sDhaNTCMF_XiNOCvUw=s900-c-k-c0x00ffffff-no-rj" width="900" height="900" alt="AAUvwnjSRt8sIbeM7P--pHoUDh67sDhaNTCMF_XiNOCvUw=s900-c-k-c0x00ffffff-no-rj" loading="lazy"></div></a></figure>







 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
