<?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: Muhammad Bilal Khalid</title>
    <description>The latest articles on DEV Community by Muhammad Bilal Khalid (@mbkhalid23).</description>
    <link>https://dev.to/mbkhalid23</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%2F842045%2F9cc0241b-6c1d-4df7-937a-220cbf2bb187.png</url>
      <title>DEV Community: Muhammad Bilal Khalid</title>
      <link>https://dev.to/mbkhalid23</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbkhalid23"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Tue, 04 Nov 2025 11:14:57 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/-1pkg</link>
      <guid>https://dev.to/mbkhalid23/-1pkg</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l" class="crayons-story__hidden-navigation-link"&gt;Mastering the ‘O’ in SOLID: Applying the Open/Closed Principle in Real-World Code&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mbkhalid23" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F842045%2F9cc0241b-6c1d-4df7-937a-220cbf2bb187.png" alt="mbkhalid23 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mbkhalid23" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Muhammad Bilal Khalid
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Muhammad Bilal Khalid
                
              
              &lt;div id="story-author-preview-content-2983821" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mbkhalid23" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F842045%2F9cc0241b-6c1d-4df7-937a-220cbf2bb187.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Muhammad Bilal Khalid&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 3 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l" id="article-link-2983821"&gt;
          Mastering the ‘O’ in SOLID: Applying the Open/Closed Principle in Real-World Code
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/architecture"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;architecture&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dotnet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dotnet&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/computerscience"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;computerscience&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>programming</category>
      <category>architecture</category>
      <category>dotnet</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Mastering the ‘O’ in SOLID: Applying the Open/Closed Principle in Real-World Code</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Mon, 03 Nov 2025 07:45:00 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l</link>
      <guid>https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Adding features shouldn’t feel like defusing a bomb. Here’s how the Open/Closed Principle (OCP) helps you extend your code without changing what already works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You’ve probably done this before:&lt;/p&gt;

&lt;p&gt;You needed to add a small feature so you end up opening a class and writing &lt;em&gt;yet another&lt;/em&gt; &lt;code&gt;if&lt;/code&gt; statement. A couple of weeks later, you had to add another one. And then another. And before you know it, the code that once felt clean turns into a mess of conditions.&lt;/p&gt;

&lt;p&gt;That’s the kind of slow creep the &lt;strong&gt;Open/Closed Principle&lt;/strong&gt; is meant to prevent.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Side note: we explored the &lt;a href="https://dev.to/mbkhalid23/solid-series-1-single-responsibility-principle-4pbj"&gt;&lt;strong&gt;&lt;em&gt;Single Responsibility Principle&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; in the previous part of this series,  worth checking out if you missed it!)&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is the Open/Closed Principle❓
&lt;/h2&gt;

&lt;p&gt;The Open/Closed Principle (OCP) is one of the five core principles of SOLID design. It states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Software should be open for extension but closed for modification.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simpler terms: you should be able to add new behavior without changing the existing code.&lt;/p&gt;

&lt;p&gt;That doesn’t mean your code never changes. It means the parts that already work shouldn’t have to be touched every time something new is added.&lt;/p&gt;

&lt;p&gt;Let's exapand on this a bit. Why we need to have our code open for extension but close for modification?&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why Apply the Open/Closed Principle?
&lt;/h2&gt;

&lt;p&gt;Because code that changes too often becomes risky, not just technically, but mentally too. You start avoiding updates, afraid of breaking something that already works. I’ve experienced this first-hand!&lt;/p&gt;

&lt;p&gt;Even a small &lt;code&gt;if&lt;/code&gt; in the wrong place can create bugs or unexpected behavior. That fear of touching code slows everything down.&lt;/p&gt;

&lt;p&gt;OCP helps you avoid that by encouraging you to add new behavior without touching old logic. It keeps the stable parts of your code safe and untouched.&lt;/p&gt;

&lt;p&gt;This leads to cleaner structure, easier testing, and a codebase that grows without becoming fragile.&lt;/p&gt;

&lt;p&gt;Let's understand this with the help of a quick example.&lt;/p&gt;




&lt;h2&gt;
  
  
  📉 What Happens When You Don’t Apply OCP?
&lt;/h2&gt;

&lt;p&gt;Let’s say you’re building a discount engine for an e-commerce platform. Initially, you just support a flat discount:&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;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DiscountCalculator&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;decimal&lt;/span&gt; &lt;span class="nf"&gt;ApplyDiscount&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;customerType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&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="n"&gt;customerType&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Regular"&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="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.95m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 5% off  &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;amount&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;Now marketing wants loyalty discounts. Then seasonal promos. Then discounts based on cart value, customer tier, or coupon codes. You start stacking conditions:&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerType&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Gold"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="c1"&gt;// 15% off  &lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="c1"&gt;// 10% off  &lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;couponCode&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"SUMMER2025"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="c1"&gt;// 20% off  &lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you know it, logic starts overlapping. You need flags to apply or skip certain discounts. And the order of these conditions becomes critical. One bug, and you end up giving 3 discounts instead of 1.&lt;/p&gt;

&lt;p&gt;All you wanted was a clean way to apply business rules. Instead, you built a tightly-coupled maze.&lt;/p&gt;

&lt;p&gt;Let's now solve this maze by the power of Open Closed Principle!&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ How to Apply the Open Closed Principle?
&lt;/h2&gt;

&lt;p&gt;You make your code extensible by introducing &lt;strong&gt;abstractions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding every rule into the &lt;code&gt;DiscountCalculator&lt;/code&gt; with &lt;code&gt;if&lt;/code&gt; statements, we shift the responsibility of applying individual discounts to their own dedicated classes. &lt;/p&gt;

&lt;p&gt;Each rule implements a shared interface, &lt;code&gt;IDiscountRule&lt;/code&gt;, which defines when the rule applies and how it calculates the discount.&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;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDiscountRule&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cart&lt;/span&gt; &lt;span class="n"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
        &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&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;This means each rule is completely self-contained. It knows when it should run and how to apply its logic. The calculator doesn’t care about what the rules are, it just loops through them and applies what matches.&lt;/p&gt;

&lt;p&gt;You want to give loyalty discount? Simple, add a new implementation for the &lt;code&gt;IDiscountRule&lt;/code&gt; interface.&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;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoyaltyDiscount&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDiscountRule&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="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cart&lt;/span&gt; &lt;span class="n"&gt;cart&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;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Gold"&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;decimal&lt;/span&gt; &lt;span class="nf"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&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;amount&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.85m&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;A discount for cart with high value? Add another implementation.&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;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighValueCartDiscount&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDiscountRule&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="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cart&lt;/span&gt; &lt;span class="n"&gt;cart&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;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Total&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1000&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;decimal&lt;/span&gt; &lt;span class="nf"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&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;amount&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.9m&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;Just like that you can introduce as many discount rules as you'd like. And the great thing is no one implementation affects another one. They are all separate.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DiscountCalculator&lt;/code&gt; now becomes a simple orchestrator. It doesn’t contain any discount rules itself. It just loops through all available rules and applies them if they match.&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;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DiscountCalculator&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;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDiscountRule&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_rules&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;DiscountCalculator&lt;/span&gt;&lt;span class="p"&gt;(&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;IDiscountRule&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="n"&gt;_rules&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rules&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;decimal&lt;/span&gt; &lt;span class="nf"&gt;ApplyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cart&lt;/span&gt; &lt;span class="n"&gt;cart&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;amount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
            &lt;span class="k"&gt;foreach&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;rule&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_rules&lt;/span&gt;&lt;span class="p"&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="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
                &lt;span class="p"&gt;{&lt;/span&gt;  
                    &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;amount&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;Want to support a new type of discount next month? Just create a new class that implements &lt;code&gt;IDiscountRule&lt;/code&gt;, register it with your dependency injection container, and you’re done. You never touch the &lt;code&gt;DiscountCalculator&lt;/code&gt; class again.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⏩ When Is It Okay to Skip OCP?
&lt;/h2&gt;

&lt;p&gt;Now here a very important thing to understand. &lt;strong&gt;Not every situation calls for this level of abstraction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the code is unlikely to change or grow, applying OCP too early might just create unnecessary layers. Why solve a problem you don’t have yet? Keep things simple when they genuinely are.&lt;/p&gt;

&lt;p&gt;But when your code deals with rules, workflows, or business logic that could evolve, that’s when OCP shines. It helps you balance simplicity today with flexibility tomorrow.&lt;/p&gt;

&lt;p&gt;Remember, OCP is just one tool in your design toolbox. It’s not a silver bullet. Use it when it makes sense . Not every problem needs it, and sometimes the problem doesn’t even exist yet.&lt;/p&gt;

&lt;p&gt;Whenever in doubt follow this &lt;a href="https://medium.com/stackademic/stop-overengineering-the-3-question-test-that-saves-weeks-of-wasted-work-ea072304df9a" rel="noopener noreferrer"&gt;&lt;em&gt;&lt;strong&gt;3 Questions Test&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; I always ask myself before adding any layer of abstraction. It helps me avoid over-engineering solutions and might help you too!&lt;/p&gt;




&lt;p&gt;💭 What about you ? where have you seen the Open/Closed Principle make the biggest impact in your own codebase? Or maybe where you wish it had been applied?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Next up:&lt;/strong&gt; &lt;em&gt;Liskov Substitution Principle&lt;/em&gt; when polymorphism quietly breaks your code.&lt;/p&gt;




&lt;p&gt;Hi, I’m Bilal 👋, a .NET developer sharing what I learn about building software, thinking in systems, and writing clean, practical code.&lt;/p&gt;

&lt;p&gt;If you’re exploring similar ideas, let’s connect and learn together.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>dotnet</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Single Responsibility Principle sounds very simple but most devs get it wrong. SRP was never about a class doing one thing only. It's about fulfilling a single responsibility. But what does a single responsibility actually stand for?</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Sun, 02 Nov 2025 06:35:52 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/single-responsibility-principle-sounds-very-simple-but-most-devs-get-it-wrong-srp-was-never-about-58m2</link>
      <guid>https://dev.to/mbkhalid23/single-responsibility-principle-sounds-very-simple-but-most-devs-get-it-wrong-srp-was-never-about-58m2</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/mbkhalid23" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F842045%2F9cc0241b-6c1d-4df7-937a-220cbf2bb187.png" alt="mbkhalid23"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/mbkhalid23/stop-overengineering-my-3-step-framework-that-helps-save-weeks-of-wasted-work-4hnj" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Stop Adding Unnecessary Abstractions: My 3-Question Kill-Switch for Over-Engineering&lt;/h2&gt;
      &lt;h3&gt;Muhammad Bilal Khalid ・ Oct 27&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#softwaredevelopment&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#softwareengineering&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
    <item>
      <title>Demystifying the Single Responsibility Principle: It’s Not What You Think</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Wed, 29 Oct 2025 19:13:44 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/solid-series-1-single-responsibility-principle-4pbj</link>
      <guid>https://dev.to/mbkhalid23/solid-series-1-single-responsibility-principle-4pbj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Clean code is not overengineering. It’s making sure small changes actually feel small when the time comes.” — &lt;em&gt;Me, after wrestling with my own code&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hi! Are you one of those people who just can’t stand SOLID principles?&lt;/p&gt;

&lt;p&gt;Don't worry, I totally get you! They can be really confusing at first. &lt;/p&gt;

&lt;p&gt;But once you grasp the main idea behind them, you’ll start to see where they fit in your code and spot the bottlenecks that appear when they’re ignored.&lt;/p&gt;

&lt;p&gt;In this SOLID series, I’ll try to explain each principle in a simple, easy-to-understand way. No heavy jargon, no overcomplication, just practical stuff.&lt;/p&gt;

&lt;p&gt;So, let’s kick things off with the first one: the &lt;strong&gt;Single Responsibility Principle (SRP).&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;The key to mastering SRP is understanding what &lt;strong&gt;“single responsibility”&lt;/strong&gt; really means. &lt;/p&gt;

&lt;p&gt;What counts as a single responsibility, and how you can tell if a class or component is handling more than one.&lt;/p&gt;

&lt;p&gt;Let's have a look!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly is Meant by “Single Responsibility”?
&lt;/h2&gt;

&lt;p&gt;A single responsibility simply means a single reason to change. In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A class, function, or module should only have one reason to be modified.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s what that really means in practice:&lt;/p&gt;

&lt;p&gt;🧩 A &lt;strong&gt;“responsibility”&lt;/strong&gt; is a role or purpose your code serves.&lt;/p&gt;

&lt;p&gt;For example, fetching data from a database is one responsibility. Formatting that data for display is another. Sending it in an email is yet another.&lt;/p&gt;

&lt;p&gt;🔄 If a change in one part of the system forces you to update that class/function, it means the class/function is responsible for that area of change.&lt;/p&gt;

&lt;p&gt;So if you have a function that needs changes whenever the business logic changes and also when the report format changes, it has at least two responsibilities.&lt;/p&gt;

&lt;p&gt;✂️ Single Responsibilities Principle  makes sure that each reason to change should belong to a different class or function.&lt;/p&gt;

&lt;p&gt;That way, when a requirement changes, you only touch one small, focused piece of code, not everything at once.&lt;/p&gt;

&lt;p&gt;Let's understand this with the help of an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Report Generator
&lt;/h2&gt;

&lt;p&gt;Imagine you just joined a logistics company as a .NET developer. Your first task is to Build a simple shipment report generator.&lt;/p&gt;

&lt;p&gt;Let’s say you come up with this (very realistic) piece of code:&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GenerateReport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Fetch data&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;shipments&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;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Shipment&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;new&lt;/span&gt; &lt;span class="n"&gt;Shipment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Cargo A"&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;Shipment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Cargo B"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Format as text&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;foreach&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;shipment&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;shipments&lt;/span&gt;&lt;span class="p"&gt;)&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;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"ID: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Description: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&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;report&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;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Save to disk&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"shipment_report.txt"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Send email&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sending email to manager..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// (Pretend there’s real SMTP logic here)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks good, right? Everything’s working. It fetches data, formats it, saves a file, and even emails it.&lt;/p&gt;

