andrew@theinternet

Software Dev Process Lecture Notes - Part 4 Lesson 5 - Software Refactoring


Refactoring

  • Process of applying transformations to a program so as to obtain a refactored program.
    • Improved design but with same functionality as the original program
    • Semantics preserving
    • Goal: keep program readable, understandable, and maintainable
    • Key feature: behavior preserving
      • How can we guarantee that?
      • No guarantees, but you can test it!
      • If you have a good test suite, that helps a lot.
      • Remember, there are no guarantees from testing alone.

Why Refactor?

  • Requirements change
    • often need to change design to acommodate
  • Design needs to be improved
    • new feature, more maintainable, etc
  • Sloppiness / laziness of developers
    • copy/paste programming abstracted into classes or libraries

History of Refactoring

  • Refactoring is something that programmers have always done
  • Especially important for object-oriented languages
    • but useful for all languages
  • Opdyke’s PhD Thesis (1990) discusses refacotring for SMALLTALK
  • Increasingly popular recently due to agile development adoption
  • Fowler’s Book - Improving the Design of Existing Code
    • Catalog of refactorings
    • List of bad smells
    • Guidelines on when to apply refactoring
    • Examples of code before and after

Types of Refacotring

  • Massive list, we will only cover a few
  • Collapse Hierarchy
  • A superclass and subclass are tgoo similar
    • Merge them
  • Consolidate Conditional Expression
    • Set of conditionals with the same result
    • each check is different but the result is the same
    • Combine and extract checks
  • Decompose Conditionals
    • A conditional statement is particularly complex
    • Might be too hard to parse why something does or doesn’t happen
    • Extract condition to method call, leverage method name to explain what you’re trying to test for
  • Extract Class
    • a class may wind up doing the work of two or more, due to code evolution
    • creat a new class and move there the relevant fields/methods
  • Inline Class
    • inverse of extracting a class
    • A class may wind up not doing much
      • move its features into another class and delete this one
  • Extract Method
    • most common of the ones we’ve covered
    • cohesive code fragment in a large method
    • create a method using that fragment, and call that method where needed

How to Refactor

  • Full length demo shown here. View video itself for refesher
  • Uses demo of Eclipse. Ugh.

Refactoring Risks

  • Powerful too, but…
  • May introduce subtle faults
    • aka regression errors
  • Should not be abused
    • performed only when needed
  • should be used very carefully on systems in production

Cost of Refactoring

  • May be free with good tooling
  • But often requires manual work, which costs
  • Test development and maintenance, especially those built or added to specifically for a refactoring effort
  • Documentation maintenance - changes to names or interfaces must be updated in docs, and that takes effort too

When Not to Refactor

  • When code is broken
    • Refactoring is not about fixing broken code, it’s about design of code
    • Refactoring should never change code behavior, so can’t fix broken code
  • When a deadline is close
    • time spent on refactoring doesn’t advance features
    • risk of regression errors increases risk of missing a deadline
  • When there is no reason to!

Bad Smells

  • What are bad smells?
    • Symptoms in code that may indicate deeper problems
    • Usually not bugs, don’t impair function
    • But indicate weaknesses in design
  • Duplicated Code
    • Same piece of code replicated in multiple places
      • common from copy/paste programming
    • fixed by extract method refactoring
  • Long method
    • extract method
    • decompose conditional
    • shorten and break down method to make it more cohesive
  • Large class
    • extract class or subclass
    • break down class to multiple, each with more cohesive functionality
  • Shotgun surgery
    • every time a change is made, have to go to many classes
    • functionality is spread among classes, too much coupling and too little cohesion
    • move method/field, inline class
    • bring related functionality together, remove dependencies between classes
  • Feature envy
    • refers to a method that seems more interested in a class other than the one it belongs to
    • extract method, move method to class it is referencing
      • decreases coupling between classes