Part 4 · 1 chapters · ~8 min
OOP Honestly
Objects as encapsulated state with behaviour, classes and prototypes, polymorphism via interfaces, inheritance and the fragile base class problem, composition and delegation, small consumer-defined interfaces (Go), dependency injection without frameworks, SOLID in brief, design patterns that survive (strategy, adapter, decorator), and Alan Kay's messaging view.
5
Interfaces and composition
code
// Go: a small interface defined where it is used; any type with Send satisfies it implicitly
type Rail interface { Send(ctx context.Context, t Transfer) (Ref, error) }
type PayoutService struct { rail Rail; ledger Ledger } // composition: collaborators are fields
func NewPayoutService(r Rail, l Ledger) *PayoutService { return &PayoutService{r, l} } // DI without a framework
// TypeScript: decorator pattern by composition, adding retries to any Rail
class RetryingRail implements Rail {
constructor(private inner: Rail, private attempts = 3) {}
async send(t: Transfer) { for (let i = 1; ; i++) { try { return await this.inner.send(t); } catch (e) { if (i >= this.attempts || !isRetryable(e)) throw e; await sleep(2 ** i * 100); } } }
}
const rail = new RetryingRail(new LoggingRail(new PaystackRail(cfg)));
// JavaScript classes are syntax over prototypes
Object.getPrototypeOf(new RetryingRail(x)) === RetryingRail.prototype // trueAlan Kay, who coined "object-oriented", said the big idea was messaging between independent objects, not classes and inheritance. That view lives on more in Erlang and Elixir processes (next part) than in Java class trees.
OBJECT-ORIENTED PROGRAMMING, HONESTLY
what to keep, what to avoid
swipe the figure sideways, or tap expand for full screen
1/4
encapsulation
The valuable part of OOP: an object guards its own rules (Account.hold checks the balance), so no caller can break them (DDD aggregates, Backend Architecture P3).
objects guard invariantsthe core value