skip to content

In a reference-counted design, which edges of a catalogue should own: its entries, its selected-entry pointer, or its registered progress observers?

level: seniorimportance: must knowfreq 56%

answer

  1. label every arrow separately
  2. containment is the backbone
  3. views and registries observe
  4. owning edges must form a hierarchy
  5. over-owning shows up as retention

basics

~20 s

Only the containment edge. The catalogue owns its entries; the selected-entry pointer and the observer registrations must not, or removing an entry frees nothing and a finished observer is kept alive by the catalogue it registered with.

solid answer

~40 s

Choose one backbone of owning edges that mirrors containment, and make every other edge observe. Here the catalogue-to-entry edges are the backbone: an entry exists because the catalogue holds it. The selected-entry pointer is a *view* of that set, not a second owner — if it owns, removing the selected entry from the catalogue frees nothing, and a stale selection can still be read and rendered as current. The observer registrations run the other way: the catalogue holds them so it can notify, so if they own, an observer whose screen has closed is kept alive and still notified. The rule that generalises: an edge owns when the holder's correctness requires the target to exist for the holder's whole lifetime. Everything else is weak, or unchecked where the target provably outlives the holder.

go deeper

for a junior

Start from containment: the thing that holds a collection owns what is in it. A pointer that merely marks which one is selected, and a list of things to notify, are not owners.

for a middle

Explain each edge's verdict and the concrete bug behind it — an owning selection means removal frees nothing, an owning notification list means a closed screen's observer lives on.

for a senior

Demonstrate the diagnosis: a live set that climbs, removals that free nothing, and a snapshot showing forgotten objects each held by one edge that was never meant to own.

for a principal

Make the ownership map a reviewable artefact for the codebase — a drawing of the owning edges with a stated root — so a strength choice is a design decision rather than a per-site habit.

## Label the graph edge by edge Draw the catalogue, its entries, the selected-entry pointer and a progress observer, and treat each arrow as a separate decision. The verdicts are not symmetric, and the bug each wrong verdict produces is different. | edge | strength | what goes wrong if it owns | what goes wrong if it does not | |---|---|---|---| | catalogue → entry | owning | nothing; this is the backbone | entries are destroyed while the catalogue still lists them | | selection → entry | weak | a removed entry stays resident and still renders as current | nothing; the selection has to handle "the selected entry is gone" | | catalogue → registered observer | weak | an observer outlives the screen that made it and keeps being notified | nothing; notification skips the dead slots | | observer → catalogue | weak, or unchecked where the observer cannot outlive it | the catalogue and everything under it survive the closed screen | nothing; each callback re-checks | | entry → parent catalogue | unchecked, if entries cannot outlive the catalogue | the pair hold each other up and neither is ever released | nothing | ## The rule that generalises **An edge should own when the holder's correctness requires the target to exist for the holder's whole lifetime.** Read it in that direction, because the reverse — "it owns when the target might disappear" — is exactly backwards and is the single most common error in this design. The catalogue's correctness requires its entries: it is the thing that answers "what is in the catalogue". The selection's correctness does not require any particular entry to exist; "the entry you had selected has been removed" is a state the product must handle anyway, because another user can remove it. The catalogue's notification list does not require any observer to exist; "that observer has gone away" is the normal end of a screen's life. ## The owning edges must form a hierarchy A useful check that needs no runtime: **draw only the owning edges and look at the picture.** 1. Every object should be reachable from some root along owning edges — otherwise nothing keeps it alive and it dies while still referenced. 2. The owning picture should have no arrow leading back into something above it. A pair of objects that own each other keeps both counts above zero for ever, and the release you were counting on never runs. 3. Each object should have an obvious answer to "whose destruction ends this one?" If two different objects could claim it, one of them is holding the wrong strength. Back edges — child to parent, entry to catalogue, observer to subject — are the ones that break rule 2, and they are the ones that should observe rather than own. ## Weak or unchecked for the non-owning edges? Having decided an edge does not own, you still choose between the checked and the unchecked form: - **Selection → entry: weak.** The entry can vanish at any moment, from a removal the selection knows nothing about. This is the definition of a checked observation. - **Catalogue → observer: weak.** A screen closes on its own schedule; the catalogue cannot know when. - **Entry → catalogue: unchecked is defensible.** If entries are created by the catalogue, stored only inside it and destroyed when it is destroyed, the catalogue's lifetime encloses each entry's, and the invariant fits in one sentence at the declaration. If entries can be detached and handed out to live on their own, that sentence is false and the edge must be weak. ## The symptoms of getting it wrong An over-owning graph does not crash. It *retains*: the live set climbs across a working day, removals free nothing, and a heap snapshot shows objects the product has already forgotten, each held by one edge that was never meant to be an owner — a selection, a cache slot, a notification list. Under-owning is the opposite and much louder: a weak handle that reads absent while the product still expects the object, or an unchecked handle that reads storage already reused. The design exercise an interviewer is actually running here is whether you label edges by *obligation* rather than by convenience. Candidates who reason "I need to reach it from here, so I will hold it" produce a graph where everything owns everything, which is a counting scheme that never counts down.

  • The selection is weak; what must the code reading it now do that an owning selection would not?
    Promote it to a temporary owning handle before use and handle the absent case explicitly, because the entry can be removed between one read and the next. That means a product decision, not just a null check: clear the selection, fall back to the neighbouring entry, or show an "item removed" state. Making the edge weak forces that decision into the open.
  • Does a weak observer registry remove the need to unregister?
    No. It removes the retention — an observer whose screen has closed can now be destroyed — but the registry still accumulates dead slots that notification has to skip, so it is pruned on access or on a schedule. Unregistering is also the only way to stop notifications at a chosen moment rather than whenever the observer happens to be released.
  • How would you validate the ownership design before writing any of it?
    Draw only the owning edges. Check that every object is reachable from a root along them, that no arrow leads back into an ancestor, and that each object has exactly one answer to "whose destruction ends this one?". Anything failing those three is an edge holding the wrong strength, and the drawing takes minutes.

A shop's stock list owns the goods in the stockroom. The sign saying "today's featured item" does not — take that item out of stock and the sign should read as pointing at nothing, not quietly keep a crate alive in the corner.

saying these in an interview costs you the question

  • Decides strength by reachability: "I need it here, so I hold it"
  • Makes the current-selection pointer an owning handle
  • Lets the notification list own the observers it notifies
  • Thinks removing an entry from a container destroys it regardless of handles
  • Cannot say which object's destruction ends another's life
  • Uses an unchecked handle for an edge whose target may be removed independently