The problem
Have you ever had a really large if-else
statement, with many variables, just to cover all cases. Let's say you have some message you want to show to the user, based on many inputs. How would you implement it? Probably, you'll start with if-else
statement, trying to cover as many cases as possible. It's totally fine, until you have too many inputs.
Every new input will increase the amount of cases progressively. For example, when you have 2 variables, it's just 4 cases, but when it's 3 variables, then you have 8 possible cases.
Possible situation
Now, imagine we build a website to order food and your restaurant provides delivery or pickup. You go to the website and see "At the moment, we have delivery issues, but you can order pickup instead".
Here's the list of possible input variables:
- do we have delivery?
- is delivery available today?
- is delivery open now?
- can I order for later?
Can you guess how large your if-else
statement will be? It's huge! And it'll be quite hard to cover everything. What if we have delivery, but pickup is not available for today? What if we have some issues with delivery and pickup will be open in an hour? The amount of possible situations is 2^4=16
and it'll be impossible to maintain when number of inputs grows. But don't worry! The solution will blow your mind! At least that's what happened to me ðĪŠ
The solution
The idea of that solution is so simple. You need to build a table of truths (all possible variants) and based on that table, each row will have a unique key that you can use as "status code". In the table below, I convert boolean values to 1 (true) and 0 (false). That way for each case we'll have a unique combination of 1 and 0 that will be our unique key, like1101
, and we could always convert this binary number to decimal number. For example, 1101
becomes 13
, and that's why you'll see normal numbers in the status code column.
Status code | Do we have delivery? | Is delivery available today? | Is delivery open now? | Can I order for later? |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 1 |
2 | 0 | 0 | 1 | 0 |
3 | 0 | 0 | 1 | 1 |
4 | 0 | 1 | 0 | 0 |
5 | 0 | 1 | 0 | 1 |
6 | 0 | 1 | 1 | 0 |
7 | 0 | 1 | 1 | 1 |
8 | 1 | 0 | 0 | 0 |
9 | 1 | 0 | 0 | 1 |
10 | 1 | 0 | 1 | 0 |
11 | 1 | 0 | 1 | 1 |
12 | 1 | 1 | 0 | 0 |
13 | 1 | 1 | 0 | 1 |
14 | 1 | 1 | 1 | 0 |
15 | 1 | 1 | 1 | 1 |
Now what? That's the beauty of that solution, it's all. You just need to return status code and map this code to any message you want. Check code examples section, to see the implementation.
Code examples
In this section, I'll provide a code you need to write to do this. It's in JavaScript, but it could be written in any language.
// Restaurant configuration, all our input variables are stored here
const restaurantConfiguration = {
haveDelivery: true,
deliveryAvailableToday: true,
deliveryOpenNow: false,
canOrderForLater: true,
}
// This function takes configuration and converts all `true` and `false` values to status code
function getStatusCode(restaurantConfiguration) {
const { haveDelivery, deliveryAvailableToday, deliveryOpenNow, canOrderForLater } =
restaurantConfiguration
// Note: don't change the order, or if you need to add more variables,
// add them to the beginning of the array.
// That way you won't break old status codes
const binaryNumberArray = [
haveDelivery,
deliveryAvailableToday,
deliveryOpenNow,
canOrderForLater,
].map((isTrue) => (isTrue ? '1' : '0')) // [true, true, false, true] => ['1', '1', '0', '1']
const binaryNumber = binaryNumberArray.join('') // '1101'
const statusCode = parseInt(binaryNumber, 2) // Converts '1101' to 13
return statusCode
}
// This is your mapping between message and status code
function buildMessagesTable() {
return {
0: null,
// ... cover any status code you need
13: 'Delivery is available today, but it is not open yet, so you could order for later',
}
}
function main() {
// Get status code
const statusCode = getStatusCode(restaurantConfiguration)
// Get a table with messages by status code
const messagesTable = buildMessagesTable()
// Get message by status code
const message = messagesTable[statusCode] || null
if (message) {
console.log(message)
}
}
main()
Summary
The only thing I want to mention about this solution is that it works great, especially when you have a bunch of inputs and when you need to cover a new case, you don't need to think about if-else
statement just to cover your case, you find out the status code and add one line with the message you need. Less code, fewer bugs ðŠ
Did you like the article? Share it with your friends. I'd appreciate that ð
Top comments (8)
It's a really clever approach to matching the conditions; but in a real-world application I'm not sure you would ever combine all these conditions into a single if-else flow. I'd expect that they would manifest themselves in the user flow so that a response is given as close to the input as possible. For example the moment a user selects 'delivery' they're immediately made aware that it isn't possible; or presented with times when it is possible. If they select pick-up they're told an approximate wait time etc. You simply wouldn't wait until all options are completed before giving any feedback.
In real world app I have 8 inputs parameters and based on the combination I show message to the user. I know itâs not usual and most applications donât need something like this. But I had a problem in a real project and this solution works really nice for me. Itâs easy to read, easy to maintain, and hard to break ð Maybe the example is not really good, but should describe the concept. I didnât want to share production code base with all 8 inputs and logic behind these inputs ð
Neat idea - thanks for sharing!
I know the decimal codes are built up from the binary codes, but how do you feel about adding the table as a comment too? I don't mean in the example above (it's fairly clear); I just meant in real-world usage.
You're right about it, in real-world usage you'll have to write some documentation. It could be a separate Markdown file, Confluence page, or whatever. I'd say it should be somewhere, where everyone from your team will have access to, as it can be used by designers, QA team, or even Product team. It could be as a comment in the code as well, if it makes sense for your team, but I feel like having a separate doc is much better, as you can share a link to the table with anyone. There is no right or wrong answer ð
Good point - the 'problem' with code comments is that they're pretty much exclusive to people who use the code directly. One thing that I've come across quite often is leaving a Jira (or other bug tracking system) ticket ID in the commit message. The ticket usually has more details/background on the task. That seems like a good candidate too.
Absolutely ð
Wow what a greate way you implement
Thanks! Happy to see that people love it ð