<?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>How HTTP Works Under the Hood: TCP, UDP, Keep-Alive &amp; HTTP/3 | Deeper Dive into HTTP #3</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Tue, 27 Oct 2026 12:28:19 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/how-http-works-under-the-hood-tcp-udp-keep-alive-http3-deeper-dive-into-http-3-28b3</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/how-http-works-under-the-hood-tcp-udp-keep-alive-http3-deeper-dive-into-http-3-28b3</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/lQpleySFQk8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;When you open a website, fetch data from an API, or submit a form, HTTP makes communication between your application and a server possible.&lt;/p&gt;

&lt;p&gt;But have you ever wondered what happens after your application sends an HTTP request?&lt;/p&gt;

&lt;p&gt;In this third article of the Deeper Dive into HTTP series, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How HTTP fits into the networking stack.&lt;/li&gt;
&lt;li&gt;How TCP establishes reliable connections.&lt;/li&gt;
&lt;li&gt;What happens during the TCP three-way handshake.&lt;/li&gt;
&lt;li&gt;What UDP is and how it differs from TCP.&lt;/li&gt;
&lt;li&gt;How Keep-Alive enables connection reuse.&lt;/li&gt;
&lt;li&gt;Why HTTP/3 uses QUIC over UDP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. Understanding the Networking Stack&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before exploring TCP, UDP, and HTTP, let's understand how these protocols fit together.&lt;/p&gt;

&lt;p&gt;Imagine your frontend needs to fetch a list of users from a backend API.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /users&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are multiple layers involved in getting this request to the server.&lt;/p&gt;

&lt;p&gt;A simplified view of the networking stack looks like this:&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%2Fysewvex5jergruqdt7d7.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%2Fysewvex5jergruqdt7d7.png" alt="Networking Stack" width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each layer has a different responsibility.&lt;/p&gt;

&lt;p&gt;First, HTTP defines the rules for communication. It describes things like the request method, headers, status codes, and message content.&lt;/p&gt;

&lt;p&gt;Next, TCP, when used, provides a reliable, ordered stream of bytes between two endpoints. It handles things like retransmission of lost data and flow control.&lt;/p&gt;

&lt;p&gt;UDP provides a lightweight way to send datagrams without built-in guarantees of delivery, ordering, or retransmission.&lt;/p&gt;

&lt;p&gt;And then there's IP, which helps route packets across networks toward their destination.&lt;/p&gt;

&lt;p&gt;Think of it this way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;HTTP defines what the message means. TCP helps deliver a reliable stream of data. And IP helps move packets through the network.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, HTTP defines what a &lt;code&gt;GET /users&lt;/code&gt; request means. TCP can provide reliable delivery of the bytes carrying that HTTP message, while IP handles packet addressing and routing.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. How Does TCP Establish a Connection?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;TCP stands for Transmission Control Protocol.&lt;/p&gt;

&lt;p&gt;Before sending HTTP data over a new TCP connection, the client and server typically establish the connection using something called the &lt;strong&gt;TCP three-way handshake&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%2Fv03wzml3gjfb72jbjdxk.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%2Fv03wzml3gjfb72jbjdxk.png" alt="TCP Handshake" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It involves three steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step one: SYN.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The client sends a TCP segment with the SYN flag set.&lt;/p&gt;

&lt;p&gt;It is essentially initiating the connection and proposing its initial sequence number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step two: SYN-ACK.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The server responds with a segment containing both SYN and ACK flags.&lt;/p&gt;

&lt;p&gt;It acknowledges the client's initial sequence number and provides its own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step three: ACK.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The client acknowledges the server's initial sequence number.&lt;/p&gt;

&lt;p&gt;At this point, the TCP handshake is complete, and both sides can exchange application data.&lt;/p&gt;

&lt;p&gt;And now, the TCP connection is established.&lt;/p&gt;

&lt;p&gt;Once the connection is ready, HTTP data can be sent over it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the HTTP request come immediately after the handshake?&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;For HTTPS over TCP, the client and server typically also establish TLS security before exchanging ordinary HTTP application data. TLS provides encryption, integrity protection, and server authentication.&lt;/p&gt;

&lt;p&gt;So, a simplified connection setup looks like this:&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%2Fr56fcw7kwjthytjjhqnh.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%2Fr56fcw7kwjthytjjhqnh.png" alt="Connection Setup" width="800" height="776"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's something important: this handshake happens when a new TCP connection is established. It doesn't need to happen before every HTTP request.&lt;/p&gt;

