<?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: Ashay Tiwari</title>
    <description>The latest articles on DEV Community by Ashay Tiwari (@ashay_tiwari_3658168ad5db).</description>
    <link>https://dev.to/ashay_tiwari_3658168ad5db</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3114225%2Fecf3ef8c-a7e9-4872-a8bf-039005be28df.jpg</url>
      <title>DEV Community: Ashay Tiwari</title>
      <link>https://dev.to/ashay_tiwari_3658168ad5db</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashay_tiwari_3658168ad5db"/>
    <language>en</language>
    <item>
      <title>Dependency Injection in JavaScript/TypeScript: Why Should a Class Create Its Own Dependencies?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Thu, 13 Aug 2026 07:26:41 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/dependency-injection-in-javascripttypescript-why-should-a-class-create-its-own-dependencies-33p9</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/dependency-injection-in-javascripttypescript-why-should-a-class-create-its-own-dependencies-33p9</guid>
      <description>&lt;p&gt;In the previous article, we explored the &lt;strong&gt;Dependency Inversion Principle (DIP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We saw how high-level business logic becomes tightly coupled when it directly creates and depends on implementation details.&lt;/p&gt;

&lt;p&gt;We also briefly introduced another concept:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Injection (DI).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feigv6p8aee1l962cmbkt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feigv6p8aee1l962cmbkt.png" alt="Dependency Injection" width="700" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may have heard this term many times.&lt;/p&gt;

&lt;p&gt;You may have even used Dependency Injection without realizing it.&lt;/p&gt;

&lt;p&gt;But instead of starting with its definition, let's start with a problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine we're building an order processing system.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;OrderService&lt;/code&gt; needs to send an email when an order is created.&lt;/p&gt;

&lt;p&gt;We might write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;`Sending email to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;to&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;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create order...&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your order has been placed.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks simple.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; needs an &lt;code&gt;EmailService&lt;/code&gt;, so it creates one.&lt;/p&gt;

&lt;p&gt;What's wrong with that?&lt;/p&gt;

&lt;p&gt;At first, nothing.&lt;/p&gt;

&lt;p&gt;But let's see what happens as the application grows.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The First Problem: Changing the Dependency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose the application initially uses one email provider.&lt;/p&gt;

&lt;p&gt;Later, the business decides to switch to another provider.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;OrderService&lt;/code&gt; is now directly connected to the original implementation.&lt;/p&gt;

&lt;p&gt;We have to change it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NewEmailService&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;The order logic shouldn't have to know which email service the company uses.&lt;/p&gt;

&lt;p&gt;But because it creates the dependency itself, it has no choice.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Bigger Problem: Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now imagine we want to test &lt;code&gt;OrderService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We only want to test:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does creating an order trigger an email?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But our test has a problem.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; automatically creates a real &lt;code&gt;EmailService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So our test may end up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connecting to an external service.&lt;/li&gt;
&lt;li&gt;Making unnecessary network requests.&lt;/li&gt;
&lt;li&gt;Depending on external configuration.&lt;/li&gt;
&lt;li&gt;Becoming slower.&lt;/li&gt;
&lt;li&gt;Becoming harder to make deterministic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All because &lt;code&gt;OrderService&lt;/code&gt; decided to create its own dependency.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What If We Could Provide the Dependency?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailService&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;What if we did this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmailService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create order...&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your order has been placed.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And outside the class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailService&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;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something important just happened.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; no longer creates its dependency.&lt;/p&gt;

&lt;p&gt;Someone else provides it.&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;Dependency Injection&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Simplest Definition&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Dependency Injection simply means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A class receives the dependencies it needs from the outside instead of creating them itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;The dependency is &lt;strong&gt;injected&lt;/strong&gt; into the object.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Is This Better?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now &lt;code&gt;OrderService&lt;/code&gt; doesn't care where the email service came from.&lt;/p&gt;

&lt;p&gt;We can provide the real implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailService&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;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or a fake implementation during testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FakeEmailService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fake email sent&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fakeEmailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FakeEmailService&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;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fakeEmailService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;OrderService&lt;/code&gt; doesn't need to change.&lt;/p&gt;

&lt;p&gt;It simply receives something that provides the behavior it needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;But There Is Still a Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our previous example depends directly on &lt;code&gt;EmailService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's better than creating it internally, but we can take it one step further.&lt;/p&gt;

&lt;p&gt;What if we define what &lt;code&gt;OrderService&lt;/code&gt; actually needs?&lt;/p&gt;

&lt;p&gt;It doesn't necessarily need an &lt;code&gt;EmailService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It needs &lt;strong&gt;something capable of sending emails&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So we define an abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;Our actual service implements it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;`Sending email to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;to&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;OrderService&lt;/code&gt; depends on the abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailSender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmailSender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create order...&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailSender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your order has been placed.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where Dependency Injection and Dependency Inversion work nicely together.&lt;/p&gt;




&lt;h2&gt;
  
  
  DI and DIP Are Not the Same Thing
&lt;/h2&gt;

&lt;p&gt;These terms are often used interchangeably, but they mean different things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Inversion Principle
&lt;/h3&gt;

&lt;p&gt;DIP is a &lt;strong&gt;design principle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It tells us that high-level modules shouldn't be tightly coupled to low-level implementation details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Injection
&lt;/h3&gt;

&lt;p&gt;DI is a &lt;strong&gt;technique&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It provides a practical way to supply dependencies from outside.&lt;/p&gt;

&lt;p&gt;You can use Dependency Injection without perfectly following DIP.&lt;/p&gt;

&lt;p&gt;And DIP can be achieved through different techniques.&lt;/p&gt;

&lt;p&gt;But in practice, they are often used together.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Dependency Injection in Real Applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You've probably already used Dependency Injection.&lt;/p&gt;

&lt;p&gt;Consider a React component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component doesn't create &lt;code&gt;userService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It receives it.&lt;/p&gt;

&lt;p&gt;The same idea appears in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend services&lt;/li&gt;
&lt;li&gt;Database repositories&lt;/li&gt;
&lt;li&gt;API clients&lt;/li&gt;
&lt;li&gt;Logging systems&lt;/li&gt;
&lt;li&gt;Authentication providers&lt;/li&gt;
&lt;li&gt;Payment processors&lt;/li&gt;
&lt;li&gt;File storage&lt;/li&gt;
&lt;li&gt;Notification services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern is always similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Instead of:

Class → creates dependency

We have:

Class ← receives dependency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  **Does DI Always Require a Framework?
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
No.&lt;/p&gt;

&lt;p&gt;This is another common misconception.&lt;/p&gt;

&lt;p&gt;Dependency Injection doesn't require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NestJS&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Spring&lt;/li&gt;
&lt;li&gt;.NET&lt;/li&gt;
&lt;li&gt;A DI container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is Dependency Injection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;paymentService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentService&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;And:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&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;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paymentService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No framework.&lt;/p&gt;

&lt;p&gt;No library.&lt;/p&gt;

&lt;p&gt;Just JavaScript/TypeScript.&lt;/p&gt;

&lt;p&gt;A DI framework simply automates the process of creating and connecting these dependencies.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Composition Root&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At some point, someone still has to create the objects.&lt;/p&gt;

&lt;p&gt;We haven't eliminated object creation.&lt;/p&gt;

&lt;p&gt;We've moved it to a better place.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StripePaymentService&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;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;paymentService&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part of the application is sometimes called the &lt;strong&gt;composition root&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's where we decide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which implementation should be used?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The business logic doesn't need to know.&lt;/p&gt;

&lt;p&gt;This creates a useful separation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application Setup
       │
       ├── StripePaymentService
       └── OrderService
                │
                ↓
        PaymentProcessor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration decides the implementation.&lt;/p&gt;

&lt;p&gt;The business logic simply uses the abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Benefits of Dependency Injection&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Easier Testing
&lt;/h3&gt;

&lt;p&gt;Dependencies can easily be replaced with mocks, fakes, or stubs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easier Maintenance
&lt;/h3&gt;

&lt;p&gt;Classes don't need to know how their dependencies are created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lower Coupling
&lt;/h3&gt;

&lt;p&gt;Business logic becomes less dependent on concrete implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Greater Flexibility
&lt;/h3&gt;

&lt;p&gt;Different implementations can be provided without changing the consuming class.&lt;/p&gt;




&lt;h2&gt;
  
  
  But Is DI Always Better?
&lt;/h2&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Dependency Injection also introduces some complexity.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;paymentService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;inventoryService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;analyticsService&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second approach can become difficult to understand if taken too far.&lt;/p&gt;

&lt;p&gt;You can also end up with a codebase where every class has an interface, every dependency is injected, and simple object creation becomes unnecessarily complicated.&lt;/p&gt;

&lt;p&gt;Again, the goal isn't to apply a principle everywhere.&lt;/p&gt;

&lt;p&gt;The goal is to solve a real problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Concluding This Series — For Now 🙂&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With this article, we've reached a natural stopping point for this part of the series.&lt;/p&gt;

&lt;p&gt;We started with the fundamentals of OOP, explored its core concepts, questioned where Factory Functions fit in, and then moved into SOLID Principles and Dependency Injection.&lt;/p&gt;

&lt;p&gt;But software design is a much bigger topic.&lt;/p&gt;

&lt;p&gt;There are still many areas worth exploring—from Design Patterns and Inversion of Control to architecture, coupling, cohesion, and many of the practical decisions we face while building real-world software.&lt;/p&gt;

&lt;p&gt;We'll continue exploring these topics in future articles, always following the same approach:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't just learn what a concept is. Understand why it exists, what problem it solves, and when it actually makes sense to use it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For now, this is where we'll conclude this part of the journey.&lt;/p&gt;

&lt;p&gt;See you in the next one. 🚀&lt;/p&gt;

</description>
      <category>dependencyinjection</category>
      <category>solidprinciples</category>
      <category>architecture</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Dependency Inversion Principle (DIP): Why Should High Level Module Depend on Details?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Wed, 12 Aug 2026 08:13:42 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/dependency-inversion-principle-dip-why-should-high-level-module-depend-on-details-54gp</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/dependency-inversion-principle-dip-why-should-high-level-module-depend-on-details-54gp</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwbsuligcu0uqrgt5wn0l.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwbsuligcu0uqrgt5wn0l.png" alt="DIP" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've finally reached the fifth and last principle of SOLID:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Inversion Principle (DIP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So far, we've talked about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SRP&lt;/strong&gt; — Keep responsibilities focused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCP&lt;/strong&gt; — Extend behaviour without constantly modifying existing code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LSP&lt;/strong&gt; — Subtypes should be genuine substitutes for their parent types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISP&lt;/strong&gt; — Don't force clients to depend on things they don't need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DIP brings many of these ideas together.&lt;/p&gt;

&lt;p&gt;Its formal definition says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;High-level modules should not depend on low-level modules. Both should depend on abstractions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the second part says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Abstractions should not depend on details. Details should depend on abstractions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's technically correct.&lt;/p&gt;

&lt;p&gt;But it's not particularly easy to understand.&lt;/p&gt;

&lt;p&gt;So, as always, let's start with a problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine we're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;When an order is placed, we need to send a confirmation email.&lt;/p&gt;

&lt;p&gt;A simple implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;`Sending email to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;to&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;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create order...&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your order has been placed.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, this looks perfectly reasonable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; needs to send an email.&lt;/p&gt;

&lt;p&gt;So it creates an &lt;code&gt;EmailService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What's wrong with that?&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Hidden Dependency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our &lt;code&gt;OrderService&lt;/code&gt; isn't really saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I need something that can send notifications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I specifically need this particular &lt;code&gt;EmailService&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's an important difference.&lt;/p&gt;

&lt;p&gt;Today, we're sending emails.&lt;/p&gt;

&lt;p&gt;Tomorrow, the business might say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We also want to send a push notification."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"For some customers, send an SMS instead."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We're moving to a different email provider."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now &lt;code&gt;OrderService&lt;/code&gt; is affected by all of those decisions.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because the high-level business logic is directly connected to a low-level implementation.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What Is High-Level and Low-Level?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This terminology can sound confusing, so let's simplify it.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-level code
&lt;/h3&gt;

&lt;p&gt;This represents &lt;strong&gt;business decisions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;OrderService&lt;/span&gt;
&lt;span class="nx"&gt;PaymentService&lt;/span&gt;
&lt;span class="nx"&gt;CheckoutService&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These answer questions like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What should the application do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Low-level code
&lt;/h3&gt;

&lt;p&gt;This represents &lt;strong&gt;implementation details&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;EmailService&lt;/span&gt;
&lt;span class="nx"&gt;StripePaymentService&lt;/span&gt;
&lt;span class="nx"&gt;MySQLRepository&lt;/span&gt;
&lt;span class="nx"&gt;S3Storage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These answer questions like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How exactly should we do it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem occurs when business logic becomes tightly coupled to implementation details.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Let's Look at a Payment Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose our checkout service directly uses Stripe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckoutService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;paymentService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StripePaymentService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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;Everything works.&lt;/p&gt;

&lt;p&gt;Until the business says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We're moving from Stripe to Razorpay.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we need to change &lt;code&gt;CheckoutService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But why should the checkout logic care which payment provider we're using?&lt;/p&gt;

&lt;p&gt;The business requirement is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Process the payment.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation detail is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use Stripe.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are two different concerns.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Idea Behind Dependency Inversion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of making the high-level module depend directly on the implementation, we introduce an abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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 Stripe can implement that abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripePaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Charging through Stripe...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Razorpay can implement the same abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RazorpayPaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Charging through Razorpay...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;CheckoutService&lt;/code&gt; no longer needs to know about either provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckoutService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;paymentProcessor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentProcessor&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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 the dependency points toward the abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What Changed?&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CheckoutService
      ↓
StripePaymentProcessor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CheckoutService
      ↓
PaymentProcessor
      ↑
StripePaymentProcessor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part isn't the arrow diagram.&lt;/p&gt;

&lt;p&gt;It's the relationship.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CheckoutService&lt;/code&gt; no longer cares about Stripe.&lt;/p&gt;

&lt;p&gt;It only cares about a capability:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me something that can process a payment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation can change without changing the business logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;This Is Where Dependency Injection Comes In&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You might have noticed something in our example.&lt;/p&gt;

&lt;p&gt;We're no longer creating the payment processor inside &lt;code&gt;CheckoutService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We're receiving it from outside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentProcessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StripePaymentProcessor&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;checkoutService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CheckoutService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;paymentProcessor&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;strong&gt;Dependency Injection&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of a class creating its own dependencies, those dependencies are provided to it.&lt;/p&gt;

&lt;p&gt;DIP and Dependency Injection are closely related, but they are not the same thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DIP is a design principle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Injection is one technique we can use to implement that principle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll explore Dependency Injection in much more detail in the next article.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Is This Useful?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This design gives us several benefits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easier to Change
&lt;/h3&gt;

&lt;p&gt;Switching payment providers doesn't require changing &lt;code&gt;CheckoutService&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easier to Test
&lt;/h3&gt;

&lt;p&gt;We can provide a fake payment processor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FakePaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fake payment&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can test checkout logic without making a real payment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Less Coupling
&lt;/h3&gt;

&lt;p&gt;Business logic isn't tied to a specific technology.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Extensibility
&lt;/h3&gt;

&lt;p&gt;Adding another implementation doesn't require modifying the high-level module.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;DIP Isn't About Interfaces Everywhere&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There's another common misunderstanding.&lt;/p&gt;

&lt;p&gt;DIP doesn't mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create an interface for every class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That would quickly turn a simple application into an unnecessarily complicated one.&lt;/p&gt;

&lt;p&gt;The real question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which dependencies represent decisions or details that are likely to vary?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are the places where abstractions become valuable.&lt;/p&gt;

&lt;p&gt;If something is simple, stable, and unlikely to change, introducing another abstraction may only add complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Bigger Picture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now look at what we've covered across SOLID.&lt;/p&gt;

&lt;p&gt;SRP tells us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep responsibilities focused.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OCP tells us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The system should be open for extension but closed for modification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;LSP tells us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Child Entities preserve the behaviour clients expect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ISP tells us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep interfaces focused.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DIP tells us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't tightly couple business logic to implementation details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These aren't isolated rules.&lt;/p&gt;

&lt;p&gt;They work together.&lt;/p&gt;

&lt;p&gt;And together, they help us build scalable and maintainable software.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Dependency Inversion isn't about avoiding dependencies.&lt;/p&gt;

&lt;p&gt;Software will always have dependencies.&lt;/p&gt;

&lt;p&gt;The goal is to control &lt;strong&gt;which direction those dependencies point&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your business logic shouldn't have to know whether data comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;REST API&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or whether a payment is processed through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stripe&lt;/li&gt;
&lt;li&gt;Razorpay&lt;/li&gt;
&lt;li&gt;PayPal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are implementation details.&lt;/p&gt;

&lt;p&gt;The business logic should depend on abstractions that represent what it actually needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now completed all five SOLID principles.&lt;/p&gt;

&lt;p&gt;But one important concept has appeared repeatedly throughout this article:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Injection.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We've used it without fully exploring it.&lt;/p&gt;

&lt;p&gt;So in the next article, we'll take a step back and ask a very practical question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why should a class create its own dependencies when someone else can provide them?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We'll explore &lt;strong&gt;Dependency Injection&lt;/strong&gt;, understand the problem it solves, and see how it works in real JavaScript and TypeScript applications.&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>dip</category>
      <category>architecture</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Interface Segregation Principle (ISP): Why Should a Class Implement What It Doesn't Need?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Tue, 11 Aug 2026 13:27:55 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/interface-segregation-principle-isp-why-should-a-class-implement-what-it-doesnt-need-2mn</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/interface-segregation-principle-isp-why-should-a-class-implement-what-it-doesnt-need-2mn</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy9yw2kn2jvg8u02yn3jm.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy9yw2kn2jvg8u02yn3jm.png" alt="ISP" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far, we've explored three SOLID principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility Principle (SRP)&lt;/strong&gt; — keep responsibilities together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open/Closed Principle (OCP)&lt;/strong&gt; — make software easier to extend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liskov Substitution Principle (LSP)&lt;/strong&gt; — objects of a superclass should be replaceable with objects of its subclasses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's look at the fourth principle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interface Segregation Principle (ISP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The formal definition says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Clients should not be forced to depend on interfaces they do not use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds reasonable.&lt;/p&gt;

&lt;p&gt;But what does that actually mean?&lt;/p&gt;

&lt;p&gt;Let's start with a problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine we're building an application for managing employees.&lt;/p&gt;

&lt;p&gt;Different employees can perform different actions.&lt;/p&gt;

&lt;p&gt;Some employees can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work&lt;/li&gt;
&lt;li&gt;Attend meetings&lt;/li&gt;
&lt;li&gt;Take breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Approve expenses&lt;/li&gt;
&lt;li&gt;Manage teams&lt;/li&gt;
&lt;li&gt;Conduct interviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we create an interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;attendMeeting&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;takeBreak&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;approveExpenses&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;conductInterview&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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;Looks convenient.&lt;/p&gt;

&lt;p&gt;Everything related to an employee is in one place.&lt;/p&gt;

&lt;p&gt;Now let's create a regular developer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Developer&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Writing code...&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="nf"&gt;attendMeeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Attending meeting...&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="nf"&gt;takeBreak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Taking a break...&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="nf"&gt;approveExpenses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Not applicable&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;conductInterview&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Not applicable&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;We have a problem.&lt;/p&gt;

&lt;p&gt;The developer is being forced to implement methods that don't make sense for them.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The "Not Applicable" Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We might try to solve this by throwing an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;approveExpenses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Developers cannot approve expenses.&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or perhaps we leave the method empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;approveExpenses&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;Neither solution feels right.&lt;/p&gt;

&lt;p&gt;Why should a &lt;code&gt;Developer&lt;/code&gt; be required to implement something that isn't part of its responsibility?&lt;/p&gt;

&lt;p&gt;The problem isn't with the developer.&lt;/p&gt;

&lt;p&gt;The problem is with our interface.&lt;/p&gt;

&lt;p&gt;We've created an interface that is trying to represent &lt;strong&gt;too many things at once&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Idea Behind ISP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of one large interface, we can split it into smaller, focused interfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Worker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MeetingParticipant&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;attendMeeting&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BreakTaker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;takeBreak&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ExpenseApprover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;approveExpenses&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Interviewer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;conductInterview&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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 a developer can implement only what they actually need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Developer&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MeetingParticipant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BreakTaker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Writing code...&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="nf"&gt;attendMeeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Attending meeting...&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="nf"&gt;takeBreak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Taking a break...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A manager might implement more capabilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Manager&lt;/span&gt;
  &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MeetingParticipant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BreakTaker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ExpenseApprover&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Interviewer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;attendMeeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;takeBreak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;approveExpenses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;conductInterview&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 our design represents reality much better.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Does This Matter?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At first, this might seem like a small improvement.&lt;/p&gt;

&lt;p&gt;But imagine the application becomes much larger.&lt;/p&gt;

&lt;p&gt;Suppose dozens of classes implement our original &lt;code&gt;Employee&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;Now we decide to add a new method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nf"&gt;generatePayrollReport&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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;Suddenly every class implementing &lt;code&gt;Employee&lt;/code&gt; has to deal with this new method.&lt;/p&gt;

&lt;p&gt;Even classes that have absolutely nothing to do with payroll.&lt;/p&gt;

&lt;p&gt;This is one of the hidden costs of large interfaces.&lt;/p&gt;

&lt;p&gt;A change in one part of an interface can force unrelated classes to change.&lt;/p&gt;

&lt;p&gt;That's exactly the kind of coupling ISP tries to reduce.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;ISP Isn't About Creating Tiny Interfaces Everywhere&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is important.&lt;/p&gt;

&lt;p&gt;After learning ISP, it's easy to go too far.&lt;/p&gt;

&lt;p&gt;You might end up creating interfaces like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanCreate&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanUpdate&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanDelete&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanRead&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And suddenly the codebase has hundreds of interfaces.&lt;/p&gt;

&lt;p&gt;That's not the goal.&lt;/p&gt;

&lt;p&gt;The goal isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make every interface as small as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't force a client to depend on behaviour it doesn't need.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes a larger interface genuinely represents one cohesive concept.&lt;/p&gt;

&lt;p&gt;There's nothing wrong with that.&lt;/p&gt;

&lt;p&gt;The problem begins when unrelated responsibilities are bundled together.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;A Simple Way to Think About ISP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Whenever you're designing an interface, ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does every implementation actually need all of these methods?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is repeatedly "no", that's a signal that the interface may be doing too much.&lt;/p&gt;

&lt;p&gt;Another useful question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I add a new method to this interface, how many unrelated classes will I have to change?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is "a lot", you may have a fat interface.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;ISP and Real-World APIs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This principle isn't limited to classes.&lt;/p&gt;

&lt;p&gt;The same thinking applies to APIs and modules.&lt;/p&gt;

&lt;p&gt;Imagine a service exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateReport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMarketingEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exportFinancialData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A component that only needs to create users shouldn't necessarily depend on everything the service can do.&lt;/p&gt;

&lt;p&gt;Smaller, focused contracts make dependencies clearer.&lt;/p&gt;

&lt;p&gt;This becomes especially important when we start discussing &lt;strong&gt;Dependency Inversion&lt;/strong&gt; and &lt;strong&gt;Dependency Injection&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Interface Segregation Principle is essentially about avoiding unnecessary dependencies.&lt;/p&gt;

&lt;p&gt;Instead of creating one large interface that tries to describe everything, create focused contracts around meaningful capabilities.&lt;/p&gt;

&lt;p&gt;That way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes implement only what they need.&lt;/li&gt;
&lt;li&gt;Changes affect fewer parts of the system.&lt;/li&gt;
&lt;li&gt;Dependencies become clearer.&lt;/li&gt;
&lt;li&gt;Interfaces become easier to understand and maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important thing isn't the number of methods in an interface.&lt;/p&gt;

&lt;p&gt;It's whether those methods belong together from the perspective of the clients using them.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now covered four of the five SOLID principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SRP&lt;/strong&gt; — Keep responsibilities focused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCP&lt;/strong&gt; — Extend behaviour without constantly modifying existing code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LSP&lt;/strong&gt; — Subtypes should genuinely be replaceable for their parent types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISP&lt;/strong&gt; — Don't force clients to depend on things they don't need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One principle remains.&lt;/p&gt;

&lt;p&gt;And arguably, it's the one that connects many of the ideas we've discussed so far.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Inversion Principle (DIP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll explore why high-level business logic shouldn't be tightly coupled to low-level implementation details—and how this idea eventually leads us to &lt;strong&gt;Dependency Injection&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>isp</category>
      <category>solidprinciples</category>
      <category>architecture</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Liskov Substitution Principle (LSP): Can Every Child Truly Replace Its Parent?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Mon, 03 Aug 2026 04:37:08 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/liskov-substitution-principle-lsp-can-every-child-truly-replace-its-parent-3h0o</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/liskov-substitution-principle-lsp-can-every-child-truly-replace-its-parent-3h0o</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz7mcz8za6j3zfu8db9v3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz7mcz8za6j3zfu8db9v3.png" alt="LSP" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far in this series, we've explored two of the SOLID principles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility Principle (SRP)&lt;/strong&gt; taught us to design classes with one clear responsibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open/Closed Principle (OCP)&lt;/strong&gt; showed us how to extend software without constantly modifying existing, stable code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now it's time to look at what is often considered the most misunderstood SOLID principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Liskov Substitution Principle (LSP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Its formal definition is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's... a mouthful.&lt;/p&gt;

&lt;p&gt;The definition is technically correct, but it doesn't tell us &lt;strong&gt;why&lt;/strong&gt; this principle exists.&lt;/p&gt;

&lt;p&gt;So, like every article in this series, let's start with a problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine we're building a payment system.&lt;/p&gt;

&lt;p&gt;Every payment method should support refunds.&lt;/p&gt;

&lt;p&gt;So we create a base class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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 we implement different payment methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPayment&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment successful.&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="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Refund successful.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything works perfectly.&lt;/p&gt;

&lt;p&gt;Later, the business introduces &lt;strong&gt;Cash on Delivery (COD)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Naturally, we extend the same parent class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CashOnDeliveryPayment&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Customer will pay on delivery.&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="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Refunds are not supported.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application compiles.&lt;/p&gt;

&lt;p&gt;The inheritance hierarchy looks correct.&lt;/p&gt;

&lt;p&gt;But do we actually have a valid substitute for &lt;code&gt;PaymentMethod&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Not really.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What goes wrong?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Somewhere else in the application, another developer writes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cancelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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 function doesn't care whether it's dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credit Card&lt;/li&gt;
&lt;li&gt;UPI&lt;/li&gt;
&lt;li&gt;PayPal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It simply assumes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every PaymentMethod supports refunds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That assumption was true...&lt;/p&gt;

&lt;p&gt;Until &lt;code&gt;CashOnDeliveryPayment&lt;/code&gt; appeared.&lt;/p&gt;

&lt;p&gt;Now the application crashes.&lt;/p&gt;

&lt;p&gt;The problem isn't the function.&lt;/p&gt;

&lt;p&gt;The problem is that one child class broke the expectations established by its parent.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Real Meaning of LSP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Liskov Substitution Principle asks a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If I replace a parent object with one of its children, should the rest of the program continue to work correctly?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is &lt;strong&gt;no&lt;/strong&gt;, the inheritance relationship is probably incorrect.&lt;/p&gt;

&lt;p&gt;The child isn't truly behaving like the parent promised.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Another Famous Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Perhaps you've seen this example before.&lt;/p&gt;

&lt;p&gt;Imagine we model shapes like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shape
├── Rectangle
└── Square
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sounds perfectly reasonable.&lt;/p&gt;

&lt;p&gt;After all...&lt;/p&gt;

&lt;p&gt;A square &lt;strong&gt;is&lt;/strong&gt; a rectangle.&lt;/p&gt;

&lt;p&gt;Right?&lt;/p&gt;

&lt;p&gt;Let's see.&lt;/p&gt;

&lt;p&gt;A rectangle allows width and height to change independently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine &lt;code&gt;Square&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Whenever we change the width, we must also change the height.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;square&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Height automatically becomes 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now consider this function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;resizeRectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&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="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getArea&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;If we pass a normal rectangle...&lt;/p&gt;

&lt;p&gt;Area = &lt;strong&gt;50&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we pass a square...&lt;/p&gt;

&lt;p&gt;Area = &lt;strong&gt;100&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The function behaves differently because the child changed the expectations established by the parent.&lt;/p&gt;

&lt;p&gt;The inheritance relationship looked correct mathematically.&lt;/p&gt;

&lt;p&gt;It wasn't correct from a software design perspective.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Root Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The issue isn't inheritance.&lt;/p&gt;

&lt;p&gt;The issue is a &lt;strong&gt;bad abstraction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inheritance creates expectations.&lt;/p&gt;

&lt;p&gt;Whenever we inherit from a parent class, we're making a promise.&lt;/p&gt;

&lt;p&gt;We're saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can use me anywhere you use my parent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If that promise isn't true...&lt;/p&gt;

&lt;p&gt;Inheritance becomes dangerous.&lt;/p&gt;

&lt;p&gt;Other developers begin making assumptions - that aren't always valid.&lt;/p&gt;

&lt;p&gt;Those assumptions eventually become bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;LSP Is About Behaviour, Not Hierarchy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the biggest misconceptions is thinking LSP is about inheritance syntax.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;The compiler only checks whether a child inherits correctly.&lt;/p&gt;

&lt;p&gt;LSP asks something deeper.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Does the child preserve the behaviour clients expect?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two classes may have identical methods.&lt;/p&gt;

&lt;p&gt;They may even share the same parent.&lt;/p&gt;

&lt;p&gt;Yet one may still violate LSP if it behaves differently in unexpected ways.&lt;/p&gt;

&lt;p&gt;Behaviour matters more than hierarchy.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How to Spot an LSP Violation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here are a few warning signs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A child throws &lt;code&gt;UnsupportedOperationException&lt;/code&gt; or similar errors for inherited methods.&lt;/li&gt;
&lt;li&gt;A child ignores methods defined by the parent.&lt;/li&gt;
&lt;li&gt;Client code starts checking object types before calling methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;CashOnDeliveryPayment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Skip refund&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever you find yourself writing lots of &lt;code&gt;instanceof&lt;/code&gt; checks for subclasses, it's often a sign that the inheritance hierarchy isn't modelling the problem correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;A Better Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of forcing every payment method to support refunds, separate the capabilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Refundable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credit Card implements both.&lt;/li&gt;
&lt;li&gt;PayPal implements both.&lt;/li&gt;
&lt;li&gt;Cash on Delivery only implements &lt;code&gt;PaymentMethod&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No fake implementations.&lt;/p&gt;

&lt;p&gt;No unexpected exceptions.&lt;/p&gt;

&lt;p&gt;No broken promises.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Liskov Substitution Principle teaches us that inheritance isn't just about sharing code.&lt;/p&gt;

&lt;p&gt;It's about preserving expectations.&lt;/p&gt;

&lt;p&gt;Whenever a child class replaces its parent, the rest of the application should continue to work without knowing the difference.&lt;/p&gt;

&lt;p&gt;If client code needs special cases for certain subclasses, or if some subclasses can't persist the behaviour promised by the parent, the inheritance hierarchy probably needs another look.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now covered three SOLID principles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SRP&lt;/strong&gt; helped us design focused classes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCP&lt;/strong&gt; taught us to extend behaviour without modifying stable code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LSP&lt;/strong&gt; reminded us that inheritance should preserve behaviour, not just structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we'll explore the &lt;strong&gt;Interface Segregation Principle (ISP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We'll answer another practical question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why is forcing classes to implement methods they don't need considered a design problem?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>solidprinciples</category>
      <category>lsp</category>
      <category>architecture</category>
      <category>designsystem</category>
    </item>
    <item>
      <title>Open/Closed Principle (OCP): How Do We Add Features Without Breaking Existing Code?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Wed, 29 Jul 2026 07:26:39 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/openclosed-principle-ocp-how-do-we-add-features-without-breaking-existing-code-2j8j</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/openclosed-principle-ocp-how-do-we-add-features-without-breaking-existing-code-2j8j</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdoytmhywsvpg5bv826dy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdoytmhywsvpg5bv826dy.png" alt="OCP" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous article, we discussed the Single Responsibility Principle (SRP) and learned that a class should have one clear reason to change.&lt;/p&gt;

&lt;p&gt;Now let's look at the second SOLID principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open/Closed Principle (OCP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This principle is often summarized as:&lt;/p&gt;

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

&lt;p&gt;It's a famous definition.&lt;/p&gt;

&lt;p&gt;It's also one of the most misunderstood.&lt;/p&gt;

&lt;p&gt;The obvious question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can something be open and closed at the same time?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's start with the problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;Initially, the business only supports two payment methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credit Card&lt;/li&gt;
&lt;li&gt;UPI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;credit-card&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing credit card payment...&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="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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;upi&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing UPI payment...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything works.&lt;/p&gt;

&lt;p&gt;A month later, the business wants to support PayPal.&lt;/p&gt;

&lt;p&gt;So we modify the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paypal&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="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 few weeks later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apple Pay&lt;/li&gt;
&lt;li&gt;Bank Transfer&lt;/li&gt;
&lt;li&gt;Gift Cards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every new payment method requires editing the same function.&lt;/p&gt;

&lt;p&gt;Again.&lt;/p&gt;

&lt;p&gt;And again.&lt;/p&gt;

&lt;p&gt;And again.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's the Real Problem?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At first glance, modifying the function doesn't seem like a problem.&lt;/p&gt;

&lt;p&gt;After all, adding new functionality usually means changing code.&lt;/p&gt;

&lt;p&gt;But consider this.&lt;/p&gt;

&lt;p&gt;That payment function is already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tested.&lt;/li&gt;
&lt;li&gt;Used by multiple parts of the application.&lt;/li&gt;
&lt;li&gt;Running successfully in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every modification introduces risk.&lt;/p&gt;

&lt;p&gt;A small mistake while adding Apple Pay could accidentally break UPI payments.&lt;/p&gt;

&lt;p&gt;The more frequently we modify stable code, the greater the chance of introducing bugs.&lt;/p&gt;

&lt;p&gt;The problem isn't adding new features.&lt;/p&gt;

&lt;p&gt;The problem is having to modify existing, working code every time a new requirement appears.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Idea Behind OCP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Open/Closed Principle encourages us to design software so that new behaviour can be added without modifying existing, tested code.&lt;/p&gt;

&lt;p&gt;Notice the wording.&lt;/p&gt;

&lt;p&gt;It doesn't say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never modify code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's unrealistic.&lt;/p&gt;

&lt;p&gt;Instead, it asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can we design our code so new features are added by extending it rather than editing it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a subtle but powerful shift in thinking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Question
&lt;/h3&gt;

&lt;p&gt;If you were designing this using what you've already learned about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Abstraction&lt;/li&gt;
&lt;li&gt;Interfaces&lt;/li&gt;
&lt;li&gt;Polymorphism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How would you avoid the growing chain of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;credit-card&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing credit card payment...&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="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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;upi&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing UPI payment...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;A Better Approach&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of one function knowing about every payment method, each payment method can be responsible for processing itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Applying Polymorphism&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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 we create separate implementations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPayment&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing credit card payment...&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpiPayment&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing UPI payment...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The checkout process no longer needs to know which payment method it's dealing with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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;Now suppose the business wants to support PayPal.&lt;/p&gt;

&lt;p&gt;Do we modify checkout()?&lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;We simply create another implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing PayPal payment...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The existing checkout logic remains untouched.&lt;/p&gt;

&lt;p&gt;We've extended the system without modifying stable code.&lt;/p&gt;

&lt;p&gt;That's exactly what OCP is encouraging.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Changed?
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;DiscountService&lt;/span&gt;
   &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="nx"&gt;knows&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;discount&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;DiscountService&lt;/span&gt;
   &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="nx"&gt;knows&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;DiscountStrategy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That's abstraction.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Is This Useful?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Following OCP provides several benefits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less Risk&lt;/li&gt;
&lt;li&gt;Existing, tested code remains unchanged.&lt;/li&gt;
&lt;li&gt;Easier Feature Development&lt;/li&gt;
&lt;li&gt;New functionality is added instead of squeezed into existing logic.&lt;/li&gt;
&lt;li&gt;Better Team Collaboration&lt;/li&gt;
&lt;li&gt;Different developers can work on new features without constantly editing the same files.&lt;/li&gt;
&lt;li&gt;Improved Maintainability&lt;/li&gt;
&lt;li&gt;The system naturally grows by adding new pieces instead of making one central component increasingly complex.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Does OCP Mean Never Modify Existing Code?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not at all.&lt;/p&gt;

&lt;p&gt;This is probably the biggest misconception.&lt;/p&gt;

&lt;p&gt;Sometimes modifying existing code is absolutely the right thing to do.&lt;/p&gt;

&lt;p&gt;If you discover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bug&lt;/li&gt;
&lt;li&gt;Poor design&lt;/li&gt;
&lt;li&gt;Duplicate logic&lt;/li&gt;
&lt;li&gt;Performance issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should improve it.&lt;/p&gt;

&lt;p&gt;OCP isn't about avoiding modifications at all costs.&lt;/p&gt;

&lt;p&gt;It's about designing systems where expected future changes are handled through extension rather than repeatedly editing the same code.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Trade-offs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Like every design principle, OCP isn't free.&lt;/p&gt;

&lt;p&gt;Supporting extension often means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More interfaces.&lt;/li&gt;
&lt;li&gt;More abstractions.&lt;/li&gt;
&lt;li&gt;More classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your application is small or unlikely to change, these extra layers may provide little value.&lt;/p&gt;

&lt;p&gt;The goal isn't to predict every future requirement.&lt;/p&gt;

&lt;p&gt;It's to recognise areas of the system that are likely to evolve and design those areas thoughtfully.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now explored two SOLID principles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SRP taught us to give each class one clear responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OCP taught us how to extend behaviour without repeatedly modifying stable code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, we'll tackle one of the most debated principles in software design:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Liskov Substitution Principle (LSP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll answer an interesting question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just because one class inherits from another, does it really mean it can replace it?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>solidprinciples</category>
      <category>ocp</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Single Responsibility Principle (SRP): How Much Responsibility Should a Class Really Have?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Mon, 27 Jul 2026 06:59:08 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/single-responsibility-principle-srp-how-much-responsibility-should-a-class-really-have-2564</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/single-responsibility-principle-srp-how-much-responsibility-should-a-class-really-have-2564</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kmnb5lccipebld8zkaz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kmnb5lccipebld8zkaz.png" alt="SRP" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous article, we discussed why Object-Oriented Programming alone wasn't enough and how the SOLID principles emerged to help developers design more maintainable software.&lt;/p&gt;

&lt;p&gt;Today, we'll explore the first principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single Responsibility Principle (SRP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many developers hear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A class should have only one responsibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then immediately wonder:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does that mean a class should have only one method?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Should every class do just one tiny thing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;Let's understand the problem SRP was trying to solve.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine we're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;We create an OrderService.&lt;/p&gt;

&lt;p&gt;Initially, its job is simple.&lt;/p&gt;

&lt;p&gt;OrderService&lt;/p&gt;

&lt;p&gt;✓ Create Order&lt;/p&gt;

&lt;p&gt;Everything looks fine.&lt;/p&gt;

&lt;p&gt;As the application grows, new requirements arrive.&lt;/p&gt;

&lt;p&gt;"We need to calculate discounts."&lt;/p&gt;

&lt;p&gt;No problem.&lt;/p&gt;

&lt;p&gt;OrderService&lt;/p&gt;

&lt;p&gt;✓ Create Order&lt;br&gt;
✓ Calculate Discount&lt;/p&gt;

&lt;p&gt;A week later:&lt;/p&gt;

&lt;p&gt;"We should send a confirmation email."&lt;/p&gt;

&lt;p&gt;OrderService&lt;/p&gt;

&lt;p&gt;✓ Create Order&lt;br&gt;
✓ Calculate Discount&lt;br&gt;
✓ Send Email&lt;/p&gt;

&lt;p&gt;A month later:&lt;/p&gt;

&lt;p&gt;"We also need to generate invoices."&lt;/p&gt;

&lt;p&gt;OrderService&lt;/p&gt;

&lt;p&gt;✓ Create Order&lt;br&gt;
✓ Calculate Discount&lt;br&gt;
✓ Send Email&lt;br&gt;
✓ Generate Invoice&lt;/p&gt;

&lt;p&gt;Then someone asks for audit logs.&lt;/p&gt;

&lt;p&gt;Inventory updates.&lt;/p&gt;

&lt;p&gt;Loyalty points.&lt;/p&gt;

&lt;p&gt;Analytics.&lt;/p&gt;

&lt;p&gt;Before long, the class looks like this:&lt;/p&gt;

&lt;p&gt;OrderService&lt;/p&gt;

&lt;p&gt;✓ Create Order&lt;br&gt;
✓ Calculate Discount&lt;br&gt;
✓ Process Payment&lt;br&gt;
✓ Update Inventory&lt;br&gt;
✓ Generate Invoice&lt;br&gt;
✓ Send Email&lt;br&gt;
✓ Record Analytics&lt;br&gt;
✓ Write Audit Logs&lt;/p&gt;

&lt;p&gt;The application still works.&lt;/p&gt;

&lt;p&gt;But something feels wrong.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;What's the Real Problem?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The issue isn't the number of methods.&lt;/p&gt;

&lt;p&gt;The issue is that the class is trying to solve too many different problems.&lt;/p&gt;

&lt;p&gt;Think about who might request changes.&lt;/p&gt;

&lt;p&gt;The finance team may ask for invoice changes.&lt;/p&gt;

&lt;p&gt;The marketing team may introduce a new discount strategy.&lt;/p&gt;

&lt;p&gt;Operations may change inventory rules.&lt;/p&gt;

&lt;p&gt;Customer support may request a different email template.&lt;/p&gt;

&lt;p&gt;Analytics may require new tracking events.&lt;/p&gt;

&lt;p&gt;Every team has a different reason to modify the same class.&lt;/p&gt;

&lt;p&gt;Now imagine multiple developers working on it simultaneously.&lt;/p&gt;

&lt;p&gt;Merge conflicts become common.&lt;/p&gt;

&lt;p&gt;Testing becomes more difficult.&lt;/p&gt;

&lt;p&gt;A small change in one area can accidentally affect another.&lt;/p&gt;

&lt;p&gt;The class has become a bottleneck.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;The Idea Behind SRP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is where the Single Responsibility Principle comes in.&lt;/p&gt;

&lt;p&gt;It says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A class should have one, and only one, reason to change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice something important.&lt;/p&gt;

&lt;p&gt;It doesn't say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It doesn't say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One line of code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One reason to change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A responsibility isn't defined by the amount of code.&lt;/p&gt;

&lt;p&gt;It's defined by the purpose the class serves.&lt;/p&gt;

&lt;p&gt;Breaking Responsibilities Apart&lt;/p&gt;

&lt;p&gt;Instead of putting everything into one class, we separate concerns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OrderService
    │
    ├── DiscountService
    ├── PaymentService
    ├── InventoryService
    ├── EmailService
    ├── InvoiceService
    └── AnalyticsService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now each class has a clear responsibility.&lt;/p&gt;

&lt;p&gt;If invoice generation changes, we modify InvoiceService.&lt;/p&gt;

&lt;p&gt;If email templates change, we modify EmailService.&lt;/p&gt;

&lt;p&gt;If discount rules change, we modify DiscountService.&lt;/p&gt;

&lt;p&gt;Each class evolves independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Another Real-World Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Think about a restaurant.&lt;/p&gt;

&lt;p&gt;One person could:&lt;/p&gt;

&lt;p&gt;Take orders.&lt;br&gt;
Cook food.&lt;br&gt;
Wash dishes.&lt;br&gt;
Manage inventory.&lt;br&gt;
Handle payments.&lt;br&gt;
Clean tables.&lt;/p&gt;

&lt;p&gt;Technically, it's possible.&lt;/p&gt;

&lt;p&gt;But would it be efficient?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;Restaurants divide responsibilities because specialization makes the system easier to manage.&lt;/p&gt;

&lt;p&gt;Software is no different.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What SRP Doesn't Mean&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SRP is often misunderstood.&lt;/p&gt;

&lt;p&gt;It doesn't mean:&lt;/p&gt;

&lt;p&gt;❌ Every class should contain only one method.&lt;/p&gt;

&lt;p&gt;❌ Every file should be tiny.&lt;/p&gt;

&lt;p&gt;❌ Every function deserves its own class.&lt;/p&gt;

&lt;p&gt;Those interpretations usually lead to unnecessary complexity.&lt;/p&gt;

&lt;p&gt;Instead, ask yourself:&lt;/p&gt;

&lt;p&gt;Does this class represent one clear responsibility?&lt;/p&gt;

&lt;p&gt;If the answer is yes, you're likely on the right track.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Benefits of SRP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Following SRP makes software easier to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand&lt;/li&gt;
&lt;li&gt;Test&lt;/li&gt;
&lt;li&gt;Maintain&lt;/li&gt;
&lt;li&gt;Extend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also reduces the chances that unrelated changes will accidentally affect each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Are There Trade-offs?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Absolutely.&lt;/p&gt;

&lt;p&gt;Like every design principle, SRP can be overused.&lt;/p&gt;

&lt;p&gt;If every tiny operation becomes its own class, you'll end up with hundreds of small classes that are difficult to navigate.&lt;/p&gt;

&lt;p&gt;Good software design is about balance.&lt;/p&gt;

&lt;p&gt;Split responsibilities when they truly represent different reasons to change.&lt;/p&gt;

&lt;p&gt;Don't split code simply because you can.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've learned how to design classes with focused responsibilities.&lt;/p&gt;

&lt;p&gt;But another challenge still remains.&lt;/p&gt;

&lt;p&gt;What happens when a new feature requires changing an existing, well-tested class?&lt;/p&gt;

&lt;p&gt;Should we keep modifying it?&lt;/p&gt;

&lt;p&gt;Or is there a better way?&lt;/p&gt;

&lt;p&gt;In the next article, we'll explore the &lt;strong&gt;Open/Closed Principle (OCP)&lt;/strong&gt; and learn why software should be open for extension but closed for modification.&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>srp</category>
      <category>oop</category>
    </item>
    <item>
      <title>Why OOP Wasn't Enough: The Problems That Led to SOLID</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Fri, 24 Jul 2026 06:01:52 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/why-oop-wasnt-enough-the-problems-that-led-to-solid-2074</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/why-oop-wasnt-enough-the-problems-that-led-to-solid-2074</guid>
      <description>&lt;p&gt;Over the last few articles, we've explored the core concepts of Object-Oriented Programming.&lt;/p&gt;

&lt;p&gt;We discussed why OOP was introduced, how objects help us organize code, and how concepts like Encapsulation, Abstraction, Inheritance, Composition, and Polymorphism make software easier to build and maintain.&lt;/p&gt;

&lt;p&gt;At this point, it might seem like we've found the perfect solution.&lt;/p&gt;

&lt;p&gt;So why did developers feel the need to introduce another set of principles called SOLID?&lt;/p&gt;

&lt;p&gt;Wasn't OOP enough?&lt;/p&gt;

&lt;p&gt;The short answer is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OOP gave us powerful tools, but it didn't tell us how to use them well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's understand why.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Early Days of OOP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When Object-Oriented Programming became popular, developers finally had a better way to organize software.&lt;/p&gt;

&lt;p&gt;Instead of scattering related data and functions across an application, they could model real-world entities as objects.&lt;/p&gt;

&lt;p&gt;It was a huge improvement.&lt;/p&gt;

&lt;p&gt;Applications became easier to understand.&lt;/p&gt;

&lt;p&gt;Code became more reusable.&lt;/p&gt;

&lt;p&gt;Responsibilities felt more organized.&lt;/p&gt;

&lt;p&gt;For a while, everything seemed to be moving in the right direction.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Then Applications Started Growing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As software evolved, projects became much larger than anyone had imagined.&lt;/p&gt;

&lt;p&gt;Applications that once had a few dozen classes now had hundreds.&lt;/p&gt;

&lt;p&gt;Large enterprise systems contained thousands of classes maintained by multiple teams.&lt;/p&gt;

&lt;p&gt;And a new kind of problem started appearing.&lt;/p&gt;

&lt;p&gt;The problem was no longer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we organize code?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we organize large codebases?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simply using classes and objects wasn't enough anymore.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;OOP Doesn't Prevent Bad Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's imagine we're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;We create a class called Order.&lt;/p&gt;

&lt;p&gt;At first, it seems reasonable.&lt;/p&gt;

&lt;p&gt;It stores order details.&lt;/p&gt;

&lt;p&gt;Then we add price calculations.&lt;/p&gt;

&lt;p&gt;Later, invoice generation.&lt;/p&gt;

&lt;p&gt;Then payment processing.&lt;/p&gt;

&lt;p&gt;Email notifications.&lt;/p&gt;

&lt;p&gt;Inventory updates.&lt;/p&gt;

&lt;p&gt;Discount calculations.&lt;/p&gt;

&lt;p&gt;Audit logging.&lt;/p&gt;

&lt;p&gt;Before we realize it, our class looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;calculateTotal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;sendConfirmationEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;generateInvoice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;updateInventory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;writeAuditLog&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nf"&gt;exportPDF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, it's Object-Oriented.&lt;/p&gt;

&lt;p&gt;It uses a class.&lt;/p&gt;

&lt;p&gt;It encapsulates data.&lt;/p&gt;

&lt;p&gt;But is it well-designed?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;The class has become responsible for almost every part of the order lifecycle.&lt;/p&gt;

&lt;p&gt;Changing one feature increases the risk of breaking another.&lt;/p&gt;

&lt;p&gt;Testing becomes harder.&lt;/p&gt;

&lt;p&gt;Understanding the class becomes harder.&lt;/p&gt;

&lt;p&gt;Maintaining it becomes harder.&lt;/p&gt;

&lt;p&gt;The problem wasn't OOP.&lt;/p&gt;

&lt;p&gt;The problem was how we were using OOP.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Classes Became Too Dependent on Each Other&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Another issue appeared.&lt;/p&gt;

&lt;p&gt;Imagine a payment service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OrderService
    │
    ▼
StripePaymentService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The OrderService creates and depends directly on StripePaymentService.&lt;/p&gt;

&lt;p&gt;Everything works.&lt;/p&gt;

&lt;p&gt;Until the business says:&lt;/p&gt;

&lt;p&gt;"We're moving to Razorpay."&lt;/p&gt;

&lt;p&gt;Now changes are needed in multiple places.&lt;/p&gt;

&lt;p&gt;The higher-level business logic is tightly coupled to a specific implementation.&lt;/p&gt;

&lt;p&gt;Again...&lt;/p&gt;

&lt;p&gt;OOP didn't prevent this.&lt;/p&gt;

&lt;p&gt;It allowed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Reusing Code Sometimes Made Things Worse&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inheritance was introduced to reduce duplication.&lt;/p&gt;

&lt;p&gt;But many applications started building deep inheritance hierarchies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Employee
    │
    ├── Manager
    │      ├── RegionalManager
    │      │       └── SeniorRegionalManager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initially, it looked elegant.&lt;/p&gt;

&lt;p&gt;Over time, it became difficult to understand.&lt;/p&gt;

&lt;p&gt;A change in a parent class unexpectedly affected several child classes.&lt;/p&gt;

&lt;p&gt;Developers realized that simply because something can inherit doesn't always mean it should.&lt;/p&gt;

&lt;p&gt;This realization eventually led to the idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Favor Composition Over Inheritance.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Missing Piece&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At this point, developers had all the building blocks.&lt;/p&gt;

&lt;p&gt;They had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes&lt;/li&gt;
&lt;li&gt;Objects&lt;/li&gt;
&lt;li&gt;Encapsulation&lt;/li&gt;
&lt;li&gt;Abstraction&lt;/li&gt;
&lt;li&gt;Inheritance&lt;/li&gt;
&lt;li&gt;Polymorphism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But something was still missing.&lt;/p&gt;

&lt;p&gt;There were no clear guidelines for questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many responsibilities should a class have?&lt;/li&gt;
&lt;li&gt;When should existing code be modified?&lt;/li&gt;
&lt;li&gt;How should dependencies be managed?&lt;/li&gt;
&lt;li&gt;How should objects communicate?&lt;/li&gt;
&lt;li&gt;How do we build software that's easy to extend?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OOP answered:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What tools do we have?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Developers now needed answers to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How should we use those tools?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🏋️ Enter SOLID&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is where the SOLID principles come in.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Felgkegvsz2eddi7s7mbm.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Felgkegvsz2eddi7s7mbm.png" alt="Solid Principles" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SOLID isn't a replacement for Object-Oriented Programming.&lt;/p&gt;

&lt;p&gt;It builds on top of it.&lt;/p&gt;

&lt;p&gt;Think of it this way.&lt;/p&gt;

&lt;p&gt;OOP gives you the bricks, cement, and steel to construct a building.&lt;/p&gt;

&lt;p&gt;SOLID gives you architectural guidelines for using those materials wisely.&lt;/p&gt;

&lt;p&gt;Without those guidelines, you can still build a structure.&lt;/p&gt;

&lt;p&gt;It just might not be easy to maintain.&lt;/p&gt;

&lt;p&gt;What SOLID Tries to Achieve&lt;/p&gt;

&lt;p&gt;The SOLID principles encourage us to build software that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to understand.&lt;/li&gt;
&lt;li&gt;Easier to modify.&lt;/li&gt;
&lt;li&gt;Easier to test.&lt;/li&gt;
&lt;li&gt;Easier to extend.&lt;/li&gt;
&lt;li&gt;Less tightly coupled.&lt;/li&gt;
&lt;li&gt;More maintainable over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these principles are magical rules.&lt;/p&gt;

&lt;p&gt;They're lessons learned from years of building—and maintaining—large software systems.&lt;/p&gt;

&lt;p&gt;Most of them were born from mistakes developers repeatedly encountered in real-world projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Object-Oriented Programming solved many problems.&lt;/p&gt;

&lt;p&gt;It gave developers a better way to organize software.&lt;/p&gt;

&lt;p&gt;But it couldn't guarantee good design.&lt;/p&gt;

&lt;p&gt;You can write terrible Object-Oriented code.&lt;/p&gt;

&lt;p&gt;You can also write excellent Object-Oriented code.&lt;/p&gt;

&lt;p&gt;The difference isn't the programming paradigm.&lt;/p&gt;

&lt;p&gt;It's the design decisions you make.&lt;/p&gt;

&lt;p&gt;That's exactly what the SOLID principles try to improve.&lt;/p&gt;

&lt;p&gt;They don't teach us how to write Object-Oriented code.&lt;/p&gt;

&lt;p&gt;They teach us how to write better Object-Oriented code.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we understand why SOLID was introduced, we can finally explore the first principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Single Responsibility Principle (SRP).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll answer a deceptively simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How many responsibilities should a class really have?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you'll see, the answer isn't "one method" or "one task."&lt;/p&gt;

&lt;p&gt;It's much more interesting than that.&lt;/p&gt;

</description>
      <category>oop</category>
      <category>solidprinciples</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Polymorphism in OOP: One Interface, Multiple Implementations</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Tue, 30 Jun 2026 05:40:47 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/polymorphism-in-oop-one-interface-multiple-implementations-3ak6</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/polymorphism-in-oop-one-interface-multiple-implementations-3ak6</guid>
      <description>&lt;p&gt;Most developers memorize:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"One interface, many forms."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unfortunately, that definition is so abstract that it doesn't teach much.&lt;/p&gt;

&lt;p&gt;Let's understand the actual problem polymorphism solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🤯 The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose you're building a payment system.&lt;/p&gt;

&lt;p&gt;Without polymorphism:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;credit-card&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="c1"&gt;// credit card logic&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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paypal&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="c1"&gt;// paypal logic&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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;upi&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="c1"&gt;// upi logic&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;Works.&lt;/p&gt;

&lt;p&gt;Then the business says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add Stripe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You modify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stripe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next month:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add Apple Pay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify again.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add Crypto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify again.&lt;/p&gt;

&lt;p&gt;The class keeps growing.&lt;/p&gt;

&lt;p&gt;This violates a key design principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Existing code should not need constant modification when new behavior is added.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;✨ Polymorphism's Solution&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What type are you?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you perform this action?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a huge mindset shift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Create a contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PaymentProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="k"&gt;void&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;Implementations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPayment&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Credit Card&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="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 tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpiPayment&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PaymentProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPI&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PaymentProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPayment&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UpiPayment&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaypalPayment&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same method call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different behavior.&lt;/p&gt;

&lt;p&gt;This is polymorphism.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🧠 The Core Idea&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Polymorphism means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Treat different objects uniformly while allowing each object to behave differently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You don't care:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Credit Card
UPI
PayPal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You only care:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you process a payment?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real World Example
&lt;/h3&gt;

&lt;p&gt;Think about a power socket.&lt;/p&gt;

&lt;p&gt;You plug in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laptop charger&lt;/li&gt;
&lt;li&gt;Phone charger&lt;/li&gt;
&lt;li&gt;Fan&lt;/li&gt;
&lt;li&gt;TV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The socket doesn't ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Are you a Samsung charger?
Are you a Dell charger?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It only expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you accept electricity?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each device behaves differently after receiving power.&lt;/p&gt;

&lt;p&gt;That is polymorphism.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Interfaces Matter&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&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;p&gt;Implementation 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostgresUserRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementation 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MongoUserRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementation 3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InMemoryUserRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="nx"&gt;privaterepo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&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;Notice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;works regardless of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Postgres&lt;/span&gt;
&lt;span class="nx"&gt;Mongo&lt;/span&gt;
&lt;span class="nx"&gt;Memory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service doesn't care.&lt;/p&gt;

&lt;p&gt;That's polymorphism.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🔑 The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Polymorphism is often described as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"One interface, many forms."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A more practical way to think about it is:&lt;/p&gt;

&lt;p&gt;Different objects can respond to the same request in their own way.&lt;/p&gt;

&lt;p&gt;The caller doesn't need to know the implementation.&lt;/p&gt;

&lt;p&gt;It only needs to know the capability the object provides.&lt;/p&gt;

&lt;p&gt;This makes systems easier to extend without constantly modifying existing code.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;⏭️ What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With this article, we've completed the four core pillars commonly associated with Object-Oriented Programming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encapsulation&lt;/li&gt;
&lt;li&gt;Abstraction&lt;/li&gt;
&lt;li&gt;Inheritance&lt;/li&gt;
&lt;li&gt;Polymorphism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But understanding these concepts doesn't automatically lead to well-designed software.&lt;/p&gt;

&lt;p&gt;Developers soon realized that even OOP applications could become difficult to maintain if responsibilities weren't clearly defined.&lt;/p&gt;

&lt;p&gt;That realization gave rise to a new set of guidelines known as the SOLID Principles.&lt;/p&gt;

&lt;p&gt;In the next article, we'll explore why SOLID was introduced and the problems it was designed to solve.&lt;/p&gt;

</description>
      <category>polymorphism</category>
      <category>interfaces</category>
      <category>oop</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Composition vs Inheritance: Why Modern Software Often Prefers Composition</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Mon, 29 Jun 2026 07:31:09 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/composition-vs-inheritance-why-modern-software-often-prefers-composition-47m5</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/composition-vs-inheritance-why-modern-software-often-prefers-composition-47m5</guid>
      <description>&lt;p&gt;In the previous article, we learned that &lt;strong&gt;Inheritance&lt;/strong&gt; was introduced to solve a very real problem—&lt;strong&gt;code duplication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of writing the same behavior repeatedly, we could move common functionality into a parent class and let child classes inherit it.&lt;/p&gt;

&lt;p&gt;It sounded like the perfect solution.&lt;/p&gt;

&lt;p&gt;For a long time, many developers thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If two classes share some behavior, just use inheritance."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that's exactly what happened.&lt;/p&gt;

&lt;p&gt;Large applications started building deep inheritance hierarchies.&lt;/p&gt;

&lt;p&gt;Unfortunately, a new set of problems emerged.&lt;/p&gt;

&lt;p&gt;Let's understand why.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🤯 The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine we're building an application for different kinds of birds.&lt;/p&gt;

&lt;p&gt;We start with a base class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Flying...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we create different birds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sparrow&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Eagle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything looks good.&lt;/p&gt;

&lt;p&gt;Then someone asks us to add a Penguin.&lt;/p&gt;

&lt;p&gt;Naturally, we do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Penguin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But now we have a problem.&lt;/p&gt;

&lt;p&gt;Penguins don't fly.&lt;/p&gt;

&lt;p&gt;Yet every Penguin automatically inherits the &lt;code&gt;fly()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;penguin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Penguin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;penguin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, the code works.&lt;/p&gt;

&lt;p&gt;Logically, it doesn't.&lt;/p&gt;

&lt;p&gt;Our inheritance hierarchy is forcing behavior onto objects that shouldn't have it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trying to Fix It
&lt;/h3&gt;

&lt;p&gt;One common approach is overriding the method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Penguin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Penguins can't fly.&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This "fixes" the issue.&lt;/p&gt;

&lt;p&gt;But think about it.&lt;/p&gt;

&lt;p&gt;We inherited behavior only to disable it.&lt;/p&gt;

&lt;p&gt;That's usually a sign that our model isn't representing reality very well.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Root Cause&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inheritance creates a very strong relationship.&lt;/p&gt;

&lt;p&gt;When a class extends another class, it says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I am a specialized version of this parent."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a big commitment.&lt;/p&gt;

&lt;p&gt;The child automatically receives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;Methods&lt;/li&gt;
&lt;li&gt;Design decisions&lt;/li&gt;
&lt;li&gt;Future changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the parent evolves, every child is affected.&lt;/p&gt;

&lt;p&gt;Sometimes that's exactly what we want.&lt;/p&gt;

&lt;p&gt;Sometimes it becomes a maintenance headache.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;😐 A Different Way of Thinking&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What should this object inherit?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What capabilities does this object need?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the idea behind &lt;strong&gt;Composition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of inheriting behavior, we build objects by combining smaller, focused pieces.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;✨ Composition in Action&lt;/strong&gt;
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0zqsfiheydimfuhwvfs.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0zqsfiheydimfuhwvfs.png" alt="InheritanceVSComposition" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rather than making every bird inherit &lt;code&gt;fly()&lt;/code&gt;, we separate flying into its own behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlyingBehavior&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Flying...&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a Sparrow can have flying behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sparrow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;flyingBehavior&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FlyingBehavior&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 Penguin simply doesn't.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Penguin&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No unnecessary methods.&lt;/p&gt;

&lt;p&gt;No overridden behavior.&lt;/p&gt;

&lt;p&gt;No pretending that penguins can fly.&lt;/p&gt;

&lt;p&gt;Each object gets only the capabilities it actually needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thinking Beyond Birds
&lt;/h3&gt;

&lt;p&gt;This idea appears everywhere.&lt;/p&gt;

&lt;p&gt;Imagine a payment system.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment
├── CreditCardPayment
├── UpiPayment
├── PayPalPayment
└── CashPayment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We might compose behavior like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refundable&lt;/li&gt;
&lt;li&gt;SupportsInstallments&lt;/li&gt;
&lt;li&gt;GeneratesInvoice&lt;/li&gt;
&lt;li&gt;RequiresAuthentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each payment method gets only the behaviors it needs.&lt;/p&gt;

&lt;p&gt;This makes the system far more flexible.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Composition Is Often Preferred&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Composition offers several advantages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smaller Responsibilities
&lt;/h3&gt;

&lt;p&gt;Each component does one thing well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Reusability
&lt;/h3&gt;

&lt;p&gt;The same behavior can be shared across unrelated objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lower Coupling
&lt;/h3&gt;

&lt;p&gt;Changing one component doesn't necessarily affect everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Greater Flexibility
&lt;/h3&gt;

&lt;p&gt;Objects can gain or lose behavior simply by changing the components they use.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Does This Mean Inheritance Is Bad?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Not at all.&lt;/p&gt;

&lt;p&gt;Inheritance is still a valuable tool.&lt;/p&gt;

&lt;p&gt;It works well when there is a genuine &lt;strong&gt;"is-a"&lt;/strong&gt; relationship.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Circle is a Shape.&lt;/li&gt;
&lt;li&gt;A Square is a Shape.&lt;/li&gt;
&lt;li&gt;A SavingsAccount is a BankAccount.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem isn't inheritance itself.&lt;/p&gt;

&lt;p&gt;The problem is using inheritance simply to reuse code.&lt;/p&gt;

&lt;p&gt;If the relationship doesn't naturally fit, inheritance often introduces more problems than it solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;A Practical Guideline&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A common piece of advice you'll hear is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Favor Composition Over Inheritance.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice the wording.&lt;/p&gt;

&lt;p&gt;It doesn't say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never use inheritance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer composition when it gives you a simpler and more flexible design.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inheritance and Composition are both tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🔑 The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inheritance helped developers eliminate duplicated behavior.&lt;/p&gt;

&lt;p&gt;Composition helped developers build systems that were easier to change.&lt;/p&gt;

&lt;p&gt;Modern software often prefers composition because requirements change far more often than class hierarchies.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;⏭️ What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've now explored three important ideas in Object-Oriented Programming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encapsulation protects an object's state.&lt;/li&gt;
&lt;li&gt;Abstraction hides unnecessary complexity.&lt;/li&gt;
&lt;li&gt;Composition helps us build flexible systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One important pillar still remains.&lt;/p&gt;

&lt;p&gt;In the next article, we'll explore &lt;strong&gt;Polymorphism&lt;/strong&gt; and understand how different objects can share a common interface while providing their own implementations.&lt;/p&gt;

</description>
      <category>composition</category>
      <category>inheritance</category>
      <category>oop</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Inheritance in OOP: Solving Code Duplication or Creating New Problems?</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Thu, 25 Jun 2026 07:29:46 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/inheritance-in-oop-solving-code-duplication-or-creating-new-problems-2d4d</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/inheritance-in-oop-solving-code-duplication-or-creating-new-problems-2d4d</guid>
      <description>&lt;p&gt;Many developers learn:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Inheritance allows code reuse.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Technically true.&lt;/p&gt;

&lt;p&gt;But if that's your primary reason for using inheritance, you'll often create bad designs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;❓ Why Was Inheritance Invented?&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ├── Customer
 ├── Admin
 └── Seller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of them have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;id&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;login()&lt;/li&gt;
&lt;li&gt;logout()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of duplicating these everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&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;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&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;class&lt;/span&gt; &lt;span class="nc"&gt;Seller&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;we extract common behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;logout&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;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Seller&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates an &lt;strong&gt;IS-A relationship&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Admin IS A User

Customer IS A User

Seller IS A User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the most important rule of inheritance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does &lt;code&gt;extends&lt;/code&gt; Actually Do?
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login&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="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 tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;works.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because JavaScript walks up the prototype chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;admin
   ↓
Admin.prototype
   ↓
User.prototype
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and finds &lt;code&gt;login()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inheritance is fundamentally prototype delegation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
   ↓
Admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Admin has everything a User has, plus additional capabilities.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;login&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;banUser&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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;banUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Overriding Methods&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Children can change behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getRole&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&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="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 tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getRole&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Admin&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getRole&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// User&lt;/span&gt;

&lt;span class="nf"&gt;newAdmin&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getRole&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same method name.&lt;/p&gt;

&lt;p&gt;Different behavior.&lt;/p&gt;

&lt;p&gt;This becomes important later when we discuss polymorphism.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🤯 The Biggest Mistake with Inheritance&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Hidden Problem&lt;/p&gt;

&lt;p&gt;Over time, developers started encountering a different challenge.&lt;/p&gt;

&lt;p&gt;Imagine we have a Vehicle class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;lockDoors&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;Seems harmless.&lt;/p&gt;

&lt;p&gt;But what happens when we introduce a Bicycle?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bicycle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bicycles don't have doors.&lt;/p&gt;

&lt;p&gt;Yet they've inherited door-related behavior.&lt;/p&gt;

&lt;p&gt;Now our model starts feeling strange.&lt;/p&gt;

&lt;p&gt;The problem becomes even worse as systems grow.&lt;/p&gt;

&lt;p&gt;Developers often found themselves inheriting behavior they didn't actually need.&lt;/p&gt;

&lt;p&gt;Changes in parent classes unexpectedly affected child classes.&lt;/p&gt;

&lt;p&gt;The hierarchy became increasingly difficult to maintain.&lt;/p&gt;

&lt;p&gt;What started as a solution to code duplication sometimes created tightly coupled systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;⚔️ The Double-Edged Sword&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inheritance solves one problem very well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reusing common behavior.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But it can introduce another:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tight coupling between parent and child classes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The child depends heavily on decisions made by the parent.&lt;/p&gt;

&lt;p&gt;As hierarchies become deeper, understanding the system becomes harder.&lt;/p&gt;

&lt;p&gt;A small change in a base class can ripple through multiple child classes.&lt;/p&gt;

&lt;p&gt;This is one reason why modern software design is often more cautious about using inheritance.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;✅ When Inheritance Is Actually Good&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Use inheritance when:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Real IS-A relationship exists
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Admin IS A User

Manager IS An Employee

Dog IS An Animal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Parent behavior is truly shared
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;logout&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;All child classes genuinely need this.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hierarchy is shallow
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ├─ Admin
 └─ Customer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Employee
 ↓
Manager
 ↓
RegionalManager
 ↓
DistrictManager
 ↓
SuperDistrictManager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;⏭️ What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Inheritance helped developers reuse behavior.&lt;/p&gt;

&lt;p&gt;But over time, many teams discovered that inheritance wasn't always the most flexible solution.&lt;/p&gt;

&lt;p&gt;This led to an important shift in software design thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of inheriting behavior, what if we assembled behavior from smaller pieces?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next article, we'll explore Composition vs Inheritance and understand why many modern applications prefer composition when building complex systems.&lt;/p&gt;

</description>
      <category>inheritance</category>
      <category>classes</category>
      <category>oop</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Abstraction in OOP: Hiding Complexity Without Hiding Capability</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Wed, 17 Jun 2026 12:24:42 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/abstraction-in-oop-hiding-complexity-without-hiding-capability-1111</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/abstraction-in-oop-hiding-complexity-without-hiding-capability-1111</guid>
      <description>&lt;p&gt;In the previous article, we discussed Encapsulation and how objects should control changes to their own state.&lt;/p&gt;

&lt;p&gt;Now let's talk about another fundamental concept of Object-Oriented Programming: Abstraction.&lt;/p&gt;

&lt;p&gt;Like always, let's start with a problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine you own a car.&lt;/p&gt;

&lt;p&gt;To drive it, you do a few simple things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start the engine.&lt;/li&gt;
&lt;li&gt;Press the accelerator.&lt;/li&gt;
&lt;li&gt;Apply the brakes.&lt;/li&gt;
&lt;li&gt;Turn the steering wheel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How fuel is injected into the engine.&lt;/li&gt;
&lt;li&gt;How the pistons move.&lt;/li&gt;
&lt;li&gt;How the gearbox changes gears.&lt;/li&gt;
&lt;li&gt;How combustion generates power.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that complexity is hidden from you.&lt;/p&gt;

&lt;p&gt;You simply interact with a straightforward interface.&lt;/p&gt;

&lt;p&gt;Software systems work in a very similar way.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;A Real-World Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose we need to send an email.&lt;/p&gt;

&lt;p&gt;The application code might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;john@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks simple.&lt;/p&gt;

&lt;p&gt;But what actually happens behind the scenes?&lt;/p&gt;

&lt;p&gt;Potentially a lot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate the email address.&lt;/li&gt;
&lt;li&gt;Create an SMTP connection.&lt;/li&gt;
&lt;li&gt;Authenticate with the provider.&lt;/li&gt;
&lt;li&gt;Build the message.&lt;/li&gt;
&lt;li&gt;Retry if sending fails.&lt;/li&gt;
&lt;li&gt;Log failures.&lt;/li&gt;
&lt;li&gt;Close the connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As consumers of email service, we don't care about those details.&lt;/p&gt;

&lt;p&gt;We only care that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I call send(), the email should be sent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is exactly the problem Abstraction tries to solve.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem with Exposing Everything&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine if sending an email required every caller to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;buildMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every single time.&lt;/p&gt;

&lt;p&gt;Suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every consumer knows too much.&lt;/li&gt;
&lt;li&gt;Every consumer is responsible for the implementation.&lt;/li&gt;
&lt;li&gt;Changing the implementation becomes painful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What if we switch from SMTP to a third-party email provider?&lt;/p&gt;

&lt;p&gt;Now every place that sends emails needs to change.&lt;/p&gt;

&lt;p&gt;The consumers have become tightly coupled to implementation details.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Idea Behind Abstraction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Abstraction is about exposing what an object can do while hiding how it does it.&lt;/p&gt;

&lt;p&gt;Instead of exposing every implementation detail, we expose only what consumers need.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The caller doesn't need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which provider we're using.&lt;/li&gt;
&lt;li&gt;How authentication works.&lt;/li&gt;
&lt;li&gt;How retries are handled.&lt;/li&gt;
&lt;li&gt;How messages are constructed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those details remain hidden.&lt;/p&gt;

&lt;p&gt;Consumers interact with a simple and stable interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstraction Is Not the Same as Encapsulation
&lt;/h3&gt;

&lt;p&gt;These two concepts are often confused.&lt;/p&gt;

&lt;p&gt;Encapsulation asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who should be allowed to change the object's state?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Abstraction asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What details should consumers be aware of?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Encapsulation protects data.&lt;/p&gt;

&lt;p&gt;Abstraction hides unnecessary complexity.&lt;/p&gt;

&lt;p&gt;They often work together, but they solve different problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So far, we've discussed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How objects protect their state using Encapsulation.&lt;/li&gt;
&lt;li&gt;How objects hide complexity using Abstraction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we'll look at another question developers faced:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If multiple objects share similar behavior, do we really need to write that code repeatedly?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This leads us to one of the most well-known—and sometimes controversial—concepts in OOP:&lt;/p&gt;

&lt;p&gt;Inheritance.&lt;/p&gt;

</description>
      <category>abstraction</category>
      <category>classes</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Encapsulation in OOP: Protecting an Object's State from Unintended Changes</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Mon, 15 Jun 2026 08:16:37 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/encapsulation-in-oop-protecting-an-objects-state-from-unintended-changes-18a2</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/encapsulation-in-oop-protecting-an-objects-state-from-unintended-changes-18a2</guid>
      <description>&lt;p&gt;In the previous articles, we discussed why Object-Oriented Programming was introduced and explored different ways of creating objects using factory functions and classes.&lt;/p&gt;

&lt;p&gt;Now it's time to look at one of the most important ideas behind OOP: Encapsulation.&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%2F9a9ggqht66ngh0l8vp45.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%2F9a9ggqht66ngh0l8vp45.png" alt="Encapsulation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like every concept in this series, let's start with the problem rather than the definition.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Real Problem Encapsulation Solves&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine you're building a bank account.&lt;/p&gt;

&lt;p&gt;Without encapsulation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankAccount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&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;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BankAccount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your account contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which may be impossible according to business rules.&lt;/p&gt;

&lt;p&gt;The problem isn't that someone changed a variable.&lt;/p&gt;

&lt;p&gt;The problem is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Anybody can put the object into an invalid state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Encapsulation is NOT About Hiding
&lt;/h3&gt;

&lt;p&gt;Most beginners think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Encapsulation = private fields&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Private fields are just one tool.&lt;/p&gt;

&lt;p&gt;The actual goal is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Protecting the integrity of an object's state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An object should control how its data changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Becomes Dangerous&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In small applications, unrestricted access may not seem like a big deal.&lt;/p&gt;

&lt;p&gt;As applications grow, however, data starts being accessed from many places.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A payment module updating balances.&lt;/li&gt;
&lt;li&gt;A refund module updating balances.&lt;/li&gt;
&lt;li&gt;An admin panel updating balances.&lt;/li&gt;
&lt;li&gt;A reporting service reading balances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now suppose an issue appears.&lt;/p&gt;

&lt;p&gt;A customer's balance becomes negative.&lt;/p&gt;

&lt;p&gt;Where did it happen?&lt;/p&gt;

&lt;p&gt;Which part of the application modified it?&lt;/p&gt;

&lt;p&gt;Was validation skipped?&lt;/p&gt;

&lt;p&gt;Did someone accidentally overwrite a value?&lt;/p&gt;

&lt;p&gt;The more places that can directly manipulate data, the harder it becomes to reason about the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;A Better Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;force all changes through methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankAccount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Insufficient funds&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getBalance&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is allowed.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is impossible.&lt;/p&gt;

&lt;p&gt;The object protects itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Think Like a Security Guard
&lt;/h3&gt;

&lt;p&gt;Imagine a company database.&lt;/p&gt;

&lt;p&gt;Bad design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Employee Database
      ↑
Everybody can modify it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Employee Database
      ↑
HR Department
      ↑
Employees submit requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Employees don't directly change records.&lt;/p&gt;

&lt;p&gt;They request changes.&lt;/p&gt;

&lt;p&gt;The HR department validates them.&lt;/p&gt;

&lt;p&gt;Encapsulation works exactly like this.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Idea Behind Encapsulation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Encapsulation is about controlling access to an object's internal state.&lt;/p&gt;

&lt;p&gt;Instead of allowing anyone to modify data directly, the object becomes responsible for managing its own data.&lt;/p&gt;

&lt;p&gt;Rather than exposing the balance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we expose behaviors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every change passes through rules defined by the object itself.&lt;/p&gt;

&lt;p&gt;The object protects its own integrity.&lt;/p&gt;

&lt;p&gt;This is the real purpose of Encapsulation.&lt;/p&gt;

&lt;p&gt;Not hiding data.&lt;/p&gt;

&lt;p&gt;Protecting data.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Encapsulation in TypeScript&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;TypeScript gives us access modifiers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;strong&gt;public&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Accessible everywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user.name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;private&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Accessible only inside the class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user.password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❌ Error&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;protected&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Accessible inside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;current class&lt;/li&gt;
&lt;li&gt;derived classes
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;checkRole&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&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;Works.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Important Reality About TypeScript&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Many developers are surprised by this.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is primarily a compile-time restriction.&lt;/p&gt;

&lt;p&gt;After compilation to JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;still exists.&lt;/p&gt;

&lt;p&gt;TypeScript prevents you from accessing it in code, but it's not true runtime privacy.&lt;/p&gt;

&lt;p&gt;Modern JavaScript introduced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which is actual runtime privacy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is impossible.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Key Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Encapsulation is often described as &lt;strong&gt;hiding data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A more useful way to think about it is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Encapsulation ensures that an object controls how its own state changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By doing so, it protects business rules, reduces accidental misuse, and makes software easier to maintain as systems grow.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Encapsulation helps us control access to data.&lt;/p&gt;

&lt;p&gt;But another challenge still remains.&lt;/p&gt;

&lt;p&gt;Even when objects manage their own state correctly, consumers often need to understand too many implementation details to use them.&lt;/p&gt;

&lt;p&gt;In the next article, we'll explore Abstraction and see how hiding unnecessary complexity allows us to build systems that are easier to use and easier to change.&lt;/p&gt;




</description>
      <category>oop</category>
      <category>encapsulation</category>
      <category>javascript</category>
      <category>classes</category>
    </item>
  </channel>
</rss>