&lt;p&gt;But here's the thing.&lt;/p&gt;

&lt;p&gt;This version technically has one function &lt;code&gt;GenerateReport()&lt;/code&gt; but it’s still doing four different things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetching data&lt;/li&gt;
&lt;li&gt;Formatting data&lt;/li&gt;
&lt;li&gt;Writing to disk&lt;/li&gt;
&lt;li&gt;Sending an email&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So even though it’s written as one function, it’s carrying multiple responsibilities.&lt;/p&gt;

&lt;p&gt;That’s the key:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SRP isn’t about how many functions or classes you have. It’s about how many reasons to change exist in one place.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the email logic changes, you’ll have to edit &lt;code&gt;GenerateReport()&lt;/code&gt;. If the file output format changes, same function again. If the report data changes, again.&lt;/p&gt;

&lt;p&gt;Each of those is a different reason to change &lt;strong&gt;(multiple responsibilities).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So let's fix this by following Single Responsibility Principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebuilding Report Generator following SRP
&lt;/h2&gt;

&lt;p&gt;Let's start by listing down all the reasons to change aka responsibilities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the way we fetch data changes, that’s one reason.&lt;/li&gt;
&lt;li&gt;If the way we format reports changes, second reason.&lt;/li&gt;
&lt;li&gt;If we save somewhere else, third.&lt;/li&gt;
&lt;li&gt;If we want to notify someone differently, fourth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, let’s split it up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Responsibilities
&lt;/h3&gt;

&lt;p&gt;So far we have identified four responsibilities. Let's create dedicated functions to serve each responsibility. &lt;/p&gt;

&lt;p&gt;We'll have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Fetcher →&lt;/strong&gt; Responsible for fetching shipment data from database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Report Formatter →&lt;/strong&gt; Responsible for formatting the shipment report to the desired format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Saver →&lt;/strong&gt; Responsible for saving the file to server, cloud storage, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Email Sender →&lt;/strong&gt; Responsible for sending the emails.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Write Dedicated Functions for each Responsibility
&lt;/h3&gt;

&lt;p&gt;Let's write functions for each of the defined responsibilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Data Fetcher
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;FetchShipmentsFromDb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Simulated DB call&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Shipment&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;new&lt;/span&gt; &lt;span class="n"&gt;Shipment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Cargo A"&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;Shipment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Cargo B"&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;h4&gt;
  
  
  Report Formatter
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;FormatAsTextReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Shipment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;shipments&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;builder&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;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;foreach&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;shipment&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;shipments&lt;/span&gt;&lt;span class="p"&gt;)&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;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"ID: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Description: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&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;ToString&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;h4&gt;
  
  
  File Saver
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SaveToFile&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;content&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;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&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;h4&gt;
  
  
  Email Sender
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendEmail&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;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sending email to manager..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Imagine SMTP logic here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Bring it all together
&lt;/h3&gt;

&lt;p&gt;Now let's rewrite the &lt;code&gt;ReportGenerator()&lt;/code&gt;, this time, delegating the responsibilities to their respective functions.&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GenerateReport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Fetch data from the database&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;shipments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;FetchShipmentsFromDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Convert to report format&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;FormatAsTextReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shipments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Save report to disk&lt;/span&gt;
    &lt;span class="nf"&gt;SaveToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"shipment_report.txt"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Send email to manager&lt;/span&gt;
    &lt;span class="nf"&gt;SendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&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;That’s it! Our &lt;code&gt;ReportGenerator&lt;/code&gt; is now only responsible for assembling the report, while all the individual tasks are delegated to their respective functions.&lt;/p&gt;

&lt;p&gt;Want to format the report in Excel? Just update the &lt;code&gt;ReportFormatter&lt;/code&gt;.&lt;br&gt;
Need to save the file to the cloud instead of the local server? Modify the &lt;code&gt;FileSaver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each function now has a single responsibility.&lt;/p&gt;

&lt;p&gt;A change in report formatting doesn’t affect the File Saver, and a change in the Email Sender doesn’t require updates anywhere else.&lt;/p&gt;

&lt;p&gt;And with that, you’ve successfully achieved the Single Responsibility Principle. 👏&lt;/p&gt;




&lt;p&gt;Now, I get that it’s harder to see the consequences of not following SRP in a small example like this. &lt;/p&gt;

&lt;p&gt;But in real-world applications, things rarely exist in isolation. Systems are made up of multiple components and modules that constantly interact with each other.&lt;/p&gt;

&lt;p&gt;Having well-defined responsibilities, and making sure each component follows SRP, goes a long way toward keeping your codebase clean and maintainable. &lt;/p&gt;

&lt;p&gt;Otherwise, it doesn’t take long before everything becomes intertwined and your code turns into spaghetti.🍝&lt;/p&gt;




&lt;p&gt;I hope this helped you grasp the concept without feeling overwhelmed.&lt;/p&gt;

&lt;p&gt;💭 What’s your take on SRP? Do you see it as essential, or do you think it’s just over-engineering? I’d love to hear your thoughts.&lt;/p&gt;




&lt;p&gt;Next Up: &lt;a href="https://dev.to/mbkhalid23/mastering-the-o-in-solid-applying-the-openclosed-principle-in-real-world-code-4c7l"&gt;The “O” in SOLID — Open/Closed Principle.&lt;/a&gt; Where we’ll dive into how adding a new feature shouldn’t mean rewriting old code (but it often does).&lt;/p&gt;




&lt;p&gt;Hi, I’m Bilal 👋, a .NET developer sharing what I learn about building software, thinking in systems, and writing clean, practical code.&lt;/p&gt;

&lt;p&gt;If you’re exploring similar ideas, let’s connect and learn together.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Stop Adding Unnecessary Abstractions: My 3-Question Kill-Switch for Over-Engineering</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Mon, 27 Oct 2025 17:26:41 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/stop-overengineering-my-3-step-framework-that-helps-save-weeks-of-wasted-work-4hnj</link>
      <guid>https://dev.to/mbkhalid23/stop-overengineering-my-3-step-framework-that-helps-save-weeks-of-wasted-work-4hnj</guid>
      <description>&lt;p&gt;Here’s something nobody tells you when you’re learning to code: &lt;strong&gt;more projects fail from overengineering than from bad code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I learned this the hard way. Three years into my career, I was that developer who obsessed over abstractions, built elaborate design patterns, and could justify every architectural decision with textbook precision. I felt good about my work.&lt;/p&gt;

&lt;p&gt;Then I started noticing the pattern. Features that should’ve taken days were taking weeks. All that “future-proofing” I’d built? Most of those future scenarios never happened.&lt;/p&gt;

&lt;p&gt;I was shipping slower, building for problems that didn’t exist, while real user needs waited.&lt;/p&gt;

&lt;p&gt;That’s when I realized: knowing when NOT to build something is just as critical as knowing how to build it well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Smart Developers Overengineer
&lt;/h2&gt;

&lt;p&gt;We do it because we care. We want scalable systems, clean architecture, code that won’t need rewrites six months from now. We’re following best practices, doing things “the right way.”&lt;/p&gt;

&lt;p&gt;But here’s the uncomfortable truth I’ve discovered: &lt;strong&gt;most of the future we design for never actually arrives.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And here’s the thing: it doesn’t feel wrong while you’re doing it. You’re learning, applying solid principles, building professional-grade systems. Everyone’s happy.&lt;/p&gt;

