软件的根本困难与次要困难
根本困难和次要困难分别指什么?
- 术语来源: 借用亚里士多德的区分, 次要(accident)不是"偶然"或"不幸", 而是"附带的""从属的";
- 根本任务(essence): 打造由抽象软件实体构成的复杂概念结构--数据集合、数据项之间的关系、算法、功能调用;
- 次要任务(accident): 用编程语言表达这些抽象实体, 在空间和时间限制内把它们映射成机器语言;
- 作者立场: 软件开发中最难的部分是规格化、设计和测试概念结构, 而不是表达它、验证它是否逼真;
软件有哪些固有特性造成根本困难?
| 特性 | 含义 | 后果 |
|---|---|---|
| 复杂度 | 没有两个软件部分相同, 元素以非线性方式交互 | 沟通困难、状态难列举、难扩充、难安全 |
| 一致性 | 复杂度很多来自必须遵循的人为惯例和接口, 而非自然规律 | 再设计也无法简化这些复杂度 |
| 可变性 | 成功软件持续承受变更压力, 生命期常长于硬件平台 | 变更无法避免, 无法靠一次性设计解决 |
| 不可见性 | 软件没有空间形体, 没有唯一可映射的图形表达 | 缺概念工具, 也阻碍相互交流 |
- 关键判断: 复杂度是本质属性, 不是次要因素; 抽掉复杂度的软件描述常常也抽掉了本质属性;
- 对比: 物理学家可假设存在简化规律, 软件工程师面对的大量复杂度来自"不同的人而非上帝"的设计;
为什么消除次要困难不能带来数量级提升?
- 推理: 若次要部分不到全部工作的 9/10, 即使把次要任务时间降到零, 也换不来数量级的生产率提升;
- 已验证的突破: 高级语言、分时、统一编程环境都只是消除次要困难;
- 高级语言: 消除了位/寄存器等整个层级的复杂度, 但剩余问题变少后, 再优化的空间也变小;
- 分时: 缩短响应时间以维持对复杂度的总体把握; 接近 100 毫秒后收益趋近于无;
- 统一环境: 靠集成库、统一文件格式、管道解决共同使用程序的困难, 并激发工具库开发;
根本困难能否被缓解?
- 可以: 固有特性造成的麻烦是能改善的, 只是不能靠单一技术一次解决;
- 复杂性是层次化的: 一部分复杂度来自应用本身随意的特性, 可以被更高层的复用规避;
- 缓解方向: 分层(模块或对象)与增量(系统持续可运行);
- 不能消灭: 概念结构本身仍要设计和调试, 复杂度、一致性、可变性、不可见性依旧存在;