SDD+AI协作开发实战:从规范到发布一个中英文排版npm包
2026/9/9 1:19:48 网站建设 项目流程

一个周末,我把“做个排版 npm 包”这件事用 SDD 的方式彻底落地了。这个包的定位很简单:解决中英文混排时的格式问题——中文和英文之间自动加空格、统一标点、规范化省略号和破折号,同时不弄坏 Markdown 的代码块和链接。整个过程里,真正写业务逻辑和测试用例的是 AI,我主要负责把需求写成规范、把规范拆成任务、以及审查 AI 产出的代码,这就是 SDD(Spec-Driven Development,规范驱动开发)在 AI 协作开发中最大的价值:让人做判断,让 AI 做实现。如果你也在研究怎么把 AI 用进自己的项目,或者想做一个能发布到 npm 的小工具,这篇实战记录应该对你有帮助。

1. 项目缘起与整体思路拆解

1.1 排版这件小事,为什么值得做成一个包

先说痛点。我平时写技术博客、整理公众号文案、维护项目 README,最烦的就是中英文混排的格式。举一个真实例子:我写“使用AI协作开发npm包”这种句子,理想状态是“使用 AI 协作开发 npm 包”,中文和英文之间要留一个空格,英文和数字之间要根据习惯处理;标点方面,中文语境下该用全角标点,英文语境下该用半角标点。这些规则非常碎,但每次要手动改一遍,改完还总有漏网之鱼。

编辑器插件我也试过几个,比如 Sublime 的自动排版插件、Typora 里的中英文一键排版功能。但问题在于,插件的规则是写死的,有些规则我不需要,我需要的规则它又没有;更麻烦的是,团队协作时,别人用的是别的编辑器,规则不一致,同一篇文章换个人打开格式就乱了。所以我一直在想,能不能把排版规则做成一个独立的 npm 包,命令行能跑、代码里能调用、还能接进 CI 流程。只要有 Node.js 环境,谁都能用同一套规则处理文本。

这个需求其实不小。排版看起来是小事,但一旦要做成通用工具,就要考虑 Markdown 特殊语法、编码问题、不同平台换行符、规则可配置性。靠手工维护一堆正则太容易翻车,这时候 SDD 的思路就派上用场了——先写清楚“这个包到底该做什么、做到什么程度”,再用 AI 去填实现细节,比我以前边写代码边想需求高效得多。

1.2 SDD:先写规范,再让 AI 干活,和 TDD 有什么本质区别

很多同学可能对 TDD(测试驱动开发)比较熟:先写一个会失败的测试,再去写功能代码让测试通过。SDD 的思路完全不同,它不是从测试出发,而是从一份“规格说明”出发。Spec 里描述的是:这个功能是什么、输入是什么、输出应该是什么、有哪些边界情况、哪些事情明确不做。AI 拿到这份 spec,再去生成代码,产出就会稳定很多。

为什么 AI 时代 SDD 反而更合适?我自己的体会是:AI 非常擅长实现,但非常不擅长猜需求。如果你只是丢一句“帮我写个排版工具”,它大概率给你一个看着能用、实际一测全是问题的半成品。因为排版里的规则太多,你不说清楚“中英文之间加空格”,它就不会加;你不说清楚“代码块内部不能动”,它可能把代码块里的注释也当成普通文本改了。Spec 就是用来消灭这种模糊性的。

TDD 和 SDD 并不是对立的。我这次的做法是:先用 SDD 把规则和验收标准定义清楚,再用类似 TDD 的方式把验收标准转成测试用例,最后让 AI 实现功能并让测试通过。Spec 管“要做成什么样”,测试管“怎么证明做对了”,两者配合起来非常舒服。

对比维度TDDSDD
起点一条会失败的测试用例一份描述行为的规格说明
关注点代码行为和结果验证需求边界和验收标准
适合场景功能逻辑明确、算法可预期需求模糊、规则众多、需要 AI 协作
AI 协作方式AI 生成实现让测试变绿AI 先帮写 spec,再按 spec 写实现
主要风险测试写偏导致实现跑偏spec 写得太空或太满导致开发困住

我在这次项目里的结论是:TDD 解决“做对了没有”,SDD 解决“做什么才算对”。AI 时代,后者更重要,因为需求一旦定义错,AI 会以极高的效率把错误放大。

