<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ZenOfCode</title>
    <description>The latest articles on DEV Community by ZenOfCode (@sung_jinwoo_ae9a810f8c46a).</description>
    <link>https://dev.to/sung_jinwoo_ae9a810f8c46a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3086995%2Fa9a8371e-f53d-4344-88fe-1851c3fa286e.png</url>
      <title>DEV Community: ZenOfCode</title>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sung_jinwoo_ae9a810f8c46a"/>
    <language>en</language>
    <item>
      <title>Feature Flags in .NET</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Mon, 05 May 2025 21:05:41 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/feature-flags-in-net-5656</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/feature-flags-in-net-5656</guid>
      <description>&lt;h2&gt;
  
  
  Feature Flags in .NET: A Minimal API with Toggle Power (Using Microsoft.FeatureManagement)
&lt;/h2&gt;

&lt;p&gt;Feature flags give you fine-grained control over your application’s behavior—turn features on or off, run experiments, and roll back instantly without redeploying. In this tutorial, you’ll integrate the first‑party &lt;code&gt;Microsoft.FeatureManagement&lt;/code&gt; package into a .NET Minimal API, source flags from configuration and a custom provider, and explore both attribute- and code-based gating.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use Microsoft.FeatureManagement?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First‑party support&lt;/strong&gt;: Official Microsoft package, integrates with .NET configuration and dependency injection.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible filters&lt;/strong&gt;: Time windows, percentages, custom logic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean architecture alignment&lt;/strong&gt;: Business logic stays decoupled from flag storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Project Setup&lt;/li&gt;
&lt;li&gt;Define Feature Flags in Configuration&lt;/li&gt;
&lt;li&gt;Wire Up Microsoft.FeatureManagement&lt;/li&gt;
&lt;li&gt;Use Flags in Endpoints&lt;/li&gt;
&lt;li&gt;FeatureGate Attributes&lt;/li&gt;
&lt;li&gt;Custom Feature Provider&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new webapi &lt;span class="nt"&gt;-n&lt;/span&gt; FlagsWithMicrosoft
&lt;span class="nb"&gt;cd &lt;/span&gt;FlagsWithMicrosoft
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit your &lt;code&gt;.csproj&lt;/code&gt; to target .NET 6+ and remove the default Weather sample. Then install the feature management package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Microsoft.FeatureManagement
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Define Feature Flags in Configuration
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;appsettings.json&lt;/code&gt;, declare flags under a &lt;code&gt;FeatureManagement&lt;/code&gt; section. This keeps flags in config, supporting environment-based overrides.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appsettings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"FeatureManagement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"NewUI"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"BetaEndpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"TimeLimitedFeature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"EnabledFor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TimeWindow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-05-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"End"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-06-01"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NewUI&lt;/strong&gt;: simple on/off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BetaEndpoint&lt;/strong&gt;: off by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TimeLimitedFeature&lt;/strong&gt;: auto‑enabled during a date range.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wire Up Microsoft.FeatureManagement
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;Program.cs&lt;/code&gt;, register feature management services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.FeatureManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add feature management and built-in filters&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFeatureManagement&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddFeatureFilter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FeatureManagement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FeatureFilters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeWindowFilter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reads &lt;code&gt;FeatureManagement&lt;/code&gt; from configuration and enables the built‑in TimeWindowFilter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Use Flags in Endpoints
&lt;/h2&gt;

&lt;p&gt;You can check flags manually using &lt;code&gt;IFeatureManagerSnapshot&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.FeatureManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/new-ui-data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;FromServices&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;IFeatureManagerSnapshot&lt;/span&gt; &lt;span class="n"&gt;fm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;fm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewUI"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"New UI not available."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Welcome to the new UI!"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above: manual check with &lt;code&gt;IsEnabledAsync()&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  FeatureGate Attributes
&lt;/h2&gt;

&lt;p&gt;For attribute-based gating, add &lt;code&gt;[FeatureGate]&lt;/code&gt; on endpoints or controllers. This automatically returns 404 if the feature is disabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.FeatureManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Attribute on Minimal API endpoint&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/beta-attr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Beta data via attribute"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RequireFeature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BetaEndpoint"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// In MVC controller&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/[controller]"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReportsController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"special"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;FeatureGate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TimeLimitedFeature"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;GetTimeLimitedReport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Time-limited report data"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.RequireFeature("BetaEndpoint")&lt;/code&gt; for Minimal APIs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[FeatureGate("TimeLimitedFeature")]&lt;/code&gt; for controllers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Custom Feature Provider
&lt;/h2&gt;

