Skip to content

Extract Method Refactoring : Workings Determining what params to move

Gareth Leachman edited this page May 21, 2016 · 7 revisions

The method applied here was inspired from a paper title "Improving Method Extraction: A Novel Approach to Data Flow Analysis Using Boolean Flags and Expressions" by Nicolas Juillerat, Béat Hirsbrunner presented at the "1st Workshop on Refactoring Tools, Berlin, 2007"

To start I have used a table. Variables on the x axis, and properties on the y axis.

The properties are expressed in terms of currently selected text, and are defined as

  • declared Before (db)
  • declared After (da)
  • declared In (di)
  • used Before (ub)
  • used After (ua)
  • assignedTo (at)
  • usedIn (ui)

Given some code

Dim x as long
Dim y as long
Dim z as long

x = 1
y = 2  'selected
z = 1

and refactoring the line y = 2 , the table becomes

db|1|1|1 
da|0|0|0 
di|0|0|0
ub|1|0|0 
ua|0|0|1 
at|0|1|0 
ui|0|1|0
------------- 
  |x|y|z 

So applying the technique to the following code snippets

'Example 2
Dim x as long
Dim y as long
Dim z as long

x = 1
y = x   'selected
z = 1

'Example 3
Dim x as long
Dim y as long
Dim z as long

x = 1
y = x   'selected
z = x

'Example 4
Dim x as long
Dim y as long
Dim z as long

x = 1
z = 1
y = x   'selected
x = 2   'selected
z = x

' Selection is line `y = x` and `x = 2`  the 2 lines 7 & 8 

'Example 5
Dim x as long
Dim y as long
Dim z as long

z = 1
y = x   'selected
x = 2   'selected
z = x

' Selection is line `y = x` and `x = 2`  the 2 lines 6 & 7 

'Example 6
Dim x as long
Dim z as long

z = 1
Dim y as long  'selected
y = x          'selected
x = 2          'selected
z = y

' Selection is line `y = x` and `x = 2`  the 2 lines 6 & 7 

The tables appear as follows

Ex1        Ex2        Ex3        Ex4        Ex5        Ex6
db|1|1|1   db|1|1|1   db|1|1|1   db|1|1|1   db|1|1|1   db|1|0|1  
da|0|0|0   da|0|0|0   da|0|0|0   da|0|0|0   da|0|0|0   da|0|0|0       These ultimately get ignored   
---------------------------------------------------------------
ub|1|0|0   ub|1|0|0   ub|1|0|0   ub|1|0|1   ub|0|0|1   ub|0|0|1      1
ua|0|0|1   ua|0|0|1   ua|1|0|1   ua|1|0|1   ua|1|0|1   ua|1|1|1      2
at|0|1|0   at|0|1|0   at|0|1|0   at|1|1|0   at|1|1|0   at|1|1|0      4
ui|0|1|0   ui|1|1|0   ui|1|1|0   ui|1|1|0   ui|1|1|0   ui|1|1|0      8
di|0|0|0   di|0|0|0   di|0|0|0   di|0|0|0   di|0|0|0   di|0|1|0      16
--------   --------   --------   --------   --------   --------   
  |x|y|z     |x|y|z     |x|y|z     |x|y|z     |x|y|z     |x|y|z    

from reviewing the required out comes of each example the abridged method signature of the refactored method would need to look as follows. In each case the variable y and its declaration are always moved into the new method.

Ex1: Sub NewMethod()
Ex2: Sub NewMethod(byval x)
Ex3: Sub NewMethod(byval x)
Ex4: Sub NewMethod(byref x)
Ex5: Sub NewMethod(byref x)
Ex6: Sub NewMethod(byref x, byref y)  - extract dim of y

It turns out we don't need to worry about whether the variable is declared before or after the selection to be moved. Determining what variables become byref, byval or are moved in to the method then becomes, with the corresponding flags as binary converted to decimal

MoveIn = usedIn + assignedIn + !usedAfter  + !usedBefore : 12
ByVal = usedIn + !assignedIn + usedBefore : 9 or 10
ByRef = usedIn + assignedIn + usedAfter : 14 or 15

Deciding if a variable needs to be declared externally becomes ExtractDim = declIn + usedAfter + (!usedIn | usedAfter) + (!assignedTo | assignedTo ) : 18+

Giving

Ignore : ByVal : MoveIn : ByRef 
       < 4- 11 <   12   <       

and ExtractDim 18 +

.... work in progress #844 #1225

Clone this wiki locally