1.3 Birgitta Böckeler 的三级分类框架,我理解的粒度分层

这次动手之前,我翻了不少 SDD 的资料。Thoughtworks 的杰出工程师 Birgitta Böckeler 提出过 SDD 的三级分类框架,业内讨论度很高。按我自己的实践体会,可以把这三个级别通俗理解为:轻量级 spec、模块级 spec、系统级 spec。

轻量级 spec 可能只是 prompt 里的两三句话,比如“把这段函数改成支持可选参数,默认值为 false,老逻辑保持不变”,适合改一个小函数或小修小补。模块级 spec 要有明确的接口和行为约束,适合一个完整模块的从零开发。系统级 spec 则面向多个模块协作,必须包含数据契约、接口协议、验收体系和边界场景。

这次排版包整体属于模块级 spec,但拆出来的每个规则文件又各自带着轻量级 spec。这样做的好处是,AI 在实现某一条规则时不会迷失在全局需求里,我也更容易审查每段代码是否达到预期。没有这个分层,容易犯“什么都往一个 spec 里塞”的毛病,最后 spec 变成一篇没人愿意读的长文档。

2. 排版包的核心功能与设计原则

2.1 功能范围:先想清楚做什么,更要想清楚不做什么

做工具最容易犯的错误是贪多。我一开始也幻想过,这个包能不能顺便把错别字也纠正了、把句子润色了、甚至把 Markdown 转成 PDF。冷静下来之后,我把功能范围收敛到了下面几块:

功能模块具体内容处理方式
中英文空格中文与英文/数字之间自动插入空格正则规则,可开关
标点规范统一中文省略号、破折号,压缩重复空格正则规则,可开关
引号处理直引号转弯引号,英文撇号保留上下文判断
Markdown 保护代码块、行内代码、链接、图片语法不受影响占位符提取+还原
多种调用方式命令行 CLI、Node.js API、直接传字符串双入口设计
行尾清理去除行尾多余空格、统一换行符基础清理规则

与此同时,我明确写下了 non-goals(非目标):不做语法检查,不做拼写纠错,不处理复杂排版(比如页边距、字体、分页),不打算做成一个在线服务。这些东西都写在 spec 里,AI 就不会在实现过程中“自由发挥”加一堆我不需要的功能,我自己的开发节奏也不会被带偏。

2.2 技术选型:为什么是 TypeScript + 正则,而不是上 AST

这个包的输入输出都是文本,核心操作是规则替换,所以最直接的技术方案就是正则表达式。有人可能会问,为什么不用完整的 Markdown AST 解析器?我的判断是:排版任务本质上是“在保留结构的前提下修整文本”,对结构理解的要求没有想象中那么高。引入 AST 会显著增加依赖体积和复杂度,而且 AST 解析器对格式的要求更严格,用户传入一段不太规范的文本时,AST 反而可能解析失败。

最终选择是 TypeScript 加少量零依赖的实现。TypeScript 可以提供类型声明,方便使用者获得智能提示;零依赖意味着安装包的时候不用担心依赖冲突,体积也小。包的整体结构我设计成下面这样:

packages/format-md/ ├── src/ │ ├── index.ts # 统一入口,导出 format 函数 │ ├── cli.ts # 命令行入口 │ ├── utils/ │ │ └── tokenizer.ts # 占位符提取与还原 │ ├── rules/ │ │ ├── space.ts # 中英文空格规则 │ │ ├── punct.ts # 标点规范规则 │ │ └── quote.ts # 引号处理规则 │ └── types.ts # 配置项和输出类型 ├── tests/ │ ├── fixtures/ │ │ ├── good.md # 期望结果 │ │ └── bad.md # 待处理输入 │ └── format.test.ts ├── package.json ├── tsconfig.json └── README.md

这个结构不是我拍脑袋定的,而是在 spec 阶段就规划好的。每个规则文件只负责一类规则,后续加新规则或者关掉旧规则都非常方便。AI 在实现时也不需要理解整个项目,只要聚焦到对应文件即可。

2.3 最关键的边界保护:先占位、再处理、后还原

排版包最容易翻车的地方,不是空格规则写不出来,而是把不该改的内容改了。比如用户文本里有一段代码块:

const str = "使用AI开发npm包";

