Refactor Renest Blocks

last modified: January 28, 2009

In a number of cases, the order of nesting of loops (and conditional tests) is not important: All must be done, but the order of nesting does not change the result.

Example: Sum the cells in a three-dimensional array.

Dim dblTotal   As Double
dblTotal = 0#
For k = 1 To MaxK
    For j = 1 To MaxJ
        For i = 1 To MaxI
            dblTotal = dblTotal + arrValues(i, j, k)
        Next i
    Next j
Next k
' Use "dblTotal" here...

...can safely be changed to...

Dim dblTotal   As Double
dblTotal = 0#
For i = 1 To MaxI
    For j = 1 To MaxJ
        For k = 1 To MaxK
            dblTotal = dblTotal + arrValues(i, j, k)
        Next k
    Next j
Next i
' Use "dblTotal" here...

Q: Why do this?

A1: We might want to print subtotals as our next move.

Dim dblTotal   As Double
Dim dblTotalI  As Double
Dim dblTotalJ  As Double
Dim dblValueK  As Double
dblTotal = 0#
For i = 1 To MaxI
    dblTotalI = 0#
    For j = 1 To MaxJ
        dblTotalJ = 0#
        For k = 1 To MaxK
            dblValueK = arrValues(i, j, k)
            dblTotalJ = dblTotalJ + dblValueK
        Next k
        Print "Total for i=" & i & ", j=" & j & " is " & dblTotalJ
        dblTotalI = dblTotalI + dblTotalJ
    Next j
    Print "Total for i=" & i & " is " & dblTotalI
    dblTotal = dblTotal + dblTotalI
Next i
' Use "dblTotal" here...
Print "Final total is " & dblTotal

A1b: To support other refactoring moves...

From...

If x Then
    If y Then
        Do A.
    Else
        Do B.
    End If
Else
    If y Then
        Do A.
    Else
        Do C.
    End If
End If

To...

If y Then
    If x Then
        Do A.
    Else
        Do A.
    End If
Else
    If x Then
        Do B.
    Else
        Do C.
    End If
End If

then...

If y Then
    Do A.
Else
    If x Then
        Do B.
    Else
        Do C.
    End If
End If

Q: Why do this?

A2: It may be necessary to make the code more efficient or intuitive.

Here 's a real example, taken from production code:

For i = 1 To MaxI
    For j = 1 To MaxJ
        If Data(i) = 0 Then
            ' Do important processing.
        End If
    Next j
Next i

changed to...

For i = 1 To MaxI
    If Data(i) = 0 Then
        For j = 1 To MaxJ
            ' Do important processing.
        Next j
    End If
Next i

Because we don't need to determine if "Data(i)" is processable MaxJ TIMES (for each and every i)!!!

This example was the inspiration for creating this page -- and the first few generic examples. -- JeffGrigg


Q: Why do this?

A3: It can be used to increase locality of reference so as to not hammer your system cache as much. -- AlastairBridgewater


Q: Why do this?

A4: Because my brain likes things to be in order. Therefore:

for i...
  for j...
    for k...

reads easier than

for j...
  for i...
    for k...

Or you might choose the J (JayLanguage) statement:

theTotal =: +/,theArray

which works for any rank array, not just the rank 3 array being discussed. --JimRussell


[CategoryRefactoring/RefactoringLanguage]


Loading...