wiki:RefactoringSteps/ExtractFunction

Version 1 (modified by manualwiki, 13 years ago) (diff)

--

Extract function

A function definition might contain an expression or a sequence of expressions which can be considered as a logical unit, hence a function definition can be created from it. The extracted function is lifted to the module level, and it is parameterized with the free variables of the original expressions: those variables which are bound outside of the expressions, but the value of which is used by the expressions.

Extracting the new function two_sol:

-module(quadratic).

-export([f/0]).

solve(A,B,C) ->
   D := B * B - 4 * A * C,
   if
      D == 0 ->
         {-B / 2 / A};
      D > 0 ->
         S = math:sqrt(D),
         {-(B+S)/2/A,
         -(B-S)/2/A}.
      D < 0 ->
         no_solution
   end.

Result:

-module(quadratic).

-export([f/0]).

solve(A,B,C) ->
   D := B * B - 4 * A * C,
   if
      D == 0 ->
         {-B / 2 / A};
      D > 0 ->
         two_sol(A, B, D);
      D < 0 ->
         no_solution
   end.

two_sol(A, B, D) ->
   Sqrt = math:sqrt(D),
   {-(B+S)/2/A,
    -(B-S)/2/A}.

Side conditions

  • The name of the new function should not conflict with another function, either defined in the same module, or imported from another module (overloading). Furthermore, the name should be a legal function name.

  • If one of the above conditions fails, the transformation starts an interaction to ask for a new function name.
  • The starting and ending positions should delimit a sequence of expressions.
  • Variables with possible binding occurrences in the selected sequence of expressions should not appear outside of the sequence of expressions.
  • The extracted sequence of expressions cannot be part of a guard sequence.
  • The extracted sequence of expressions cannot be part of a pattern.
  • The extracted sequence of expressions cannot be part of macro definition.

Transformation steps and compensations

  1. Collect all variables that the selected sequence of expressions depends on.
  1. Collect variables from the selected variables in step 1, which has binding occurrence out of the selected part of the module.
  1. Add a new function definition to the current module with a single alternative. The name of the function is an argument to the refactoring. The formal parameter list consists of the variables selected in step 2.
  1. Replace the selected sequence of expressions with a function call expression, where the name of the function is given as an argument to the refactoring, and the actual parameter list consists of the variables selected in step 2.
  1. The order of the variables must be the same in steps 3 and 4.
  1. If the selected expression is a block-expression, eliminate the begin-end keywords from the expression in the body of the created new function.