Skip to content

🧙‍♀️ Example code for session 2 of weekly refactoring mentoring sessions in TypeScript.

Notifications You must be signed in to change notification settings

Squaretechre/refactoring-2

Repository files navigation

Refactoring 2

Example code for weekly refactoring sessions.

Slides: https://bit.ly/39xupAQ

Notes

  • Before doing the refactorings try to clear the decks and see how much you can improve the code only by renaming things.
  • In the Introduce Parameter Object example, doesNotContain is a stylistic choice, feel free to extract contains as per the book.
    • Pick one style and stick with it, either verbose names or using !contains, remember when in rome.

Introduce Parameter Object

  1. Create NumberRange class, move to number-range.ts:
  class NumberRange {
    constructor(
      readonly min: number,
      readonly max: number,
    ){}
  } 
  1. Introduce range alongside existing parameters for readingsOutsideRange:
    const range = new NumberRange(operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling)

    const alerts = readingsOutsideRange(station, operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling, range)
  1. Redirect usages of min and max to range.min and range.max in readingsOutsideRange:
    // from
    function readingsOutsideRange(station: Station, min: number, max: number, range: NumberRange): Reading[] {
        return station.readings.filter((r) => r.temp < min || r.temp > max)
    }
    
    // to
    function readingsOutsideRange(station: Station, min: number, max: number, range: NumberRange): Reading[] {
        return station.readings.filter((r) => r.temp < range.min || r.temp > range.max)
    }
  1. Safe delete the unused min and max parameters:
    const alerts = readingsOutsideRange(station, range)

    function readingsOutsideRange(station: Station, range: NumberRange): Reading[] {
        return station.readings.filter((r) => r.temp < range.min || r.temp > range.max)
    }
  1. Extract method doesNotContain on r.temp < range.min || r.temp > range.max in readingsOutsideRange:
    function doesNotContain(r: Reading, range: NumberRange): boolean {
      return r.temp < range.min || r.temp > range.max
    }

    export function readingsOutsideRange(station: Station, range: NumberRange): Reading[] {
      return station.readings.filter((r) => doesNotContain(r, range))
    }
  1. Extract parameter on both occurrences of r.temp in doesNotContain:
    function doesNotContain(r: Reading, range: NumberRange, number: number): boolean {
      return number < range.min || number > range.max
    }

    export function readingsOutsideRange(station: Station, range: NumberRange): Reading[] {
      return station.readings.filter((r) => doesNotContain(r, range, r.temp))
    }
  1. Safe delete the unused r parameter:
    function doesNotContain(range: NumberRange, number: number): boolean {
      return number < range.min || number > range.max
    }

    export function readingsOutsideRange(station: Station, range: NumberRange): Reading[] {
      return station.readings.filter((r) => doesNotContain(range, r.temp))
    }
  1. Move doesNotContain to number-range.ts:
    export class NumberRange {
      constructor(readonly min, readonly max) {}
    }

    export function doesNotContain(range: NumberRange, number: number): boolean {
      return number < range.min || number > range.max
    }
    
    // In introduce-parameter-object.ts
    // import { doesNotContain } from './number-range'
  1. Manually create method doesNotContain(number: number): boolean on NumberRange and delegate to doesNotContain:
    export class NumberRange {
      constructor(readonly min, readonly max) {}
      
      doesNotContain(number: number): boolean {
        return doesNotContain(this, number)
      }
    }

    export function doesNotContain(range: NumberRange, number: number) {
      return number < range.min || number > range.max
    }
  1. Redirect call to doesNotContain in readingsOutsideRange to range.doesNotContain:
    function readingsOutsideRange(station: Station, range: NumberRange): Reading[] {
      return station.readings.filter((r) => range.doesNotContain(r.temp))
    }
  1. Inline doesNotContain inside of number-range.ts:
    export class NumberRange {
      constructor(readonly min, readonly max) {}

      doesNotContain(number: number): boolean {
        return number < this.min || number > this.max
      }
    }
  1. Remove unused import of doesNotContain in introduce-parameter-object.ts:
    import { NumberRange } from './number-range'

About

🧙‍♀️ Example code for session 2 of weekly refactoring mentoring sessions in TypeScript.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published