Control-of-Flow Guidelines
A good way to keep yourself out of trouble when it comes to
debugging and code maintenance is to employ good control-of-flow coding practices. This
might seem like a no-brainer, but experience has shown that the concept definitely
warrants reinforcement.
If Statements and Case/Switch Constructs
For simple decisions in
your code that have two or fewer possible alternatives, If statements are ideal. They are
a quick and easy way to guide the flow of your code. If you need to make a selection based
on a long list of possible alternatives, however, If statements can get messy and
intertwined. If you are choosing the path of execution based on the value of a single
variable, we strongly recommend using a Case construct (Switch construct, in C#). Consider
Listings 4.16 and 4.17 that use multiple If statements.
Listing 4.16. Large If Statement Block
public int Foo(int someVar)
{
if(someVar==10 || someVar==20 || somevar==30)
{//do something here}
else if(someVar==15 || someVar==25 || someVar==35)
{//do something here}
else if(someVar==40 || someVar==50 || someVar==60)
{//do something here}
else
{//do something here}
}
|
Listing 4.17. Large If Statement Block (Visual Basic .NET)
Public Function Foo(someVar As Integer) As Integer
If someVar = 10 Or someVar = 20 Or someVar = 30 Then
' do something here
ElseIf someVar = 15 Or someVar = 25 Or someVar = 35 Then
' do something here
ElseIf someVar = 40 Or someVar = 50 Or someVar = 60 Then
' do something here
Else
' do something here
End If
End Function
|
Although you can tell what is going on upon close examination of the code, it
might not be apparent when you are scanning it for bugs. A more concise and organized way
of accomplishing this task is to use a Case/Switch construct as shown in Listings 4.18 and
4.19.
Listing 4.18. Switch Block (C#)
public int Foo(int someVar)
{
switch(someVar)
{
case 10: case 20: case 30:
//do something here
break;
case 15: case 25: case 35:
//do something here
break;
case 40: case 50: case 60:
//do something here
break;
default:
//do something here
break;
}
}
|
Listing 4.19. Case Statement Block (Visual Basic .NET)
Public Function Foo(someVar As Integer) As Integer
Select Case someVar
Case 10, 20, 30
' do something here
Case 15, 25, 35
' do something here
Case 40, 50, 60
' do something here
Case Else
' do something here
End Select
End Function
|
Function and Loop Exit Points
Some of the most elusive bugs in applications
arise from improper use of function and loop exit points. As a general rule, a function or
loop should have only one exit point. Why should this be so? If a function or loop has
more than one exit point, then it is more difficult to track down which exit point your
code is using when you are debugging. An exit point could be hidden in your code, leaving
you scratching your head when you try to determine why your code is not working properly.
Consider the following function that violates the single exit point rule (shown in
Listings 4.20 and 4.21).
Listing 4.20. Code with Multiple Exit Points
public int Foo(int someVar)
{
int i = 0;
for(i=0;i<=100;i++)
{
//do something to someVar
someVar = i;
//see whether you need to get out early
if(someVar==50)
{break;}
if((someVar * 2) % 10 == 0)
{break;}
}
if(i < 100)
{return 1;}
return 0;
}
|
Listing 4.21. Code with Multiple Exit Points (Visual Basic .NET)
Public Function Foo(someVar As Integer) As Integer
Dim i As Integer
For i = 1 To 100
' do something to someVar
someVar = i
' see whether you need to get out early
If someVar = 50 Then
Exit For
End If
If (someVar * 2) Mod 10 = 0 Then
Exit For
End If
Next i
If i < 100 Then
' loop ended prematurely, so get out
Return 1
End If
Return 0
End Function
|
You would need to set breakpoints and step through your code line by line to
determine what is going on here. A more effective approach is to use status flags. Status
flags can be included in loop definitions to determine when the loop should end. Status
flags can also be used to set return codes at the single function exit point. Listings 4
.22 and 4.23 demonstrate this concept.
Listing 4.22. Code with a Single Exit Point
public int Foo2(int someVar)
{
int status = 0;
for(int i=0;i<=100;i++)
{
//do something to someVar
someVar = i;
//see whether you need to get out early
if(someVar==50)
{status = 1;}
if((someVar * 2) % 10 == 0)
{status = 1;}
//single place where loop can terminate early
if(status==1) {break;}
}
return status;
}
|
Listing 4.23. Code with Single Exit Point (Visual Basic .NET)
Public Function Foo(someVar As Integer) As Integer
Dim i As Integer = 0
Dim status As Integer = 0
For i = 1 To 100
' do something to someVar
someVar = i
' see whether you need to get out early
If someVar = 50 Then
status = 1
End If
If (someVar * 2) Mod 10 = 0 Then
status = 1
End If
' single place where loop can terminate early
If status = 1 Then Exit For
Next i
Return status
End Function
|