requirements-writing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Requirements Writing Skill

需求编写技能

You are assisting with writing clear, testable requirements that drive development and testing for Manifest Logistics SaaS.
您正在协助编写清晰、可测试的需求,为Manifest Logistics SaaS的开发和测试提供指导。

Core Principles

核心原则

Requirements Should Be

需求应具备以下特性

  • Clear: Unambiguous and understandable
  • Testable: Can be verified through RSpec/Cucumber
  • Complete: All necessary information included
  • Consistent: No contradictions
  • Traceable: Linked to business needs
  • Feasible: Technically and economically possible
  • 清晰:无歧义、易于理解
  • 可测试:可通过RSpec/Cucumber进行验证
  • 完整:包含所有必要信息
  • 一致:无矛盾内容
  • 可追溯:与业务需求关联
  • 可行:在技术和经济层面均可实现

Primary Format: User Stories + Gherkin

主要格式:用户故事 + Gherkin

User Stories (High-Level Features)

用户故事(高层级功能)

Format:
As a [role]
I want [feature/capability]
So that [benefit/value]
Good Examples:
As a Merchant
I want to create delivery tasks via API
So that my e-commerce orders are automatically dispatched

As a Carrier
I want to see bundled tasks on my route
So that I can deliver multiple packages efficiently

As an Account Admin
I want to configure SMS templates
So that recipients receive branded notifications
Bad Examples:
As a user, I want a button                    # Too vague
As a developer, I want to use Sidekiq         # Technical, not user-focused
The system should create tasks                # Not user-story format
格式:
As a [角色]
I want [功能/能力]
So that [收益/价值]
优秀示例:
As a Merchant
I want to create delivery tasks via API
So that my e-commerce orders are automatically dispatched

As a Carrier
I want to see bundled tasks on my route
So that I can deliver multiple packages efficiently

As an Account Admin
I want to configure SMS templates
So that recipients receive branded notifications
反面示例:
As a user, I want a button                    # 过于模糊
As a developer, I want to use Sidekiq         # 技术导向,非用户聚焦
The system should create tasks                # 不符合用户故事格式

Acceptance Criteria (Detailed Requirements)

验收标准(详细需求)

For each user story, define acceptance criteria using Gherkin scenarios.
Gherkin Format:
gherkin
Feature: [Feature name and brief description]
  [Optional: Longer description explaining business value]

  Scenario: [Specific situation to test]
    Given [initial context/preconditions]
    And [additional context]
    When [action/event occurs]
    Then [expected outcome]
    And [additional expectations]
针对每个用户故事,使用Gherkin场景定义验收标准。
Gherkin格式:
gherkin
Feature: [功能名称及简要描述]
  [可选:解释业务价值的详细描述]

  Scenario: [待测试的特定场景]
    Given [初始上下文/前置条件]
    And [额外上下文]
    When [动作/事件发生]
    Then [预期结果]
    And [额外预期]

Complete Example for Manifest

Manifest完整示例

gherkin
Feature: Zone-Based Task Bundling
  As a dispatch system
  I need to bundle delivery tasks by origin and destination zones
  So that carriers can deliver multiple packages efficiently

  Scenario: Tasks from same origin zone to same destination zone are bundled
    Given a Zone "Riyadh-North" exists as origin
    And a Zone "Riyadh-East" exists as destination
    And 3 pending tasks exist from "Riyadh-North" to "Riyadh-East"
    When the bundling service runs
    Then the tasks should be grouped into 1 bundle
    And the bundle status should be "ready_for_dispatch"

  Scenario: Tasks to different destination zones are not bundled together
    Given a Zone "Riyadh-North" exists as origin
    And a Zone "Riyadh-East" exists as destination
    And a Zone "Riyadh-West" exists as destination
    And 2 pending tasks exist from "Riyadh-North" to "Riyadh-East"
    And 1 pending task exists from "Riyadh-North" to "Riyadh-West"
    When the bundling service runs
    Then 2 separate bundles should be created

  Scenario: Express tasks are not bundled with Next-Day tasks
    Given 2 Express tasks exist for Zone "Riyadh-East"
    And 2 Next-Day tasks exist for Zone "Riyadh-East"
    When the bundling service runs
    Then Express tasks should be in a separate bundle
    And Next-Day tasks should be in a separate bundle

  Scenario: Single task creates single-item bundle
    Given only 1 pending task exists for Zone "Riyadh-East"
    When the bundling service runs
    Then the task should be bundled alone
    And the bundle should be dispatchable
gherkin
Feature: Zone-Based Task Bundling
  As a dispatch system
  I need to bundle delivery tasks by origin and destination zones
  So that carriers can deliver multiple packages efficiently

  Scenario: Tasks from same origin zone to same destination zone are bundled
    Given a Zone "Riyadh-North" exists as origin
    And a Zone "Riyadh-East" exists as destination
    And 3 pending tasks exist from "Riyadh-North" to "Riyadh-East"
    When the bundling service runs
    Then the tasks should be grouped into 1 bundle
    And the bundle status should be "ready_for_dispatch"

  Scenario: Tasks to different destination zones are not bundled together
    Given a Zone "Riyadh-North" exists as origin
    And a Zone "Riyadh-East" exists as destination
    And a Zone "Riyadh-West" exists as destination
    And 2 pending tasks exist from "Riyadh-North" to "Riyadh-East"
    And 1 pending task exists from "Riyadh-North" to "Riyadh-West"
    When the bundling service runs
    Then 2 separate bundles should be created

  Scenario: Express tasks are not bundled with Next-Day tasks
    Given 2 Express tasks exist for Zone "Riyadh-East"
    And 2 Next-Day tasks exist for Zone "Riyadh-East"
    When the bundling service runs
    Then Express tasks should be in a separate bundle
    And Next-Day tasks should be in a separate bundle

  Scenario: Single task creates single-item bundle
    Given only 1 pending task exists for Zone "Riyadh-East"
    When the bundling service runs
    Then the task should be bundled alone
    And the bundle should be dispatchable

Gherkin Best Practices

Gherkin最佳实践

1. Use Domain Language

1. 使用领域语言

Use terms from Manifest's ubiquitous language:
gherkin
undefined
使用Manifest的通用语言术语:
gherkin
undefined

GOOD

推荐

Given a Merchant "Salla Store" exists for the Account When creating a Task with delivery_type "express" And the recipient Zone is "Jeddah-Central"
Given a Merchant "Salla Store" exists for the Account When creating a Task with delivery_type "express" And the recipient Zone is "Jeddah-Central"

BAD

不推荐

Given a store exists When making a delivery order And the area is downtown
undefined
Given a store exists When making a delivery order And the area is downtown
undefined

2. One Scenario, One Behavior

2. 一个场景对应一种行为

gherkin
undefined
gherkin
undefined

GOOD - Tests one thing

推荐 - 仅测试一项内容

Scenario: OTP verification completes Express delivery Given a Task with status "out_for_delivery" And the Task requires OTP verification When the Carrier submits correct OTP "1234" Then the Task status should be "delivered"
Scenario: OTP verification completes Express delivery Given a Task with status "out_for_delivery" And the Task requires OTP verification When the Carrier submits correct OTP "1234" Then the Task status should be "delivered"

BAD - Tests multiple things

不推荐 - 测试多项内容

Scenario: OTP and payment and status Given a Task exists When carrier submits OTP and collects cash Then multiple things happen
undefined
Scenario: OTP and payment and status Given a Task exists When carrier submits OTP and collects cash Then multiple things happen
undefined

3. Use Background for Common Setup

3. 使用Background处理通用前置

gherkin
Feature: Carrier Task Assignment

  Background:
    Given an Account "Acme Logistics" exists
    And a Carrier "Mohammed" is active for the Account
    And the following Zones exist:
      | Zone Name      | City    |
      | Riyadh-North   | Riyadh  |
      | Riyadh-East    | Riyadh  |

  Scenario: Carrier assigned to tasks within their zones
    Given "Mohammed" is assigned to Zone "Riyadh-North"
    And a Task exists for Zone "Riyadh-North"
    When auto-assigning carriers
    Then "Mohammed" should be assigned to the Task

  Scenario: Carrier not assigned to tasks outside their zones
    Given "Mohammed" is assigned to Zone "Riyadh-North"
    And a Task exists for Zone "Riyadh-East"
    When auto-assigning carriers
    Then "Mohammed" should not be assigned to the Task
gherkin
Feature: Carrier Task Assignment

  Background:
    Given an Account "Acme Logistics" exists
    And a Carrier "Mohammed" is active for the Account
    And the following Zones exist:
      | Zone Name      | City    |
      | Riyadh-North   | Riyadh  |
      | Riyadh-East    | Riyadh  |

  Scenario: Carrier assigned to tasks within their zones
    Given "Mohammed" is assigned to Zone "Riyadh-North"
    And a Task exists for Zone "Riyadh-North"
    When auto-assigning carriers
    Then "Mohammed" should be assigned to the Task

  Scenario: Carrier not assigned to tasks outside their zones
    Given "Mohammed" is assigned to Zone "Riyadh-North"
    And a Task exists for Zone "Riyadh-East"
    When auto-assigning carriers
    Then "Mohammed" should not be assigned to the Task

4. Use Scenario Outlines for Multiple Cases

4. 使用Scenario Outline处理多案例

gherkin
Scenario Outline: Task status transitions
  Given a Task with status "<current_status>"
  When the event "<event>" occurs
  Then the Task status should be "<new_status>"

  Examples:
    | current_status     | event              | new_status         |
    | pending            | dispatch           | dispatched         |
    | dispatched         | pickup             | picked_up          |
    | picked_up          | out_for_delivery   | out_for_delivery   |
    | out_for_delivery   | deliver            | delivered          |
    | out_for_delivery   | fail_delivery      | failed_attempt     |
    | failed_attempt     | return_to_facility | sorting_facility   |
gherkin
Scenario Outline: Task status transitions
  Given a Task with status "<current_status>"
  When the event "<event>" occurs
  Then the Task status should be "<new_status>"

  Examples:
    | current_status     | event              | new_status         |
    | pending            | dispatch           | dispatched         |
    | dispatched         | pickup             | picked_up          |
    | picked_up          | out_for_delivery   | out_for_delivery   |
    | out_for_delivery   | deliver            | delivered          |
    | out_for_delivery   | fail_delivery      | failed_attempt     |
    | failed_attempt     | return_to_facility | sorting_facility   |

Requirements Categories

需求分类

1. Functional Requirements

1. 功能性需求

What the system must do.
User Story:
As an Account Admin
I want to view all tasks ranked by priority and age
So that I can identify delayed deliveries
Gherkin Scenario:
gherkin
Scenario: Tasks sorted by priority then creation date
  Given the following Tasks exist:
    | Reference | Priority | Created At |
    | TASK-001  | high     | 2 days ago |
    | TASK-002  | normal   | 1 day ago  |
    | TASK-003  | high     | 1 day ago  |
  When viewing the task queue
  Then the order should be:
    | Rank | Reference |
    | 1    | TASK-001  |
    | 2    | TASK-003  |
    | 3    | TASK-002  |
系统必须实现的功能。
用户故事:
As an Account Admin
I want to view all tasks ranked by priority and age
So that I can identify delayed deliveries
Gherkin场景:
gherkin
Scenario: Tasks sorted by priority then creation date
  Given the following Tasks exist:
    | Reference | Priority | Created At |
    | TASK-001  | high     | 2 days ago |
    | TASK-002  | normal   | 1 day ago  |
    | TASK-003  | high     | 1 day ago  |
  When viewing the task queue
  Then the order should be:
    | Rank | Reference |
    | 1    | TASK-001  |
    | 2    | TASK-003  |
    | 3    | TASK-002  |

2. Non-Functional Requirements

2. 非功能性需求

How the system should behave.
Categories:
  • Performance (response time, throughput)
  • Security (authentication, authorization)
  • Reliability (uptime, error handling)
  • Scalability (concurrent users, data volume)
  • Maintainability (code quality, documentation)
Format:
The system shall [requirement]
Measured by [metric]
Examples:
The system shall process webhook deliveries within 500ms
Measured by: Average response time for POST /api/v1/tasks

The system shall handle 10,000 concurrent task updates
Measured by: Load testing with simulated peak traffic

The system shall maintain 99.9% uptime
Measured by: Monthly uptime percentage

The system shall process SMS notifications within 5 seconds
Measured by: Time from task status change to SMS delivery
系统的运行方式要求。
分类:
  • 性能(响应时间、吞吐量)
  • 安全性(身份验证、授权)
  • 可靠性(可用性、错误处理)
  • 可扩展性(并发用户数、数据量)
  • 可维护性(代码质量、文档)
