What do you attach to a one-function code request so the result fits your codebase?
answer
- the failure is fit, not correctness
- some choices were already made for you
- invented shapes carry invented conventions
- the tell is writing a wrapper
basics
~20 sAttach what the codebase has already fixed and the answer should not re-choose: the signature the caller expects, the record type it must return, the helper that already exists. Otherwise you get a correct function that needs an adapter.
solid answer
~50 sThe failure I am designing against is not a wrong answer — it is a right one that does not compose. Asked for a function that turns a fixed-width statement line into a record, with nothing attached, it will invent a plausible signature, a plausible record shape and its own date handling, and all three will be defensible without being the ones my codebase already uses. So I attach the parts the codebase has already decided: the **signature the caller expects**, the **record type it has to return**, and the **helper that already exists** for the piece it would otherwise rewrite. The test I apply is not "is this relevant" but "is this already fixed, so choosing it again is not the answer's job". The tell that I under-supplied is a result I have to wrap before I can use it.
code
pseudocode · 26 lines// WHAT CAME BACK from "parse a fixed-width statement line into a record",
// with nothing attached. Correct in isolation.
function parseStatementLine(line):
return {
date: parseDate(slice(line, 0, 8)), // its own date handling
description: trim(slice(line, 8, 40)),
amount: toDecimal(slice(line, 40, 52)) // its own amount convention
} // and no field for column 52 at all
// WHAT THE IMPORTER ALREADY HAS - none of this was the answer's to choose
type StatementEntry(postedOn, description, amountMinor, direction)
function ingest(entry: StatementEntry) // the call site, already written
function parseStatementDate(field) // already reads this format's dates
// THE MISMATCH IS NOT A NAMING DIFFERENCE
// amountMinor holds whole minor units: "000000123456" is 1234.56
// toDecimal on the same field yields 123456 - the same digits, a different meaning
// direction is a separate field; this format never puts a sign on the number
// WHAT FITS - same parsing, nothing invented
function parseStatementLine(line) -> StatementEntry:
return StatementEntry(
postedOn: parseStatementDate(slice(line, 0, 8)),
description: trim(slice(line, 8, 40)),
amountMinor: toWholeNumber(slice(line, 40, 52)),
direction: directionFrom(slice(line, 52, 53)))go deeper
The thing to recall is that a result can be entirely correct and still not usable. Hand over the signature it must match and the type it must return, and you remove most of that.
Explain what an invented return shape decides on your behalf — field names carry units and sign conventions — and why that kind of mismatch survives a reading that only asks whether the code works.
Show the discipline of selecting rather than dumping: what is already fixed goes in, the rest does not, and material you attach is read as the house style whether or not you meant it that way.
The angle to own is duplication at scale. Requests that do not carry the helpers a project already has produce second implementations, and review is a poor place to catch duplication spread thinly across many small changes — the fix belongs in how requests are written.
## Correct and unusable are not opposites Ask for **one function that parses a fixed-width bank-statement line into a record**, attach nothing, and what comes back is usually a working parser. It slices the line by column position, trims the padding, turns the date field into a date, turns the amount field into a number, and hands back a record. Every step is defensible. The choices inside them are not yours. The function takes a raw line and returns a shape it invented. Your importer already has a record type, already has a date helper written for this exact format, and already calls the parser from a place with a fixed signature. So you now hold a correct function and a small pile of glue: a conversion from its record to yours, a decision about whether to keep its date handling or yours, and an argument list to reshape. **The answer was not wrong. It was generically right, which is a different thing and a more annoying one**, because nothing in it looks like a defect and much of it costs you an edit. ## The three things that are not the answer's to choose 1. **The signature the caller expects.** The call site already exists. Its parameter list and its return type are facts, not preferences — so attach the caller, or at least the declaration. 2. **The type it has to return.** A record type carries more than field names: it carries the units and the conventions inside it. If the amount in your record is whole minor units with the sign held separately, an invented record that stores a decimal amount with a leading sign is not a naming difference, it is a different representation. 3. **The helper it should use rather than rewrite.** If something in the project already parses this format's dates, an answer that does not know it exists will write a second one, and the second one will be subtly different. Two of anything is worse than one of either. ## The tell that you under-supplied You do not need a rule for this; the result tells you. Watch for: - a result you have to **wrap** before the existing caller can use it; - a **second implementation** of something the project already has; - a record or parameter shape that is *nearly* yours, off by a field name or a unit; - a convention the project does not use — a different error style, a different way of signalling a bad line; - your own first instinct on reading it being *"that is fine, I just need to…"*. That sentence is the cost, and it is the one that is easy not to count. ## What an invented return shape takes with it | The answer invents | What it silently decides | What that costs you | |---|---|---| | The record type | Field names, and the units inside them | A conversion, plus a chance to get the unit wrong | | The amount representation | Decimal or whole minor units; sign on the number or beside it | A defect that survives review, because both shapes look correct | | Its own date handling | A second reading of the same format | Two implementations that drift apart | | The error behaviour | Whether a malformed line throws, returns nothing, or returns a partial record | A caller that handles the wrong one | | The signature | Argument order, and what the caller has to hold | An edit at every call site | **The middle row is the one worth remembering.** A record that stores an amount as a decimal number and one that stores whole minor units both read as sensible. If the format supplies the amount as digits with an implied decimal point, one of those readings is out by a factor of a hundred, and nothing in the generated code looks wrong. ## Where this stops Attaching is not free and more is not better. The material you attach is read as *how things are done here*, so attaching a tired old path you are about to replace tends to produce something shaped like it. That trade — how much context a whole working session should carry, and what surplus costs — is a separate subject with its own answer; for one bounded request the selector is narrower and easier: **attach what is already fixed, and let the answer choose the rest.** Nor does attaching the shape guarantee the fit. An answer can be given the exact record type and still populate a field with the wrong unit, and it can be given the helper and still not call it. The attachments remove the *invention*; they do not remove the reading. ## Answering this in an interview Name the failure first — *a correct function that does not compose* — because that is what separates this from a general plea for more context. Then give the selector in one line: attach what the codebase has already decided, not everything that is relevant. Then name the tell, which is that you find yourself writing a wrapper. A candidate who says "give it as much context as possible" has not answered the question; the interesting part is which context, and why those and not others.
- Is attaching the caller enough on its own?It fixes the signature and the return type, which is most of the fit. It does not reveal the helper that already exists elsewhere, and that is the attachment people forget — so a duplicate implementation is the residue you look for even when the shape came back right.
- How do you decide between attaching a type and describing it?Attach it when the conventions inside it matter — units, sign handling, what a field means when it is empty — because a description tends to carry the names and lose the conventions. Describe it when the shape is trivial and attaching would drag a large file along with it.
- If the result needs only a small wrapper, is that actually a problem?Once, no. As a pattern, yes: the wrapper is work that recurs on every request, and each one is a place for a unit or a field to be mapped wrongly. Treat a wrapper as a signal about the request rather than as the end of the task.
A part machined exactly to spec, for a different machine. Nothing is wrong with the part, and it still does not go in.
saying these in an interview costs you the question
- Attach everything — more context can only improve the result
- If the function is correct, fit is just naming and cosmetics
- Describing the record type is the same as attaching it
- Relevance is the test for what to attach
- A wrapper around the result means the request worked