&lt;p&gt;But there’s a hidden cost accumulating beneath the surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Cost Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;The problem with overengineering isn’t dramatic failure. It’s &lt;strong&gt;quiet inefficiency&lt;/strong&gt; that compounds over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You spend more time maintaining abstractions than solving actual problems&lt;/strong&gt;. That “flexible” system becomes rigid because changing it means updating five interconnected pieces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’re shipping slower than you need to.&lt;/strong&gt; Every extra abstraction is another decision point, another layer to think through. That feature that could’ve taken two days now takes a week because you’re “doing it right.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical debt accumulates in disguise&lt;/strong&gt;. Those flexible abstractions? They become rigid constraints. You thought you were preventing technical debt, but you were creating a different kind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance takes hidden hits.&lt;/strong&gt; All those layers, all that flexibility, it’s not free. Your app is carrying weight it doesn’t need, running code for scenarios that will never happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And here’s the kicker:&lt;/strong&gt; Most of the flexibility you build for? Those future use cases you’re preparing for? They never actually arrive.&lt;/p&gt;

&lt;p&gt;Requirements change. The product pivots. That “definitely coming” feature gets canceled. You spent time and added complexity for a future that didn’t happen.&lt;/p&gt;

&lt;p&gt;Meanwhile, you could’ve shipped faster, simpler, and been ready to adapt when you &lt;em&gt;actually&lt;/em&gt; knew what was needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mindset Shift That Changed Everything
&lt;/h2&gt;

&lt;p&gt;Good code solves today’s problems and leaves room to evolve tomorrow. That’s it.&lt;/p&gt;

&lt;p&gt;It doesn’t try to predict every scenario. It doesn’t build for imaginary scale. It doesn’t create abstractions just because they’re “proper.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplicity isn’t laziness,&lt;/strong&gt; it’s discipline. Every line of code is a liability until it proves its value. Every abstraction is overhead until it earns its keep.&lt;/p&gt;

&lt;p&gt;The best engineers I’ve worked with? They don’t build perfect systems. They build sensible ones. They know complexity is easy, simplicity takes thought.&lt;/p&gt;

&lt;h2&gt;
  
  
  My “Now / Later / Never” Filter
&lt;/h2&gt;

&lt;p&gt;Over the years, I’ve developed a three-question sanity check I run before adding any new abstraction, pattern, or architectural layer. It’s saved me countless hours and kept my codebases actually maintainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  🟢 Question 1: Does this solve a problem we have right now?
&lt;/h3&gt;

&lt;p&gt;If yes — build it. If no — stop.&lt;/p&gt;

&lt;p&gt;This is your primary filter. Be ruthlessly honest here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ask yourself:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What actually breaks if I don’t add this today?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is anyone blocked by the current simple solution?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Am I solving a real pain point or an imaginary one?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer is &lt;strong&gt;“nothing breaks”, it’s not a “now” problem.&lt;/strong&gt; And “now” problems are the only ones worth solving today.&lt;/p&gt;

&lt;h3&gt;
  
  
  🟡 Question 2: If not now, will it definitely be needed later?
&lt;/h3&gt;

&lt;p&gt;Sometimes you actually know what’s coming. A confirmed roadmap item. A pattern you’ve seen emerge three times already. A specific requirement from stakeholders with a hard deadline.&lt;/p&gt;

&lt;p&gt;Notice the word “definitely.” Not “might.” Not “could.” Definitely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can you point to a concrete, scheduled future use case?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Has this exact need appeared multiple times already?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you have actual data suggesting this will matter?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re building based on “what if” or “just in case”, you’re guessing. And engineering based on guesses is expensive.&lt;/p&gt;

&lt;p&gt;Here’s what I’ve learned: &lt;strong&gt;You can’t future-proof what you don’t understand yet.&lt;/strong&gt; The future becomes clear after you’ve lived it once. That’s when you know exactly what abstraction you need.&lt;/p&gt;

&lt;p&gt;Until then? You’re probably building the wrong thing anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔴 Question 3: If neither, why am I really adding it?
&lt;/h3&gt;

&lt;p&gt;This is your stop sign.&lt;/p&gt;

&lt;p&gt;Be honest with yourself. If it’s not solving a current problem and not clearly needed soon, why are you building it?&lt;/p&gt;

&lt;p&gt;Usually, it’s one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Habit:&lt;/strong&gt; “This is how we’re supposed to architect things”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fear:&lt;/strong&gt; “What if we need to change this later?”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resume-driven development:&lt;/strong&gt; “This pattern will look great in my portfolio”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intellectual curiosity:&lt;/strong&gt; “This would be fun to build”&lt;br&gt;
All of these are valid feelings. None of them justify adding complexity to production code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If your abstraction exists mainly to look smart or feel sophisticated, it’s already technical debt.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Delete it. Ship simpler. You’ll move faster, your team will thank you, and you’ll actually sleep better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Skill: Knowing When to Stop
&lt;/h2&gt;

&lt;p&gt;After a few years in this industry, I’ve realized the most valuable developers aren’t the ones who can build the most complex systems. They’re the ones who know when not to.&lt;/p&gt;

&lt;p&gt;They ship working code instead of perfect architecture. They write clear solutions instead of clever ones. They build for today’s problems while staying ready to evolve.&lt;/p&gt;

&lt;p&gt;That’s not being lazy or short-sighted. That’s being efficient. That’s being practical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can always add complexity later when you actually need it. Removing unnecessary complexity costs many times more.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Challenge
&lt;/h2&gt;

&lt;p&gt;Next time you’re about to add a new layer, abstraction, or pattern, pause. Run it through the filter:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now?&lt;/strong&gt; Build it.&lt;br&gt;
&lt;strong&gt;Later?&lt;/strong&gt; Prepare for it specifically.&lt;br&gt;
&lt;strong&gt;Never?&lt;/strong&gt; Delete it.&lt;/p&gt;

