Refactoring: Refactorings/Replace Data Value with Object

From Notes
Jump to navigation Jump to search

Simple data items like strings can become complex to the point where they need behaviors. For example. A telephone field might start out as a simple string, but then needs special formatting behaviors, area code extraction, etc. The best way to fix this is to create an object.

Mechanics

  1. Create the class for the value. Give it an equivalent to the field in the source class. Add an attribute reader and a constructor that takes the field as an argument.
  2. Change the attribute reader in the source class to call the reader in the new class.
  3. If the field is mentioned in the source class constructor, assign the field using the constructor of the new class.
  4. Change the attribute reader to create a new instance of the new class.
  5. Test
  6. You may now need to Change Value to Reference on the new object.

Example

Before

class Order
  attr_accessor :customer

  def initialize(customer)
    @customer = customer
  end
end


# Usage

def self.number_of_orders_for(orders, customer)
  orders.select{ |order| order.customer == customer}.size
end

After

class Customer
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

class Order
  def initialize(customer)
    @customer = Customer.new(customer)
  end

  def customer
    @customer.name
  end

  def customer=(value)
    @customer = Customer.new(value)
  end
end
Refactorings
Composing Methods

Extract MethodInline MethodInline TempReplace Temp with QueryReplace Temp with ChainIntroduce Explaining VariableSplit Temporary VariableRemove Assignments to ParametersReplace Method with Method ObjectSubstitute AlgorithmReplace Loop with Collection Closure MethodExtract Surrounding MethodIntroduce Class AnnotationIntroduce Named ParameterRemove Named ParameterRemove Unused Default ParameterDynamic Method DefinitionReplace Dynamic Receptor with Dynamic Method DefinitionIsolate Dynamic ReceptorMove Eval from Runtime to Parse Time

Moving Features Between Objects

Move MethodMove FieldExtract ClassInline ClassHide DelegateRemove Middle Man

Organizing Data

Self Encapsulate FieldReplace Data Value with ObjectChange Value to ReferenceChange Reference to ValueReplace Array with ObjectReplace Hash with ObjectChange Unidirectional Association to BidirectionalChange Bidirectional Association to UnidirectionalReplace Magic Number with Symbolic ContentEncapsulate CollectionReplace Record with Data ClassReplace Type Code with PolymorphismReplace Type Code with Module ExtensionReplace Type Code with State-StrategyReplace Subclass with FieldsLazily Initialized AtributeEagerly Initialized Attribute

Simplifying Conditional Expressions

Decompose ConditionalRecompose ConditionalConsolidate Conditional ExpressionConsolidate Duplicate Conditional FragmentsRemove Control FlagReplace Nested Conditional with Guard ClausesReplace Conditional with PolymorphismIntroduce Null ObjectIntroduce Assertion

Making Method Calls Simpler

Rename MethodAdd ParameterRemove ParameterSeparate Query from ModifierParameterize MethodReplace Parameter with Explicit MethodsPreserve Whole ObjectReplace Parameter with MethodIntroduce Parameter ObjectRemove Setting MethodHide MethodReplace Constructor with Factory MethodReplace Error Code with ExceptionReplace Exception with TestIntroduce GatewayIntroduce Expression Builder

Dealing with Generalization

Pull Up MethodPush Down MethodExtract ModuleInline ModuleExtract SubclassIntroduce InheritanceCollapse HierarchyForm Template MethodReplace Inheritance with DelegationReplace Delegation with HierarchyReplace Abstract Superclass with Module

Big Refactorings

Tease Apart InheritanceConvert Procedural Design to ObjectsSeparate Domain from PresentationExtract Hierarchy