# 软件设计的取舍：抽象、契约与复杂度

作者：Hex4C59 · 发布于 2026-10-14

原文：https://hex4c59.cc/articles/software-design/


这个系列讨论一个能运行的小程序增加功能后，代码怎样安排才能继续容易理解、容易修改。每篇围绕一个实际选择，比较它省掉了什么工作、增加了什么要求，以及什么变化出现后需要重新考虑。

系列以本地待办事项程序逐步展开：最初添加和完成任务，随后增加不同页面、失败处理、文件保存与桌面界面。第一篇用更短的版本查询比较一层函数的收益；第二篇开始围绕“完成任务”建立共同的行为约定，后续沿同一程序继续推进。

读者需要能阅读简单 JavaScript，不预设熟悉软件开发术语。各篇先解释要解决的问题和中心概念，再进入代码。篇幅用于补足案例、推理和比较，不按固定长度把一个完整问题拆碎。

## 当前文章

- [导读：软件设计怎样形成可检查的判断](https://hex4c59.cc/articles/software-design-00-reading-guide/)。先说明整个系列要解决什么问题，再用一段查询代码练习区分实际行为与设计判断。
- [第 01 篇：抽象的收益与代价：封装何时降低复杂度](https://hex4c59.cc/articles/software-design-01-abstraction/)。比较直接读对象、统一组装和单纯转调，用内部结构变化检查修改范围；附完整示例与行为检查。
- [第 02 篇：接口与契约：两段代码怎样可靠地配合工作](https://hex4c59.cc/articles/software-design-02-contracts/)。围绕完成任务解释双方约定，比较失败处理、数据修改和重复执行，再观察返回形式及保存需求变化带来的影响；附完整演示、检查与版本查询练习。
- [第 03 篇：间接调用与依赖：程序怎样按名称选择要做的事](https://hex4c59.cc/articles/software-design-03-indirection/)。先解释把函数本身存起来与立即执行它的区别，再比较条件分支和处理器表，沿完成任务追踪参数、结果与修改位置；附两种完整实现、查找陷阱和统计功能扩展。
- [第 04 篇：模块边界与信息隐藏：哪些代码应该放在一起](https://hex4c59.cc/articles/software-design-04-module-boundaries/)。解释模块与文件的区别，比较两种组织方式怎样应对数组换成 Map，追踪修改范围、返回数据和外部约定；附四个完整版本与反例。
- [第 05 篇：状态与副作用：谁能修改数据，失败后保留什么](https://hex4c59.cc/articles/software-design-05-state-effects/)。解释状态与数据所有者，比较直接修改和先计算再采用，用保存失败、重试、临时文件与两个所有者的例子检查副作用的范围；附完整实现与运行检查。
- [第 06 篇：错误传播与异步边界：需要等待时，成功和失败怎样交回来](https://hex4c59.cc/articles/software-design-06-async-errors/)。从 Promise 与任务结果的区别讲起，比较等待、拒绝与局部错误转换，沿保存和第二次修改说明忙碌策略；附完整异步实现、两个反例与真实文件检查。
- [第 07 篇：可测试性：怎样写出能发现问题的检查](https://hex4c59.cc/articles/software-design-07-testability/)。从行为约定推导断言，控制保存何时结束，用三个故意改错的版本检验检查，再接上真实文件说明验证范围；附完整示例与运行检查。
- [第 08 篇：重构中的行为保持：换一种实现，怎样确认功能没变](https://hex4c59.cc/articles/software-design-08-refactoring/)。保留四个可运行阶段，分开迁移内部容器与完成计算，用相同约定检查结果、顺序和保存格式，区分内部整理与行为变化；附完整迁移、反例和真实文件检查。
- [第 09 篇：持久化与设计演化：任务保存后，怎样重新读回来](https://hex4c59.cc/articles/software-design-09-persistence/)。连接保存、退出与重新读取，解释文件验证、显式初始化、旧格式升级和临时替换，用损坏拒绝与真实独立进程检查持久化的范围；附完整命令行与运行检查。

## 后续写作方向

| 篇目 | 要回答的问题 | 状态 |
| --- | --- | --- |
| 10 进程与权限边界 | 从按钮到完成任务，信息经过哪些部分，哪些请求应当拒绝？ | 规划中 |

前九篇从小例子进入待办事项程序，讨论抽象、共同约定、按名称选择功能、模块边界、状态变化、等待、行为检查、分步重构与保存重读。后续将把任务接到界面请求，继续检查输入与权限边界。

后续篇目随案例调整，完成后加入阅读目录。每篇的结论限定在明确的需求和验证范围内，示例通过不代表其他项目、运行时或部署条件也已得到验证。