&lt;p&gt;You’ll be amazed how much faster you move when you stop carrying weight you don’t need.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What’s your experience with overengineering?&lt;/strong&gt; I’d love to hear your stories, both the times you got burned by too much architecture and the times you successfully kept things simple. Drop a comment below! 👇&lt;/p&gt;




&lt;p&gt;Hi, I’m Bilal, a .NET developer sharing what I learn about building software, thinking in systems, and writing clean, practical code.&lt;/p&gt;

&lt;p&gt;If you’re exploring similar ideas, let’s connect and learn together.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Clean Architecture: A Beginner's Guide</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Fri, 26 Jan 2024 13:17:12 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/understanding-clean-architecture-3f86</link>
      <guid>https://dev.to/mbkhalid23/understanding-clean-architecture-3f86</guid>
      <description>&lt;p&gt;Clean Architecture is one of the most popular software architectures to help organize your source code.&lt;/p&gt;

&lt;p&gt;Here is everything you need to get started with Clean Architecture!&lt;/p&gt;

&lt;p&gt;Proposed by Robert C Martin, aka Uncle Bob, the Clean Architecture offers some significant advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Independent of Frameworks:&lt;/strong&gt; The architecture does not require some external libraries to work. It can stand on its own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testability:&lt;/strong&gt; The business logic is independent of the web UI, Databases, and external sources so that it can be tested independently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; Web UI, Databases, and Business logic are all separated into different layers, making the system modular and less interdependent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Cohesion and Low Coupling:&lt;/strong&gt; All the layers specialize in their own domain and are not coupled to each other. Thus, any change in UI or databases will not affect the business logic and so on.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;So, what is it that makes this architecture so powerful?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer to this question is the &lt;em&gt;Dependency Inversion Principle.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Dependency Inversion Principle is the main engine or the driving force behind any Layered Architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Dependency Inversion Principle basically states that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;High-level modules should not depend on low-level implementation details. Instead, they should depend on abstractions that are implemented by the low-level modules. Thus, inverting the direction of the dependencies.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider a traditional Asp.Net Webforms application. In such applications, business logic is strongly tied to the User Interface and Database.&lt;/p&gt;

&lt;p&gt;Thus, any changes in the UI or database logic would force changes in the business logic as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqqe71qv9t18509s8sch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqqe71qv9t18509s8sch.png" alt="Business Layer Tightly Coupled with UI and Data" width="660" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, with dependency inversion, we can separate the business logic from the user interface and database by separating them into individual layers.&lt;/p&gt;

&lt;p&gt;These layers, instead of depending on each other, depend on abstractions. Thus, any change in one layer does not affect any other layer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8irucg05fgoj6oci6xtx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8irucg05fgoj6oci6xtx.png" alt="Business Layer Depends on the Interface and Independent of UI and Data" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far, there have been multiple implementations of Layered Architecture, including Hexagonal, Onion, Clean Architecture, and more.&lt;/p&gt;

&lt;p&gt;Let’s dive deep into the Clean Architecture now.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Clean Architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you google the term Clean Architecture, you will see a diagram somewhat like this one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9a9tekh3gaz6igws81s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9a9tekh3gaz6igws81s.png" alt="Layer Diagram of Clean Architecture" width="339" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram consists of concentric circles representing the different layers of the system.&lt;/p&gt;

&lt;p&gt;As you get closer to the center, you will find high-level abstract details like the Domain Entities.&lt;/p&gt;

&lt;p&gt;Moving outwards, you will encounter low-level implementation details like services, databases, etc.&lt;/p&gt;

&lt;p&gt;Let’s have a look at what is inside each of these layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Domain Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;At the heart of the system is the Domain Layer. The domain layer consists of the core business entities.&lt;/p&gt;

&lt;p&gt;All the other layers in the system depend on the Domain layer and are there to support the Domain Layer.&lt;/p&gt;

&lt;p&gt;Domain Layer itself does not depend on any other Layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Application Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Neighboring the Domain Layer is the Application Layer.&lt;/p&gt;

&lt;p&gt;The Application layer is where all the magic happens. This is where your business logic resides.&lt;/p&gt;

&lt;p&gt;Based on the business rules and regulations, this layer controls the flow of data to and from your business entities.&lt;/p&gt;

&lt;p&gt;Generally, this layer consists of all your services, commands, queries, exceptions, logs, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Infrastructure Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next, we have the Infrastructure Layer. This is where all your external services and database logic are located.&lt;/p&gt;

&lt;p&gt;All your external services, like email service, storage solutions, message queues, third-party API calls, etc., are handled by this layer.&lt;/p&gt;

&lt;p&gt;Besides, it is also a common practice to separate database logic into its own Persistence Layer. This is where your DbContext and migrations, etc., will go.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Presentation Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lastly, we have the presentation layer. This is the gateway or the entry point to your application.&lt;/p&gt;

&lt;p&gt;This layer is responsible for presenting data to the end user in an easily understandable manner.&lt;/p&gt;

&lt;p&gt;You will probably implement this layer as a Web or API project consisting of controllers defining the Action Methods or API endpoints.&lt;/p&gt;

&lt;p&gt;So, these are the four layers in the Clean Architecture. But, now the question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Will there always be 4 layers?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer to that question is &lt;em&gt;“No”.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can always add more layers according to your requirements. The point of the layers is to organize and manage the source code.&lt;/p&gt;

&lt;p&gt;For example, you may add a Common Layer at the center for storing static data like enums, magic strings, etc.&lt;/p&gt;

&lt;p&gt;Or add a Storage Layer at the outermost to manage your storage in case you are using multiple storage solutions.&lt;/p&gt;