格式:
系统应[需求内容]
衡量标准:[指标]
示例:
系统应在500ms内处理webhook交付
衡量标准:POST /api/v1/tasks的平均响应时间

系统应支持10,000个并发任务更新
衡量标准:模拟峰值流量的负载测试

系统应保持99.9%的可用性
衡量标准:月度可用性百分比

系统应在5秒内处理SMS通知
衡量标准:从任务状态变更到SMS送达的时间

3. Business Rules

3. 业务规则

Constraints and policies from the domain.
gherkin
Feature: 3PL Handoff Rules
  Business Rule: Tasks destined for cities without carrier coverage
  must be handed off to integrated 3PL providers after sorting.

  Scenario: Task handed to 3PL when destination city has no coverage
    Given the Account has no Carriers covering "Dammam"
    And the Account has 3PL integration with "SMSA" for "Dammam"
    And a Task exists with destination city "Dammam"
    When the Task arrives at sorting facility
    Then a 3PL label should be generated via "SMSA"
    And the Task should transition to "awaiting_3pl_pickup"
来自业务领域的约束和政策。
gherkin
Feature: 3PL Handoff Rules
  Business Rule: Tasks destined for cities without carrier coverage
  must be handed off to integrated 3PL providers after sorting.

  Scenario: Task handed to 3PL when destination city has no coverage
    Given the Account has no Carriers covering "Dammam"
    And the Account has 3PL integration with "SMSA" for "Dammam"
    And a Task exists with destination city "Dammam"
    When the Task arrives at sorting facility
    Then a 3PL label should be generated via "SMSA"
    And the Task should transition to "awaiting_3pl_pickup"

Requirements Organization

需求组织

Directory Structure

目录结构

requirements/
├── user-stories/
│   ├── merchant-stories.md
│   ├── carrier-stories.md
│   ├── admin-stories.md
│   └── recipient-stories.md
├── features/
│   ├── task-management.feature
│   ├── zone-bundling.feature
│   ├── carrier-dispatch.feature
│   ├── 3pl-integration.feature
│   ├── billing.feature
│   └── notifications.feature
├── business-rules/
│   ├── delivery-rules.md
│   ├── bundling-policies.md
│   └── cod-collection-rules.md
└── non-functional/
    ├── performance-requirements.md
    ├── security-requirements.md
    └── scalability-requirements.md
requirements/
├── user-stories/
│   ├── merchant-stories.md
│   ├── carrier-stories.md
│   ├── admin-stories.md
│   └── recipient-stories.md
├── features/
│   ├── task-management.feature
│   ├── zone-bundling.feature
│   ├── carrier-dispatch.feature
│   ├── 3pl-integration.feature
│   ├── billing.feature
│   └── notifications.feature
├── business-rules/
│   ├── delivery-rules.md
│   ├── bundling-policies.md
│   └── cod-collection-rules.md
└── non-functional/
    ├── performance-requirements.md
    ├── security-requirements.md
    └── scalability-requirements.md

Requirement Quality Checklist

需求质量检查清单

Use the INVEST criteria for user stories:
  • Independent: Can be developed independently
  • Negotiable: Details can be discussed
  • Valuable: Delivers value to users
  • Estimable: Can estimate effort
  • Small: Can be completed in one sprint
  • Testable: Can verify when done
For Gherkin scenarios:
  • Uses Manifest domain language
  • Tests one specific behavior
  • Has clear Given-When-Then structure
  • Includes edge cases and error conditions
  • Is executable (can be automated with Cucumber/RSpec)
使用INVEST标准评估用户故事:
  • 独立(Independent):可独立开发
  • 可协商(Negotiable):细节可讨论
  • 有价值(Valuable):为用户交付价值
  • 可估算(Estimable):可估算工作量
  • 小型(Small):可在一个迭代内完成
  • 可测试(Testable):可验证完成状态
针对Gherkin场景:
  • 使用Manifest领域语言
  • 仅测试一种特定行为
  • 具备清晰的Given-When-Then结构
  • 包含边缘案例和错误场景
  • 可执行(可通过Cucumber/RSpec自动化)

Example Mapping (Discovery Technique)

示例映射(探索技术)

