← Template method lesson
Lab

Template method

Sign in to run your code

Read the brief and the starter here. With a free account you can edit it, run the sample, step through it and check your work, and your progress is kept.

type Route = { name: string; problems: string[] };

// The gym's two reset routines, written a year apart.
function resetRope(route: Route): string {
  const done = `${route.name}: close > strip holds, draws > set holds, draws`;
  if (route.problems.includes('bolts')) {
    return `${done} > inspect: loose bolts > stays closed`;
  }
  if (route.problems.includes('anchors')) {
    return `${done} > inspect: worn anchors > stays closed`;
  }
  return `${done} > inspect > reopen`;
}

// Written later, for the bouldering wall.
function resetBoulder(route: Route): string {
  const done = `${route.name}: close > strip holds > set holds, place pads`;
  let inspected = 'inspect';
  if (route.problems.includes('bolts')) inspected = 'inspect: loose bolts';
  else if (route.problems.includes('pads')) inspected = 'inspect: missing pads';
  return `${done} > ${inspected} > reopen`;
}

// The shared reset, started in a refactor and not finished.
abstract class RouteReset {
  protected abstract strip(route: Route): string;
  protected abstract set(route: Route): string;
  // The problem the inspection found, or null when the route is safe.
  protected abstract inspect(route: Route): string | null;

  // Not written yet: each kind of route still overrides it with its old routine.
  reset(route: Route): string {
    return `${route.name}: not written yet`;
  }
}

class RopeReset extends RouteReset {
  // The steps are not moved here yet.
  protected strip(route: Route): string {
    return '';
  }

  protected set(route: Route): string {
    return '';
  }

  protected inspect(route: Route): string | null {
    return null;
  }

  // Until the refactor is done: the old routine.
  override reset(route: Route): string {
    return resetRope(route);
  }
}

class BoulderReset extends RouteReset {
  // The steps are not moved here yet.
  protected strip(route: Route): string {
    return '';
  }

  protected set(route: Route): string {
    return '';
  }

  protected inspect(route: Route): string | null {
    return null;
  }

  // Until the refactor is done: the old routine.
  override reset(route: Route): string {
    return resetBoulder(route);
  }
}