&lt;p&gt;In short, there is no restriction on the number of layers you can add.&lt;/p&gt;

&lt;p&gt;However, there is one principle that you must always follow. That is the &lt;em&gt;Rule of Dependencies&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rule of Dependencies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The rule of dependencies gives clear instructions about the direction of dependencies. It states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Source code dependencies can only point from outside towards inside of the circle.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs96saq7fhjek7qo508w8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs96saq7fhjek7qo508w8.png" alt="Flow of Dependencies in Clean Architecture" width="339" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That means that no inner layer can know anything about the outer layers. Anything defined in an outer layer should not be visible to any inner layer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So, how do the layers interact then?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's simple. An inner layer defines an abstraction or an interface. The implementation of this interface is then provided by an outer layer.&lt;/p&gt;

&lt;p&gt;That way, the inner layer doesn’t have to know about the outer layer and thus becomes independent of the implementation details.&lt;/p&gt;

&lt;p&gt;Sounds good. But there is one more question remaining.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we transfer data between the layers?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Remember, we can not violate the Rule of Dependencies.&lt;/p&gt;

&lt;p&gt;This implies we cannot directly pass data to and from layers using our domain entities.&lt;/p&gt;

&lt;p&gt;Doing so would require the inner layer (Domain Layer) to know about the outer layers, violating the Rule of Dependencies.&lt;/p&gt;

&lt;p&gt;So, instead of domain entities, we can create special Data Transfer Objects called DTOs to transfer the data between different layers.&lt;/p&gt;

&lt;p&gt;DTOs must be simple data structures or objects containing the data required for an inner layer. You can also use immutable types like records for DTOs.&lt;/p&gt;

&lt;p&gt;In the end, remember that software architectures are opinionated and very subjective. They are not a set of hard rules that must be followed.&lt;/p&gt;

&lt;p&gt;Therefore, experiment with different architectures and feel free to make modifications to best suit your application.&lt;/p&gt;

&lt;p&gt;After all, the goal of any architecture is to make clean, maintainable, testable, and scalable applications.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article. Let me know how you would structure your project for Clean Architecture. Feel free to share any insights!&lt;/p&gt;




&lt;p&gt;PS: Check out my implementation of the Clean Architecture on my &lt;a href="https://github.com/mbkhalid23/dotnet-clean-arch" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For now, it’s just the basic structure. Over the next few weeks, I will add different services and features to this project, like logging, dependency Injection, Authentication, CQRS, Emails, and more.&lt;/p&gt;

&lt;p&gt;My goal is to make it into a starter template that is configured with all the necessary features that are a must in any modern application.&lt;/p&gt;

&lt;p&gt;Feel free to follow along and share your suggestions.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>webdev</category>
      <category>cleancode</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why I Switched from Engineering to Computer Science</title>
      <dc:creator>Muhammad Bilal Khalid</dc:creator>
      <pubDate>Mon, 04 Apr 2022 19:28:13 +0000</pubDate>
      <link>https://dev.to/mbkhalid23/why-i-switched-from-engineering-to-computer-science-268b</link>
      <guid>https://dev.to/mbkhalid23/why-i-switched-from-engineering-to-computer-science-268b</guid>
      <description>&lt;p&gt;Let me begin with a quick overview. &lt;/p&gt;

&lt;p&gt;So basically, I completed my bachelor's in Electrical Engineering in 2018. Back when I got admission in Electrical Engineering, it was of the most in-demand fields. There were a lot of opportunities, and the field, in general, promised a great career.&lt;/p&gt;

&lt;p&gt;However, the demand started to go down gradually while I was still studying. By the time I graduated, there were only a handful of opportunities open for freshers.&lt;/p&gt;

&lt;p&gt;Anyhow, I decided to give it some time and kept preparing for any opportunities that may come. However, the demand never went up, and not enough opportunities were created. &lt;/p&gt;

&lt;p&gt;So, long story short. After giving my best for nearly 3 years, I realized it's not going to work. So, after re-evaluating my options, I finally decided to switch to Computer Science. And here I am today, sharing my journey with you! &lt;/p&gt;

&lt;p&gt;So, let's address the first question first. Why did I leave Engineering?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did I leave Engineering?
&lt;/h2&gt;

&lt;p&gt;During my 3 years of job hunt, I observed a number of things that eventually brought me to my decision. I'll break it down into three main reasons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason# 1: Not Enough Opportunities
&lt;/h3&gt;

&lt;p&gt;I was unable to land a job for almost 3 years. There were simply not enough opportunities for freshers. &lt;/p&gt;

&lt;p&gt;Even among the few available opportunities, most were internal hirings. So, they never even got to me. On this point, I agree my networking wasn't that strong either. But still, the opportunities were scarce. &lt;/p&gt;

&lt;p&gt;On top of that, the influx of graduating engineers further saturated the job market, which made the competition really tough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason# 2: Uncertainty in the Job Market
&lt;/h3&gt;

&lt;p&gt;The job market for Electrical Engineering had been quite uncertain. Those of us who did get a job had no certainty about their future. And in case one gets laid off, hunting for a job again will be a pain. &lt;/p&gt;

&lt;p&gt;Besides uncertainty, salaries were also lower in comparison to other fields with equivalent qualifications. Because the competition was very high, people were willing to work at lower pay. After all, it is still better than being jobless.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason# 3: COVID-19!
&lt;/h3&gt;

&lt;p&gt;Since the breakout of the pandemic, there was a complete lockdown in place. The industrial sector remained close for a significant share of time. This situation resulted in a huge number of layoffs.&lt;/p&gt;