Before writing requirements, use Example Mapping to explore:
Rule: Express deliveries require OTP verification

Examples:
  ✓ Correct OTP submitted → Task delivered
  ✓ Incorrect OTP submitted → Rejected, retry allowed
  ✗ 3 failed OTP attempts → Task marked for callback
  ✗ OTP expired after 10 minutes → New OTP generated

Questions:
  ? What if recipient is unavailable and alternative contact accepts?
  ? Should OTP be required for zero-value (non-COD) deliveries?
  ? How to handle OTP when recipient has no phone?
Then write Gherkin scenarios for each example + questions.
编写需求前,使用示例映射进行探索:
Rule: Express deliveries require OTP verification

Examples:
  ✓ Correct OTP submitted → Task delivered
  ✓ Incorrect OTP submitted → Rejected, retry allowed
  ✗ 3 failed OTP attempts → Task marked for callback
  ✗ OTP expired after 10 minutes → New OTP generated

Questions:
  ? What if recipient is unavailable and alternative contact accepts?
  ? Should OTP be required for zero-value (non-COD) deliveries?
  ? How to handle OTP when recipient has no phone?
然后为每个示例和问题编写Gherkin场景。

Integration with TDD

与TDD的集成

Requirements drive test development:
  1. Write User Story: Define what's needed
  2. Write Gherkin Scenarios: Define acceptance criteria
  3. Generate Step Definitions: Convert scenarios to RSpec/Cucumber
  4. Implement TDD: Red-Green-Refactor cycle
Traceability:
User Story → Gherkin Scenario → Cucumber/RSpec Test → Service Object Implementation
需求驱动测试开发:
  1. 编写用户故事:定义需求内容
  2. 编写Gherkin场景:定义验收标准
  3. 生成步骤定义:将场景转换为RSpec/Cucumber代码
  4. 实施TDD:红-绿-重构循环
可追溯性:
用户故事 → Gherkin场景 → Cucumber/RSpec测试 → 服务对象实现

Manifest Domain Examples

Manifest领域示例

Example 1: Cash on Delivery Collection

示例1:货到付款(COD)收款

User Story:
As an Account Admin
I want COD amounts automatically tracked in Carrier wallets
So that I can reconcile cash collections accurately

Acceptance Criteria:
gherkin
Feature: COD Wallet Tracking
  Cash collected by Carriers is tracked in their Wallet
  and must be reconciled before payout.

  Scenario: COD amount added to Carrier wallet on delivery
    Given a Carrier "Ahmed" has wallet balance 0 SAR
    And a Task with COD amount 150 SAR assigned to "Ahmed"
    When "Ahmed" marks the Task as delivered
    Then "Ahmed" wallet balance should be 150 SAR
    And a wallet transaction "cod_collection" should be recorded

  Scenario: Multiple COD collections accumulate
    Given a Carrier "Ahmed" has wallet balance 200 SAR
    And a Task with COD amount 100 SAR assigned to "Ahmed"
    When "Ahmed" marks the Task as delivered
    Then "Ahmed" wallet balance should be 300 SAR
User Story:
As an Account Admin
I want COD amounts automatically tracked in Carrier wallets
So that I can reconcile cash collections accurately

Acceptance Criteria:
gherkin
Feature: COD Wallet Tracking
  Cash collected by Carriers is tracked in their Wallet
  and must be reconciled before payout.

  Scenario: COD amount added to Carrier wallet on delivery
    Given a Carrier "Ahmed" has wallet balance 0 SAR
    And a Task with COD amount 150 SAR assigned to "Ahmed"
    When "Ahmed" marks the Task as delivered
    Then "Ahmed" wallet balance should be 150 SAR
    And a wallet transaction "cod_collection" should be recorded

  Scenario: Multiple COD collections accumulate
    Given a Carrier "Ahmed" has wallet balance 200 SAR
    And a Task with COD amount 100 SAR assigned to "Ahmed"
    When "Ahmed" marks the Task as delivered
    Then "Ahmed" wallet balance should be 300 SAR

Example 2: SMS Notification Templates

示例2:SMS通知模板

User Story:
As an Account Admin
I want to customize SMS templates with placeholders
So that recipients receive branded, relevant notifications

