Robert’s Rules of Coders #9: Eliminate Deep Nesting by Using Switch Statements and Functions
Posted by robkraft on February 14, 2016
The ‘If’ statement is one of the fundamental coding constructs of almost every programming language. Along with the ‘If’ statement, most languages also support ‘else’ conditions and the ability to nest ‘If’ statements. But this simple construct can also become one of the biggest contributors to code that is difficult to understand and modify. This often happens when ‘If’ statements get nested within ‘If’ statements; but there are two simple techniques you can use to reduce this complexity, ‘Switch’ statements and functions.
Switch statements offer these benefits to most developers:
- They are easier to read, and thus
- They are easier to understand, and thus
- They are easier to maintain.
- They are also easier to debug
- In many languages, they also can be compiled to execute a little more swiftly that nested ‘If’ statements
Here is an example of an ‘If’ statement than can be improved by converting it to a ‘Switch’ statement:
If aValue = 6 then
Stars = stars + 1
Else
if aValue = 7
Stars = stars + 3
Else
if aValue = 8
Stars = stars + 5
Else
if aValue = 9
Stars = stars + 9
End if
End if
End if
End if
Here is the same logic from above, using a ‘Switch’ statement:
Switch aValue
Case 6:
Stars = Stars + 1
Case 7:
Stars = Stars + 3
Case 8:
Stars = Stars + 5
Case 9:
Stars = Stars + 9
I suspect that you will agree that it is easier to understand the code in the switch statement than the code in the nested ‘If’s. Another technique to eliminate nested ‘If’ statements is to move some of the code into separate functions. Although the hierarchy of ‘If’ statements may remain the same from the computer’s point of view, to most humans it becomes much easier to manage.
If input data is valid
If filename is valid
Create File
If file was created
Log “Success”
Return “Success”
Else
If error due to size
Log “Failure”
Return “Could not create file because it is too large.”
If error due to permission
Log “Failure”
Return “Could not create file because you do not have permissions.”
Else
Log “Failure”
Return “Unable to create the file. Reason unknown.”
End if
End if
Else
Log “Failure”
Return “Your file name is invalid.”
End if
Else
Log “Failure”
Return “The file input is invalid.”
End if
Here is the same logic from above, using functions:
String response = “”
Response = IsInputValid(myinput)
If (response= “”)
Return response
Response = IsFileNameValid(myfile)
If (response= “”)
Return response
return FileCreationResultMessage(myfile, myinput)
The functions called from the code above:
Function string IsInputValid(string input)
If input is not valid
Log “Failure”
Return “The file input is invalid.”
Else
Return “”
End if
End Function
Function string IsFileNameValid(string input)
If input is not valid
Log “Failure”
Return “Your file name is invalid.”
Else
Return “”
End if
End Function
Function string FileCreationResultMessage(string file, string input)
Create File
If file was created
Log “Success”
Return “Success”
Else
If error due to size
Log “Failure”
Return “Could not create file because it is too large.”
If error due to permission
Log “Failure”
Return “Could not create file because you do not have permissions.”
Else
Log “Failure”
Return “Unable to create the file. Reason unknown.”
End if
End if
End Function
As with any of Robert’s Rules of Coding, you don’t need to adhere to them all of the time and there are cases where it is better not to. But most programmers should follow the rules most of the time. I hope you agree.
Go to Robert’s Rules of Coders for more.
richardtallent said
While I agree in principle that switch statements have some advantages, no one in their right might nests if/else as shown, so it’s a bit of an unfair comparison. Also, depending on the language, switch-like statements require “break” statements after the code for each case to avoid fall-through, creating fertile ground for silent bugs.
robkraft said
Thanks for the comments Richard. Unfortunately I have seen code with if/else as shown, in fact, much worse than that. When I see them, I suspect the code-writer was not aware switch statements exist. And you are certainly correct that some languages such as C# require “break” statements; but my article is intended to focus on concepts that apply to most languages, and not the syntax of a specific language.
richardtallent said
Thanks Rob. Still, most coders do use the ElseIf statement in BASIC-like languages and the “} else if {” form in C-like languages rather than nesting each “else” block visually deeper.
The switch statement in C# requires “break,” but it’s also required in C (including Objective-C, C++, etc.), JavaScript (including TypeScript), Java, FORTRAN, PHP… the only languages I can think of off-hand that *don’t* require it are Swift, BASIC, and Perl.
Again, I don’t want to dump on switch — unlike Douglas Crockford, I don’t ban it from my code, for some of the very reasons you mentioned. But it should be used with caution, and preferably only if you have a good linter to warn you about fall-throughs in your code.
robkraft said
I did not realize Douglas Crockford was opposed to the switch. Like you, I also am not opposed to it, but you make a good point that you need to be careful with it in some languages. I also checked out your site and I like the layout to the links of many of the sites you contribute to, and ways to contact you; I might have to borrow that design! 🙂
Brothwell said
The biggest limitation of switch statements is the restriction that they can only use compile time integer values on the cases. I would also suggest that nest switch statements should generally be avoided.
robkraft said
Good suggestion. When I revise this article I will recommend avoided nested switches also.