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

用可运行的案例比较抽象、契约与模块边界,沿需求变化检查软件设计的收益和代价。

课程 导读 + 9 章约 193 分钟更新于 连载中
从序言开始 软件设计导读:怎样形成可检查的判断

可以按章节顺序阅读,也可以从下面的目录选读。

从系列目录查看阅读路线。先读导读,再进入第 01 篇:抽象的收益与代价。

目前完成导读和前九篇:第 02 篇以完成待办任务为主线,讨论输入、结果、失败与数据变化的约定,并比较需求变化后的选择。第 03 篇继续解释按操作名称选择函数的过程,比较条件分支与处理器表的收益、依赖和阅读成本。第 04 篇比较按操作拆分与集中维护任务表示,沿内部容器变化解释模块边界和信息隐藏。第 05 篇解释状态与副作用,沿保存顺序、失败和重试检查内存及外部数据的变化。第 06 篇继续讨论 Promise、等待与错误传播,处理同一所有者等待期间的新修改。第 07 篇从行为约定推导检查,用错误版本核对检查能发现什么,再说明受控保存与真实文件各自覆盖的范围。第 08 篇沿数组到 Map 的分步迁移,检查可观察行为,讨论过渡代码与行为变化的边界。第 09 篇把文件保存与重新启动接起来,处理初始化、数据验证、损坏拒绝和旧格式迁移,并说明临时替换的保证范围。后续将讨论界面请求与权限边界。各篇使用合成数据,并记录对应代码的运行环境和验证范围。

抽象、契约与依赖

4 篇
  1. 序言软件设计导读:怎样形成可检查的判断

    说明软件设计系列要解决的问题与待办事项主线,再从短小的版本查询练习区分程序行为、设计目的和判断依据。

  2. 01抽象的收益与代价:封装何时降低复杂度

    比较直接读取、查询函数和单纯转调,通过版本数据的结构变化,检查一层抽象隐藏了什么、保留了什么依赖,以及新增了什么成本。

  3. 02接口与契约:两段代码怎样可靠地配合工作

    以待办事项程序为主线,从接口与契约的含义讲到输入、结果、失败、数据修改和重复操作,再比较不同设计及需求变化后的影响。

  4. 03间接调用与依赖:程序怎样按名称选择要做的事

    沿用待办事项程序,解释直接调用、按操作名称分支和处理器表的工作过程,比较函数值、参数转换、修改范围与定位错误的成本。

模块、状态与行为保持

5 篇
  1. 04模块边界与信息隐藏:哪些代码应该放在一起

    沿用待办事项程序,解释模块、边界与信息隐藏,比较按操作拆文件和集中维护任务表示,通过数组改为 Map 观察修改传播、行为保持与拆分成本。

  2. 05状态与副作用:谁能修改数据,失败后保留什么

    沿用待办事项程序,解释状态、副作用与数据所有者,比较直接修改、先计算再采用和两种保存顺序,用重试及临时文件观察失败后的实际数据。

  3. 06错误传播与异步边界:需要等待时,成功和失败怎样交回来

    沿用任务保存例子,解释 Promise、async、await 与错误传播,比较正常失败结果和拒绝、缺少等待与局部捕获,并处理等待期间的第二次修改。

  4. 07可测试性:怎样写出能发现问题的检查

    沿任务保存例子解释测试、断言和测试替身,从行为约定推导检查,用三个故意改错的版本检验检查,再接上真实文件说明验证范围。

  5. 08重构中的行为保持:换一种实现,怎样确认功能没变

    沿异步任务保存程序,把数组实现分步迁移到 Map,用相同约定检查每个阶段,解释重构范围、过渡代码、列表顺序、保存格式和行为变化。

保存、重读与应用边界

1 篇
  1. 09持久化与设计演化:任务保存后,怎样重新读回来

    把任务保存、退出与重新读取接起来,解释持久化、文件格式验证和版本迁移,处理缺失或损坏文件,并比较直接覆盖与先写临时文件再替换的范围。