# 示例
# 实际案例
本章提供一些实际案例,帮助您更好地理解 SDD 的应用。
# 案例 1:RESTful API 开发
# 场景
开发一个博客系统的 API,包括:
- 文章列表
- 文章详情
- 创建文章
- 更新文章
- 删除文章
# 规范示例
openapi: 3.0.0
info:
title: Blog API
version: 1.0.0
paths:
/api/v1/posts:
get:
summary: Get posts list
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 10
maximum: 100
responses:
'200':
description: Posts list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Post'
pagination:
type: object
properties:
page:
type: integer
limit:
type: integer
total:
type: integer
post:
summary: Create a new post
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title, content]
properties:
title:
type: string
minLength: 1
maxLength: 200
content:
type: string
minLength: 1
tags:
type: array
items:
type: string
responses:
'201':
description: Post created
content:
application/json:
schema:
$ref: '#/components/schemas/Post'
'400':
description: Validation error
/api/v1/posts/{id}:
get:
summary: Get post by ID
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Post details
content:
application/json:
schema:
$ref: '#/components/schemas/Post'
'404':
description: Post not found
put:
summary: Update post
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
title:
type: string
content:
type: string
responses:
'200':
description: Post updated
'404':
description: Post not found
delete:
summary: Delete post
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'204':
description: Post deleted
'404':
description: Post not found
components:
schemas:
Post:
type: object
properties:
id:
type: integer
title:
type: string
content:
type: string
tags:
type: array
items:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# 实现要点
- 分页处理 - 实现分页逻辑
- 输入验证 - 验证标题和内容
- 错误处理 - 处理 404 等情况
- 数据格式 - 确保响应格式符合规范
# 案例 2:微服务接口定义
# 场景
定义用户服务和订单服务之间的接口:
- 用户服务提供用户信息
- 订单服务需要获取用户信息
# 规范示例
# user-service-api.yaml
openapi: 3.0.0
info:
title: User Service API
version: 1.0.0
servers:
- url: http://user-service:3000
paths:
/api/v1/users/{id}:
get:
summary: Get user by ID
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: User information
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not found
/api/v1/users/batch:
post:
summary: Get multiple users
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
ids:
type: array
items:
type: integer
responses:
'200':
description: Users list
content:
application/json:
schema:
type: object
properties:
users:
type: array
items:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id:
type: integer
email:
type: string
name:
type: string
status:
type: string
enum: [active, inactive, suspended]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 契约测试
// order-service 的契约测试
const { Pact } = require('@pact-foundation/pact');
const provider = new Pact({
consumer: 'Order Service',
provider: 'User Service',
port: 1234
});
describe('User Service Contract', () => {
beforeAll(() => provider.setup());
afterAll(() => provider.finalize());
it('should get user by ID', async () => {
await provider.addInteraction({
state: 'user exists',
uponReceiving: 'a request for user by ID',
withRequest: {
method: 'GET',
path: '/api/v1/users/1'
},
willRespondWith: {
status: 200,
body: {
id: 1,
email: 'user@example.com',
name: 'John Doe',
status: 'active'
}
}
});
// 测试订单服务调用用户服务
const response = await orderService.getUserInfo(1);
expect(response.email).toBe('user@example.com');
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 案例 3:前后端协作
# 场景
前端和后端协作开发用户管理功能:
- 用户列表
- 用户详情
- 创建用户
- 更新用户
# 工作流程
# 1. 后端编写规范
# api-spec.yaml
openapi: 3.0.0
info:
title: User Management API
version: 1.0.0
paths:
/api/v1/users:
get:
summary: Get users list
# ...
post:
summary: Create user
# ...
/api/v1/users/{id}:
get:
summary: Get user by ID
# ...
put:
summary: Update user
# ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2. 生成 Mock 服务
# 使用 Prism 生成 Mock
npx @stoplight/prism-cli mock api-spec.yaml
1
2
2
# 3. 前端基于 Mock 开发
// frontend/src/services/userService.js
const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:4010';
export const userService = {
async getUsers() {
const response = await fetch(`${API_BASE}/api/v1/users`);
return response.json();
},
async getUser(id) {
const response = await fetch(`${API_BASE}/api/v1/users/${id}`);
return response.json();
},
async createUser(userData) {
const response = await fetch(`${API_BASE}/api/v1/users`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
return response.json();
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 4. 后端实现 API
// backend/routes/users.js
router.get('/api/v1/users', async (req, res) => {
const users = await userService.getUsers();
res.json(users);
});
router.post('/api/v1/users', async (req, res) => {
const user = await userService.createUser(req.body);
res.status(201).json(user);
});
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 5. 集成测试
// 前端切换到真实 API
const API_BASE = 'http://localhost:3000';
// 运行集成测试
npm run test:integration
1
2
3
4
5
2
3
4
5
# 案例 4:GraphQL API
# 场景
使用 GraphQL 开发 API,也需要定义规范。
# 规范示例
# schema.graphql
type User {
id: ID!
email: String!
name: String
posts: [Post!]!
createdAt: DateTime!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
createdAt: DateTime!
}
type Query {
user(id: ID!): User
users(limit: Int = 10, offset: Int = 0): [User!]!
post(id: ID!): Post
posts(limit: Int = 10, offset: Int = 0): [Post!]!
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
createPost(input: CreatePostInput!): Post!
}
input CreateUserInput {
email: String!
password: String!
name: String
}
input UpdateUserInput {
email: String
name: String
}
input CreatePostInput {
title: String!
content: String!
authorId: ID!
}
scalar DateTime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 实现
// resolvers.js
const resolvers = {
Query: {
user: async (parent, { id }) => {
return await userService.getUserById(id);
},
users: async (parent, { limit, offset }) => {
return await userService.getUsers({ limit, offset });
}
},
Mutation: {
createUser: async (parent, { input }) => {
return await userService.createUser(input);
}
},
User: {
posts: async (parent) => {
return await postService.getPostsByAuthorId(parent.id);
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 总结
这些案例展示了 SDD 在不同场景下的应用:
- RESTful API - 使用 OpenAPI 规范
- 微服务 - 服务间接口定义和契约测试
- 前后端协作 - 基于 Mock 的并行开发
- GraphQL - GraphQL Schema 作为规范
无论使用什么技术栈,SDD 的核心思想都是:先定义规范,再实现功能。
继续阅读工具了解相关工具和资源。