Skip to content
All articles

Requirements Engineering: Modeling Before You Build

Dean Jain

Dean Jain

Senior Staff Software Engineer · Enterprise AI, Data & Cloud Architect

· 8 min read

RequirementsSoftware EngineeringDesign

Editor’s note, 2026: In 2012, code was the expensive part and this discipline was what teams skipped to get to it faster. Fourteen years and one AI revolution later, it’s the last part of the job the machines can’t do for you. Why this became the whole game →

---
config:
  theme: neutral
  fontSize: 16
---
flowchart LR
    R["Requirements<br/>(cheap to fix)"]:::stage1 --> D["Design"]:::stage2 --> C["Code"]:::stage3 --> P["Production<br/>(expensive to fix)"]:::stage4
    classDef stage1 fill:#FFFFFF,stroke:#333333,stroke-width:1px,color:#111111
    classDef stage2 fill:#F0F0F0,stroke:#333333,stroke-width:1px,color:#111111
    classDef stage3 fill:#DCDCDC,stroke:#333333,stroke-width:1px,color:#111111
    classDef stage4 fill:#C0C0C0,stroke:#333333,stroke-width:1px,color:#111111

Figure 1: The cost curve a defect caught in requirements is trivial to fix; the same defect found in production is enormously expensive.

The most expensive bugs aren’t coding mistakes they’re requirements mistakes: building the wrong thing, correctly. A misunderstanding caught while writing requirements costs a conversation; the same misunderstanding caught in production costs a rewrite, plus everything built on top of it. That cost curve is why requirements engineering exists a systematic discipline for defining, creating, and verifying what to build before you build it. It’s unglamorous next to coding, and it’s where projects are quietly won or lost. Here’s the discipline.

Summary

  • Fix-cost rises by phase. Defects get exponentially more expensive to fix the later you catch them so invest in getting requirements right first.
  • Requirements engineering is a 5-step process: feasibility study → elicitation → specification → verification & validation → management.
  • Elicit with intent (interviews, brainstorming, Delphi, prototyping); specify formally (functional and non-functional, with ER/data-flow diagrams, data dictionaries).
  • Model the requirements from multiple angles scenario, class, behavioral, data, and flow models to understand them before designing.
  • Refine into design top-down (architectural → high-level → detailed) via stepwise refinement decompose, refine, repeat.

1. The five-step process

Requirements engineering is the systematic and strict approach to defining and verifying what a system must do. Skipping it doesn’t save time it defers the cost to a far more expensive phase. The five steps:

  1. Feasibility study can this even be done, across technical, operational, cost, legal, and schedule dimensions? Kill non-viable ideas here, where it’s free.
  2. Requirements elicitation actively gain knowledge of the domain and needs. Use real techniques interviews, brainstorming, task analysis, the Delphi technique, prototyping because stakeholders rarely hand you complete, correct requirements; you have to draw them out.
  3. Requirements specification produce formal models of both functional (what it does) and non-functional (how well performance, security, reliability) requirements, captured in artifacts like ER diagrams, data-flow diagrams (DFDs), function-decomposition diagrams, and data dictionaries.
  4. Verification & validation two different checks: verification confirms the software correctly implements a function; validation confirms what you built is traceable to the customer’s actual requirements. (Building it right vs. building the right thing.)
  5. Requirements management analyze, document, track, prioritize, agree on, and control the communication of requirements with stakeholders over the project’s life.

The two that teams shortchange are elicitation (assuming the first ask is complete) and the functional/non-functional split in specification (capturing what but forgetting how well until performance or security bites in production). Get those right and most downstream pain disappears.

2. Model the requirements before you design

A list of requirements in prose is easy to misread. Requirements modeling captures them from several complementary angles so gaps and contradictions surface before code:

---
config:
  theme: neutral
  fontSize: 16
---
flowchart TD
    REQ["Requirements"]:::root
    REQ --> SC["Scenario<br/>from each actor's view"]:::leaf
    REQ --> CL["Class-oriented<br/>objects + collaborations"]:::leaf
    REQ --> BE["Behavioral<br/>response to events"]:::leaf
    REQ --> DA["Data<br/>the information domain"]:::leaf
    REQ --> FL["Flow-oriented<br/>how data transforms"]:::leaf
    classDef root fill:#DAE8FC,stroke:#333333,stroke-width:1px,color:#111111
    classDef leaf fill:#FFFFFF,stroke:#333333,stroke-width:1px,color:#111111

Figure 2: Five modeling lenses scenario, class, behavioral, data, and flow each catching a different kind of misunderstanding.

  • Scenario-based requirements from the point of view of each system actor (use cases). Catches “we forgot about that user.”
  • Class-oriented the object-oriented classes (attributes, operations) and how they collaborate to meet requirements.
  • Behavioral how the software reacts to events. The recipe: evaluate all use cases, identify the driving events, build a sequence diagram per use case, then a state diagram for the system, and review for consistency.
  • Data the information domain: entities and relationships (ER diagrams).
  • Flow-oriented the functional elements and how they transform data as it moves through the system (DFDs).

A useful distinction the modeling surfaces: some applications are data-driven (produce reports from data) while a large class are control-driven (driven by events, producing control information, with heavy time/performance concern) and you model them differently (data-flow modeling vs control-flow modeling). Modeling isn’t bureaucracy; it’s the cheapest place to discover that two stakeholders meant different things by the same word.

3. From requirements to design top-down

Once requirements are understood and modeled, design proceeds top-down, from the most abstract view to the most concrete:

---
config:
  theme: neutral
  fontSize: 16
---
flowchart LR
    A["Architectural design<br/>system as interacting<br/>components"]:::box --> H["High-level design<br/>sub-systems &amp; modules"]:::box
    H --> D["Detailed design<br/>logic &amp; interfaces<br/>per module"]:::box
    classDef box fill:#FFFFFF,stroke:#333333,stroke-width:1px,color:#111111

