Refactoring: Refactorings/Move Eval from Runtime to Parse Time

From Notes
Jump to navigation Jump to search

Calling Kernel#eval is always expensive from a performance standpoint. If performance is necessary, move the eval call to parse-time instead of calling it from run-time

Mechanics

  1. Expand the scope of the string being eval'd
  2. Test


Example

Before

class Person
  def self.attr_with_default(options)
    options.each_pair do |attribute, default_value|
      define_method attribute do
        eval "@#{attribute} ||== #{default_value}"
      end
    end
  end

  attr_with_default :emails => "[]", :employee_number => "EmployeeNumberGenerator.next"
end

After

class Person
  def self.attr_with_default(options)
    options.each_pair do |attribute, default_value|
      eval "define_method attribute do
            @#{attribute} ||== #{default_value}
            end"
    end
  end

  attr_with_default :emails => "[]", :employee_number => "EmployeeNumberGenerator.next"
end
Refactorings
Composing Methods

Extract Method • Inline Method • Inline Temp • Replace Temp with Query • Replace Temp with Chain • Introduce Explaining Variable • Split Temporary Variable • Remove Assignments to Parameters • Replace Method with Method Object • Substitute Algorithm • Replace Loop with Collection Closure Method • Extract Surrounding Method • Introduce Class Annotation • Introduce Named Parameter • Remove Named Parameter • Remove Unused Default Parameter • Dynamic Method Definition • Replace Dynamic Receptor with Dynamic Method Definition • Isolate Dynamic Receptor • Move Eval from Runtime to Parse Time

Moving Features Between Objects

Move Method • Move Field • Extract Class • Inline Class • Hide Delegate • Remove Middle Man

Organizing Data

Self Encapsulate Field • Replace Data Value with Object • Change Value to Reference • Change Reference to Value • Replace Array with Object • Replace Hash with Object • Change Unidirectional Association to Bidirectional • Change Bidirectional Association to Unidirectional • Replace Magic Number with Symbolic Content • Encapsulate Collection • Replace Record with Data Class • Replace Type Code with Polymorphism • Replace Type Code with Module Extension • Replace Type Code with State-Strategy • Replace Subclass with Fields • Lazily Initialized Atribute • Eagerly Initialized Attribute

Simplifying Conditional Expressions

Decompose Conditional • Recompose Conditional • Consolidate Conditional Expression • Consolidate Duplicate Conditional Fragments • Remove Control Flag • Replace Nested Conditional with Guard Clauses • Replace Conditional with Polymorphism • Introduce Null Object • Introduce Assertion

Making Method Calls Simpler

Rename Method • Add Parameter • Remove Parameter • Separate Query from Modifier • Parameterize Method • Replace Parameter with Explicit Methods • Preserve Whole Object • Replace Parameter with Method • Introduce Parameter Object • Remove Setting Method • Hide Method • Replace Constructor with Factory Method • Replace Error Code with Exception • Replace Exception with Test • Introduce Gateway • Introduce Expression Builder

Dealing with Generalization

Pull Up Method • Push Down Method • Extract Module • Inline Module • Extract Subclass • Introduce Inheritance • Collapse Hierarchy • Form Template Method • Replace Inheritance with Delegation • Replace Delegation with Hierarchy • Replace Abstract Superclass with Module

Big Refactorings

Tease Apart Inheritance • Convert Procedural Design to Objects • Separate Domain from Presentation • Extract Hierarchy