Template Method Pattern
debt(d7/e5/b5/t3)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints note automated=no, and while phpstan is listed as a tool, it cannot reliably detect misapplication of the Template Method pattern (e.g. making steps public, having too many abstract steps, or missing documentation). These issues surface only during code review when a reviewer notices the structural problem — duplicated algorithm skeletons or incorrectly scoped methods.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes defining an abstract base class with abstract steps, but common mistakes such as too many abstract steps, wrong visibility, or choosing Template Method over Strategy each require revisiting the class hierarchy across multiple concrete subclasses. This is more than a one-line swap but typically contained within one component or feature area.
Closest to 'persistent productivity tax' (b5). Template Method is inheritance-based and applies broadly across web, cli, and queue-worker contexts. Every subclass author must read and understand the base class to know the call order and what to override, imposing an ongoing comprehension burden. It doesn't define the whole system's shape, but any algorithm governed by this pattern imposes a persistent structural constraint on all subclass authors.
Closest to 'minor surprise (one edge case)' (t3). The misconception field clarifies the main trap — developers assume deep hierarchies are needed, when only one level is required. The common mistakes (public steps, too many abstract steps, missing documentation) are well-known OOP gotchas rather than catastrophic wrong-guesses. A competent OOP developer will broadly understand the pattern but may misjudge scope or visibility on first use.
Also Known As
TL;DR
Explanation
The Template Method pattern places an algorithm's invariant steps in a base class method, while hook or abstract methods allow subclasses to provide varying implementations of specific steps. For example, a ReportGenerator base class defines generate() which calls fetchData(), formatRows(), and renderHeader() in sequence — subclasses override only the steps that differ. This enforces the algorithm's structure while permitting extension at defined points. In PHP it naturally uses abstract classes. Prefer Strategy over Template Method when the varying behaviour should be composable or swappable at runtime.
Common Misconception
Why It Matters
Common Mistakes
- Making template steps public — they should be protected so only the template method calls them.
- Too many abstract steps — if every step is abstract, the base class provides no structure.
- Not documenting the template method — subclass authors must read the base class to understand the call order.
- Using Template Method when Strategy would allow runtime behaviour switching without subclassing.
Code Examples
// Duplicated algorithm skeleton in two classes:
class CsvExporter {
public function export(): void { $this->open(); $this->writeHeader(); $this->writeRows(); $this->close(); }
}
class XmlExporter {
public function export(): void { $this->open(); $this->writeHeader(); $this->writeRows(); $this->close(); }
}
// The sequence is identical — extract to a template method in base class
abstract class DataImporter {
// Template method — defines the algorithm skeleton
final public function import(string $source): int {
$raw = $this->read($source); // step 1 — abstract
$rows = $this->parse($raw); // step 2 — abstract
$valid = $this->validate($rows); // step 3 — hook with default
return $this->save($valid); // step 4 — abstract
}
abstract protected function read(string $source): string;
abstract protected function parse(string $raw): array;
abstract protected function save(array $rows): int;
protected function validate(array $rows): array {
return $rows; // default: no-op; subclasses can override
}
}
class CsvImporter extends DataImporter { ... }
class JsonImporter extends DataImporter { ... }