&lt;p&gt;Implement &lt;code&gt;IFeatureDefinitionProvider&lt;/code&gt; to fetch flags from an external service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Infrastructure/ExternalFeatureProvider.cs&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.FeatureManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.FeatureManagement.FeatureDefinitions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExternalFeatureProvider&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IFeatureDefinitionProvider&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IExternalFlagRepository&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ExternalFeatureProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IExternalFlagRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FeatureDefinition&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetFeatureDefinitionAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;featureName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FetchFlagAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;featureName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FeatureDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;featureName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;enabledFor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&lt;/span&gt; 
                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FeatureFilterConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AlwaysOn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FeatureFilterConfiguration&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FeatureDefinition&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAllFeatureDefinitionsAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FetchAllFlagsAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FeatureDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FeatureFilterConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AlwaysOn"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FeatureFilterConfiguration&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Infrastructure/ExternalFlagRepository.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IExternalFlagRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FlagDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FetchFlagAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FlagDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FetchAllFlagsAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InMemoryExternalFlagRepo&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IExternalFlagRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_store&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"NewUI"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"BetaEndpoint"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FlagDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FetchFlagAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FlagDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FlagDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FetchAllFlagsAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kv&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FlagDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;FlagDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register in &lt;code&gt;Program.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IExternalFlagRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InMemoryExternalFlagRepo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeatureDefinitionProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExternalFeatureProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit test&lt;/strong&gt; attribute endpoints by mocking &lt;code&gt;IFeatureManagerSnapshot&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration test&lt;/strong&gt; custom provider by seeding &lt;code&gt;InMemoryExternalFlagRepo&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example xUnit test for manual check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;NewUI_ReturnsNotFound_WhenFlagOff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IFeatureManagerSnapshot&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;fm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEnabledAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NewUI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAny&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;())).&lt;/span&gt;&lt;span class="nf"&gt;ReturnsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UIEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NotFoundObjectResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Feature flags give you the serenity to release often and safely. Stay Zen.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Official docs: &lt;a href="https://learn.microsoft.com/en-gb/azure/azure-app-configuration/feature-management-dotnet-reference" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-gb/azure/azure-app-configuration/feature-management-dotnet-reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub repo: &lt;a href="https://github.com/microsoft/FeatureManagement-Dotnet" rel="noopener noreferrer"&gt;https://github.com/microsoft/FeatureManagement-Dotnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>api</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Cryptocurrency &amp; Blockchain 101: Bitcoin, Ethereum, dApps, and Beyond</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Sat, 03 May 2025 06:00:00 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/cryptocurrency-blockchain-101-bitcoin-ethereum-dapps-and-beyond-418c</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/cryptocurrency-blockchain-101-bitcoin-ethereum-dapps-and-beyond-418c</guid>
      <description>&lt;p&gt;Cryptocurrency and blockchain technology have shifted from niche curiosities to mainstream innovations powering finance, supply chains, gaming, and more. If you’ve ever wondered what makes Bitcoin different from Ethereum, or how decentralized apps (dApps), DeFi, and Web3 fit together, you’ve come to the right place. Let’s demystify the landscape in a calm, practical ZenOfCode style.  &lt;/p&gt;




&lt;h3&gt;
  
  
  1. What Is Blockchain? (Simple Terms)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shared digital notebook&lt;/strong&gt;: Everyone holds the same copy. Write once, can’t erase.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocks &amp;amp; chain&lt;/strong&gt;: Full pages (blocks) glue shut and link in order.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No single boss&lt;/strong&gt;: The group agrees on new pages.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zen tip&lt;/strong&gt;: Blockchain is trust through transparency—everyone sees the same notebook.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  2. Why Was Blockchain Invented?
&lt;/h3&gt;

&lt;p&gt;Before blockchain, digital records and money relied on banks or companies to verify and store data. In 2008, &lt;strong&gt;Satoshi Nakamoto&lt;/strong&gt; introduced Bitcoin and its blockchain to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;strong&gt;peer‑to‑peer&lt;/strong&gt; transactions without banks.
&lt;/li&gt;
&lt;li&gt;Guarantee &lt;strong&gt;immutability&lt;/strong&gt;—once recorded, transactions can’t be altered.
&lt;/li&gt;
&lt;li&gt;Allow &lt;strong&gt;open participation&lt;/strong&gt;—anyone can join, verify, and view data.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This created a “trustless” system: you don’t trust a single authority, the network enforces honesty.  &lt;/p&gt;




