Refactoring: Refactorings/Extract Class

From Notes
Jump to navigation Jump to search

Classes should have crisp abstraction and a few clear responsibilities. When the classes get too big and complicated, you should create a new class to handle the extra responsibilities.

Mechanics

  1. Decide how to split the responsibilities of the class
  2. Create a new class to express the split-off responsibilities. Rename the old class to better describe if necessary
  3. Make a link from the old to the new class (might need a back link, but not unless absolutely necessary)
  4. Use Move Field on each field you want to move
  5. Test after each move
  6. Use Move Method to move methods from old to new class. Start with low-level methods (called rather than calling) and build to higher level.
  7. Test after each move
  8. Review and reduce interfaces of each class (try to remove back link if possible)

Example

Before

class Person
  attr_reader :name
  attr_accessor :office_area_code, :office_number
  def telephone_number
    '(' + @office_area_code + ') ' + @office_number
  end
  # ...
end

After

class Person
  attr_reader :name
  def initialize
    @office_telephone = TelephoneNumber.new
  end

  def telephone_number
    @office_telephone.telephone_number
  end

  def office_telephone
    @office_telephone
  end
end

class TelephoneNumber
  attr_accessor :area_code, :number
  def telephone_number
    '(' + area_code + ') ' + number
  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