DEV Community

Cover image for Leave Switch Behind: The Power of Maps and Patterns in JavaScript Development
waelhabbal
waelhabbal

Posted on

Leave Switch Behind: The Power of Maps and Patterns in JavaScript Development

In this post, we'll explore the limitations of using switch statements in JavaScript and discuss alternative approaches using maps and patterns. We'll cover how maps can be used for dynamic lookups and how patterns can be used to encapsulate complex logic.

The Case Against Overusing Switch Statements

While switch statements are efficient for simple value comparisons, they have several limitations:

  • Readability: Long chains of case statements become difficult to read and debug.
  • Extensibility: Adding new cases requires modifying the existing structure.
  • Default Handling: The default case can become a catch-all, potentially hiding errors.

Enter Maps: Key-Value Pairs for Dynamic Lookups

Maps (introduced in ES6) offer a powerful alternative:

  • Key-Value Pairs: Store data as associations between keys and values.
  • Dynamic Lookups: Retrieve values efficiently based on keys.
  • Flexibility: Easily add, remove, or modify key-value pairs without altering the core logic.

Example: User Role Permissions (Map vs. Switch)

Using Switch:

function getUserPermissions(role) {
  switch (role) {
    case 'admin':
      return ['read', 'write', 'delete'];
    case 'editor':
      return ['read', 'write'];
    case 'reader':
      return ['read'];
    default:
      return [];
  }
}
Enter fullscreen mode Exit fullscreen mode

Using Map:

const permissionsMap = new Map([
  ['admin', ['read', 'write', 'delete']],
  ['editor', ['read', 'write']],
  ['reader', ['read']],
]);

function getUserPermissions(role) {
  return permissionsMap.get(role) || []; // Return empty array for missing roles
}
Enter fullscreen mode Exit fullscreen mode

Patterns for Encapsulating Behavior

Sometimes, complex logic within a switch case deserves its own reusable function. Here's how patterns come in:

  • Strategy Pattern: Define an interface for different behavior types and create concrete implementations for each case.
  • Command Pattern: Encapsulate actions within objects, allowing decoupled execution.

Example: Discount Calculations (Pattern vs. Switch)

Using Switch:

function calculateDiscount(productType, quantity) {
  switch (productType) {
    case 'electronics':
      return quantity > 5 ? 0.1 : 0.05;
    case 'clothing':
      return 0.1;
    default:
      return 0;
  }
}
Enter fullscreen mode Exit fullscreen mode

Using Strategy Pattern:

interface DiscountStrategy {
  calculateDiscount(quantity: number): number;
}

class ElectronicsDiscount implements DiscountStrategy {
  calculateDiscount(quantity: number) {
    return quantity > 5 ? 0.1 : 0.05;
  }
}

class ClothingDiscount implements DiscountStrategy {
  calculateDiscount() {
    return 0.1;
  }
}

function calculateDiscount(productType: string, quantity: number) {
  const strategies = {
    electronics: new ElectronicsDiscount(),
    clothing: new ClothingDiscount(),
  };
  return strategies[productType]?.calculateDiscount(quantity) || 0;
}
Enter fullscreen mode Exit fullscreen mode

Applying SOLID Principles

  • Single Responsibility Principle: switch often mixes data logic with control flow. Maps and patterns help isolate responsibilities.
  • Open/Closed Principle: Maps and patterns allow extending behavior without modifying existing code.
  • Liskov Substitution Principle: Patterns like Strategy ensure interchangeable behavior based on interfaces.
  • Interface Segregation Principle: Maps provide a clean interface for data lookup.
  • Dependency Inversion Principle: Patterns encourage relying on abstractions (interfaces) rather than concrete implementations (switch).

Conclusion:
By embracing maps and patterns, you can improve code readability and maintainability, enhance flexibility for future changes, and adhere to SOLID principles for better design. Remember, the best approach depends on the complexity of your logic. Consider using switch for simple cases, but for more intricate scenarios, maps and patterns are more suitable alternatives.

Top comments (0)