&lt;p&gt;For a field already facing saturation, this was a big blow. And with it, my hopes of making a career in Electrical Engineering went low. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS: It is important to note that the job market varies significantly from region to region. Everything I have shared is within my radius. Your experiences in another part of the world might be completely different.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, this was my journey of Electrical Engineering which came to an end half a year ago. Let's talk about the future now. So, why Computer Science? &lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Decided to Go for Computer Science
&lt;/h2&gt;

&lt;p&gt;Choosing Computer Science was a pretty straightforward decision for me. I'll break it down into three reasons. &lt;/p&gt;

&lt;h3&gt;
  
  
  Reason# 1: Familiarity
&lt;/h3&gt;

&lt;p&gt;Since Electrical Engineering is closely related to CS, I was already familiar with the programming concepts. I had studied the core concepts of programming and data structures during my course of study.&lt;/p&gt;

&lt;p&gt;Moreover, I did a number of projects that involved the programming of microcontrollers and Arduino boards. So, I already had some experience with programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason# 2: Better Opportunities.
&lt;/h3&gt;

&lt;p&gt;Computer Science, in the foreseeable future, is only expected to grow. There are already a huge number of opportunities in the field, and the demand for IT professionals is growing continually.&lt;/p&gt;

&lt;p&gt;Besides, you get so many options within the field. You can go for Software Development, Cloud Computing, Data Science, AI, Blockchain, etc. And the best thing is all are in high demand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason# 3: Sustainability and Better Career Growth
&lt;/h3&gt;

&lt;p&gt;If there is one industry that continued to grow even during the pandemic, it is definitely the IT industry.&lt;/p&gt;

&lt;p&gt;Moreover, the demand for IT professionals is high. And in case you leave a job or get laid off, you can easily find another job, of course, with a bit of effort.&lt;/p&gt;

&lt;p&gt;On top of that, IT professionals are getting competitive salaries and the field, in general, offers much better career growth as well.&lt;/p&gt;

&lt;p&gt;To sum up, it made perfect sense for me to go with something I am already familiar with, that has decent opportunities and offers better growth. So, that's what I did!&lt;/p&gt;

&lt;h2&gt;
  
  
  Going Forward . . .
&lt;/h2&gt;

&lt;p&gt;I actually decided to switch my career back in mid-2021. It took me some time to figure out my way forward. So, after some evaluation, here are the goals I've set for myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goal# 1: Complete my Master's in Computer Science
&lt;/h3&gt;

&lt;p&gt;So, currently, I am enrolled in a Master's program in Computer Science at &lt;a href="https://www.nu.edu.pk/" rel="noopener noreferrer"&gt;FAST&lt;/a&gt;. However, since I did not come from a CS background, I had to take deficiency courses to make up for it.&lt;/p&gt;

&lt;p&gt;Hopefully, I will clear the deficiency courses by June 2022. And after the summer break, My actual Master's degree will begin in Sep 2022. &lt;/p&gt;

&lt;p&gt;It's a two-year program, so if everything goes well, I will graduate in mid-2024, &lt;a href="https://www.nytimes.com/2022/01/25/magazine/inshallah.html" rel="noopener noreferrer"&gt;InShaaAllah&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goal# 2: Become a Self-Taught Developer
&lt;/h3&gt;

&lt;p&gt;Besides the MS degree, I intend to learn web development using online resources. My aim is to go full-stack. However, for now, I am only focusing on front-end development.&lt;/p&gt;

&lt;p&gt;Once I am well versed in front-end development, I plan to go for an entry-level web developer role. After that, I can continue to learn backend development alongside.&lt;/p&gt;

&lt;p&gt;I haven't decided on a full-stack yet. Both MERN stack and .NET are in high demand in my region. So, I'll go with one of these, but that's a decision I will wait on for now.&lt;/p&gt;

&lt;h4&gt;
  
  
  Online Resources for Learning Web Development
&lt;/h4&gt;

&lt;p&gt;If you are looking for online resources, do check out &lt;a href="https://www.theodinproject.com/paths" rel="noopener noreferrer"&gt;the Odin Project&lt;/a&gt;. It's a free online resource. I like it because the content is well structured and focuses more on the practical aspect.&lt;/p&gt;

&lt;p&gt;Besides the Odin Project, we have other great resources like &lt;a href="https://www.freecodecamp.org/" rel="noopener noreferrer"&gt;freecodecamp&lt;/a&gt;, &lt;a href="https://www.codecademy.com/catalog/subject/web-development" rel="noopener noreferrer"&gt;Codecademy&lt;/a&gt;, &lt;a href="https://www.udemy.com/courses/development/web-development/?search-query=web+development" rel="noopener noreferrer"&gt;Udemy&lt;/a&gt;, etc. So feel free to check them out as well. Find the one that best suits your learning style.&lt;/p&gt;

&lt;p&gt;Please note that they are all great resources, and you can't go wrong with any of them. What's important is to just pick one and then stick with it. You'll make more progress that way. Wish you all the best!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Moving on, I have decided to document my web development journey. So, I will be writing about all the things that I learn along the way.&lt;/p&gt;

&lt;p&gt;So far, I have covered the HTML and CSS foundations section of the Odin Project. I will be writing shortly about that. So, feel free to follow along. After all, it's fun learning together!&lt;/p&gt;

&lt;p&gt;In the end, I must say I have heard great things about the hashnode community. So, my expectations are high. Please feel free to share your valuable suggestions in the comments section. Cheers!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>webdev</category>
      <category>career</category>
    </item>
  </channel>
</rss>
