Agent Wranglers

TKO-14Recommended

Rewrite behind the old interface

When you rewrite a part, put the old and the new code behind one interface and choose between them with a flag. Callers never change.

How to do it

This is called branch by abstraction. First extract an interface that the old code already fits. Then build the new code against it and run both under the same characterization tests. Turn the flag on for a small share first, as Separate deploying from releasing says. When the new code has run for everyone, delete the old code and the flag.

Examples

TypeScript example

interface TaxCalculator { vatFor(order: Order): Money }

class LegacyTax implements TaxCalculator { vatFor(order: Order) { return legacyVat(order); } }
class RulesTax implements TaxCalculator { vatFor(order: Order) { return vatRules.apply(order); } }

export const taxCalculator = (flags: Flags): TaxCalculator =>
  flags.isEnabled('rules-tax', { defaultValue: false }) ? new RulesTax() : new LegacyTax();

Python example

class TaxCalculator(Protocol):
    def vat_for(self, order: Order) -> Money: ...

class LegacyTax:
    def vat_for(self, order: Order) -> Money: return legacy_vat(order)

class RulesTax:
    def vat_for(self, order: Order) -> Money: return vat_rules.apply(order)

def tax_calculator(flags: Flags) -> TaxCalculator:
    return RulesTax() if flags.is_enabled("rules-tax", default=False) else LegacyTax()

How to check

The same test suite runs against both implementations and passes. Switching the flag back to the old code needs no deploy.

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor/rewrite-behind-interface">Agent Wranglers codebase takeover playbook</a>. In code you write, add a comment next to it with the same link.