An interface introduced in 2022 for testing, which turned out to be the only reason a subsystem could be replaced in a fortnight.
interface PricingEngine
{
public function priceFor(Basket $basket, Customer $customer): PricedBasket;
}
// one method, one implementation for three years, and a
// second one written in 2025 that runs alongside it:
final class ComparingPricingEngine implements PricingEngine
{
public function priceFor(Basket $b, Customer $c): PricedBasket
{
$old = $this->legacy->priceFor($b, $c);
$new = $this->rewritten->priceFor($b, $c);
$this->recordDifference($old, $new);
return $old;
}
}
A comparing implementation running both and returning the old one is the safest possible rewrite, and it is only available if there is a single method to wrap. The seam was created for a reason that turned out to be secondary — the tests were fine either way — which is the usual story with the interfaces that matter.