{"course":{"slug":"how-software-changed","title":"How Software Development Changed","url":"https://addaly.com/learn/how-software-changed","level":"intermediate","track":"work"},"lesson":{"slug":"examples-beat-adjectives","title":"Examples beat adjectives","url":"https://addaly.com/learn/how-software-changed/examples-beat-adjectives","position":37,"of":87,"minutes":8,"answer":"An example fixes the properties you would not have thought to name, so replace adjectives with worked cases and domain vocabulary, while varying the examples along dimensions that do not matter.","keyIdea":"An example fixes the properties you would not have thought to name, so replace adjectives with worked cases and domain vocabulary, while varying the examples along dimensions that do not matter, or they will be copied too."},"body":{"format":"markdown","text":"## Why an example carries more than a paragraph\n\n\"Write a validation error message that is helpful and friendly\" produces something. Which something depends entirely on what the words *helpful* and *friendly* pull towards, and you have no control over that.\n\nThree examples specify the same thing exactly:\n\n```\nEmail: \"That email address is missing an @ symbol.\"\nDate:  \"That date is in the future. Bookings can only be for today or earlier.\"\nMoney: \"Amounts can have at most 2 decimal places. You entered 3.\"\n```\n\nNow the register, the length, the sentence structure, the decision to state what was wrong rather than what is required, and the absence of \"please\" and exclamation marks are all fixed: by demonstration rather than description. A fourth message will match, and you did not have to know that you cared about any of those properties.\n\nThis is the same reason a worked example beats a rule in a specification. Examples encode the properties you would not have thought to name, and those are usually the ones that make the difference between right and nearly right.\n\n## The translation table for common adjectives\n\nEvery vague word in a request has a concrete form. The exercise of finding it is ten seconds and it is most of the value of a specification.\n\n- *Clean* → follows the existing pattern in `X`; here is the file.\n- *Efficient* → a single database round trip, not one per row.\n- *Simple* → under 40 lines, no new dependencies, no new abstraction.\n- *Consistent* → matches the naming in `models/order.py`, which is the reference.\n- *Well tested* → these five cases must be covered, named here.\n- *Idiomatic* → here are two functions from this repository; match them.\n- *Production ready* → has a timeout, a retry policy, a metric, and a documented failure mode.\n\nThe last one is worth dwelling on. \"Production ready\" is the single vaguest phrase in software and it can be turned into a four-item checklist that anyone can verify.\n\n## Use the words your domain actually uses\n\nA specification full of *item*, *object*, *record*, *process* and *handle* is a specification that has not yet decided anything.\n\nUse the vocabulary of the business, exactly, and use each word to mean one thing. If finance says *invoice*, *credit note* and *statement*, then those three words appear in the specification, in the code, in the table names and in the conversation. If a *shipment* can contain items from several *orders*, that sentence goes in, because it is the fact that determines the data model.\n\nThis idea has a name in domain-driven design (the ubiquitous language) and its practical payoff is that the gap between what the business said and what the code does becomes visible. A function called `processItems` cannot be checked against a requirement. A function called `allocate_stock_to_shipment` can.\n\nThere is a second payoff now. Precise domain vocabulary is a much stronger signal to a generator than generic vocabulary, because it narrows what is being asked for. \"Reconcile the settlement file against the ledger\" produces something far closer to what you want than \"process the data\", not because of any magic, but because the first sentence carries information and the second does not.\n\n## Show the shape of the output\n\nWhen you want a particular structure, show it rather than describe it.\n\n```json\n{\n  \"invoice_id\": \"INV-2026-000412\",\n  \"lines\": [\n    {\"sku\": \"TS-BLUE-M\", \"qty\": 2, \"amount_minor\": 249900, \"currency\": \"INR\"}\n  ],\n  \"total_minor\": 249900,\n  \"base_currency\": \"INR\",\n  \"issued_at\": \"2026-08-14T09:31:00Z\"\n}\n```\n\nOne sample fixes the naming convention, the money representation, the date format, the nesting, the currency handling and the identifier format. Writing all of that as prose would take a paragraph and still leave ambiguity about whether `total_minor` includes tax.\n\n## The limit, stated honestly\n\nExamples over-specify as easily as adjectives under-specify. Three error messages that all happen to start with \"That\" will produce a fourth starting with \"That\", including where it reads badly. A sample JSON with two line items may produce code that assumes there are always at least two.\n\nSo choose examples that vary along the dimensions that do not matter and hold constant the ones that do. If length is irrelevant, make one example short and one long. If the number of items is irrelevant, show one with a single item and one with several. And where an example is deliberately not representative, say so in one line.\n\nThe underlying discipline is the same one as everywhere else in this module: decide what actually matters, and say it in the form that leaves the least room to be read differently."},"check":{"question":"A team specifies an API response by supplying one sample payload containing two line items. The implementation later fails on single-item orders. What went wrong with the specification technique?","options":[{"text":"Samples are inherently ambiguous about structure, so a JSON Schema should have been provided instead of an example.","correct":false,"tempting":"A schema pins cardinality precisely, but it loses the naming, formatting and convention information that made the example valuable."},{"text":"The example held constant a dimension that was meant to vary, so its incidental shape was treated as required.","correct":true},{"text":"One example is never enough, and the rule of thumb is at least three for any structural specification.","correct":false,"tempting":"Turns a real principle into a count, when two well-chosen examples that differ on cardinality would have sufficed."},{"text":"The specification should have described the response in prose, since prose can state that the list may contain any number of items.","correct":false,"tempting":"Prose can state cardinality but loses the exact field names, money representation and date format the example fixed for free."}]},"prev":{"slug":"scope-and-blast-radius","title":"Bounding what a change is allowed to touch","url":"https://addaly.com/learn/how-software-changed/scope-and-blast-radius"},"next":{"slug":"specs-that-do-not-rot","title":"Keeping the written thing true","url":"https://addaly.com/learn/how-software-changed/specs-that-do-not-rot"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'Examples beat adjectives', in How Software Development Changed. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/how-software-changed/examples-beat-adjectives (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"Examples beat adjectives","courseTitle":"How Software Development Changed","module":{"index":4,"slug":"saying-what-you-want","title":"Saying what you want"},"answer":null,"keyIdea":"An example fixes the properties you would not have thought to name, so replace adjectives with worked cases and domain vocabulary, while varying the examples along dimensions that do not matter, or they will be copied too.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"why-an-example-carries-more-than-a-paragraph","runs":[{"text":"Why an example carries more than a paragraph"}]},{"t":"p","runs":[{"text":"“Write a validation error message that is helpful and friendly” produces something. Which something depends entirely on what the words "},{"text":"helpful","i":true},{"text":" and "},{"text":"friendly","i":true},{"text":" pull towards, and you have no control over that."}]},{"t":"p","runs":[{"text":"Three examples specify the same thing exactly:"}]},{"t":"code","lang":"","label":"Text","text":"Email: \"That email address is missing an @ symbol.\"\nDate:  \"That date is in the future. Bookings can only be for today or earlier.\"\nMoney: \"Amounts can have at most 2 decimal places. You entered 3.\""},{"t":"p","runs":[{"text":"Now the register, the length, the sentence structure, the decision to state what was wrong rather than what is required, and the absence of “please” and exclamation marks are all fixed: by demonstration rather than description. A fourth message will match, and you did not have to know that you cared about any of those properties."}]},{"t":"p","runs":[{"text":"This is the same reason a worked example beats a rule in a specification. Examples encode the properties you would not have thought to name, and those are usually the ones that make the difference between right and nearly right."}]},{"t":"h2","id":"the-translation-table-for-common-adjectives","runs":[{"text":"The translation table for common adjectives"}]},{"t":"p","runs":[{"text":"Every vague word in a request has a concrete form. The exercise of finding it is ten seconds and it is most of the value of a specification."}]},{"t":"ul","items":[[{"text":"Clean","i":true},{"text":" → follows the existing pattern in "},{"text":"X","code":true},{"text":"; here is the file."}],[{"text":"Efficient","i":true},{"text":" → a single database round trip, not one per row."}],[{"text":"Simple","i":true},{"text":" → under 40 lines, no new dependencies, no new abstraction."}],[{"text":"Consistent","i":true},{"text":" → matches the naming in "},{"text":"models/order.py","code":true},{"text":", which is the reference."}],[{"text":"Well tested","i":true},{"text":" → these five cases must be covered, named here."}],[{"text":"Idiomatic","i":true},{"text":" → here are two functions from this repository; match them."}],[{"text":"Production ready","i":true},{"text":" → has a timeout, a retry policy, a metric, and a documented failure mode."}]]},{"t":"p","runs":[{"text":"The last one is worth dwelling on. “Production ready” is the single vaguest phrase in software and it can be turned into a four-item checklist that anyone can verify."}]},{"t":"h2","id":"use-the-words-your-domain-actually-uses","runs":[{"text":"Use the words your domain actually uses"}]},{"t":"p","runs":[{"text":"A specification full of "},{"text":"item","i":true},{"text":", "},{"text":"object","i":true},{"text":", "},{"text":"record","i":true},{"text":", "},{"text":"process","i":true},{"text":" and "},{"text":"handle","i":true},{"text":" is a specification that has not yet decided anything."}]},{"t":"p","runs":[{"text":"Use the vocabulary of the business, exactly, and use each word to mean one thing. If finance says "},{"text":"invoice","i":true},{"text":", "},{"text":"credit note","i":true},{"text":" and "},{"text":"statement","i":true},{"text":", then those three words appear in the specification, in the code, in the table names and in the conversation. If a "},{"text":"shipment","i":true},{"text":" can contain items from several "},{"text":"orders","i":true},{"text":", that sentence goes in, because it is the fact that determines the data model."}]},{"t":"p","runs":[{"text":"This idea has a name in domain-driven design (the ubiquitous language) and its practical payoff is that the gap between what the business said and what the code does becomes visible. A function called "},{"text":"processItems","code":true},{"text":" cannot be checked against a requirement. A function called "},{"text":"allocate_stock_to_shipment","code":true},{"text":" can."}]},{"t":"p","runs":[{"text":"There is a second payoff now. Precise domain vocabulary is a much stronger signal to a generator than generic vocabulary, because it narrows what is being asked for. “Reconcile the settlement file against the ledger” produces something far closer to what you want than “process the data”, not because of any magic, but because the first sentence carries information and the second does not."}]},{"t":"h2","id":"show-the-shape-of-the-output","runs":[{"text":"Show the shape of the output"}]},{"t":"p","runs":[{"text":"When you want a particular structure, show it rather than describe it."}]},{"t":"code","lang":"json","label":"JSON","text":"{\n  \"invoice_id\": \"INV-2026-000412\",\n  \"lines\": [\n    {\"sku\": \"TS-BLUE-M\", \"qty\": 2, \"amount_minor\": 249900, \"currency\": \"INR\"}\n  ],\n  \"total_minor\": 249900,\n  \"base_currency\": \"INR\",\n  \"issued_at\": \"2026-08-14T09:31:00Z\"\n}"},{"t":"p","runs":[{"text":"One sample fixes the naming convention, the money representation, the date format, the nesting, the currency handling and the identifier format. Writing all of that as prose would take a paragraph and still leave ambiguity about whether "},{"text":"total_minor","code":true},{"text":" includes tax."}]},{"t":"h2","id":"the-limit-stated-honestly","runs":[{"text":"The limit, stated honestly"}],"role":"limit"},{"t":"p","runs":[{"text":"Examples over-specify as easily as adjectives under-specify. Three error messages that all happen to start with “That” will produce a fourth starting with “That”, including where it reads badly. A sample JSON with two line items may produce code that assumes there are always at least two."}]},{"t":"p","runs":[{"text":"So choose examples that vary along the dimensions that do not matter and hold constant the ones that do. If length is irrelevant, make one example short and one long. If the number of items is irrelevant, show one with a single item and one with several. And where an example is deliberately not representative, say so in one line."}]},{"t":"p","runs":[{"text":"The underlying discipline is the same one as everywhere else in this module: decide what actually matters, and say it in the form that leaves the least room to be read differently."}]}],"check":{"question":[{"text":"A team specifies an API response by supplying one sample payload containing two line items. The implementation later fails on single-item orders. What went wrong with the specification technique?"}],"options":[{"text":[{"text":"Samples are inherently ambiguous about structure, so a JSON Schema should have been provided instead of an example."}],"correct":false,"tempting":[{"text":"A schema pins cardinality precisely, but it loses the naming, formatting and convention information that made the example valuable."}]},{"text":[{"text":"The example held constant a dimension that was meant to vary, so its incidental shape was treated as required."}],"correct":true,"tempting":null},{"text":[{"text":"One example is never enough, and the rule of thumb is at least three for any structural specification."}],"correct":false,"tempting":[{"text":"Turns a real principle into a count, when two well-chosen examples that differ on cardinality would have sufficed."}]},{"text":[{"text":"The specification should have described the response in prose, since prose can state that the list may contain any number of items."}],"correct":false,"tempting":[{"text":"Prose can state cardinality but loses the exact field names, money representation and date format the example fixed for free."}]}],"order":[3,2,1,0],"why":null},"prev":{"slug":"scope-and-blast-radius","title":"Bounding what a change is allowed to touch","minutes":9},"next":{"slug":"specs-that-do-not-rot","title":"Keeping the written thing true","minutes":8}}}