skip to content

On one bounded code request, how do you constrain which names the generated code may call?

level: middleimportance: should knowfreq 48%

answer

  1. the answer picks tools as well as solutions
  2. both names resolve to nothing
  3. one has an off-ramp, one does not
  4. close the list, do not just open it

basics

~20 s

Pin the surface: list the names the code may call with their shapes, close the list against anything new, and ask it to say so rather than substitute when something is missing. Pinning narrows the answer; it does not enforce it.

solid answer

~50 s

An unpinned request hands over the choice of tools along with the solution, and for anything touching dates or decimal amounts what gets chosen is often a well-known third-party helper. That fails to resolve, exactly as an invented name does — but the two failures end differently. An invented helper has no off-ramp, so you go back to the request. A real, popular library has an obvious one: add the dependency, one line, done in a reflex — and a dependency decision has been taken without anyone noticing they took one. So I pin the surface: the names it may use and the shape of each, a stated closure against anything outside that list, and an instruction to **say so and stop** rather than substitute. The list is an instruction, not a fence, so I still read what the result calls.

go deeper

for a junior

Recall the two clauses doing most of the work: list the names the code may call, and say plainly that it may not add anything outside that list.

for a middle

Explain why a real library you do not depend on is the worse outcome. Both it and an invented name fail to resolve; only one offers a one-line fix that hides a dependency decision.

for a senior

Show judgement about the gap case: an answer reporting that the pinned surface is insufficient has handed you a real decision, and taking it deliberately is why you asked for it.

for a principal

Own the standing question of who may add a dependency and how that decision surfaces. A request convention that closes the surface by default keeps the choice with people instead of leaking it into diffs.

## The request that does not pin a surface is choosing tools too Ask for a function to parse a fixed-width statement line and the answer has to call *something*: to slice the columns, to read the date field, to turn the amount digits into a number. Where the request is silent about what may be called, the answer picks what is most common for the job — for plain slicing usually whatever is built in, but for anything around dates or decimal amounts quite possibly a widely used third-party helper, because that is what most code does. **You asked for a solution and you also got a decision about your dependency list**, taken by something that has no way of knowing what your project depends on, in a request that never mentioned dependencies. ## Why the real library is the worse outcome, and it is not about loudness It is tempting to say the invented name fails loudly and the real one slips through quietly. That is wrong, and it is worth being precise about why. **Both fail to resolve** — an invented helper and a library your project does not depend on are equally absent, and each fails wherever names get resolved: ahead of running where that is checked, at first execution otherwise. The difference is what a developer does next. | What the answer called | What you see | What you do next | What it costs | |---|---|---|---| | A helper that exists nowhere | Unresolved name | Go back to the request, or write it | A turn | | A real library you do not depend on | Unresolved name, with an obvious fix | **Add the dependency** — one line, reflexively | A dependency nobody decided on | | A name you do have, used on a wrong assumption | Nothing; it resolves and runs | Read it, or find out later | Detection, which is a different subject | **The middle row is the whole point.** The invented name has no off-ramp, so it sends you back to the request where the problem actually is. The real library offers an off-ramp so cheap that taking it feels like fixing a build error rather than like accepting a new dependency — its licence, its maintenance, its supply-chain surface, its upgrade path. The decision was real; it just never presented itself as one. ## What pinning the surface means in practice 1. **List the names the code may call, with their shapes.** Not "use our helpers" — the actual declarations: the date helper written for this format, the record type, the way the importer reports a bad line. A name without its shape gets called with invented arguments. 2. **Close the list.** State the negative explicitly: nothing outside this list, and no new dependency. An open list is read as a set of suggestions sitting alongside everything else that exists; the sentence that closes it is the clause doing the work, and it is the one most often left out. 3. **Ask for a statement instead of a substitute.** *If the list does not contain what you need, say so and stop.* This converts a silent choice into a question you can answer — and sometimes the honest answer is that you do want the dependency, which is a fine outcome when it is chosen deliberately. 4. **Pin the version line where the surface has more than one shape.** A name that has meant different things across major lines is only pinned once you say which line you are on. ## Pinning is a preference, not a fence Nothing in a request is enforced. A pinned list makes the intended surface the most available thing to reach for and makes a departure from it visible; it does not make departure impossible, and an answer is likeliest to reach past the list exactly where the listed surface does not really cover the job. Treat it as **narrowing the space, not closing it.** The practical consequence is that the pin does not replace the check — it makes the check cheap: - With a closed list, reading the result for what it calls is short and mechanical, because you have something definite to compare against. With nothing pinned, the same pass means reconstructing from memory what the project already has, which is the reconstruction that tends not to happen. - A departure from the list is **information about the request**: either the list was missing something the job needed, or the job is bigger than the request said it was. - **Check arguments against the real declaration**, not against how the generated code uses them. A pinned name called with a plausible but wrong argument order is residue the pin does not catch. - **Watch the dependency file as part of the diff.** That is where the effect of pinning, or of not pinning, actually shows up. ## Answering this in an interview Resist the easy version. Saying "an invented name fails loudly and a real one slips through" sounds right and is not: both fail to resolve. The distinction that survives scrutiny is **the fix each failure invites** — one sends you back to the request, the other offers a one-line off-ramp that quietly settles a dependency question. Then give the three clauses: the list with shapes, the closure, and say-so-and-stop. Finish with the limit — a pinned list is an instruction, so you still read what the result calls.

  • Why does the closing negative matter more than the list itself?
    A list on its own reads as a set of suggestions sitting alongside everything else that exists. The sentence saying nothing outside this list turns it into a constraint, and it is what stops a well-known library arriving beside the names you actually named.
  • What do you do when the answer reports that the pinned surface does not cover the job?
    Treat it as the useful outcome it is. Either the list was incomplete, in which case you extend it, or the job genuinely needs something new — and that is a dependency decision taken deliberately, by you, rather than discovered later in a diff.
  • Does pinning reduce the need to review what the generated code calls?
    It changes the review rather than removing it. With a closed list you check a short, comparable thing — does it call anything else, and are the arguments shaped right — instead of reconstructing from memory what the project already has.

saying these in an interview costs you the question

  • A pinned list is enforced, so the result cannot depart from it
  • An invented name fails loudly; a real library slips through quietly
  • Saying 'use our existing helpers' is enough to pin them
  • Naming a helper without its shape is enough to pin it
  • Pinning only matters in projects with unusual in-house helpers