<?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: Lakshay Kalra</title>
    <description>The latest articles on DEV Community by Lakshay Kalra (@lakshaykalra).</description>
    <link>https://dev.to/lakshaykalra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F471478%2F0cd81c3e-6144-4e81-a0bc-f69e440cf9f2.jpeg</url>
      <title>DEV Community: Lakshay Kalra</title>
      <link>https://dev.to/lakshaykalra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lakshaykalra"/>
    <language>en</language>
    <item>
      <title>🧩 Building a Pluggable Notification System in JavaScript Using the Factory Pattern</title>
      <dc:creator>Lakshay Kalra</dc:creator>
      <pubDate>Fri, 18 Apr 2025 11:30:06 +0000</pubDate>
      <link>https://dev.to/lakshaykalra/building-a-pluggable-notification-system-in-javascript-using-the-factory-pattern-3lcp</link>
      <guid>https://dev.to/lakshaykalra/building-a-pluggable-notification-system-in-javascript-using-the-factory-pattern-3lcp</guid>
      <description>&lt;p&gt;Sending notifications — via email, SMS, push, or Slack — is a common requirement in most applications. But how do you design such a system so that it's easy to extend without modifying existing logic every time a new channel is added?&lt;/p&gt;

&lt;p&gt;Enter the Factory Pattern and Open/Closed Principle.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through how to build a flexible notification system using modern JavaScript, following clean architecture principles.&lt;/p&gt;

&lt;p&gt;🧱 &lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most developers start with something 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;if (type === 'EMAIL') {
  sendEmail(message);
} else if (type === 'SMS') {
  sendSms(message);
} else if (type === 'PUSH') {
  sendPush(message);
}

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

&lt;/div&gt;



&lt;p&gt;This works — until your PM says, "We also need to support Slack. Oh, and WhatsApp next week."&lt;/p&gt;

&lt;p&gt;Suddenly you're modifying the same block of logic again and again. That's not scalable.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;The Goal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We want a system where:&lt;/p&gt;

&lt;p&gt;Each notification type is its own class.&lt;/p&gt;

&lt;p&gt;We can register new types without changing core logic.&lt;/p&gt;

&lt;p&gt;The notification center can dynamically send messages based on type.&lt;/p&gt;

&lt;p&gt;🏗️ &lt;strong&gt;Step-by-Step Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define Notification Classes
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class EmailNotification {
  send(message) {
    console.log(`sending email notification with message ${message}`);
  }
}

class SmsNotification {
  send(message) {
    console.log(`sending sms notification with message ${message}`);
  }
}

class PushNotification {
  send(message) {
    console.log(`sending push notification with message ${message}`);
  }
}

class SlackNotification {
  send(message) {
    console.log(`sending slack notification with message ${message}`);
  }
}

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

&lt;/div&gt;



&lt;p&gt;Each class follows the same interface: a send() method that takes a message.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Factory Base Class
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NotificationCreator {
  constructor() {
    this.registry = {
      'EMAIL': EmailNotification,
      'SMS': SmsNotification,
      'PUSH': PushNotification,
    };
  }

  register(type, notificationClass) {
    if (!this.registry[type]) {
      this.registry[type] = notificationClass;
    }
  }

  createNotification(type) {
    const NotificationClass = this.registry[type];
    if (!NotificationClass) {
      throw new Error(`${type} class is not implemented`);
    }
    return new NotificationClass();
  }
}

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

&lt;/div&gt;



&lt;p&gt;This class:&lt;/p&gt;

&lt;p&gt;Holds a registry of notification types&lt;/p&gt;

&lt;p&gt;Provides a register() method to add new types dynamically&lt;/p&gt;

&lt;p&gt;Has a createNotification() method that acts as a factory&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notification Center That Sends Messages
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NotificationCenter extends NotificationCreator {
  send(message, type) {
    const notification = this.createNotification(type);
    notification.send(message);
  }
}

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Putting It All Together
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const notification = new NotificationCenter();

notification.send("Hey Email", "EMAIL");
notification.send("hey SMS", "SMS");
notification.send("hey PUSH-Notification", "PUSH");

