Combination therapy for requirements using BDD and UML

Ask ten experienced developers how to write a use case and you’ll get ten different answers. Some will give you a two-paragraph narrative. Others will reach for a structured template with pre-conditions, post-conditions, and alternate flows. A few will argue use cases are dead and pull out user stories. The format wars are real, and they have a cost—when vendor and client each carry a different mental model of what “a use case” means, the gap shows up in the delivered software.

That gap is expensive. In fixed-price projects especially, ambiguous requirements aren’t just an inconvenience; they become contractual disputes.

What’s broken about conventional use cases

The problem isn’t use cases as a concept. The problem is that the form is underspecified. Every organisation develops its own flavour, its own level of detail, its own assumptions about what belongs in the main flow versus an alternate flow. Without a shared, precise format, two people reading the same document can build two very different systems.

There’s also a participation problem. Stakeholders often can’t read or critique a use case written in technical prose. They sign off without genuinely validating the requirement. The bug report three months later is the first real review.

BDD as a requirements language

Behaviour-Driven Development, introduced by Dan North, was designed to solve exactly this problem. BDD stories are structured in plain English using a format that’s both human-readable and machine-executable:

Title: Withdraw cash from ATM

As a bank customer
I want to withdraw cash from an ATM
So that I can access my money without visiting a branch

Scenario: Account has sufficient funds
  Given the account balance is $100
  And the card is valid
  And the machine contains enough money
  When the customer requests $20
  Then the ATM should dispense $20
  And the account balance should be $80
  And the card should be returned

Scenario: Account has insufficient funds
  Given the account balance is $10
  When the customer requests $20
  Then the ATM should not dispense any money
  And the ATM should say there are insufficient funds
  And the account balance should remain $10

Each scenario is an executable specification. Tools like SpecFlow and Gherkin can run these directly as acceptance tests. The requirement and the test are the same artefact. There’s no translation step where meaning gets lost.

Where UML still helps

BDD stories describe behaviour well. They don’t describe structure, layout, or data types. That’s where selective use of UML remains valuable—not as a replacement for stories, but as a supplement.

A mockup or wireframe attached to a story gives the UI requirement a concrete anchor. A simple sequence diagram can clarify the interaction between services when the Given/When/Then prose starts to feel ambiguous. Data type specifications prevent the perennial argument about what “date” means—UTC? Local? Which format?

The combination is deliberately minimal: one story with acceptance scenarios, plus whatever visual artefacts remove the remaining ambiguity. Not a full UML model. Not a 40-page specification document. Just enough.

What this changes in practice

When requirements are written in this form, estimation becomes more honest. You can count scenarios and use them as a basis for effort forecasting. The testing team participates from the start because the acceptance criteria are already test cases—they don’t need to be reverse-engineered from a requirements document after the fact. The client can read and challenge each scenario before development begins, which is the closest thing to a genuine review that most projects ever see.

Dan North described BDD as a technique for having better conversations about software. The format is almost beside the point. What matters is that requirements become precise enough to be falsifiable—and therefore worth writing down.

The tools have matured considerably since this was written. nBehave evolved into SpecFlow; Cucumber and Gherkin became standard in the Ruby and JVM ecosystems. But the underlying insight hasn’t changed: if a stakeholder can’t validate a requirement before you build it, you’re specifying the wrong things in the wrong way.