<?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: Vikash Kumar</title>
    <description>The latest articles on DEV Community by Vikash Kumar (@codemason_vikash).</description>
    <link>https://dev.to/codemason_vikash</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%2F4126415%2Fe39ebd0e-2d85-40db-9ec7-8b0dc5d67906.jpg</url>
      <title>DEV Community: Vikash Kumar</title>
      <link>https://dev.to/codemason_vikash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codemason_vikash"/>
    <language>en</language>
    <item>
      <title>I'm Exploring Low Level Design , and SOLID Is Changing How I Look At Code</title>
      <dc:creator>Vikash Kumar</dc:creator>
      <pubDate>Tue, 15 Sep 2026 14:17:27 +0000</pubDate>
      <link>https://dev.to/codemason_vikash/im-exploring-low-level-design-and-solid-is-changing-how-i-look-at-code-3a72</link>
      <guid>https://dev.to/codemason_vikash/im-exploring-low-level-design-and-solid-is-changing-how-i-look-at-code-3a72</guid>
      <description>&lt;p&gt;I've started going deeper into Low-Level Design as part of my journey toward becoming a stronger software engineer.&lt;/p&gt;

&lt;p&gt;My initial understanding of LLD was mostly around classes, objects, relationships, and design patterns.&lt;/p&gt;

&lt;p&gt;But one thing became clear very quickly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Good LLD isn't about writing more classes or using more design patterns.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's about making code easier to change without creating unnecessary complexity.&lt;/p&gt;

&lt;p&gt;That's where SOLID started making more sense to me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;SOLID isn't five rules to memorize&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The five principles are:&lt;/p&gt;

&lt;p&gt;Single Responsibility Principle&lt;br&gt;
Open/Closed Principle&lt;br&gt;
Liskov Substitution Principle&lt;br&gt;
Interface Segregation Principle&lt;br&gt;
Dependency Inversion Principle&lt;/p&gt;

&lt;p&gt;But instead of memorizing their definitions, I'm trying to understand the problems they're trying to prevent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. SRP — How many reasons can make this class change?_&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine an Invoice class responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calculating the invoice&lt;/li&gt;
&lt;li&gt;printing the invoice&lt;/li&gt;
&lt;li&gt;saving it to the database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It may work perfectly today.&lt;/p&gt;

&lt;p&gt;But these responsibilities can change independently.&lt;/p&gt;

&lt;p&gt;A change in calculation logic shouldn't necessarily require touching printing logic.&lt;/p&gt;

&lt;p&gt;A database change shouldn't necessarily affect invoice calculation.&lt;/p&gt;

&lt;p&gt;That made the idea of SRP much clearer to me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The important question isn't simply "How many things does this class do?&lt;/em&gt;"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;It's "How many independent reasons can make this class change?&lt;/em&gt;"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. OCP — What happens when a new requirement arrives?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose an invoice can currently be saved to a database.&lt;/p&gt;

&lt;p&gt;Tomorrow the requirement becomes:&lt;/p&gt;

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

&lt;p&gt;One approach is to keep adding methods to the existing class.&lt;/p&gt;

&lt;p&gt;But as requirements continue to grow, the class becomes a collection of unrelated variations.&lt;/p&gt;

&lt;p&gt;Using an abstraction allows different implementations to provide different behaviors.&lt;/p&gt;

&lt;p&gt;This made OCP feel less like:&lt;/p&gt;

&lt;p&gt;"Never modify existing code."&lt;/p&gt;

&lt;p&gt;and more like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Design stable parts so that new behavior can be added without constantly changing them."&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. LSP — Inheritance is more than code reuse&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Liskov Substitution Principle was particularly interesting to me.&lt;/p&gt;

&lt;p&gt;Imagine a Vehicle abstraction that assumes every vehicle has an engine.&lt;/p&gt;

&lt;p&gt;A car fits.&lt;/p&gt;

&lt;p&gt;A motorcycle fits.&lt;/p&gt;

&lt;p&gt;But a bicycle doesn't.&lt;/p&gt;

&lt;p&gt;If client code expects every Vehicle to provide engine-related behavior, substituting a bicycle can break the program's assumptions.&lt;/p&gt;

&lt;p&gt;The problem isn't simply that the child class has a different implementation.&lt;/p&gt;

&lt;p&gt;The problem is that the parent abstraction made a promise that the child cannot satisfy.&lt;/p&gt;

&lt;p&gt;That gave me a better way to think about inheritance:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A subtype should preserve the behavioral expectations of its parent.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. ISP — Don't make clients implement what they don't need&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine one RestaurantEmployee interface containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;washDishes()&lt;/li&gt;
&lt;li&gt;serveCustomers()&lt;/li&gt;
&lt;li&gt;cookFood()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A waiter shouldn't need to implement cooking and dishwashing just because those methods happen to exist on a large interface.&lt;/p&gt;

&lt;p&gt;Breaking the interface into smaller, focused interfaces makes the dependency more meaningful.&lt;/p&gt;

&lt;p&gt;The lesson:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;An abstraction should be focused enough that its clients actually need what it exposes.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. DIP — Depend on capability, not implementation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I'm taking away&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The biggest change in my thinking isn't that I now know what SOLID stands for.&lt;/p&gt;

&lt;p&gt;It's that I'm starting to look at code by asking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;How easily can this code change?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I see a class, I want to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What can cause it to change?&lt;/li&gt;
&lt;li&gt;Is it taking too many responsibilities?&lt;/li&gt;
&lt;li&gt;What happens when a new behavior is introduced?&lt;/li&gt;
&lt;li&gt;Can its subclasses really substitute for it?&lt;/li&gt;
&lt;li&gt;Are clients depending on things they don't need?&lt;/li&gt;
&lt;li&gt;Am I coupling the design to implementation details?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I still have a lot to learn.&lt;/p&gt;

&lt;p&gt;Next, I'm going deeper into design patterns and LLD problems to understand how these principles translate into actual designs and code.&lt;/p&gt;

&lt;p&gt;I'm documenting that journey as I go.&lt;/p&gt;

&lt;p&gt;Consider a MacBook that directly creates:&lt;/p&gt;

&lt;p&gt;WiredKeyboard&lt;br&gt;
WiredMouse&lt;/p&gt;

&lt;p&gt;The class now knows too much about concrete implementations.&lt;/p&gt;

&lt;p&gt;If we instead make it depend on:&lt;/p&gt;

&lt;p&gt;Keyboard&lt;br&gt;
Mouse&lt;/p&gt;

&lt;p&gt;we can provide different implementations without changing the MacBook itself.&lt;/p&gt;

&lt;p&gt;This is where dependency inversion starts becoming practical:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;High-level logic shouldn't be tightly coupled to low-level implementation details.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>learning</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