&lt;h3&gt;
  
  
  3. Bitcoin: The Digital Gold
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Launch&lt;/strong&gt;: 2009 by Satoshi Nakamoto
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consensus&lt;/strong&gt;: Proof‑of‑Work (PoW)—miners solve puzzles to add blocks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supply cap&lt;/strong&gt;: 21 million BTC (deflationary)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use case&lt;/strong&gt;: Store of value, peer‑to‑peer cash
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitcoin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Consensus&lt;/td&gt;
&lt;td&gt;Proof‑of‑Work (PoW)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supply cap&lt;/td&gt;
&lt;td&gt;21 million BTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block time&lt;/td&gt;
&lt;td&gt;~10 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart contracts&lt;/td&gt;
&lt;td&gt;Very limited (scripts)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: PoW secures the network but uses significant energy.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  4. Ethereum: The World Computer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Launch&lt;/strong&gt;: 2015 by Vitalik Buterin et al.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart contracts&lt;/strong&gt;: Self‑executing code stored on‑chain.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EVM&lt;/strong&gt;: The sandboxed “computer” that runs smart contracts.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consensus&lt;/strong&gt;: Switched to Proof‑of‑Stake (PoS) in 2022’s “Merge” (‑99% energy).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Ethereum&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Consensus&lt;/td&gt;
&lt;td&gt;Proof‑of‑Stake (PoS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supply policy&lt;/td&gt;
&lt;td&gt;No fixed cap; dynamic issuance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block time&lt;/td&gt;
&lt;td&gt;~12–14 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart contracts&lt;/td&gt;
&lt;td&gt;First‑class citizens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: PoS uses far less energy and allows token‑holders to secure the network.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  5. Other Blockchains at a Glance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Network&lt;/th&gt;
&lt;th&gt;Consensus&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Notable dApps / Projects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BSC (Binance Smart Chain)&lt;/td&gt;
&lt;td&gt;PoSA (Staked Authority)&lt;/td&gt;
&lt;td&gt;Low‑fee DeFi&lt;/td&gt;
&lt;td&gt;PancakeSwap, Venus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solana&lt;/td&gt;
&lt;td&gt;PoH + PoS&lt;/td&gt;
&lt;td&gt;High throughput, low latency&lt;/td&gt;
&lt;td&gt;Serum, Audius&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polkadot&lt;/td&gt;
&lt;td&gt;Nominated PoS (NPoS)&lt;/td&gt;
&lt;td&gt;Interoperability (parachains)&lt;/td&gt;
&lt;td&gt;Acala, Moonbeam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avalanche&lt;/td&gt;
&lt;td&gt;Snow-based PoS&lt;/td&gt;
&lt;td&gt;Scalability and subnets&lt;/td&gt;
&lt;td&gt;Trader Joe, Benqi&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Analogy&lt;/strong&gt;: Each blockchain is a café—pick the vibe and speed you like.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  6. Decentralized Apps (dApps)
&lt;/h3&gt;

&lt;p&gt;A dApp is like a vending machine on the blockchain:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You insert coins (crypto).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart contract runs automatically.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You get your snack (service) with no middleman.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Core parts&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On‑chain smart contract (backend logic)
&lt;/li&gt;
&lt;li&gt;Web/mobile UI (frontend)
&lt;/li&gt;
&lt;li&gt;Wallet (e.g., MetaMask) to connect
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Popular categories&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DeFi&lt;/strong&gt;: Aave, Uniswap
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NFT marketplaces&lt;/strong&gt;: OpenSea
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gaming &amp;amp; metaverse&lt;/strong&gt;: Axie Infinity
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DAOs&lt;/strong&gt;: Aragon, Snapshot
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  7. What Is DeFi?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Decentralized Finance (DeFi)&lt;/strong&gt; uses blockchain to offer financial services without banks.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lending &amp;amp; borrowing&lt;/strong&gt;: You lock crypto as collateral to borrow assets (Aave, Compound).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decentralized exchanges (DEXs)&lt;/strong&gt;: Trade assets directly with others (Uniswap, SushiSwap).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yield farming&lt;/strong&gt;: Earn rewards by providing liquidity.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stablecoins&lt;/strong&gt;: Crypto pegged to fiat (USDC, DAI) for price stability.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zen tip&lt;/strong&gt;: DeFi is like an automated market of money lego—compose services without permission.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  8. What Is Web3 &amp;amp; Its Evolution?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Web1 (1990s–early 2000s):&lt;/strong&gt; Read‑only web—static pages and basic hyperlinks.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Web2 (mid 2000s–today):&lt;/strong&gt; Read‑write web—dynamic, social, centralized platforms (Facebook, YouTube).&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Web3 (emerging):&lt;/strong&gt; Read‑write‑own web—decentralized, user‑owned networks powered by blockchain.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key ideas&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ownership&lt;/strong&gt;: Users truly own data and digital assets via wallets.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissionless&lt;/strong&gt;: Anyone can build and use services without gatekeepers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trustless interactions&lt;/strong&gt;: Smart contracts enforce rules rather than companies.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Evolution summary&lt;/strong&gt;: Web1 gave information, Web2 enabled interaction, Web3 returns control to users.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  9. Vital Concepts to Know
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wallets&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hot wallets&lt;/strong&gt; (online): MetaMask, Trust Wallet
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold wallets&lt;/strong&gt; (offline): Ledger, Trezor
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Exchanges&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Centralized: Coinbase, Binance
&lt;/li&gt;
&lt;li&gt;Decentralized: Uniswap, PancakeSwap
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Gas fees&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Payment to process transactions (varies by network load).
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Private key vs. seed phrase&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Private key: Your secret password to spend crypto.
&lt;/li&gt;
&lt;li&gt;Seed phrase: Backup to recover your wallet.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security Zen&lt;/strong&gt;: Never share your private key or seed phrase—treat it like your toothbrush.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  10. Getting Started: Tools &amp;amp; Tips
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explore&lt;/strong&gt; on testnets (Ropsten, Goerli) before mainnet.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use faucets&lt;/strong&gt; to get test tokens.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simulate&lt;/strong&gt; with local chains (Ganache).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit&lt;/strong&gt; contracts (MythX, CertiK) before deploying.
&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Blockchain is simply a shared, unchangeable notebook for recording transactions without a central boss. Bitcoin gave us digital gold; Ethereum opened programmable finance; DeFi unlocked permissionless money legos; and Web3 returns data and asset ownership to users. Armed with this understanding—and the right wallets, tools, and security habits—you’re ready to explore and build in the decentralized world.  &lt;/p&gt;

&lt;p&gt;Stay calm, stay curious, and code (and transact) on.  &lt;/p&gt;




&lt;p&gt;&lt;em&gt;All information is accurate as of May 2025. Always do your own research before investing or deploying smart contracts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>web3</category>
      <category>bitcoin</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Vibe Coding: The Calm Revolution in Developer Workflows</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Wed, 30 Apr 2025 05:00:00 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/vibe-coding-the-calm-revolution-in-developer-workflows-d04</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/vibe-coding-the-calm-revolution-in-developer-workflows-d04</guid>
      <description>&lt;h2&gt;
  
  
  Vibe Coding: The Calm Revolution in Developer Workflows
&lt;/h2&gt;

&lt;p&gt;In the ever-evolving landscape of software development, 2025 has ushered in a paradigm shift known as &lt;strong&gt;vibe coding&lt;/strong&gt;. Coined by AI researchers, vibe coding represents a transition from traditional, syntax-heavy programming to a more intuitive, AI-assisted approach where developers articulate their intentions in natural language, and AI tools generate the corresponding code.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Vibe Coding?
&lt;/h3&gt;

&lt;p&gt;At its core, vibe coding is about conveying the desired functionality or behavior of software through conversational prompts. Instead of meticulously writing out code line by line, developers describe what they want the software to do, and AI models translate these descriptions into executable code. This method emphasizes clarity of thought and design over manual coding, allowing developers to focus on the “what” rather than the “how.”&lt;/p&gt;

&lt;h3&gt;
  
  
  The Tools Empowering Vibe Coding
&lt;/h3&gt;

&lt;p&gt;Several AI tools have emerged to facilitate vibe coding, catering to both novice and experienced developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Copilot&lt;/strong&gt;: Provides code suggestions based on natural language comments and code context.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replit&lt;/strong&gt;: Offers an interactive coding environment with AI assistance for real-time code generation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor&lt;/strong&gt;: An AI-first code editor designed to streamline the vibe coding experience.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windsurf&lt;/strong&gt;: Tailored for advanced users, offering sophisticated AI-driven code generation capabilities.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools integrate seamlessly into existing workflows, enhancing productivity without overwhelming the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Vibe Coding
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Productivity&lt;/strong&gt;: Reduces boilerplate coding, letting developers focus on design and problem-solving.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower Barrier to Entry&lt;/strong&gt;: Enables contributors with limited coding experience to articulate ideas in plain language.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rapid Prototyping&lt;/strong&gt;: Transforms concepts into working prototypes quickly, facilitating faster iteration.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus on Intent&lt;/strong&gt;: Shifts emphasis to desired outcomes and user experience rather than syntax details.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenges and Considerations
&lt;/h3&gt;

&lt;p&gt;While vibe coding offers many advantages, it also brings considerations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understanding Generated Code&lt;/strong&gt;: Developers must review and understand AI-generated code to ensure maintainability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Concerns&lt;/strong&gt;: AI models can introduce vulnerabilities if outputs aren’t carefully audited.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintaining Skills&lt;/strong&gt;: Over-reliance on AI may erode fundamental coding abilities; balance is key.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Embracing the Zen of Vibe Coding
&lt;/h3&gt;

&lt;p&gt;Vibe coding aligns perfectly with ZenOfCode’s principles: simplicity, clarity, and intentionality. By abstracting away syntax complexities, developers engage more deeply with the essence of their work, crafting software that is both functional and elegant.&lt;/p&gt;

&lt;p&gt;As we integrate AI into our workflows, a balanced approach—leveraging AI for efficiency while preserving human insight—will define the next era of calm, focused development.&lt;/p&gt;




&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>softwaredevelopment</category>
      <category>aidev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Crafting a Minimalist File Upload API with Node.js and Express</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Mon, 28 Apr 2025 17:00:00 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/crafting-a-minimalist-file-upload-api-with-nodejs-and-express-1dob</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/crafting-a-minimalist-file-upload-api-with-nodejs-and-express-1dob</guid>
      <description>&lt;h2&gt;
  
  
  Crafting a Minimalist File Upload API with Node.js and Express
&lt;/h2&gt;

&lt;p&gt;Need a simple file upload API without the overhead of a full-blown framework? Today, we’ll craft a calm, minimalist solution using Node.js and Express.&lt;/p&gt;

&lt;p&gt;Just pure backend bliss.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why Keep It Simple?&lt;/li&gt;
&lt;li&gt;Project Setup&lt;/li&gt;
&lt;li&gt;Building the API&lt;/li&gt;
&lt;li&gt;Testing the Upload&lt;/li&gt;
&lt;li&gt;Next Steps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Keep It Simple?
&lt;/h2&gt;

&lt;p&gt;A basic file upload service is a common sidekick:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Upload profile pictures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Submit documents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store small attachments&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using only &lt;strong&gt;Node.js + Express&lt;/strong&gt; with a sprinkle of &lt;strong&gt;Multer&lt;/strong&gt;, we can avoid bloat and focus on clarity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;Let’s spin up a fresh project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;file-upload-api
&lt;span class="nb"&gt;cd &lt;/span&gt;file-upload-api
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express multer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create an entry file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Building the API
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create the Express Server
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// index.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Set storage engine&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;diskStorage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./uploads/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Middleware&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Upload endpoint&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/upload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No file uploaded.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Start server&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running on http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create the Express Server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Make sure there’s a folder to store uploaded files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;uploads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing the Upload
&lt;/h2&gt;

&lt;p&gt;You can test the API using Postman or cURL: Using cURL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"file=@/path/to/your/file.jpg"&lt;/span&gt; http://localhost:3000/upload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"filename"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"timestamp-file.jpg"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the file should appear inside the /uploads directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Postman:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new POST request to &lt;a href="http://localhost:3000/upload" rel="noopener noreferrer"&gt;http://localhost:3000/upload&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Under “Body” select “form-data”&lt;/li&gt;
&lt;li&gt;Add a field named file&lt;/li&gt;
&lt;li&gt;Attach a file&lt;/li&gt;
&lt;li&gt;Hit Send!&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;This calm little project can be expanded:&lt;br&gt;
    *   Add file type restrictions (only images, only PDFs)&lt;br&gt;
    *   Limit file size&lt;br&gt;
    *   Integrate cloud storage (S3, Azure Blob)&lt;br&gt;
    *   Add simple authentication&lt;/p&gt;




&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>node</category>
      <category>webdev</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Building a RESTful To-Do API with Clean Architecture in Python</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Mon, 28 Apr 2025 13:40:00 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/building-a-restful-to-do-api-with-clean-architecture-in-python-48am</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/building-a-restful-to-do-api-with-clean-architecture-in-python-48am</guid>
      <description>&lt;h2&gt;
  
  
  Building a RESTful To-Do API with Clean Architecture in Python
&lt;/h2&gt;

&lt;p&gt;APIs power modern apps, but without good structure they become tangled. In this tutorial, you’ll learn how to create a simple To-Do API in Python—organized with clean architecture patterns for maintainability and testability.&lt;/p&gt;




&lt;h3&gt;
  
  
  Table of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
What You’ll Build
&lt;/li&gt;
&lt;li&gt;
Why Clean Architecture?
&lt;/li&gt;
&lt;li&gt;
Project Structure
&lt;/li&gt;
&lt;li&gt;
Step 1: Define Entities
&lt;/li&gt;
&lt;li&gt;
Step 2: Use Cases (Business Logic)
&lt;/li&gt;
&lt;li&gt;
Step 3: Interface Adapters (Controllers &amp;amp; Repos)
&lt;/li&gt;
&lt;li&gt;
Step 4: Framework &amp;amp; Drivers (Flask)
&lt;/li&gt;
&lt;li&gt;
Step 5: Testing
&lt;/li&gt;
&lt;li&gt;Next Steps&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What You’ll Build
&lt;/h3&gt;

&lt;p&gt;A minimal To-Do API with endpoints to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a task
&lt;/li&gt;
&lt;li&gt;List all tasks
&lt;/li&gt;
&lt;li&gt;Update a task’s status
&lt;/li&gt;
&lt;li&gt;Delete a task
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All following clean architecture layers so code remains decoupled and easy to evolve.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Clean Architecture?
&lt;/h3&gt;

&lt;p&gt;Clean architecture separates concerns into layers:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entities&lt;/strong&gt;: Core business objects
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Cases&lt;/strong&gt;: Business rules
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interface Adapters&lt;/strong&gt;: Convert data between layers
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework &amp;amp; Drivers&lt;/strong&gt;: External tools (e.g., Flask)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benefits:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testable business logic
&lt;/li&gt;
&lt;li&gt;Easier to swap frameworks or databases
&lt;/li&gt;
&lt;li&gt;Clear dependency rule: outer layers depend on inner ones&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;📂 todo-api
 ├── 📂 entities
 │    └── 📄 task.py
 ├── 📂 use_cases
 │    └── 📄 task_manager.py
 ├── 📂 adapters
 │    ├── 📄 repository.py
 │    └── 📄 controller.py
 ├── 📂 infrastructure
 │    └── 📄 flask_app.py
 └── 📂 tests
      └── 📄 test_use_cases.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 1: Define Entities
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# entities/task.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid4&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Task holds data and invariants.&lt;/li&gt;
&lt;li&gt;create() ensures every task gets a unique ID.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 2: Use Cases (Business Logic)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# use_cases/task_manager.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;entities.task&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;adapters.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskRepository&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaskManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TaskRepository&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_tasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mark_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Business rules live here—no Flask or database code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 3: Interface Adapters
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# adapters/repository.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;entities.task&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaskRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# adapters/controller.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Blueprint&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;use_cases.task_manager&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskManager&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;adapters.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskRepository&lt;/span&gt;

&lt;span class="n"&gt;bp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Blueprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TaskRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TaskManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@bp.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/tasks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;

&lt;span class="nd"&gt;@bp.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/tasks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_tasks&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_tasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@bp.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/tasks/&amp;lt;id&amp;gt;/complete&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PATCH&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;complete_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mark_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nd"&gt;@bp.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/tasks/&amp;lt;id&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DELETE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;204&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 4: Framework and Drivers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# infrastructure/flask_app.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;adapters.controller&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bp&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_app&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_blueprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/api&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Runs on &lt;a href="http://localhost:5000/api/tasks" rel="noopener noreferrer"&gt;http://localhost:5000/api/tasks&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Testing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_use_cases.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;use_cases.task_manager&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskManager&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;adapters.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskRepository&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;TaskManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TaskRepository&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_and_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write blog post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_tasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write blog post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Focus on use cases—no need to spin up Flask.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Persist to a real database (SQLAlchemy adapter).&lt;/li&gt;
&lt;li&gt;Add authentication (JWT middleware).&lt;/li&gt;
&lt;li&gt;Expand entities (due dates, priorities).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cleancode</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>How I Use ChatGPT to Refactor Smarter, Not Harder</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Sat, 26 Apr 2025 21:00:00 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/how-i-use-chatgpt-to-refactor-smarter-not-harder-385d</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/how-i-use-chatgpt-to-refactor-smarter-not-harder-385d</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📬 Originally published on &lt;a href="https://zencoding.hashnode.dev/how-i-use-chatgpt-to-refactor-smarter-not-harder" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
I'm reposting here to share with more devs — feedback welcome!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How I Use ChatGPT to Refactor Smarter, Not Harder
&lt;/h2&gt;

&lt;p&gt;Refactoring old code feels like walking through a minefield. One wrong move and &lt;em&gt;boom&lt;/em&gt; — tests fail, bugs spawn, and your day is ruined.&lt;/p&gt;

&lt;p&gt;Here’s how I use &lt;strong&gt;ChatGPT&lt;/strong&gt; as a legit refactoring assistant — not just a novelty.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Step 1: Let It Explain Old Code
&lt;/h2&gt;

&lt;p&gt;Before I even touch anything, I drop chunks into ChatGPT and ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Explain what this code does and if there are any smells.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It helps me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Understand legacy patterns&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spot anti-patterns&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See opportunities to clean up&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Step 2: Ask for a Refactored Version
&lt;/h2&gt;

&lt;p&gt;Once I know what it does, I ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Refactor this code to use cleaner naming and extract logic to smaller methods.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You’ll get suggestions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Breaking up long methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extracting reusable logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better naming&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧼 Step 3: Keep the Parts You Like
&lt;/h2&gt;

&lt;p&gt;ChatGPT isn’t perfect — but it’s a powerful second brain.&lt;/p&gt;

&lt;p&gt;Use its suggestions as a starting point, then tweak it to your taste.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Bonus: Custom Prompts That Work
&lt;/h2&gt;

&lt;p&gt;Here are a few prompts I’ve saved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;“Refactor this async method to improve readability and keep exception safety.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Can you convert this into a more testable service class?”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Suggest a more SOLID-compliant structure for this code.”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Tools I Pair With It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; – for inline suggestions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TestGPT&lt;/strong&gt; – helps generate test cases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prettier&lt;/strong&gt; – keep things neat post-refactor&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ChatGPT can help you read, refactor, and rethink your code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s not cheating — it’s upgrading your solo dev experience&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You still drive — AI just helps navigate&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>programming</category>
      <category>refactoring</category>
      <category>productivity</category>
    </item>
    <item>
      <title>10 VS Code Extensions That Actually Save You Time (Not Just Look Cool)</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Fri, 25 Apr 2025 21:00:00 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/10-vs-code-extensions-that-actually-save-you-time-not-just-look-cool-2a18</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/10-vs-code-extensions-that-actually-save-you-time-not-just-look-cool-2a18</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📬 Originally published on &lt;a href="https://zencoding.hashnode.dev/10-vs-code-extensions-that-actually-save-you-time-not-just-look-cool" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
I'm reposting here to share with more devs — feedback welcome!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  10 VS Code Extensions That Actually Save You Time (Not Just Look Cool)
&lt;/h2&gt;

&lt;p&gt;VS Code is 🔥 by default — but the right extensions can take you from &lt;em&gt;dev mode&lt;/em&gt; to &lt;em&gt;flow state&lt;/em&gt;. Here are 10 extensions I use regularly that &lt;em&gt;actually make me faster&lt;/em&gt;, not just flashy.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 1. &lt;strong&gt;GitLens&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Shows git blame, history, authorship inline.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Stop asking “Who wrote this?” — GitLens shows it in your editor.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📁 2. &lt;strong&gt;Path Intellisense&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Auto-suggests file paths as you type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: No more guessing folder structures or mistyping filenames.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🪛 3. &lt;strong&gt;REST Client&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Send HTTP requests without leaving your editor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Great for quick API testing — faster than Postman for small stuff.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 4. &lt;strong&gt;TODO Highlight&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Highlights your &lt;code&gt;// TODO:&lt;/code&gt; and &lt;code&gt;// FIXME:&lt;/code&gt; comments.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Keeps dev debt visible before it becomes tech debt.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔄 5. &lt;strong&gt;Prettier&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Auto-formats your code on save.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Consistency, peace of mind, and zero arguments in PRs.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⚙️ 6. &lt;strong&gt;Error Lens&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Shows linting + runtime errors directly in-line.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Fix bugs faster with less clicking.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔒 7. &lt;strong&gt;dotenv&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Syntax highlighting for &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: So small but so helpful. Especially for backend projects.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧱 8. &lt;strong&gt;Bracket Pair Colorizer 2&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Color-codes matching brackets.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Essential for nested functions, JSX, or regex hell.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧭 9. &lt;strong&gt;CodeSnap&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Take beautiful code screenshots.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Perfect for blogs, tweets, or docs.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🤖 10. &lt;strong&gt;GitHub Copilot&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You know the deal.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 Why it matters: Not just autocomplete — it gives full suggestions that can unblock you.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧠 TL;DR
&lt;/h2&gt;

&lt;p&gt;Install a few of these today. Don’t go plugin crazy — but the right tools &lt;em&gt;compound&lt;/em&gt; your speed every day.&lt;/p&gt;




&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stop Overengineering: Clean Architecture for Real-World APIs</title>
      <dc:creator>ZenOfCode</dc:creator>
      <pubDate>Fri, 25 Apr 2025 02:29:40 +0000</pubDate>
      <link>https://dev.to/sung_jinwoo_ae9a810f8c46a/stop-overengineering-clean-architecture-for-real-world-apis-2n9m</link>
      <guid>https://dev.to/sung_jinwoo_ae9a810f8c46a/stop-overengineering-clean-architecture-for-real-world-apis-2n9m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📬 Originally published on &lt;a href="https://zencoding.hashnode.dev/stop-overengineering-clean-architecture-for-real-world-apis" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
I'm reposting here to share with more devs — feedback welcome!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Stop Overengineering: Clean Architecture for Real-World APIs
&lt;/h2&gt;

&lt;p&gt;If you’ve ever opened a codebase and thought &lt;em&gt;“WTF is all this layering?”&lt;/em&gt;, you’re not alone. Clean architecture is powerful — but it’s easy to take it too far and turn your API into a slow-motion car crash of abstraction.&lt;/p&gt;

&lt;p&gt;In this post, I’ll break down a practical version of clean architecture for building APIs that are &lt;strong&gt;clean, scalable, and easy to ship&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ What is “Clean Architecture”... really?
&lt;/h2&gt;

&lt;p&gt;At its core:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Business logic should live in one place&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External systems (DBs, APIs, UI) are &lt;em&gt;details&lt;/em&gt;, not your core&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your code should read like the use-case it solves&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧱 Layers That Actually Matter
&lt;/h2&gt;

&lt;p&gt;Here’s a simple structure that works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
  /Application  ← Business logic (use cases, services)
  /Domain       ← Models and rules
  /Infrastructure ← Database, API clients
  /Web          ← Controllers, HTTP handlers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No fluff. No 13 interfaces for a method that sends an email.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧼 Keep These Rules in Mind
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Use Interfaces Where You Actually Swap Implementations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you’re never going to mock or switch your &lt;code&gt;EmailService&lt;/code&gt;, don’t create &lt;code&gt;IEmailSenderFactoryAdapterV2&lt;/code&gt;. Keep it simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Your Controllers Should Do Almost Nothing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No logic in the controller. Just call your use case, handle the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateUserRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_createUserUseCase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Dependency Injection is a Tool, Not a Religion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Wire up only what you need. Avoid over-wiring things you’ll never use.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Real-World Example: Creating a User API
&lt;/h2&gt;

&lt;p&gt;Here’s how a &lt;em&gt;real&lt;/em&gt; CreateUser use case might flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Controller gets the HTTP request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls &lt;code&gt;CreateUserUseCase&lt;/code&gt; from &lt;code&gt;Application&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;CreateUserUseCase&lt;/code&gt; validates + handles logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls &lt;code&gt;UserRepository&lt;/code&gt; (in &lt;code&gt;Infrastructure&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns a result&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Boom. Clean. Easy to test. Easy to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don’t overengineer for problems you don’t have&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep things layered — but practical&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean code is readable, not academic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code Zen = Calm Code = Happy Dev 😌&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🧘‍♂️ Like this kind of content?&lt;br&gt;&lt;br&gt;
Follow my dev blog → &lt;a href="https://zencoding.hashnode.dev" rel="noopener noreferrer"&gt;ZenOfCode&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Or drop me a follow here on Dev.to 💬&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>dotnet</category>
      <category>cleanarchitecture</category>
    </item>
  </channel>
</rss>