&lt;p&gt;And that's where connection reuse becomes important.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. What Is UDP, and How Is It Different from TCP?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;UDP stands for User Datagram Protocol.&lt;/p&gt;

&lt;p&gt;Like TCP, UDP operates at the transport layer. However, it provides a different set of capabilities.&lt;/p&gt;

&lt;p&gt;TCP establishes a connection and provides reliable, ordered delivery of a byte stream.&lt;/p&gt;

&lt;p&gt;UDP sends independent datagrams without providing built-in mechanisms for reliable delivery, retransmission, or ordered delivery.&lt;/p&gt;

&lt;p&gt;Let's compare them.&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%2F1xngkmfb237er1yteuqx.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%2F1xngkmfb237er1yteuqx.png" alt="TCP-UDP Comparison" width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UDP has less built-in transport machinery, but that doesn't mean every UDP application is unreliable.&lt;/p&gt;

&lt;p&gt;An application can implement additional mechanisms on top of UDP when it needs them.&lt;/p&gt;

&lt;p&gt;And this is exactly where QUIC becomes important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does HTTP/3 use UDP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If TCP already provides reliable delivery, why build a new transport protocol over UDP?&lt;/p&gt;

&lt;p&gt;The answer involves connection setup, encryption, and how multiple streams behave when packets are lost.&lt;/p&gt;

&lt;p&gt;TCP provides one ordered byte stream per connection. If TCP cannot deliver a missing portion of that stream, later bytes in the same stream cannot be delivered to the application in order until the gap is resolved.&lt;/p&gt;

&lt;p&gt;With HTTP/2, multiple HTTP streams can share one TCP connection. A lost TCP segment can therefore delay delivery of data for multiple streams on that connection.&lt;/p&gt;

&lt;p&gt;HTTP/3 uses QUIC to address important limitations of this architecture.&lt;/p&gt;

&lt;p&gt;QUIC implements reliability, congestion control, stream multiplexing, and integrated TLS 1.3 security over UDP.&lt;/p&gt;

&lt;p&gt;UDP is the underlying datagram transport; QUIC supplies the transport features needed by HTTP/3.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. What Is Keep-Alive in HTTP?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now let's look at another important concept: connection reuse.&lt;/p&gt;

&lt;p&gt;Imagine your frontend needs to make five API requests to the same server.&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 yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /api/profile&lt;/span&gt;
&lt;span class="s"&gt;GET /api/posts&lt;/span&gt;
&lt;span class="s"&gt;GET /api/notifications&lt;/span&gt;
&lt;span class="s"&gt;GET /api/settings&lt;/span&gt;
&lt;span class="s"&gt;GET /api/followers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If every request required a new TCP connection, the client would repeatedly incur connection setup overhead.&lt;/p&gt;

&lt;p&gt;For HTTPS over TCP, new connections can also require a TLS handshake.&lt;/p&gt;

&lt;p&gt;That adds work and can increase latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without connection reuse&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A simplified sequence might look 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;Request 1 → Establish connection → Response 1
Request 2 → Establish connection → Response 2
Request 3 → Establish connection → Response 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example assumes the client closes or doesn't reuse each connection. Real clients may reuse connections even when applications make separate requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With persistent connections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead, the client can keep a connection open and reuse it for additional HTTP exchanges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Establish connection
        |
        v
Request 1 → Response 1
        |
        v
Request 2 → Response 2
        |
        v
Request 3 → Response 3
        |
        v
Connection remains available for reuse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces repeated connection setup overhead and can improve performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does HTTP Keep-Alive work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In HTTP/1.1, persistent connections are the default unless the connection is otherwise closed or a message explicitly indicates that it should close.&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 yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /api/profile HTTP/1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client and server can reuse the connection for additional requests.&lt;/p&gt;

&lt;p&gt;A server might also send:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keep-alive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this header is not required to enable persistence in HTTP/1.1.&lt;/p&gt;

&lt;p&gt;In HTTP/1.0, persistent connections were commonly negotiated using the &lt;code&gt;Connection: keep-alive&lt;/code&gt; convention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens in HTTP/2 and HTTP/3?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Connection reuse becomes even more powerful with modern HTTP versions.&lt;/p&gt;

&lt;p&gt;HTTP/2 supports multiplexing multiple independent HTTP streams over a single TCP connection.&lt;/p&gt;

&lt;p&gt;HTTP/3 also supports multiplexing, but it uses QUIC streams over a QUIC connection instead of HTTP/2's streams over TCP.&lt;/p&gt;

&lt;p&gt;This means multiple requests can make progress concurrently without requiring a separate connection for every request.&lt;/p&gt;