Figure 3: Design in three levels architectural (the system), high-level (sub-systems/modules), detailed (per-module logic and interfaces).

  • Architectural design the highest abstraction: the software as a system of interacting components; the solution-domain shape.
  • High-level design break that single entity into sub-systems and modules, recognizing their structure and interactions.
  • Detailed design the implementation view: each module’s logical structure and the interfaces it uses to talk to others.

The technique that gets you down the levels is stepwise refinement a top-down approach: start with the big picture, decompose into smaller subproblems, refine each (adding detail until it’s clearly implementable), and repeat iteratively. It’s what makes a daunting system tractable: you never design the whole thing at once, you keep splitting and refining. The payoff is a design that’s modular, has distinct representations of data/architecture/interface/components, and can be implemented and tested evolutionarily which then flows into component design, decomposing into reusable, well-defined components with clear interfaces (the goal being reusability a component as a self-deployable unit).

Why it matters: the romantic image of engineering is writing code, but the leverage is upstream a defect in requirements multiplies in cost through every later phase. Treat requirements as engineering, not paperwork: elicit deliberately, specify the non-functional as carefully as the functional, model from multiple angles to expose misunderstandings, and refine top-down into design. The hours spent making sure you’re building the right thing are the cheapest hours in the whole project and the ones most often skipped.

2026 postscript: fourteen years later, this is the whole game

I wrote this article in 2012, when “writing the code” was the expensive part and requirements discipline was the thing teams skipped to get to it faster. Fourteen years on, AI and agentic coding have inverted the economics and made every section above more relevant, not less. Here’s why.

---
config:
  theme: dark
  fontSize: 17
  themeVariables:
    fontFamily: "Comic Sans MS, Comic Neue, Chalkboard SE, cursive"
---
flowchart LR
    SPEC["📋 Requirements / spec<br/>the human bottleneck"]:::gov --> AGENT["🤖 Agentic coding<br/>near-zero cost, machine speed"]:::obs
    AGENT --> RIGHT["✅ Right spec<br/>right system, 10× faster"]:::good
    AGENT --> WRONG["💥 Wrong spec<br/>wrong system, 10× faster"]:::danger
    classDef gov fill:#E0D6F5,stroke:#9B7EDE,stroke-width:2px,color:#0F172A
    classDef obs fill:#AED6F1,stroke:#2E86C1,stroke-width:2px,color:#0F172A
    classDef good fill:#BFEFC8,stroke:#3FA34D,stroke-width:2px,color:#0F172A
    classDef danger fill:#FFB3B3,stroke:#D14545,stroke-width:2px,color:#0F172A

Figure 4: AI didn't flatten the 2012 cost curve it steepened it. Code generation is near-free, so the quality of the requirements is now the dominant variable in what gets built.

1. When code is nearly free, requirements are the bottleneck. The cost curve in Figure 1 assumed coding was expensive. Now an agent produces in minutes what a team produced in weeks which means the only remaining expensive artifact is the specification. AI doesn’t fix a requirements defect; it amplifies it at machine speed. Building the wrong thing, correctly, used to take a quarter. Now it takes an afternoon, plus everything the swarm built on top of it before anyone noticed.

2. Prompts and specs are requirements engineering. What the industry now calls prompt engineering, context engineering, and spec-driven development is this article wearing new clothes. A well-run agentic workflow starts from a written spec with explicit constraints, acceptance criteria, and non-goals that is a requirements specification, and the teams who never learned to write one are re-discovering why elicitation and specification were steps 2 and 3. The agent does the coding phase; the human owns everything upstream of it.

3. Verification vs. validation is now the central distinction. Agents are good at verification the tests pass, the types check, the build is green. They are structurally bad at validation, because they cannot know what the customer actually meant; they only know what the prompt said. The 2012 distinction “building it right vs. building the right thing” has become the exact boundary between what you can delegate to an agent and what remains irreducibly human judgment.

4. Non-functional requirements don’t generate themselves. Ask an agent for a feature and you get a functional happy path. Latency budgets, security posture, compliance constraints, failure behavior the how well appear only if they were specified. The section above about teams forgetting non-functional requirements until production bites was a warning in 2012; with generated code it’s a guarantee.

5. Ambiguity is more dangerous now, not less. A human engineer who hits an ambiguous requirement asks a question. An agent fills the gap with a plausible assumption and keeps going confidently, at scale, in every file it touches. The modeling lenses in Figure 2 scenario, behavioral, data exist precisely to surface ambiguity before it’s load-bearing. Feeding those models into an agent’s context is the difference between constraining the machine and letting it guess.

6. Stepwise refinement is literally how you run agents. Decompose, refine until clearly implementable, repeat the 2012 recipe for making a daunting system tractable is, word for word, how you decompose work for agentic coding today: break the system into bounded tasks, specify each precisely, dispatch, verify, integrate. Task decomposition for a swarm is stepwise refinement with a new executor.

The punchline: fourteen years ago this discipline was how you avoided expensive rework. Today it’s the job description. As the coding phase compresses toward zero, the engineer’s remaining leverage concentrates in exactly what this article describes knowing precisely what to build, specifying it unambiguously, and validating that what came back is what was meant. The romance of engineering moved upstream. The discipline was already waiting there ❤️😁.

2012 vs 2026: in 2012 manual coding outweighed requirements; in 2026 the scale flipped — specification & modeling is the heavy cube, coding the small one

Figure 5: The scale flipped. In 2012, manual coding was the heavy side and requirements the small cube; in 2026, specification & modeling carry the weight while coding compresses toward near-zero.

References