Writing Specs That Don't Lie (EARS)
A spec is only useful if it's precise enough to be checkable. Learn EARS - a simple way to write requirements an agent can't misread
Most Specs Are Too Mushy to Help
"The app should be fast and user-friendly." That's not a spec - it's a wish. Fast how? User-friendly to whom? An agent (or a human) can't build it and can't check it. A good spec has one job: be precise enough that you can tell whether it was met.
Functional vs. Non-Functional Requirements
Specs hold two kinds of requirements, and you need both:
Concrete behaviors. "A user can reset their password via an emailed link." "Tasks can be filtered by status." These are features.
Qualities, not features. Speed, security, accessibility, reliability. "Pages load in under 2 seconds." "All actions are keyboard-accessible." Beginners forget these, and they're where products quietly fail.
EARS: A Simple Recipe for Clear Requirements
EARS (Easy Approach to Requirements Syntax) is a tiny set of sentence templates that force precision. You don't need jargon - just fill in the blanks. The magic is that every EARS sentence has a clear trigger and a clear response, so there's nothing to misread.
The five EARS patterns:
UBIQUITOUS "The <system> shall <do something>."
โ always true. "The app shall store tasks in a database."
EVENT "WHEN <trigger>, the <system> shall <response>."
โ "WHEN a user submits the form, the app shall save the task."
STATE "WHILE <in some state>, the <system> shall <response>."
โ "WHILE a user is logged out, the app shall hide the dashboard."
CONDITIONAL "IF <condition>, THEN the <system> shall <response>."
โ "IF the password is wrong, THEN the app shall show an error."
OPTIONAL "WHERE <feature is included>, the <system> shall <response>."
โ "WHERE dark mode is enabled, the app shall use dark colors."Mushy vs. EARS - Side by Side
MUSHY EARS (checkable)
"Login should work well" โ WHEN a user enters a valid email and
password, the app shall log them in and
redirect to the dashboard.
IF the email or password is invalid, THEN
the app shall show "Invalid credentials" and
keep them on the login page.
"Make it secure" โ The app shall store passwords only as salted
hashes, never as plain text.
WHILE a user is logged out, the app shall
deny access to all /dashboard routes.Notice the mushy line became four precise requirements. That expansion is the work - it's where you find the decisions you hadn't made yet.
Acceptance Criteria: How You Know It's Done
Each requirement should come with acceptance criteria - the specific, observable conditions that prove it works. These are what tests get written against (a theme you'll see explode in LID two lessons from now).
Requirement: WHEN a user submits a new task, the app shall
save it and show it at the top of the list.
Acceptance criteria:
โ The task appears in the list without a page reload.
โ The task persists after refreshing the page.
โ Submitting an empty task shows a validation error instead.Hands-On: Rewrite a Wish as EARS
A good requirement lets two people agree on whether the software meets it - otherwise it's a guess waiting to happen
What the system does - a concrete behavior or feature
How well it does it - speed, security, accessibility, reliability
Easy Approach to Requirements Syntax - sentence templates with a clear trigger and response
Ubiquitous, Event (WHEN), State (WHILE), Conditional (IF/THEN), Optional (WHERE)
The specific, observable conditions that prove a requirement is met - what tests check