&lt;p&gt;We'll explore that distinction further in the next section.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. HTTP/1.1 vs HTTP/2 vs HTTP/3&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;HTTP has evolved over time to improve performance, efficiency, and communication behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/1.1: Persistent connections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HTTP/1.1 allows multiple requests and responses to reuse the same connection.&lt;/p&gt;

&lt;p&gt;However, it doesn't natively multiplex independent HTTP exchanges in the way HTTP/2 does. On a single connection, responses must be sent in request order, so a slow response can delay later responses.&lt;/p&gt;

&lt;p&gt;Browsers historically worked around some of these limitations by opening multiple connections to a server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/2: Multiplexing over TCP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HTTP/2 introduces multiplexing, which allows multiple streams to share a single TCP connection.&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 plaintext"&gt;&lt;code&gt;One TCP connection
    ├── Stream 1: Profile request
    ├── Stream 3: Posts request
    ├── Stream 5: Settings request
    └── Stream 7: Notifications request

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The streams can be interleaved, allowing requests and responses to make progress concurrently.&lt;/p&gt;

&lt;p&gt;But there is an important limitation.&lt;/p&gt;

&lt;p&gt;TCP still provides one ordered byte stream. If a TCP segment is lost, TCP cannot deliver subsequent bytes to the application in order until the missing data is recovered.&lt;/p&gt;

&lt;p&gt;As a result, data from multiple HTTP/2 streams sharing that connection can experience transport-level head-of-line blocking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/3: QUIC over UDP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HTTP/3 uses QUIC rather than TCP.&lt;/p&gt;

&lt;p&gt;QUIC provides reliable delivery within its streams while allowing data from independent streams to progress separately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One QUIC connection
    ├── Stream 1: Profile request
    ├── Stream 3: Posts request
    ├── Stream 5: Settings request
    └── Stream 7: Notifications request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If packet loss affects data belonging to one stream, other streams can continue delivering available data rather than waiting for a single ordered TCP byte stream to recover.&lt;/p&gt;

&lt;p&gt;This doesn't mean packet loss has no impact on other streams. Streams can still share network capacity and congestion control, and loss can delay any data that depends on the missing information.&lt;/p&gt;

&lt;p&gt;QUIC also integrates TLS 1.3 security into its connection establishment. Depending on the connection setup and whether session resumption or 0-RTT is available, it can reduce the number of round trips needed before application data is sent.&lt;/p&gt;

&lt;p&gt;These improvements can make HTTP/3 particularly useful on networks with higher latency or changing connectivity.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. What Should Developers Take Away?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You don't need to implement TCP, UDP, or QUIC yourself to build most web applications. Browsers, operating systems, networking libraries, and servers handle these protocols.&lt;/p&gt;

&lt;p&gt;However, understanding them helps explain real-world behavior.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a new connection is slow, connection establishment and TLS negotiation may contribute to latency.&lt;/li&gt;
&lt;li&gt;If an application makes many requests to the same server, connection reuse can reduce overhead.&lt;/li&gt;
&lt;li&gt;If multiple resources are fetched concurrently, HTTP/2 and HTTP/3 multiplexing can improve efficiency.&lt;/li&gt;
&lt;li&gt;If a network has packet loss, the transport protocol can influence how that loss affects application data.&lt;/li&gt;
&lt;li&gt;If a connection changes networks, QUIC can support connection migration in scenarios where its connection identifiers and network conditions allow it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts are useful when investigating API latency, performance bottlenecks, browser networking behavior, and modern web infrastructure.&lt;/p&gt;




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

&lt;p&gt;HTTP is more than a format for sending requests and receiving responses. Its performance also depends on the transport protocols and connection-management mechanisms underneath it.&lt;/p&gt;

&lt;p&gt;Here's a quick recap:&lt;/p&gt;

&lt;p&gt;TCP provides reliable, ordered byte-stream delivery and establishes connections through a three-way handshake.&lt;/p&gt;

&lt;p&gt;UDP sends datagrams without built-in delivery or ordering guarantees.&lt;/p&gt;

&lt;p&gt;Keep-Alive and persistent connections allow connection reuse and reduce repeated setup overhead.&lt;/p&gt;

&lt;p&gt;HTTP/2 adds multiplexing over TCP, but TCP-level head-of-line blocking can affect all streams sharing a connection.&lt;/p&gt;

&lt;p&gt;HTTP/3 uses QUIC over UDP to support reliable streams, multiplexing, integrated TLS 1.3 security, and improved handling of packet loss across independent streams.&lt;/p&gt;

