ethan-skill 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +83 -24
  2. package/dist/skills/15-git-workflow.d.ts +3 -0
  3. package/dist/skills/15-git-workflow.d.ts.map +1 -0
  4. package/dist/skills/15-git-workflow.js +288 -0
  5. package/dist/skills/15-git-workflow.js.map +1 -0
  6. package/dist/skills/16-unit-testing.d.ts +3 -0
  7. package/dist/skills/16-unit-testing.d.ts.map +1 -0
  8. package/dist/skills/16-unit-testing.js +298 -0
  9. package/dist/skills/16-unit-testing.js.map +1 -0
  10. package/dist/skills/17-system-design.d.ts +3 -0
  11. package/dist/skills/17-system-design.d.ts.map +1 -0
  12. package/dist/skills/17-system-design.js +294 -0
  13. package/dist/skills/17-system-design.js.map +1 -0
  14. package/dist/skills/18-database-optimize.d.ts +3 -0
  15. package/dist/skills/18-database-optimize.d.ts.map +1 -0
  16. package/dist/skills/18-database-optimize.js +294 -0
  17. package/dist/skills/18-database-optimize.js.map +1 -0
  18. package/dist/skills/19-docker.d.ts +3 -0
  19. package/dist/skills/19-docker.d.ts.map +1 -0
  20. package/dist/skills/19-docker.js +360 -0
  21. package/dist/skills/19-docker.js.map +1 -0
  22. package/dist/skills/20-cicd.d.ts +3 -0
  23. package/dist/skills/20-cicd.d.ts.map +1 -0
  24. package/dist/skills/20-cicd.js +364 -0
  25. package/dist/skills/20-cicd.js.map +1 -0
  26. package/dist/skills/21-performance.d.ts +3 -0
  27. package/dist/skills/21-performance.d.ts.map +1 -0
  28. package/dist/skills/21-performance.js +139 -0
  29. package/dist/skills/21-performance.js.map +1 -0
  30. package/dist/skills/22-refactoring.d.ts +3 -0
  31. package/dist/skills/22-refactoring.d.ts.map +1 -0
  32. package/dist/skills/22-refactoring.js +235 -0
  33. package/dist/skills/22-refactoring.js.map +1 -0
  34. package/dist/skills/23-observability.d.ts +3 -0
  35. package/dist/skills/23-observability.d.ts.map +1 -0
  36. package/dist/skills/23-observability.js +266 -0
  37. package/dist/skills/23-observability.js.map +1 -0
  38. package/dist/skills/24-design-patterns.d.ts +3 -0
  39. package/dist/skills/24-design-patterns.d.ts.map +1 -0
  40. package/dist/skills/24-design-patterns.js +258 -0
  41. package/dist/skills/24-design-patterns.js.map +1 -0
  42. package/dist/skills/index.d.ts +10 -0
  43. package/dist/skills/index.d.ts.map +1 -1
  44. package/dist/skills/index.js +41 -1
  45. package/dist/skills/index.js.map +1 -1
  46. package/dist/skills/skills.test.js +3 -3
  47. package/dist/skills/skills.test.js.map +1 -1
  48. package/dist/templates/templates.test.js +2 -3
  49. package/dist/templates/templates.test.js.map +1 -1
  50. package/package.json +1 -1
  51. package/rules/claude-code/CLAUDE.md +2410 -3
  52. package/rules/cline/.clinerules +2262 -2
  53. package/rules/codebuddy/CODEBUDDY.md +2361 -2
  54. package/rules/continue/.continuerules +2262 -2
  55. package/rules/copilot/copilot-instructions.md +2331 -2
  56. package/rules/cursor/.cursorrules +2399 -2
  57. package/rules/cursor/smart-flow.mdc +2399 -2
  58. package/rules/jetbrains/smart-flow.md +2331 -2
  59. package/rules/lingma/smart-flow.md +2352 -3
  60. package/rules/windsurf/.windsurf/rules/smart-flow.md +2332 -3
  61. package/rules/zed/smart-flow.rules +2251 -1
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unitTestingSkill = void 0;
4
+ exports.unitTestingSkill = {
5
+ id: 'unit-testing',
6
+ name: '单元测试',
7
+ nameEn: 'unit_testing',
8
+ order: 16,
9
+ category: '质量侧',
10
+ description: '运用 AAA 模式和 TDD 工作流编写高质量单元测试,建立覆盖率目标和 Mock 策略',
11
+ descriptionEn: 'Write high-quality unit tests using AAA pattern, TDD workflow, mocking strategies, and coverage goals',
12
+ detailDescription: `系统指导单元测试的设计与实现,涵盖 AAA(Arrange-Act-Assert)模式、TDD 红绿重构循环、
13
+ Mock/Stub/Spy 策略选择、覆盖率目标制定和测试命名规范,帮助团队建立可维护、有效的测试体系。`,
14
+ triggers: [
15
+ '单元测试',
16
+ 'unit test',
17
+ '写测试',
18
+ 'write tests',
19
+ 'TDD',
20
+ '测试设计',
21
+ 'test design',
22
+ 'mock 策略',
23
+ 'mocking',
24
+ '测试覆盖率',
25
+ 'coverage',
26
+ '@ethan test',
27
+ '@ethan unit-testing',
28
+ ],
29
+ steps: [
30
+ {
31
+ title: '1. 明确测试目标与范围',
32
+ content: `在编写测试前,先明确测什么:
33
+
34
+ **测试金字塔**
35
+ \`\`\`
36
+ ┌───────────┐
37
+ │ E2E 测试 │ (少量,慢,高置信)
38
+ ┌┴───────────┴┐
39
+ │ 集成测试 │ (适量,中速)
40
+ ┌┴─────────────┴┐
41
+ │ 单元测试 │ (大量,快,低成本)
42
+ └───────────────┘
43
+ \`\`\`
44
+
45
+ **单元测试应该覆盖**
46
+ - ✅ 纯函数的各种输入输出(含边界)
47
+ - ✅ 类/模块的公共方法逻辑
48
+ - ✅ 条件分支(if/switch/三元)
49
+ - ✅ 错误处理路径(throw/catch)
50
+ - ✅ 异步操作(Promise/async-await)
51
+
52
+ **不应该单元测试**
53
+ - ❌ 简单的 getter/setter(无逻辑)
54
+ - ❌ 第三方库内部实现
55
+ - ❌ 框架本身(如 React 渲染机制)
56
+ - ❌ 私有方法(通过公共方法间接测试)`,
57
+ },
58
+ {
59
+ title: '2. AAA 模式编写测试用例',
60
+ content: `每个测试用例遵循 **Arrange → Act → Assert** 三段式结构:
61
+
62
+ **基础示例(JavaScript/TypeScript with Vitest/Jest)**
63
+ \`\`\`typescript
64
+ describe('calculateDiscount', () => {
65
+ it('should apply 20% discount for premium users', () => {
66
+ // Arrange(准备:设置测试数据和依赖)
67
+ const user = { type: 'premium', cart: [{ price: 100 }, { price: 50 }] };
68
+ const expectedTotal = 120; // 150 * 0.8
69
+
70
+ // Act(执行:调用被测函数)
71
+ const result = calculateDiscount(user);
72
+
73
+ // Assert(断言:验证结果)
74
+ expect(result.total).toBe(expectedTotal);
75
+ expect(result.discountRate).toBe(0.2);
76
+ });
77
+ });
78
+ \`\`\`
79
+
80
+ **测试命名规范(Given-When-Then)**
81
+ \`\`\`typescript
82
+ // 格式: should <expected behavior> when <condition>
83
+ it('should return null when user is not found')
84
+ it('should throw AuthError when token is expired')
85
+ it('should apply 20% discount when user has premium status')
86
+
87
+ // 或使用 Given-When-Then 风格
88
+ it('given empty cart, when checkout, then throws EmptyCartError')
89
+ \`\`\`
90
+
91
+ **边界条件测试清单**
92
+ \`\`\`typescript
93
+ describe('parseAge', () => {
94
+ // 正常值
95
+ it('should parse valid age 25')
96
+ // 边界值
97
+ it('should accept minimum age 0')
98
+ it('should accept maximum age 150')
99
+ // 非法值
100
+ it('should throw when age is negative')
101
+ it('should throw when age exceeds 150')
102
+ // 类型边界
103
+ it('should throw when age is not a number')
104
+ it('should throw when age is null or undefined')
105
+ it('should handle decimal by flooring to integer')
106
+ });
107
+ \`\`\``,
108
+ },
109
+ {
110
+ title: '3. TDD 工作流(红-绿-重构)',
111
+ content: `**TDD 循环步骤**
112
+
113
+ \`\`\`
114
+ 🔴 Red → 写一个失败的测试(先设计接口)
115
+ 🟢 Green → 写最少代码让测试通过(不过度设计)
116
+ 🔵 Refactor → 在测试保护下重构代码
117
+ \`\`\`
118
+
119
+ **实践示例:用 TDD 实现邮箱验证**
120
+
121
+ \`\`\`typescript
122
+ // Step 1 🔴 先写测试(此时 validateEmail 还不存在)
123
+ describe('validateEmail', () => {
124
+ it('should return true for valid email', () => {
125
+ expect(validateEmail('user@example.com')).toBe(true);
126
+ });
127
+ it('should return false for missing @', () => {
128
+ expect(validateEmail('userexample.com')).toBe(false);
129
+ });
130
+ it('should return false for empty string', () => {
131
+ expect(validateEmail('')).toBe(false);
132
+ });
133
+ });
134
+
135
+ // Step 2 🟢 写最简实现让测试通过
136
+ export function validateEmail(email: string): boolean {
137
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
138
+ }
139
+
140
+ // Step 3 🔵 重构:提取正则为常量,添加类型注释
141
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
142
+ export function validateEmail(email: string): boolean {
143
+ if (!email) return false;
144
+ return EMAIL_REGEX.test(email);
145
+ }
146
+ \`\`\`
147
+
148
+ **TDD 适用场景**
149
+ - 明确需求的业务逻辑函数
150
+ - 工具库/SDK 开发
151
+ - Bug 修复(先写复现测试再修复)
152
+
153
+ **不强制 TDD 的场景**
154
+ - 探索性开发阶段
155
+ - UI 组件(先实现再补测试)`,
156
+ },
157
+ {
158
+ title: '4. Mock / Stub / Spy 策略',
159
+ content: `**三种测试替身的区别**
160
+
161
+ | 类型 | 用途 | 验证方式 |
162
+ |------|------|---------|
163
+ | **Stub** | 替换外部依赖,控制返回值 | 只验证输出 |
164
+ | **Mock** | 验证函数是否被正确调用 | 验证调用行为 |
165
+ | **Spy** | 监听真实函数的调用情况 | 包装真实实现 |
166
+
167
+ **Vitest/Jest 实践**
168
+ \`\`\`typescript
169
+ import { vi, describe, it, expect, beforeEach } from 'vitest';
170
+
171
+ // Stub: 控制外部 API 返回值
172
+ vi.mock('../api/user', () => ({
173
+ fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Alice' }),
174
+ }));
175
+
176
+ // Mock: 验证函数被调用
177
+ it('should call sendEmail when user registers', async () => {
178
+ const sendEmail = vi.fn();
179
+ await registerUser({ email: 'test@test.com' }, { sendEmail });
180
+ expect(sendEmail).toHaveBeenCalledOnce();
181
+ expect(sendEmail).toHaveBeenCalledWith('test@test.com', expect.objectContaining({ subject: 'Welcome' }));
182
+ });
183
+
184
+ // Spy: 包装真实函数监听
185
+ it('should log error when fetch fails', async () => {
186
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
187
+ vi.mocked(fetchUser).mockRejectedValue(new Error('Network Error'));
188
+ await loadUserProfile(1);
189
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Network Error'));
190
+ consoleSpy.mockRestore();
191
+ });
192
+ \`\`\`
193
+
194
+ **Mock 黄金法则**
195
+ - 只 Mock 跨边界的依赖(网络、数据库、文件系统、时间)
196
+ - 不要 Mock 被测单元的内部实现
197
+ - 每次测试后还原 Mock(使用 \`beforeEach(() => vi.clearAllMocks())\`)`,
198
+ },
199
+ {
200
+ title: '5. 覆盖率目标与质量保障',
201
+ content: `**覆盖率类型与目标**
202
+
203
+ | 覆盖率类型 | 说明 | 建议目标 |
204
+ |----------|------|---------|
205
+ | 语句覆盖(Statements) | 执行的语句比例 | ≥ 80% |
206
+ | 分支覆盖(Branches) | if/else 分支比例 | ≥ 75% |
207
+ | 函数覆盖(Functions) | 调用的函数比例 | ≥ 80% |
208
+ | 行覆盖(Lines) | 执行的代码行比例 | ≥ 80% |
209
+
210
+ **Vitest 覆盖率配置**
211
+ \`\`\`typescript
212
+ // vitest.config.ts
213
+ export default defineConfig({
214
+ test: {
215
+ coverage: {
216
+ provider: 'v8', // 或 'istanbul'
217
+ reporter: ['text', 'html', 'lcov'],
218
+ thresholds: {
219
+ statements: 80,
220
+ branches: 75,
221
+ functions: 80,
222
+ lines: 80,
223
+ },
224
+ exclude: [
225
+ 'node_modules/',
226
+ 'src/types/',
227
+ '**/*.config.*',
228
+ '**/*.d.ts',
229
+ ],
230
+ },
231
+ },
232
+ });
233
+ \`\`\`
234
+
235
+ **覆盖率反模式(要避免)**
236
+ \`\`\`typescript
237
+ // ❌ 为了覆盖率写无意义断言
238
+ it('does something', () => {
239
+ expect(doSomething()).toBeDefined(); // 没有验证具体行为
240
+ });
241
+
242
+ // ✅ 验证真实业务逻辑
243
+ it('should return correct discounted price', () => {
244
+ expect(calculatePrice(100, 0.1)).toBe(90);
245
+ });
246
+ \`\`\`
247
+
248
+ **CI 集成**
249
+ \`\`\`yaml
250
+ # .github/workflows/test.yml
251
+ - name: Run tests with coverage
252
+ run: npm run test -- --coverage
253
+
254
+ - name: Comment coverage on PR
255
+ uses: MishaKav/jest-coverage-comment@main
256
+ with:
257
+ coverage-summary-path: ./coverage/coverage-summary.json
258
+ \`\`\``,
259
+ },
260
+ ],
261
+ outputFormat: 'Markdown 测试方案文档,含测试用例设计(AAA 格式)、Mock 策略说明、覆盖率目标和 CI 配置示例',
262
+ examples: [
263
+ {
264
+ input: '帮我为这个 calculateTax 函数写单元测试',
265
+ output: `## 单元测试方案:calculateTax
266
+
267
+ \`\`\`typescript
268
+ describe('calculateTax', () => {
269
+ describe('standard rate (20%)', () => {
270
+ it('should apply 20% tax to positive amount', () => {
271
+ expect(calculateTax(100, 'standard')).toBe(20);
272
+ });
273
+ it('should return 0 tax for zero amount', () => {
274
+ expect(calculateTax(0, 'standard')).toBe(0);
275
+ });
276
+ });
277
+
278
+ describe('error cases', () => {
279
+ it('should throw when amount is negative', () => {
280
+ expect(() => calculateTax(-1, 'standard')).toThrow('Amount must be positive');
281
+ });
282
+ it('should throw for unknown tax category', () => {
283
+ expect(() => calculateTax(100, 'unknown' as any)).toThrow('Unknown tax category');
284
+ });
285
+ });
286
+ });
287
+ \`\`\``,
288
+ },
289
+ ],
290
+ notes: [
291
+ '测试应该是自文档化的,好的测试名称比注释更有价值',
292
+ '避免测试实现细节,测试行为而非内部结构,有助于重构时测试不频繁失败',
293
+ '不要追求 100% 覆盖率,关注核心业务逻辑的质量覆盖',
294
+ '测试代码同样需要维护,避免过度复杂的测试辅助函数',
295
+ ],
296
+ nextSkill: 'system-design',
297
+ };
298
+ //# sourceMappingURL=16-unit-testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"16-unit-testing.js","sourceRoot":"","sources":["../../src/skills/16-unit-testing.ts"],"names":[],"mappings":";;;AAEa,QAAA,gBAAgB,GAAoB;IAC/C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,cAAc;IACtB,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,8CAA8C;IAC3D,aAAa,EAAE,uGAAuG;IACtH,iBAAiB,EAAE;qDACgC;IACnD,QAAQ,EAAE;QACR,MAAM;QACN,WAAW;QACX,KAAK;QACL,aAAa;QACb,KAAK;QACL,MAAM;QACN,aAAa;QACb,SAAS;QACT,SAAS;QACT,OAAO;QACP,UAAU;QACV,aAAa;QACb,qBAAqB;KACtB;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;qBAwBM;SAChB;QACD;YACE,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+CR;SACF;QACD;YACE,KAAK,EAAE,oBAAoB;YAC3B,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4CE;SACZ;QACD;YACE,KAAK,EAAE,yBAAyB;YAChC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4DAsC6C;SACvD;QACD;YACE,KAAK,EAAE,eAAe;YACtB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyDR;SACF;KACF;IACD,YAAY,EACV,0DAA0D;IAC5D,QAAQ,EAAE;QACR;YACE,KAAK,EAAE,4BAA4B;YACnC,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;OAsBP;SACF;KACF;IACD,KAAK,EAAE;QACL,0BAA0B;QAC1B,mCAAmC;QACnC,6BAA6B;QAC7B,0BAA0B;KAC3B;IACD,SAAS,EAAE,eAAe;CAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SkillDefinition } from './types';
2
+ export declare const systemDesignSkill: SkillDefinition;
3
+ //# sourceMappingURL=17-system-design.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"17-system-design.d.ts","sourceRoot":"","sources":["../../src/skills/17-system-design.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,iBAAiB,EAAE,eAkS/B,CAAC"}
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.systemDesignSkill = void 0;
4
+ exports.systemDesignSkill = {
5
+ id: 'system-design',
6
+ name: '系统设计',
7
+ nameEn: 'system_design',
8
+ order: 17,
9
+ category: '执行侧',
10
+ description: '从需求澄清到架构设计全流程,完成高并发分布式系统的方案设计与权衡分析',
11
+ descriptionEn: 'Full system design process from requirement clarification to architecture with scalability and availability tradeoffs',
12
+ detailDescription: `系统性指导大型系统设计流程,涵盖需求澄清与非功能指标量化、容量估算、高层架构选型、
13
+ 核心组件设计、数据库模型与扩展性分析,帮助在面试或实际项目中输出结构清晰、考量全面的系统设计方案。`,
14
+ triggers: [
15
+ '系统设计',
16
+ 'system design',
17
+ '架构设计',
18
+ 'architecture design',
19
+ '高并发系统',
20
+ '分布式系统',
21
+ 'distributed system',
22
+ '容量估算',
23
+ 'capacity estimation',
24
+ '扩展性设计',
25
+ 'scalability',
26
+ '@ethan design',
27
+ '@ethan system-design',
28
+ ],
29
+ steps: [
30
+ {
31
+ title: '1. 需求澄清与范围界定',
32
+ content: `在动手设计前,花 5 分钟澄清需求:
33
+
34
+ **功能需求(Functional Requirements)**
35
+ - 系统的核心用例是什么?(写出 3-5 个最关键的)
36
+ - 哪些功能在 scope 内,哪些明确 out of scope?
37
+ - 用户角色有哪些?各自的主要操作是什么?
38
+
39
+ **非功能需求(Non-Functional Requirements)**
40
+
41
+ | 维度 | 问题 | 示例指标 |
42
+ |------|------|---------|
43
+ | 规模 | 用户量 / DAU / QPS 是多少? | 1亿用户,1000万 DAU |
44
+ | 性能 | 读写延迟要求?P99 是多少? | P99 < 100ms |
45
+ | 可用性 | 允许多少停机时间? | 99.9%(每年 8.7h) |
46
+ | 一致性 | 强一致 or 最终一致? | 最终一致(可接受) |
47
+ | 持久性 | 数据丢失容忍度? | RPO = 0(不允许丢失) |
48
+
49
+ **明确边界的示例问题**
50
+ \`\`\`
51
+ Q: 设计一个 Twitter
52
+ A(先澄清):
53
+ - 只需要发推/关注/Feed 功能吗?(排除私信、广告)
54
+ - 用户规模:3亿用户,1亿 DAU?
55
+ - 读写比例:推文读多写少,100:1?
56
+ - 媒体文件:支持图片/视频吗?
57
+ - 全球分发还是单地区?
58
+ \`\`\``,
59
+ },
60
+ {
61
+ title: '2. 容量估算(Back-of-Envelope)',
62
+ content: `快速估算系统规模,为架构决策提供数据依据:
63
+
64
+ **常用基准数字**
65
+ \`\`\`
66
+ 内存访问: ~100ns
67
+ SSD 访问: ~100μs
68
+ HDD 访问: ~10ms
69
+ 网络往返(同数据中心):~0.5ms
70
+ 网络往返(跨地区): ~100ms
71
+
72
+ 1 MB = 10^6 bytes
73
+ 1 GB = 10^9 bytes
74
+ 1 TB = 10^12 bytes
75
+ \`\`\`
76
+
77
+ **估算示例:设计微博(Twitter-like)**
78
+ \`\`\`
79
+ 用户数据:
80
+ - DAU: 1亿
81
+ - 每用户每天发1条推文 → 写 QPS = 100M / 86400 ≈ 1160 QPS
82
+ - 每用户每天读100条 → 读 QPS = 100 × 1160 = 116,000 QPS
83
+
84
+ 存储估算:
85
+ - 单条推文: 140字 × 2字节(UTF-16) = 280字节 ≈ 300字节
86
+ - 元数据(user_id, timestamp等): 100字节
87
+ - 每条推文总计: ~400字节
88
+ - 每日新增: 1.16K QPS × 400字节 × 86400 = ~40 GB/天
89
+ - 5年存储: 40GB × 365 × 5 ≈ 73 TB
90
+
91
+ 带宽估算:
92
+ - 写带宽: 1160 × 400字节 = ~450 KB/s
93
+ - 读带宽: 116K × 400字节 = ~45 MB/s
94
+ \`\`\`
95
+
96
+ **结论:** 读多写少(100:1),需要读缓存;存储量大需分库分表;单机无法支撑读 QPS 需多副本。`,
97
+ },
98
+ {
99
+ title: '3. 高层架构设计',
100
+ content: `从整体入手,画出系统的核心模块和数据流:
101
+
102
+ **通用分层架构**
103
+ \`\`\`
104
+ 客户端 (Web/Mobile/API Consumer)
105
+
106
+
107
+ DNS + CDN (静态资源 / 地理路由)
108
+
109
+
110
+ Load Balancer (L4/L7, 负载均衡 + SSL 终止)
111
+ ┌────┴────┐
112
+ ▼ ▼
113
+ API Srv API Srv (无状态,水平扩展)
114
+
115
+ ├──→ Cache (Redis: 热数据)
116
+ ├──→ Message Queue (Kafka: 异步解耦)
117
+ ├──→ Primary DB (写操作)
118
+ └──→ Read Replica (读操作)
119
+
120
+
121
+ Object Storage (S3: 文件/媒体)
122
+ Search Engine (Elasticsearch)
123
+ \`\`\`
124
+
125
+ **架构选型决策点**
126
+
127
+ | 场景 | 选型建议 |
128
+ |------|---------|
129
+ | 读多写少 | 读写分离 + 缓存层 |
130
+ | 高写入吞吐 | 异步消息队列削峰 |
131
+ | 数据量超百亿行 | 分库分表 / NoSQL |
132
+ | 强一致性 | 单主 / Paxos / Raft |
133
+ | 最终一致性 | 多主 / CRDT |
134
+ | 低延迟全球访问 | CDN + 多地域部署 |
135
+ | 复杂查询 | 专用搜索引擎 |
136
+
137
+ **微服务 vs 单体 决策**
138
+ - 团队 < 10人,初创期:单体优先(避免过度工程)
139
+ - 明确的服务边界、独立扩展需求:拆分微服务
140
+ - 拆分原则:按业务边界(DDD 限界上下文),而非技术层`,
141
+ },
142
+ {
143
+ title: '4. 核心组件深度设计',
144
+ content: `针对最关键的 2-3 个组件进行深入设计:
145
+
146
+ **数据库 Schema 设计**
147
+ \`\`\`sql
148
+ -- 示例:推文表设计
149
+ CREATE TABLE tweets (
150
+ id BIGINT PRIMARY KEY, -- Snowflake ID(分布式唯一ID)
151
+ user_id BIGINT NOT NULL,
152
+ content VARCHAR(280) NOT NULL,
153
+ created_at TIMESTAMP DEFAULT NOW(),
154
+ like_count INT DEFAULT 0,
155
+ retweet_count INT DEFAULT 0,
156
+ INDEX idx_user_created (user_id, created_at DESC) -- 用户时间线查询
157
+ );
158
+
159
+ -- Fan-out 策略:预写 vs 拉取
160
+ -- 方案A: Push(写扩散): 发推时写入所有粉丝的 Feed 表
161
+ -- 方案B: Pull(读扩散): 读取时聚合关注者的推文
162
+ -- 混合方案: 普通用户 Push,大V(粉丝>100万)Pull
163
+ \`\`\`
164
+
165
+ **缓存策略**
166
+ \`\`\`
167
+ Cache-Aside(旁路缓存)- 最通用
168
+ 读: 查缓存 → miss → 查DB → 写缓存 → 返回
169
+ 写: 更新DB → 删除缓存(避免双写不一致)
170
+
171
+ Write-Through(写穿)- 一致性高
172
+ 写: 同时写DB和缓存
173
+
174
+ Write-Behind(写回)- 高性能
175
+ 写: 先写缓存,异步批量写DB(风险:缓存宕机丢数据)
176
+
177
+ 缓存 Key 设计示例:
178
+ user:{userId}:profile → 用户资料
179
+ user:{userId}:feed:page:{n} → 用户 Feed 分页
180
+ tweet:{tweetId} → 单条推文
181
+ \`\`\`
182
+
183
+ **API 接口设计**
184
+ \`\`\`
185
+ POST /tweets 发布推文
186
+ GET /users/{id}/feed 获取 Feed (cursor分页)
187
+ POST /tweets/{id}/like 点赞
188
+ GET /tweets/{id} 获取单条推文
189
+
190
+ 分页策略: cursor-based > offset-based(大数据量场景)
191
+ cursor: base64(created_at + tweet_id)
192
+ \`\`\``,
193
+ },
194
+ {
195
+ title: '5. 可扩展性与可用性权衡',
196
+ content: `**CAP 定理实践**
197
+ \`\`\`
198
+ C(一致性)+ A(可用性)+ P(分区容错)三选二
199
+ 网络分区不可避免 → 通常是 CP 或 AP 的选择
200
+
201
+ CP 系统: ZooKeeper, HBase(金融交易、库存扣减)
202
+ AP 系统: Cassandra, DynamoDB(社交Feed、购物车)
203
+ \`\`\`
204
+
205
+ **水平扩展策略**
206
+
207
+ | 层次 | 策略 |
208
+ |------|------|
209
+ | 无状态应用层 | 直接水平扩展 + 负载均衡 |
210
+ | 有状态缓存 | 一致性哈希分片(Redis Cluster) |
211
+ | 数据库水平 | 分库分表(按 user_id % N) |
212
+ | 数据库垂直 | 主从复制,读写分离 |
213
+
214
+ **单点故障(SPOF)消除清单**
215
+ - [ ] Load Balancer 双活/主备
216
+ - [ ] 数据库主从 + 自动故障转移(MHA/Orchestrator)
217
+ - [ ] 缓存集群(Redis Sentinel / Cluster)
218
+ - [ ] 消息队列多副本(Kafka Replication Factor ≥ 3)
219
+ - [ ] 跨可用区部署(Multi-AZ)
220
+
221
+ **限流与熔断**
222
+ \`\`\`
223
+ 限流: Token Bucket(突发流量友好)
224
+ Sliding Window(精准限流)
225
+ 分级限流: 用户级 → 接口级 → 全局
226
+
227
+ 熔断: Closed → Open(失败率>50%)→ Half-Open(探测恢复)
228
+ 工具: Resilience4j(Java)/ hystrix-go / Polly(.NET)
229
+ \`\`\``,
230
+ },
231
+ {
232
+ title: '6. 输出系统设计文档',
233
+ content: `整理为结构化设计文档:
234
+
235
+ \`\`\`markdown
236
+ ## 系统设计方案:[系统名称]
237
+
238
+ ### 1. 需求概述
239
+ **功能需求**(核心功能列表)
240
+ **非功能需求**(QPS / 延迟 / 可用性 / 存储)
241
+
242
+ ### 2. 容量估算
243
+ | 指标 | 估算值 |
244
+ |------|-------|
245
+ | DAU | X 万 |
246
+ | 写 QPS | X |
247
+ | 读 QPS | X |
248
+ | 存储(5年) | X TB |
249
+
250
+ ### 3. 系统架构图
251
+ [ASCII 图或 Mermaid 图]
252
+
253
+ ### 4. 核心组件设计
254
+ - **数据库 Schema**:[关键表设计]
255
+ - **缓存策略**:[策略选择与理由]
256
+ - **API 设计**:[关键接口]
257
+
258
+ ### 5. 扩展性方案
259
+ - **瓶颈点**:[识别的瓶颈]
260
+ - **解决方案**:[具体方案]
261
+
262
+ ### 6. 权衡与风险
263
+ [已知权衡和设计风险]
264
+ \`\`\``,
265
+ },
266
+ ],
267
+ outputFormat: 'Markdown 系统设计文档,含需求澄清结果、容量估算数据、架构图、核心组件设计方案和扩展性权衡分析',
268
+ examples: [
269
+ {
270
+ input: '设计一个短链接服务(如 bit.ly)',
271
+ output: `## 短链接服务设计
272
+
273
+ **规模**:每天 1 亿次创建,10 亿次访问(10:1 读写比)
274
+ **写 QPS**:~1160,**读 QPS**:~11600,存储5年:~40TB
275
+
276
+ **核心架构**:Web → LB → API Server → Redis(热门短链缓存)→ Cassandra(主存储)
277
+
278
+ **短链生成**:Base62 编码 7位(62^7 ≈ 3500亿,够用)
279
+ - 方案A: 预生成随机串存DB(无冲突)
280
+ - 方案B: ID自增 → Base62编码(简单高效,推荐)
281
+
282
+ **重定向**:301(永久,浏览器缓存,减少服务压力)vs 302(临时,可统计点击)
283
+ **数据库**:Cassandra(key-value 访问模式完美匹配,易扩展)`,
284
+ },
285
+ ],
286
+ notes: [
287
+ '系统设计没有标准答案,重点展示思考过程和权衡意识',
288
+ '先画出高层架构,再逐步深入细节,避免一开始陷入细节',
289
+ '主动提出设计中的权衡和不足,展示对复杂度的认知',
290
+ '数量级估算误差在 10x 以内即可,重要的是数量级概念',
291
+ ],
292
+ nextSkill: 'database-optimize',
293
+ };
294
+ //# sourceMappingURL=17-system-design.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"17-system-design.js","sourceRoot":"","sources":["../../src/skills/17-system-design.ts"],"names":[],"mappings":";;;AAEa,QAAA,iBAAiB,GAAoB;IAChD,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,oCAAoC;IACjD,aAAa,EAAE,uHAAuH;IACtI,iBAAiB,EAAE;kDAC6B;IAChD,QAAQ,EAAE;QACR,MAAM;QACN,eAAe;QACf,MAAM;QACN,qBAAqB;QACrB,OAAO;QACP,OAAO;QACP,oBAAoB;QACpB,MAAM;QACN,qBAAqB;QACrB,OAAO;QACP,aAAa;QACb,eAAe;QACf,sBAAsB;KACvB;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BR;SACF;QACD;YACE,KAAK,EAAE,2BAA2B;YAClC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAkCuC;SACjD;QACD;YACE,KAAK,EAAE,WAAW;YAClB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAwCe;SACzB;QACD;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDR;SACF;QACD;YACE,KAAK,EAAE,eAAe;YACtB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCR;SACF;QACD;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BR;SACF;KACF;IACD,YAAY,EACV,qDAAqD;IACvD,QAAQ,EAAE;QACR;YACE,KAAK,EAAE,qBAAqB;YAC5B,MAAM,EAAE;;;;;;;;;;;;0CAY4B;SACrC;KACF;IACD,KAAK,EAAE;QACL,0BAA0B;QAC1B,2BAA2B;QAC3B,yBAAyB;QACzB,6BAA6B;KAC9B;IACD,SAAS,EAAE,mBAAmB;CAC/B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SkillDefinition } from './types';
2
+ export declare const databaseOptimizeSkill: SkillDefinition;
3
+ //# sourceMappingURL=18-database-optimize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"18-database-optimize.d.ts","sourceRoot":"","sources":["../../src/skills/18-database-optimize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,qBAAqB,EAAE,eAkSnC,CAAC"}