The Zen of Refactoring

buddha

Refactoring is the process of restructuring existing computer code -- changing its factors -- without changing its behavior. You probably knew that. But did you know it’s also a meditation technique? Come improve your practice of mindful coding.

After these slides, we’ll start with some actual production code, make sure its unit tests work ok, then collaboratively, consciously contemplate the many forking paths that twine and wind through the Garden of Abstract Delights.

What is refactoring?

refactoring (verb): to restructure software by applying a series of refactorings without changing its observable behavior

refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior

(definitions by Martin Fowler)

What is Zen?

mostly an excuse for pretty pictures and hippie jokes

zen

disclaimer: This presentation uses some spiritual imagery but is not intended to parody any religion or culture (except American New Age Hippies)

What is Refactoring?

Refactoring is changing code without changing its behavior.

What is Refactoring?

Refactoring is changing code without changing its behavior.

Refactoring is change without change.

What is Refactoring?

Refactoring is changing code without changing its behavior.

Refactoring is change without change.

Refactoring is Zen.

refactoring is NOT

rewriting

rebuilding

porting

upgradging

debugging

Why refactor?

yoda

(Yoda ≈ Buddha)

Refactor to understand

clarity calm insight knowledge understanding

pool

See the code for what it is, not what you think it is, or what you want it to be

Refactor to remove duplication

DRY

sand

Refactor to increase code clarity

sometimes clarity requires more duplication

What is code clarity?

Clear code is:

rereading and rewriting

“Curiously enough, one cannot read a book; one can only reread it. A good reader, a major reader, an active and creative reader is a rereader.” - Nabokov

https://www.goodreads.com/quotes/34497-curiously-enough-one-cannot-read-a-book-one-can-only

"Zen Refactoring"

Let your eyes blur and scroll through the code

See what pops out

How?

  1. Write some tests
  2. Change the code
  3. Run the tests
  4. Move ahead, or move back (revert)

Tests Are Essential

run them before

change them during

tests are an extension of code

What are the qualities of a refactoring?

Reversible

reversible

Mechanical

grievous.gif

Brief

or at least made of many short, reversible steps

Automated

I choose my text editor based on how well it refactors my code

(Other programmers may have different criteria.)

real programmers use https://xkcd.com/378/

Refactoring: Rename

The simplest and most powerful

Refactoring: Extract

Extract Variable, Extract Function, Extract Method

Example: Extract Function

console.log('' + new Date() + ' - error: too many notes') 
console.log('' + new Date() + ' - error: not enough cowbell')

=>

function logError(message) {
    console.log('' + new Date() + ' - error: ' + message)
}
logError('too many notes')
logError('not enough cowbell')

Refactoring: Inline

"Inline" is the reverse of "Extract"

Introduces duplication to increase clarity

Refactoring: Replace Comment With Name

A medium-length comment can often be replaced with a variable / function / method / class whose name is the comment

"A comment is a lie waiting to happen." - Alex

Example: Replace Comment With Name

// 11 days at 24 hours per day times 60 minutes per hour
let duration = 11 * 24 * 60 

=>

let hoursPerDay = 24
let minutesPerHour = 60
let durationInMinutes = 11 * hoursPerDay * minutesPerHour

Refactoring: Introduce Parameter

function logError(message, severity = 'error') {
    console.log('' + new Date() + ' - ' + severity + ': ' + message)
}
logError('too many notes')
logError('volume too low', 'warning')

Refactoring: Extract Object (Struct)

Example: Extract Object (Struct)

function distanceBetween(x1, y1, x2, y2) {
    let deltaX = x2 - x1;
    let deltaY = y2 - y1;
    return Math.sqrt(deltaX * deltaX + deltaY * deltaY)
}
let distance = distanceBetween(41.12, -72.22, 42.18, -72.34)

=>

function distanceBetween(point1, point2) {
    let deltaX = point2.x - point1.x;
    let deltaY = point2.y - point1.y;
    return Math.sqrt(deltaX * deltaX + deltaY * deltaY)
}

let distance = distanceBetween( { x: 41.12, y: -72.22 },
                                { x: 42.18, y: -72.34 })

This type of object -- with fields but no methods -- is sometimes called a struct.

Refactoring: Extract Class

class Point {
    distanceFrom(otherPoint) {
        let deltaLat = otherPoint.x - this.x;
        let deltaLon = otherPoint.y - this.y;
        return Math.sqrt(deltaLat * deltaLat + deltaLon * deltaLon)
    }
}

let point1 = new Point();
point1.x = 41.12
point1.y = -72.22
let point2 = new Point();
point2.x = 42.18
point2.y = -72.34

let distance = point1.distanceFrom(point2)

Refactoring: Introduce Constructor

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    //... 
}
let point1 = new Point(41.12, -72.22)
let point2 = new Point(42.18, -72.34)
let distance = point1.distanceFrom(point2)

Code Smells

a "code smell" means "something might be wrong here"

more at Code Smells

Some Guidelines

Dots In A Row

don't confuse method chaining (often good) with feature envy (usually bad))

Method Chaining

string.split(' ').map((s)=>s.toUpperCase()).join(' ')

Feature Envy

course.students[0].phone.sendText('hi')
style dots collaborators
method chaining 4 2 (String, Array)
feature envy 3 5 (Course, Array, Student, Phone, String)

The Book

refactoring-fowler

https://martinfowler.com/books/refactoring.html

...coming soon in JavaScript!

References

 Previous Lesson Next Lesson 

Outline

[menu]

/