&lt;p&gt;This is the third article in the &lt;strong&gt;Deeper Dive into HTTP&lt;/strong&gt; series by &lt;strong&gt;AshayCodes&lt;/strong&gt;. In the next article, we'll explore HTTP methods such as GET, POST, PUT, PATCH, and DELETE, along with safe and idempotent methods.&lt;/p&gt;

&lt;p&gt;Happy learning!&lt;/p&gt;

</description>
      <category>backend</category>
      <category>computerscience</category>
      <category>networking</category>
      <category>webdev</category>
    </item>
    <item>
      <title>HTTP Requests, Responses, and Headers Explained with Examples | Deeper Dive into HTTP #2</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Fri, 16 Oct 2026 08:16:22 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/http-requests-responses-and-headers-explained-with-examples-deeper-dive-into-http-2-416g</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/http-requests-responses-and-headers-explained-with-examples-deeper-dive-into-http-2-416g</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/0eqynq2Bbec" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Every time you open a website, fetch data from an API, submit a form, or upload a file, your application communicates with a server.&lt;/p&gt;

&lt;p&gt;But what does that communication actually look like?&lt;/p&gt;

&lt;p&gt;How does a browser tell a server which resource it wants? How does the server communicate whether the request succeeded? And how do they exchange information about authentication, caching, content types, and security?&lt;/p&gt;

&lt;p&gt;The answer lies in three fundamental building blocks of HTTP communication:&lt;/p&gt;

&lt;p&gt;Requests — messages sent by a client to a server.&lt;/p&gt;

&lt;p&gt;Responses — messages returned by the server.&lt;/p&gt;

&lt;p&gt;Headers — metadata that provides additional information about requests and responses.&lt;/p&gt;

&lt;p&gt;In the previous article, we explored what HTTP is, why it is stateless, and how authentication works despite that statelessness.&lt;/p&gt;

&lt;p&gt;Now, let's look at how HTTP messages are structured and how to understand them when working with APIs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. What Is an HTTP Request?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;An HTTP request is a message sent by a client to a server to request a resource or perform an operation.&lt;/p&gt;

&lt;p&gt;The client could be a browser, a mobile application, a frontend built with React, or another backend service.&lt;/p&gt;

&lt;p&gt;For example, imagine that your frontend needs to fetch a list of users from a backend API.&lt;/p&gt;

&lt;p&gt;It might send this request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /api/users HTTP/1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the server that the client wants to retrieve the users resource and can accept a JSON response.&lt;/p&gt;

&lt;p&gt;The structure of an HTTP request&lt;/p&gt;

&lt;p&gt;A traditional HTTP/1.1 request has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Request Line&lt;/span&gt;
&lt;span class="s"&gt;Headers&lt;/span&gt;

&lt;span class="s"&gt;Optional Blank Line + Message Body&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1 Request line
&lt;/h3&gt;

&lt;p&gt;The request line contains three parts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /api/users HTTP/1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Method: GET — describes the intended operation.&lt;/p&gt;

&lt;p&gt;Request target: /api/users — identifies the target resource.&lt;/p&gt;

&lt;p&gt;HTTP version: HTTP/1.1 — identifies the HTTP version used by this message.&lt;/p&gt;

&lt;p&gt;Other common HTTP methods include POST, PUT, PATCH, and DELETE. We'll explore them in a future article.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Request headers
&lt;/h3&gt;

&lt;p&gt;Headers provide additional information about the request.&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 yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bearer &amp;lt;access-token&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These headers communicate different things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Host&lt;/strong&gt; identifies the target host (where we are requesting a resource) in HTTP/1.1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accept&lt;/strong&gt; describes the response media types the client can accept.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt; carries credentials used for authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Type&lt;/strong&gt; describes the media type of the request body, when one is present.&lt;/p&gt;

&lt;p&gt;Not every request needs every header. Their presence depends on the request and the application's requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.3 Request body
&lt;/h3&gt;

&lt;p&gt;A request body carries data sent by the client.&lt;/p&gt;

&lt;p&gt;For example, when creating a user, a client might send:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;POST /api/users HTTP/1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ashay"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ashay@example.com"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the body contains the user data in JSON format.&lt;/p&gt;

&lt;p&gt;A request body is common with methods such as POST and PUT, but the HTTP method alone doesn't always determine whether a body can exist. For example, GET requests generally shouldn't include content unless a specific, well-defined use case supports it.&lt;/p&gt;

