Agent Wranglers

SOLID and DRY Required

Keep the contract in every subtype

A subtype must work everywhere its parent type works. It may not demand more, promise less or throw "not supported".

How to do it

Before you extend a class, list what callers rely on. If the subtype cannot keep all of it, use a separate type or a smaller interface instead. Never override a method only to throw.

Example

// Bad: callers of Storage break on the read-only subtype
class ReadOnlyStorage extends Storage {
  save(): void { throw new Error('not supported'); }
}

// Good: separate the roles, so nothing has to refuse
interface Reader { load(key: string): string; }
interface Writer { save(key: string, value: string): void; }
# Good in Python: two small protocols, so nothing has to refuse
class Reader(Protocol):
    def load(self, key: str) -> str: ...

class Writer(Protocol):
    def save(self, key: str, value: str) -> None: ...

How to check

Run the parent type's tests against every subtype. A grep for NotImplemented or "not supported" in overriding methods fails the build.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers architecture playbook: https://agentwranglers.se/playbook/architecture/solid-and-dry/liskov-substitution.