< All Articles

3 ways to avoid if-else hell in JavaScript

4 minute read | Jul 26, 2024
engineering

Share this article:

Here are three ways to avoid if-else hell in JavaScript.

Imagine we are writing a program to determine the priority of an issue affecting a piece of equipment given the associated impact.

Here is the bad way of using nested if-else statements. The logic quickly becomes unclear and difficult to maintain.

// BAD WAY - Using nested IF ELSE statements to determine priority

let determinePriorityIfElse = (issue) => {
 let equipment = issue.equipment
 let impact = issue.impact

 // Major equipment priority rules
 if (equipment === "chiller" || equipment === "boiler" || equipment === "coolingtower") {
   if (impact === "safety" || impact === "uptime" || impact === "water") {
     return "urgent"
   } else if (impact === "energy") {
     return "maintenance"
   } else {
     return "low"
   }
 }

 // Secondary equipment priority rules
 if (equipment === "lighting" || equipment === "meter") {
   if (impact === "safety") {
     return "urgent"
   } else if (impact === "uptime" || impact === "water" || impact === "energy") {
     return "maintenance"
   } else {
     return "low"
   }
 }
}

let issue = {
 equipment: "coolingtower",
 impact: "energy"
}

determinePriorityIfElse(issue) // 'maintenance'

Use Array.includes and return early

Use Array.includes when checking multiple criteria. Capture criteria rules within arrays early in your logic. Return early to reduce nesting.

Advantages to if-else

Improves maintainability, adding new equipment affected and associated impact can be done by updating the equipment and impacts arrays.

// BETTER WAY - Using Array.includes for multiple criteria

let determinePriorityArrayIncludes = (issue) => {
 // Major equipment priority rules
 const majorEquipment = ["chiller", "boiler", "coolingtower"]
 const urgentImpactsMajor = ["safety", "uptime", "water"]
 const maintenanceImpactsMajor = ["energy"]

 // Secondary equipment priority rules 
 const secondaryEquipment = ["lighting", "meter"]
 const urgentImpactsSecondary = ["safety"]
 const maintenanceImpactsSecondary = ["uptime", "water", "energy"]

 let equipment = issue.equipment
 let impact = issue.impact

 // Determine priority for major equipment
 if (majorEquipment.includes(equipment)) {
   if (urgentImpactsMajor.includes(impact)) return "urgent"
   if (maintenanceImpactsMajor.includes(impact)) return "maintenance"
   return "low"
 }

 // Determine priority for secondary equipment
 if (secondaryEquipment.includes(equipment)) {
   if (urgentImpactsSecondary.includes(impact)) return "urgent"
   if (maintenanceImpactsSecondary.includes(impact)) return "maintenance"
   return "low"
 }

 // Default priority if no match found
 return "low"
}

let issue = {
 equipment: "coolingtower",
 impact: "energy"
}
determinePriorityArrayIncludes(issue) // 'maintenance'

Separate logic in a dictionary

Capture priority rules in a separate dictionary object named equipmentImpactPriorityMap. Add each equipment as an object with every impact as a property with the associated priority.

To determine the issue priority, look up the equipment and associated impact - as expressed by determinePriorityDictionary(issue).

Advantages to if-else

Better clarity and scalability. Separating out the logic into a config file makes it easier to debug and allow feedback from non-technical teams. Matches mental model of looking up the equipment and associated impact to find the determined priority.

// BETTER WAY - Separate logic in a dictionary
const equipmentImpactPriorityMap = {
 chiller: {
   safety: 'urgent',
   uptime: 'urgent',
   water: 'urgent',
   energy: 'maintenance',
   other: 'low'
 },
 boiler: {
   safety: 'urgent',
   uptime: 'urgent',
   water: 'urgent',
   energy: 'maintenance',
   other: 'low'
 },
 coolingtower: {
   safety: 'urgent',
   uptime: 'urgent',
   water: 'urgent',
   energy: 'maintenance',
   other: 'low'
 },
 lighting: {
   safety: 'urgent',
   uptime: 'maintenance',
   water: 'maintenance',
   energy: 'maintenance',
   other: 'low'
 },
 meter: {
   safety: 'urgent',
   uptime: 'maintenance',
   water: 'maintenance',
   energy: 'maintenance',
   other: 'low'
 }
};

let determinePriorityDictionary = (issue) => {
 return equipmentImpactPriorityMap[issue.equipment][issue.impact]
}

let issue = {
 equipment: "coolingtower",
 impact: "energy"
}

determinePriorityDictionary(issue) // 'maintenance'

Want more tips?

Get future posts with actionable tips in under 5 minutes and a bonus cheat sheet on '10 Biases Everyone Should Know'.

Your email stays private. No ads ever. Unsubscribe anytime.


Share this article:

< All Articles