&lt;p&gt;The server processes the request according to the endpoint's implementation, validation rules, authentication requirements, and business logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. What Is an HTTP Response?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After receiving and processing a request, a server sends an HTTP response.&lt;/p&gt;

&lt;p&gt;A response communicates the outcome of the request and may include the requested resource or other useful information.&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 yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;HTTP/1.1 200 OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;
  &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;101"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Doe"&lt;/span&gt;
  &lt;span class="pi"&gt;},&lt;/span&gt;
  &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;102"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Jane&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Doe"&lt;/span&gt;
  &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the server returns a successful response containing a JSON array of users.&lt;/p&gt;

&lt;p&gt;The structure of an HTTP response&lt;/p&gt;

&lt;p&gt;A traditional HTTP/1.1 response has this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Status Line&lt;/span&gt;
&lt;span class="s"&gt;Headers&lt;/span&gt;

&lt;span class="s"&gt;Optional Blank Line + Message Body&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's examine each part.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Status line
&lt;/h3&gt;

&lt;p&gt;The status line contains the HTTP version, status code, and a reason phrase in HTTP/1.1.&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 yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;HTTP/1.1 200 OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTTP version: HTTP/1.1&lt;/p&gt;

&lt;p&gt;Status code: 200&lt;/p&gt;

&lt;p&gt;Reason phrase: OK&lt;/p&gt;

&lt;p&gt;The status code communicates the outcome of the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Response headers
&lt;/h3&gt;

&lt;p&gt;Response headers provide metadata about the response.&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 yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Cache-Control&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no-cache&lt;/span&gt;
&lt;span class="na"&gt;Set-Cookie&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;session_id=abc123; HttpOnly; Secure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These headers can tell the client how to interpret the response, how to handle caching, or whether to store a cookie.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 Response body
&lt;/h3&gt;

&lt;p&gt;The response body contains the returned representation or other response content, when applicable.&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 yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;101"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Doe"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;developer"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A response body is common when an API returns data, HTML, or an error document.&lt;/p&gt;

&lt;p&gt;However, not every response includes a body. For example, a 204 No Content response indicates that the request succeeded and there is no response content to return.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. What Are HTTP Headers?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've already seen headers in both requests and responses. Now let's understand them in more detail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;HTTP headers are fields that carry metadata and control information associated with HTTP messages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They help clients and servers communicate information beyond the request target or response status.&lt;/p&gt;

&lt;p&gt;For example, headers can communicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which media types the client accepts.&lt;/li&gt;
&lt;li&gt;What format the request body uses.&lt;/li&gt;
&lt;li&gt;Whether authentication credentials are present.&lt;/li&gt;
&lt;li&gt;How a response can be cached.&lt;/li&gt;
&lt;li&gt;Which security policies apply.&lt;/li&gt;
&lt;li&gt;Information about content negotiation and representation metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTTP headers are generally written as field names followed by a colon and a value in HTTP/1.1:&lt;/p&gt;

&lt;p&gt;Content-Type: application/json&lt;br&gt;
Accept: application/json&lt;br&gt;
Cache-Control: no-cache&lt;/p&gt;

&lt;p&gt;Header names are &lt;strong&gt;case-insensitive&lt;/strong&gt;, so Content-Type and content-type refer to the same field name.&lt;/p&gt;

&lt;p&gt;Headers can appear in requests, responses, or both, depending on the field's defined purpose.&lt;/p&gt;

&lt;p&gt;A quick note about HTTP versions&lt;/p&gt;

&lt;p&gt;The examples in this article use the traditional HTTP/1.1 text format because it is easy to read and understand.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Different Types of HTTP Headers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For our understanding, we can group commonly encountered headers into several categories.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Request headers
&lt;/h3&gt;

&lt;p&gt;Request headers provide information about the client, its preferences, the request context, or the credentials being presented.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Accept: application/json&lt;br&gt;
Indicates that the client can accept JSON responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Authorization: Bearer &lt;br&gt;
Carries credentials used by the server to authenticate the request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User-Agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;User-Agent: ExampleClient/1.0&lt;br&gt;
Identifies the client software. The exact format and usefulness of this value depend on the client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Origin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Origin: &lt;a href="https://app.example.com" rel="noopener noreferrer"&gt;https://app.example.com&lt;/a&gt;&lt;br&gt;
Identifies the origin associated with a request, particularly in browser security and CORS scenarios.&lt;/p&gt;

&lt;p&gt;Request headers help the server understand the context of an incoming request, but their presence doesn't automatically make the request trustworthy. The server must validate security-sensitive information.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Response headers
&lt;/h3&gt;