在代码块内部,"使用AI开发npm包"是字符串字面量,加了空格可能导致语义变化,而且用户大概率不想改它。再比如行内代码`npm i -D format-md`,如果被空格规则处理成`npm i -D format-md`还好,但如果正则没写好,把反引号破坏了,用户的 Markdown 就废了。

所以处理流程必须设计成三步:先提取保护对象,用占位符替换;再对剩余文本执行排版规则;最后把占位符还原成原始内容。提取保护对象时,我用的是全局匹配加数组存储:

// utils/tokenizer.ts const CODE_BLOCK_RE = /```[\s\S]*?```/g; const INLINE_CODE_RE = /`[^`\n]+`/g; const LINK_RE = /\[[^\]]*\]\([^)]*\)/g; export function protect(input: string): { text: string; tokens: string[] } { const tokens: string[] = []; let text = input; const replaceTokens = (match: string) => { tokens.push(match); return `\x00TOKEN_${tokens.length - 1}\x00`; }; text = text .replace(CODE_BLOCK_RE, replaceTokens) .replace(INLINE_CODE_RE, replaceTokens) .replace(LINK_RE, replaceTokens); return { text, tokens }; } export function restore(text: string, tokens: string[]): string { return text.replace(/\x00TOKEN_(\d+)\x00/g, (_, index) => tokens[Number(index)]); }

选用\x00这种不可见字符做占位符前缀,是为了尽可能避免和用户原文冲突。AI 生成第一版时用的是普通字符串占位,我审查时发现如果原文本身包含相同字符串,还原就会出错,改成不可见字符后这个问题彻底消失。这种细节,只有真正处理过文本替换的人才想得到。

3. SDD 六步 + AI 的实操全流程

3.1 第一步:用 AI 产出 spec 初稿,我再人工校审

我的经验是,不要从零开始写 spec,可以先让 AI 基于一个大致想法生成初稿,然后人工做详细的增删和校准。这一步我用了一个结构化的 prompt:

你是一名资深前端工程师。请你帮我为「中英文排版 npm 包」编写一份规格说明书,需要包括: 1. 项目目标和用户场景 2. 功能清单,分为必须实现和可选实现 3. 每条功能的输入输出示例 4. 边界情况和明确不做的 non-goals 5. 验收标准,尽量用可测试的句式 请用中文输出,条理清晰,可以直接作为 AI 编码的输入依据。

AI 生成初稿后,我没有直接采用,而是做了两轮修改。第一轮是收敛:把一些不切实际的功能划入 non-goals,比如“自动翻译”“语气润色”,这些功能很诱人,但会无限抬高复杂度。第二轮是补细节:给每条规则补上正反例。比如“中英文之间加空格”这一条,正例是使用AI开发->使用 AI 开发,反例是代码块内部不能动、URL 不能动、连续数字不能拆。

最终 spec 里的验收标准长这样:

# 排版规则 spec v0.1 ## 必须实现 - 在中文与英文之间插入一个空格 - 在中文与数字之间插入一个空格 - 将连续三个英文句点替换为中文省略号「……」 - 将连续三个及以上英文连字符替换为中文破折号「——」 - 去除行尾多余空格 - Markdown 代码块、行内代码、链接内容不得被任何规则改动 ## 非目标 - 不检查拼写错误 - 不处理字体、字号、页边距 - 不做内容润色或语义改写 - 不提供在线服务 ## 验收示例 | 输入 | 期望输出 | | --- | --- | | 使用AI开发npm包 | 使用 AI 开发 npm 包 | | 一共100个文件 | 一共 100 个文件 | | ...等待中 | ……等待中 | | ---分割线--- | ——分割线—— |

有了这样一份 spec,后面所有环节都有了判断依据。AI 写出的代码是否符合预期,我用 spec 来检查;我自己写测试用例,也直接从验收示例里抄。

提示:Spec 不是写给甲方看的文档,而是写给 AI 和未来的自己看的“施工图纸”。它可以短,但不能含糊。

3.2 第二步:拆任务、逐个对话,而不是扔一个大 prompt

Spec 定好之后,我没有把整份 spec 一次性扔给 AI,让它“按这个开发”。原因有两个:一是上下文太长,AI 容易忽略后面的细节;二是一次性生成大量代码,审查成本很高,出了问题也很难定位。正确做法是把 spec 拆成独立的小任务,每个任务单独起一个对话。

我实际执行的任务拆解表是这样的:

任务编号任务内容AI 输入要点交付物
T1搭建项目骨架和 TypeScript 配置技术栈、包结构、tsconfig 要求package.json、tsconfig
T2实现占位符提取与还原代码块、行内代码、链接的正则和占位符方案tokenizer.ts
T3实现中英文空格规则中文和拉丁字符集定义、正反例space.ts
T4实现标点统一规则省略号、破折号、重复空格处理punct.ts
T5实现引号处理规则直引号、弯引号、撇号的上下文判断quote.ts
T6实现 CLI 入口参数解析、文件读写、标准输入cli.ts
T7编写测试用例验收示例 + 边界用例format.test.ts
T8编写 README 和发布准备使用说明、API 示例、npm 配置README.md

每个任务我给 AI 的 prompt 非常聚焦,比如 T3 我是这么写的:

请实现 fixSpacing 函数,功能是:在中文与英文之间、中文与数字之间插入空格。 字符范围:中文使用 \u4e00-\u9fff,英文使用 A-Za-z,数字使用 0-9。 要求: 1. 输入 `使用AI开发`,输出 `使用 AI 开发` 2. 输入 `一共100个文件`,输出 `一共 100 个文件` 3. 如果已经存在空格,不要重复插入 4. 不要处理占位符 \x00TOKEN_xxx\x00 里的内容 请输出 TypeScript 代码和简短的说明。

小任务的每一个输出,我都会立即 review,确认没问题再进入下一个任务。这样即使某个环节出错,影响面也被控制在单个文件以内,修复成本很低。

3.3 第三步:AI 写核心逻辑,我 review 边界条件

这一步是整个项目里“人机协作”密度最高的环节。AI 负责生成主体代码,我负责盯细节。以空格规则为例,AI 第一版生成的是这样的:

// rules/space.ts const CJK = '\\u4e00-\\u9fff\\u3400-\\u4dbf\\uf900-\\ufaff'; const LATIN = 'A-Za-z0-9'; export function fixSpacing(text: string): string { return text .replace(new RegExp(`([${CJK}])([${LATIN}])`, 'g'), '$1 $2') .replace(new RegExp(`([${LATIN}])([${CJK}])`, 'g'), '$1 $2'); }

这段代码核心思路是对的:正则一处理“中文在前英文/数字在后”,正则二处理“英文/数字在前中文在后”。但我 review 时发现了几个问题。

第一个问题是 LATIN 字符集把下划线排除了。URL 和文件名里经常有下划线,比如my_file.md出现在中文句子里时,按照当前正则md和中文边界会被加空格,变成my _file .md这种奇怪格式吗?不会,因为_不在正则匹配范围内,所以可能出现“中文字符_英文字符”这种混合却没被处理的情况。排版包的规则是允许这种混合出现吗?我当时和 AI 就这个点来回了两轮,最终决定把_排除在自动空格范围之外,即中文与下划线之间不补空格,因为下划线通常表示文件名或代码标识符,不应该拆开。

第二个问题更隐蔽。如果输入是“AI 开发”这样已经有空格,上面的正则不会重复插入,因为匹配模式要求中文后面紧跟英文,中间不能有空格。这一点 AI 第一版实现是对的,但我还是补了一个测试用例来防止以后改动时回归。

第三个问题是我手工追加的:当文本里有占位符\x00TOKEN_0\x00时,中文和数字之间如果被插入空格,占位符就被破坏了。比如“使用\x00TOKEN_0\x00开发”,正则会把“用”和“\x00”当作中文和符号边界,虽然不影响占位符本身,但还原后会变成“使用 code``` 和开发”中间多出一个空格。解决方式是在 fixSpacing 执行前,先检查文本中是否包含占位符,如果包含,就把整个替换逻辑限制在非占位符分段中。这个需求我写进了 T3 的验收标准,AI 实现时一次性做对了。

3.4 第四步:测试驱动验证,AI 生成用例,人工补边界

Spec 里的验收示例是我写测试用例的第一手素材,但我没有让 AI 直接照抄,而是让它先把验收示例转成 Vitest 用例,然后我再人工补了三类边界用例:空字符串、纯英文文本、包含代码块和链接的 Markdown 文本。

实际测试文件里有一段长这样:

// tests/format.test.ts import { describe, expect, it } from 'vitest'; import { format } from '../src/index'; describe('format', () => { it('should insert space between CJK and latin', () => { expect(format('使用AI开发npm包')).toBe('使用 AI 开发 npm 包'); }); it('should insert space between CJK and digits', () => { expect(format('一共100个文件')).toBe('一共 100 个文件'); }); it('should keep code blocks unchanged', () => { const input = '```js\nconst msg = "使用AI开发";\n```\n然后是正文'; const output = format(input); expect(output).toContain('const msg = "使用AI开发"'); }); it('should keep inline code unchanged', () => { const input = '执行 `npm i -D format-md` 后完成安装'; const output = format(input); expect(output).toContain('`npm i -D format-md`'); }); it('should handle empty string', () => { expect(format('')).toBe(''); }); });

这些用例跑起来之后,AI 生成的代码第一次全绿了。但我没有就此收手,因为“全绿”只能说明我写的这些用例通过了,不能说明规则本身没有遗漏。我额外准备了一个fixtures/bad.md,里面故意放了一堆真实场景的混乱排版,然后手动跑一遍命令,再对照fixtures/good.md逐行检查差异。这一步属于“看起来不起眼、实际最管用”的环节。

检查过程中我发现了一个预期之外的问题:中文省略号替换。原文如果是...,规则会统一成……,但如果在英文语境里,比如 She saidWait...,用户可能希望保留英文风格。最后我在配置里加了一个选项preserveEnglishPunct,默认关闭,开启后英文语境下的标点不会被强制转换。这个选项也是我在测试中实际用到的需求,不是凭空想出来的。

3.5 第五步:打包发布,从本地验证到 npm publish

发布 npm 包之前有一堆准备工作,我第一次发布时踩过不少坑,这次直接按流程来。首先是package.json的关键字段:

{ "name": "format-md", "version": "0.1.0", "description": "中英文混排排版工具,支持 Markdown 代码块保护", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", "bin": { "format-md": "./dist/cli.js" }, "files": [ "dist", "README.md" ], "scripts": { "build": "tsc", "test": "vitest run", "prepublishOnly": "npm run build && npm test" }, "license": "MIT" }

files字段很关键,它决定哪些文件会被打进 npm 包。如果你不写,npm 默认会塞一堆无关文件进去,比如testssrcnode_modules里的一些东西,包体积变大不说,还有可能泄露不必要的代码。我这次只发布distREADME.md,干净又简洁。

bin字段是 CLI 入口。这里有个容易被忽略的点:如果用了 ESM,CLI 文件第一行必须有#!/usr/bin/env node这样的 shebang,否则安装后命令行工具无法执行。AI 生成代码时不会自动加这行,是我 review 时补上的。

发布前我用npm pack命令在本地生成了一个 tarball,然后在一个干净的临时目录里安装,模拟用户的使用环境。这一步能发现很多问题,比如漏了dist、入口路径不对、依赖没打全。确认没问题后再执行npm publish。整个过程下来,真正在 npm 中心和本地操作的时间反而很少,大部分时间花在了前置校验上。

4. 常见问题与排查技巧实录

4.1 npm 环境问题速查:从“禁止运行脚本”到证书过期

开发这个包的过程中,我被 npm 环境问题折磨过好几次,这些报错看起来吓人,其实多半是环境配置问题。我把最常遇到的几类整理成了一张速查表:

报错信息原因解决方案
npm : 无法加载文件 npm.ps1,因为在此系统上禁止运行脚本PowerShell 执行策略限制脚本运行以管理员身份执行Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser,然后重开终端
npm 不是内部或外部命令Node.js 未正确加入 PATH重新安装 Node.js 并勾选 “Add to PATH”,或者手动把 Node.js 安装目录加入环境变量
npm ERR! code CERT_HAS_EXPIRED镜像源证书过期或本地时间不正确先检查系统时间,再执行npm config set registry https://registry.npmjs.org/切回官方源
npm install卡住或超时默认源访问不稳定切换为访问速度更快的公共镜像源,或使用公司内部私有源

CERT_HAS_EXPIRED这个错误我想多说一句。我遇到的情况是某个旧镜像源的证书过期了,请求registry.npm.taobao.org时直接报错。这种问题不一定是代码引起的,第一步应该是检查本地系统时间,如果时间不对,所有证书校验都会失败。时间没问题的话,执行npm config get registry看看当前用的是哪个源,再决定是切换还是清除缓存。

关于 PowerShell 执行策略,有人可能会问为什么要用RemoteSigned而不是UnrestrictedRemoteSigned的意思是:本地创建的脚本可以运行,从网上下载的脚本必须经过签名才能运行。这个限制级别既满足开发需求,又保留了基本的安全防护,是当前场景下最稳妥的选择。如果你只需要当前用户生效,一定要加-Scope CurrentUser,别全局修改。

4.2 发布 npm 包时容易踩的坑

发布流程本身不复杂,但有几个坑非常隐蔽。第一次发布时我连续踩了三个,这次全部提前规避了。

第一个坑是包名冲突。npm publish的时候如果提示403 Forbidden,多半是这个包名已经被别人占用了。先执行npm view 包名查一下,如果返回一堆信息说明名字已存在,换一个名字或者改成@你的用户名/包名的作用域包。

第二个坑是忘记登录。新终端里执行npm publish,提示ENEEDAUTH或者 401,说明你还没登录。执行npm login,输入用户名、密码和邮箱即可。这里有个细节:如果你配置了非官方镜像源,npm login会往那个源的服务器上登录,可能会导致登录信息不对。稳妥做法是先切回官方源再登录。

第三个坑是版本号忘记更新。npm 不允许用相同的版本号重复发布,第二次发布时如果不手动更新package.json里的version,会直接报错。我现在的习惯是在prepublishOnly脚本里加一个版本检查,同时写代码时尽量用npm version patch这种命令来提升版本号,这样package.json和 git tag 会一起更新,避免忘记。

4.3 排版规则处理文本时的三个大坑

这个部分是纯业务层面的经验,就算你不用 SDD 也能直接用上。第一个坑是正则对代码块的破坏。如果你不先保护代码块,空格规则会把代码块里的字符串、注释全部按照中英文规则改一遍,轻则格式乱掉,重则改变代码含义。占位符机制就是用来解决这个问题的,一定要在最开始做,而不是最后兜底。

第二个坑是引号处理。把直引号转成弯引号看起来简单,实际非常容易误伤。比如英文中的撇号'和引号是同一个字符,规则一不小心就会把don't改成don’t,这可能不是用户想要的。英文文本和中文文本混在一起时,这种误伤很难通过简单正则完全避开。我的处理方式是让引号规则默认只处理中文字符前后的引号,英文内部的撇号保持不变,同时提供一个高级选项让用户按需开启更激进的转换。

第三个坑是连续数字的处理。规则里“中文和数字之间加空格”,但遇到iPhone15Pro这种词,数字 15 夹在字母中间,如果正则写得粗糙,会被拆成iPhone 15 Pro,这显然不是想要的。我在 spec 里明确规定:只处理“中文直接相邻数字”的场景,字母内部的数字不动。这类边界情况必须在 spec 阶段就写清楚,否则 AI 实现出来一定会踩。

5. 实操体会与后续计划

做完这个包,我最大的感受是:SDD 和 AI 协作开发,真正改变的其实是开发者时间的分配方式。以前写一个工具,一半时间在写代码,另一半时间在纠结“这个行为到底该怎么定义”。现在有了 AI,写代码的时间被大幅压缩,我在定义规范和 review 边界上花的时间反而更多了。但这不是坏事,因为把问题想清楚本身就会减少返工,而且这部分的思考很难被 AI 替代。

对这个包本身,我后续有几个明确的扩展方向。一是把规则引擎抽出来,支持用户通过配置文件自定义规则,这样不光我自己的排版习惯能用,其他人也可以按自己团队的规范来。二是增加一个 Web 演示页面,把命令行工具做成一个可以粘贴文本、实时预览效果的网页,方便不熟悉命令行的内容创作者使用。三是研究一下要不要接入 Markdown AST 解析器,虽然目前零依赖方案够用,但如果要支持更复杂的语法保护,引入 AST 会是更稳妥的路线。

最后再分享一个小技巧:开发这类发布到 npm 的小工具时,无论你用不用 SDD,都建议先把README.md的“快速开始”部分写好,哪怕功能还没实现。因为 README 里写清楚“安装后输入什么命令、看到什么输出”,就是在用最简单的方式定义验收标准。等代码写完了,把 README 里的命令原样跑一遍,整个工具好不好用立刻见分晓。这次我就是先写了 README 再开始写代码,后面所有实现都在围绕 README 里承诺的能力服务,基本没跑偏。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询