Refactor Renest Blocks

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]


EditText of this page (last edited January 28, 2009) or FindPage with title or text search