&lt;p&gt;Response headers provide information about the server's response and instructions or metadata for the client.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set-Cookie&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax&lt;br&gt;
Instructs the browser to store a cookie according to its attributes and cookie policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Location: &lt;a href="https://example.com/new-page" rel="noopener noreferrer"&gt;https://example.com/new-page&lt;/a&gt;&lt;br&gt;
Identifies a URI associated with a redirect or another response that uses this field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache-Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cache-Control: no-store&lt;br&gt;
Directs caches not to store the response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access-Control-Allow-Origin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Access-Control-Allow-Origin: &lt;a href="https://app.example.com" rel="noopener noreferrer"&gt;https://app.example.com&lt;/a&gt;&lt;br&gt;
Indicates which origin is permitted by the server's CORS policy for browser-based cross-origin access.&lt;/p&gt;

&lt;p&gt;Response headers often determine how browsers and other clients handle the response, rather than simply describing its content.&lt;/p&gt;

&lt;p&gt;4.3 Representation and content-related headers&lt;/p&gt;

&lt;p&gt;These headers help describe the representation being sent or provide information relevant to its interpretation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Type&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Content-Type: application/json&lt;br&gt;
Indicates the media type of the message content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Encoding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Content-Encoding: gzip&lt;br&gt;
Indicates the content coding applied to the representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Language&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Content-Language: en&lt;br&gt;
Identifies the language or languages intended for the representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Length&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Content-Length: 128&lt;br&gt;
Indicates the content length in bytes when applicable to the message framing.&lt;/p&gt;

&lt;p&gt;These headers are useful because the client needs to understand what it received and, where relevant, how to interpret or decode it.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.4 Authentication-related headers
&lt;/h3&gt;

&lt;p&gt;Authentication-related headers communicate credentials or authentication challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Authorization: Bearer &lt;br&gt;
Used by a client to present credentials to the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WWW-Authenticate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WWW-Authenticate: Bearer realm="api"&lt;br&gt;
Sent by a server to indicate an authentication scheme or challenge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proxy-Authorization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Proxy-Authorization: Basic &lt;br&gt;
Carries credentials intended for a proxy that requires authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proxy-Authenticate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Proxy-Authenticate: Basic realm="proxy"&lt;br&gt;
Used by a proxy to indicate its authentication requirements.&lt;/p&gt;

&lt;p&gt;These fields have different roles depending on whether authentication is being performed with an origin server or a proxy.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.5 Caching headers
&lt;/h3&gt;

&lt;p&gt;Caching headers help clients and intermediary caches decide whether a response can be reused and whether it needs revalidation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache-Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cache-Control: max-age=3600&lt;br&gt;
Allows a response to be considered fresh for up to 3,600 seconds, subject to the applicable caching rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ETag&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ETag: "v1-abc123"&lt;br&gt;
Provides a validator for a particular representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If-None-Match&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If-None-Match: "v1-abc123"&lt;br&gt;
Allows a client to ask whether the representation still matches a previously received entity tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Last-Modified&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Last-Modified: Fri, 16 Oct 2026 08:00:00 GMT&lt;br&gt;
Indicates when the representation was last modified, when the server provides that information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If-Modified-Since&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If-Modified-Since: Fri, 16 Oct 2026 08:00:00 GMT&lt;br&gt;
Allows a client to request a response based on whether the representation has changed since a specified time.&lt;/p&gt;

&lt;p&gt;For example, if a cached representation is still valid, the server might return 304 Not Modified, allowing the client to reuse its cached copy instead of downloading the representation again.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.6 Security-related headers
&lt;/h3&gt;

&lt;p&gt;Security-related response headers can instruct browsers to apply certain security protections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strict-Transport-Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Strict-Transport-Security: max-age=31536000&lt;br&gt;
Instructs supporting browsers to use HTTPS for future requests to the relevant host for the specified duration, subject to the header's rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content-Security-Policy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Content-Security-Policy: default-src 'self'&lt;br&gt;
Defines restrictions on the sources from which a browser may load certain resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;X-Content-Type-Options&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;X-Content-Type-Options: nosniff&lt;br&gt;
Helps prevent browsers from interpreting certain responses as a different content type through MIME sniffing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referrer-Policy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Referrer-Policy: strict-origin-when-cross-origin&lt;br&gt;
Controls how much referrer information the browser includes in requests.&lt;/p&gt;

&lt;p&gt;These headers can strengthen browser-side security, but they are not substitutes for proper authentication, authorization, input validation, and secure application design.&lt;/p&gt;




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

