What Are You Delegating?

Every abstraction is a trade: it removes work by making decisions for you. Those decisions are still being made — just not by you, and not visibly. For each abstraction: what it genuinely handles, what remains yours, and the escape hatch.

What are you delegating to a library function?
DSA
You write
1items.sort((a, b) => a.score - b.score)
2const seen = new Set(ids)
The abstraction handles
  • A correct, tested, adaptive algorithm chosen for the general case
  • Memory layout, cache behaviour, the small-input special cases
  • Stability guarantees (if documented) and edge cases (empty, one element, NaN)
  • Decades of bug fixes
Still your responsibility
  • ComplexityO(n log n) is the general bound; whether your case is general is your call
  • The escape hatch the library cannot see — small-integer keys sort in linear time; top-K needs a heap, not a sort
  • The comparator — an inconsistent comparator produces silently wrong order
  • Where it runs — a sort inside a loop is the most common accidental quadratic
  • The data structure underneath — a Set is a hash table; its guarantees and its pathologies are the hash table's
Know your escape hatch

When: The general algorithm is measurably the bottleneck, and your input has structure the library cannot assume.

Drop to: The specific algorithm — counting sort, a heap, a bloom filter, a trie — chosen from the constraints.

This is what the DSA domain is for: not to rewrite the standard library, but to recognise the day its assumptions do not hold.

Go deeper on this one: