Acceptance Criteria: Defining "Done"
In Silicon Valley, "Done" doesn't mean "I finished coding." It means the feature meets the Acceptance Criteria (AC). AC are the specific conditions that a software product must satisfy to be accepted by a user, customer, or other stakeholder. Without clear AC, scope creep happens, and teams waste time building the wrong things.
Why AC Matter
Clear AC remove the "I thought you meant..." conversations. They provide:
- Alignment: Everyone agrees on what is being built.
- Testing: QA and engineers know exactly what to test.
- Estimation: It's easier to estimate a task when the boundaries are clear.
The Anatomy of Good AC
Good acceptance criteria are testable. Avoid vague words like "fast," "easy," "intuitive," or "robust." Instead, use specific, measurable targets.
1. The Checklist Format
Best for UI/UX and simple functional requirements.
- [ ] The "Submit" button is disabled until all required fields are filled.
- [ ] Error message "Invalid Email" appears if the @ symbol is missing.
- [ ] The user is redirected to the /dashboard after a successful login.
2. The Given/When/Then Format (BDD)
Best for complex logic and business rules.
- Given: The user has an expired subscription.
- When: They click on a "Premium" feature.
- Then: They are shown the pricing page with a "Renew Now" banner.
Functional vs. Non-Functional AC
Don't just focus on what the feature does. Focus on how it performs.
- Functional: "The user can export the report as a PDF."
- Non-Functional: "The PDF export must complete in under 5 seconds for files up to 10MB."
Common Pitfalls
- Too broad: "The system should handle all errors." (Which errors? How?)
- Too technical: "The API should return a 404 from the controller." (AC should focus on the behavior, not the implementation.)
- Untestable: "The user should enjoy the experience." (How do you measure 'enjoy'?)
When writing AC, ask yourself: "Could a new engineer join the team today and know exactly how to verify this is finished?" If the answer is no, your AC need more detail.
A PR is not just a code diff. The description explains the reasoning the diff cannot show. A good PR description has:
- Summary: what this PR does, in 2-3 sentences.
- Why: the motivation and the problem it solves.
- How to test: steps a reviewer can follow to verify it.
- Related issues: links with Resolves #123.
- Screenshots (for UI changes): before and after.
Example:
Summary: Adds retry logic to the payment email service. Why: ~5% of Stripe orders did not send confirmation emails due to transient service timeouts (#123). How to test: 1) Checkout with the Stripe test card. 2) Check the email service logs for a retry on first failure. 3) Confirm email arrives. Resolves #123
Linking issues and PRs
Use GitHub keywords to connect work:
- Resolves #123 or Closes #123: closes the issue when the PR merges.
- Refs #123: links without closing.
- Part of #123: links to a larger epic.
Linking makes work traceable. A reviewer can click from PR to issue to understand the full context.
The code review conversation
A PR is also a conversation. Reviewers leave comments; the author responds. Keep the language professional and focused on the code, not the person:
- Could you explain the choice of a Set here? I wonder if an array is simpler.
- Nice catch on the edge case.
- Left a small suggestion on line 42. Otherwise, looks good.
Review comments are about the work, never about the author.
Common mistakes
- Bare issue titles. BUG tells the assignee nothing.
- PR with no description. The reviewer must guess the why and the how-to-test.
- No issue links. Work becomes untraceable.
Practice
Write a one-paragraph PR description for a change you have made or would make:
- Summary: _
- Why: _
- How to test: _
- Related issue: _
In the next lesson, you will learn to write for mixed technical and non-technical audiences.