&lt;p&gt;HTTP communication is built around requests and responses.&lt;/p&gt;

&lt;p&gt;A request tells the server what the client wants to do and may include headers and a body. A response communicates the outcome through a status code and may return headers and a body.&lt;/p&gt;

&lt;p&gt;Headers provide additional information about the request or response, including content types, authentication, caching, and security policies.&lt;/p&gt;

&lt;p&gt;Understanding these building blocks is essential for anyone working with frontend applications, backend APIs, mobile applications, or web infrastructure.&lt;/p&gt;

&lt;p&gt;In the next part of our Deeper Dive into HTTP series, we'll explore what happens beneath these messages: how HTTP communication travels across the network, the role of TCP and UDP, connection reuse with Keep-Alive, and what changes with HTTP/3.&lt;/p&gt;

&lt;p&gt;If you found this useful, follow AshayCodes - &lt;a href="https://www.instagram.com/ashaycodes/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.youtube.com/@AshayCodes" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; for more practical explanations of the technologies we use every day.&lt;/p&gt;

&lt;p&gt;Happy learning!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What Is HTTP? Why Is It Stateless? So how does login work? | Deeper Dive into HTTP #1</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Thu, 15 Oct 2026 09:46:32 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/what-is-http-why-is-it-stateless-deeper-dive-into-http-1-17pm</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/what-is-http-why-is-it-stateless-deeper-dive-into-http-1-17pm</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/O5IYezUaX1k" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Have you ever wondered how your browser communicates with a backend server? Or how a website remembers that you're logged in, even though HTTP is a stateless protocol?&lt;/p&gt;

&lt;p&gt;These questions might seem simple, but understanding them gives you a much stronger foundation for building web applications, debugging APIs, and understanding what happens behind the scenes when you interact with a website.&lt;/p&gt;

&lt;p&gt;In this first article of the &lt;strong&gt;Deeper Dive into HTTP&lt;/strong&gt; series, we'll explore three fundamental questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What exactly is HTTP?&lt;/li&gt;
&lt;li&gt;Why is HTTP considered stateless?&lt;/li&gt;
&lt;li&gt;If HTTP is stateless, how does login work?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's understand them quickly.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What Is HTTP?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;HTTP stands for Hypertext Transfer Protocol. It is an application-layer protocol that defines how clients and servers communicate by exchanging messages.&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%2F60jve2zzzhqt4cr28ilf.jpg" 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%2F60jve2zzzhqt4cr28ilf.jpg" alt="HTTP" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whenever you open a website, fetch data from an API, submit a form, or load resources for a web application, HTTP is likely involved in that communication.&lt;/p&gt;

&lt;p&gt;Consider a typical web application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: Your browser or mobile application.&lt;/li&gt;
&lt;li&gt;Server: A backend application that processes requests and returns responses.&lt;/li&gt;
&lt;li&gt;HTTP: The protocol that defines how those requests and responses are structured and exchanged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, imagine opening a user profile page.&lt;/p&gt;

&lt;p&gt;Your browser might send a request like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /api/users/123 HTTP/1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This request tells the server that the client wants to retrieve information about a user.&lt;/p&gt;

&lt;p&gt;The server might respond with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;HTTP/1.1 200 OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ashay"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;GET&lt;/code&gt; is the HTTP method, &lt;code&gt;/api/users/123&lt;/code&gt; is the request target, and &lt;code&gt;200 OK&lt;/code&gt; is the status code indicating success.&lt;/p&gt;

&lt;p&gt;The response contains a status code, headers, and a body with the requested data.&lt;/p&gt;

&lt;p&gt;This is the fundamental communication pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Client → HTTP Request → Server → HTTP Response → Client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTTP defines the format and structure of this exchange. It doesn't, by itself, define how your application stores users, queries a database, or implements its business logic.&lt;/p&gt;

&lt;p&gt;The application and its infrastructure handle those responsibilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What Does It Mean That HTTP Is Stateless?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's start with a simple example.&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%2Fnhb3tpdkylgtvsyz36ew.jpg" 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%2Fnhb3tpdkylgtvsyz36ew.jpg" alt="HTTP Statless" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine sending the following request to a server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /home HTTP/1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server processes the request and returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;HTTP/1.1 200 OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, suppose you send another request to a server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /profile HTTP/1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server processes the request and returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;HTTP/1.1 200 OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ashay"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the perspective of HTTP's request semantics, the second request does not automatically carry the server's memory of the first request.&lt;/p&gt;