Acceptance Criteria:
gherkin
Feature: SMS Template Processing

  Scenario: Template placeholders are replaced with task data
    Given an SMS template with body:
      """
      Your order {{task_reference}} is out for delivery. 
      Track: {{tracking_url}}
      """
    And a Task with reference "ORD-12345"
    And tracking URL "https://track.manifest.sa/ORD-12345"
    When sending the delivery notification
    Then the SMS body should be:
      """
      Your order ORD-12345 is out for delivery. 
      Track: https://track.manifest.sa/ORD-12345
      """

  Scenario: Missing placeholder data handled gracefully
    Given an SMS template with body "Contact: {{alternative_phone}}"
    And a Task with no alternative contact
    When sending the notification
    Then the placeholder should be replaced with empty string
    And no error should be raised
User Story:
As an Account Admin
I want to customize SMS templates with placeholders
So that recipients receive branded, relevant notifications

Acceptance Criteria:
gherkin
Feature: SMS Template Processing

  Scenario: Template placeholders are replaced with task data
    Given an SMS template with body:
      """
      Your order {{task_reference}} is out for delivery. 
      Track: {{tracking_url}}
      """
    And a Task with reference "ORD-12345"
    And tracking URL "https://track.manifest.sa/ORD-12345"
    When sending the delivery notification
    Then the SMS body should be:
      """
      Your order ORD-12345 is out for delivery. 
      Track: https://track.manifest.sa/ORD-12345
      """

  Scenario: Missing placeholder data handled gracefully
    Given an SMS template with body "Contact: {{alternative_phone}}"
    And a Task with no alternative contact
    When sending the notification
    Then the placeholder should be replaced with empty string
    And no error should be raised

Example 3: Multi-Tenant Data Isolation

示例3:多租户数据隔离

gherkin
Feature: Account Data Isolation
  All data must be scoped to the owning Account
  to ensure multi-tenant security.

  Scenario: Tasks only visible to owning Account
    Given Account "Acme" has 5 Tasks
    And Account "Beta" has 3 Tasks
    When "Acme" admin queries their Tasks
    Then only 5 Tasks should be returned
    And no Tasks from "Beta" should be visible

  Scenario: Carrier cannot access other Account's Tasks
    Given Carrier "Ahmed" belongs to Account "Acme"
    And a Task belongs to Account "Beta"
    When "Ahmed" attempts to view the Task
    Then access should be denied
    And an authorization error should be logged
gherkin
Feature: Account Data Isolation
  All data must be scoped to the owning Account
  to ensure multi-tenant security.

  Scenario: Tasks only visible to owning Account
    Given Account "Acme" has 5 Tasks
    And Account "Beta" has 3 Tasks
    When "Acme" admin queries their Tasks
    Then only 5 Tasks should be returned
    And no Tasks from "Beta" should be visible

  Scenario: Carrier cannot access other Account's Tasks
    Given Carrier "Ahmed" belongs to Account "Acme"
    And a Task belongs to Account "Beta"
    When "Ahmed" attempts to view the Task
    Then access should be denied
    And an authorization error should be logged

Response Format

响应格式

When writing requirements:
  1. Start with a user story to capture WHO, WHAT, WHY
  2. Add Gherkin scenarios for detailed acceptance criteria
  3. Include happy path, edge cases, and error conditions
  4. Use Manifest domain language consistently
  5. Ensure scenarios are testable and executable
  6. Link requirements to business rules
  7. Consider non-functional requirements
编写需求时:
  1. 从用户故事开始,明确WHO(谁)、WHAT(做什么)、WHY(为什么)
  2. 添加Gherkin场景作为详细验收标准
  3. 包含正常流程、边缘案例和错误场景
  4. 持续使用Manifest领域语言
  5. 确保场景可测试、可执行
  6. 将需求与业务规则关联
  7. 考虑非功能性需求

Tools for Requirements Management

需求管理工具

  • BDD Tools: RSpec, Cucumber (Ruby)
  • Documentation: Markdown, Gherkin
    .feature
    files
  • Collaboration: Example Mapping sessions
  • Traceability: Link stories → scenarios → tests → code
  • BDD工具:RSpec、Cucumber(Ruby)
  • 文档工具:Markdown、Gherkin
    .feature
    文件
  • 协作工具:示例映射研讨会
  • 可追溯性:关联故事 → 场景 → 测试 → 代码