// Register Slack dynamically
notification.register("SLACK", SlackNotification);
notification.send("Hey Slack", "SLACK");

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

&lt;/div&gt;



&lt;p&gt;🎯 &lt;strong&gt;Benefits of This Approach&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Open/Closed Principle: You can add new notification types without modifying existing logic.&lt;br&gt;
✅ Scalable: Future types like WhatsApp, Telegram, Discord can be plugged in with one register() call.&lt;br&gt;
✅ Testable: Each class can be tested independently.&lt;br&gt;
✅ Clean Code: No repetitive if/else or switch blocks.&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Bonus Tip: Make It Even Cleaner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Move the default registry into a method like registerDefaults() if your base class grows. Also, consider adding validation or interfaces if you're using TypeScript.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This pattern works great for:&lt;/p&gt;

&lt;p&gt;Notification systems&lt;/p&gt;

&lt;p&gt;Payment gateways (Stripe, Razorpay, PayPal)&lt;/p&gt;

&lt;p&gt;Message formatters (Markdown, HTML, plain text)&lt;/p&gt;

&lt;p&gt;By following this strategy, you're not only making your code cleaner — you're also writing software that's built to scale.&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Got questions or improvements? Drop them in the comments — let’s chat clean code!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Optional Chaining in javascript.</title>
      <dc:creator>Lakshay Kalra</dc:creator>
      <pubDate>Sun, 15 Nov 2020 09:56:57 +0000</pubDate>
      <link>https://dev.to/lakshaykalra/optional-chaining-in-javascript-54e8</link>
      <guid>https://dev.to/lakshaykalra/optional-chaining-in-javascript-54e8</guid>
      <description>&lt;p&gt;Imagine we have a deeply nested object of level "N" and we want to check the "Mth" level if it exists or not. Let me put an example in front of you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let customer={
name:'Foo',
cars:{
carOne:'Audi',
carTwo:'BMW'
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I have to say lets check "carOne" property is present or not in customer object, I can do this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(customer &amp;amp;&amp;amp; customer.cars &amp;amp;&amp;amp; customer.cars.carOne) {
// do your stuff
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's easy, right? &lt;/p&gt;

&lt;p&gt;But if we observe the code above carefully, What we have found?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate Code - To check a property exists or not, we are re-writing some conditions of the code again and again. Means some part of the code is executing many times. Thereby increasing code execution time. &lt;/li&gt;
&lt;li&gt;Longer version - If we are writing multiple conditions to check for a property, The code becomes lengthy and if we skip some validation in between, we can get an error.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
let customer={
  name:'Foo',
  }

  if(customer  &amp;amp;&amp;amp; customer.cars.carOne) { // will result in TypeError:Cannot read property 'carOne' of undefined
    // do your stuff
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How about we fix this guy into a one-liner statement. And here's the code for your rescue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if( customer?.cars?.carOne ) {
// do your stuff
}

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

&lt;/div&gt;



&lt;p&gt;Boom!! All your problems just got vanished. &lt;/p&gt;

&lt;p&gt;Here's How.&lt;/p&gt;

&lt;p&gt;The expression "?." is called &lt;strong&gt;Optional Chaining&lt;/strong&gt; and it's evaluating whether an expression before the "?" statement is &lt;strong&gt;Nullable&lt;/strong&gt; and/or &lt;strong&gt;Undefined&lt;/strong&gt;. If it is, The whole expression will stop executing, or in a technical term, it's called "Short-Circuiting" and the code execution will just be carried on afterward. &lt;/p&gt;

&lt;p&gt;Benefits?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No Duplicate code - The optional chaining expression is &lt;strong&gt;not&lt;/strong&gt; checking the same condition again and again if it's already been examined. Here's, Kind of continuous chaining is happening. So no object property will be traversed multiple times. Thereby, Saving code execution time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shorter and simplified version - This is of course shorter and easy to read, unlike the vanilla code. As optional chaining is also checking &lt;strong&gt;Nullable&lt;/strong&gt; and/or &lt;strong&gt;Undefined&lt;/strong&gt; throughout the way, it will not result in "TypeError". In this case, execution still continues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you find this blog interesting. Until next time, Adios amigos.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