&lt;p&gt;The server doesn't inherently know whether this is your first request, your tenth request, or a request made by someone who visited the website yesterday.&lt;/p&gt;

&lt;p&gt;That's the central idea behind HTTP statelessness.&lt;/p&gt;

&lt;p&gt;HTTP is designed so that each request can be understood independently, without requiring the server to remember the context of previous requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Was HTTP Designed This Way?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Statelessness offers several advantages.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Simplicity
&lt;/h3&gt;

&lt;p&gt;Each request can be handled independently.&lt;/p&gt;

&lt;p&gt;The server doesn't have to maintain the complete history of every client request just because HTTP exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Scalability
&lt;/h3&gt;

&lt;p&gt;Imagine you have millions of users.&lt;/p&gt;

&lt;p&gt;If every request depended on a particular server remembering the user's previous requests, scaling your application could become more complicated.&lt;/p&gt;

&lt;p&gt;With stateless requests, different servers can handle different requests as long as the required state is available through other mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Reliability
&lt;/h3&gt;

&lt;p&gt;Because requests aren't inherently tied to one server's HTTP-level memory, the system can be designed to distribute requests across multiple servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;But Then... How Does Login Work?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's say you open a website and enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ashay&lt;/span&gt;
&lt;span class="na"&gt;Password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;********&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your browser sends a login request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;POST /login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server verifies your credentials.&lt;/p&gt;

&lt;p&gt;If they're correct, the server needs some way to identify you on future requests.&lt;/p&gt;

&lt;p&gt;One common approach is a &lt;strong&gt;session&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The server creates a session and gives the browser a &lt;strong&gt;session identifier&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That identifier can be stored in a cookie.&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 yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Session ID → abc123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then later, when your browser requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;GET /profile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the browser sends the cookie along with the request.&lt;/p&gt;

&lt;p&gt;The server can use that session identifier to determine which authenticated session the request belongs to.&lt;/p&gt;

&lt;p&gt;So the server can say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This request belongs to the authenticated session associated with this session ID."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that's how it can recognize you across multiple requests.&lt;/p&gt;

&lt;p&gt;But Wait...&lt;br&gt;
Does this mean HTTP is no longer stateless?&lt;/p&gt;

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

&lt;p&gt;This is a very important distinction.&lt;/p&gt;

&lt;p&gt;HTTP itself is still stateless.&lt;/p&gt;

&lt;p&gt;We're simply using an &lt;strong&gt;additional mechanism&lt;/strong&gt;, such as cookies and server-side sessions, to carry authentication state between requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Point to remember&lt;/strong&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTTP is stateless.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication state is managed on top of HTTP.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Understanding this distinction is an important step toward understanding web applications beyond the code we write every day.&lt;/p&gt;

&lt;p&gt;And this is just the beginning of our Deeper Dive into HTTP series.&lt;/p&gt;

&lt;p&gt;In the next article, we'll explore HTTP requests, responses, and headers in more detail, including what these messages actually look like and how to interpret them when working with APIs.&lt;/p&gt;

&lt;p&gt;If you found this useful, follow AshayCodes - &lt;a href="https://www.instagram.com/ashaycodes/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.youtube.com/@AshayCodes" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; for more practical explanations of the technologies we use every day.&lt;/p&gt;

&lt;p&gt;Happy learning!&lt;/p&gt;

</description>
      <category>backend</category>
      <category>networking</category>
      <category>web</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Excited to share a small new beginning! 🚀</title>
      <dc:creator>Ashay Tiwari</dc:creator>
      <pubDate>Fri, 02 Oct 2026 15:16:38 +0000</pubDate>
      <link>https://dev.to/ashay_tiwari_3658168ad5db/excited-to-share-a-small-new-beginning-4d5o</link>
      <guid>https://dev.to/ashay_tiwari_3658168ad5db/excited-to-share-a-small-new-beginning-4d5o</guid>
      <description>&lt;p&gt;Excited to share a small new beginning! 🚀&lt;/p&gt;

&lt;p&gt;I’ve started AshayCodes, where I’ll be sharing my experiences, learnings, and practical knowledge from my journey as a Software Engineer.&lt;/p&gt;

&lt;p&gt;My first introduction video is now live on YouTube and Instagram. 🎥&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/TNxHWRM7EWc" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Would love to have you along for the journey!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=TNxHWRM7EWc" rel="noopener noreferrer"&gt;Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.instagram.com/ashaycodes/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ashaycodes</category>
      <category>softwareengineering</category>
      <category>developer</category>
      <category>coding</category>
    </item>
    <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>
  </channel>
</rss>
