第 10 / 26 个单元计算机与软件基础设施区
第 9 章 软件为何不等于代码
核心问题一段能运行的代码,为什么还不是能够长期承担真实任务的软件?
一张成绩统计表在作者电脑上运行正常:输入数字,平均分计算正确。交给小组后,问题连续出现。有人填入“缺考”,有人覆盖整列,多人修改产生不同版本,还有人本不该看到姓名。
计算公式没有错,工具仍不能可靠承担真实任务。代码是软件的重要组成部分,软件还要面对需求、输入、数据、界面、权限、协作、测试、变化和维护。
本章的成绩表为教学构造,不使用真实学生数据。
算法规定处理方法,代码给出一种实现
算法是为解决一类问题规定的明确处理步骤或计算方法。“把有效成绩相加,再除以有效人数”是一种口语算法。
真正执行以前,需要定义“有效成绩”:缺考算零分还是不计入人数,补考怎样处理,小数保留几位,输入超出范围怎么办。算法中的一个词没有定义清楚,代码再准确也会稳定地产生错误结果。
同一算法可以用不同语言和结构实现;一段代码也可能同时处理界面、文件、网络和异常。程序能运行,只说明当前实现通过了某些条件,不证明需求正确、所有输入都处理过或系统适合真实使用。
需求决定软件要证明什么
作者说“我要一个成绩统计工具”,使用者真正需要的可能是:教师能导入名单,系统识别缺考,学生只能查看自己的结果,修改有记录,计算规则符合当前课程要求。
需求要区分功能和约束。功能说明系统做什么;约束涉及安全、性能、可用性、兼容性、维护和规则。练习程序与影响真实成绩的系统,即使界面相似,所需证据完全不同。
需求还会变化。课程调整评分规则,原代码可能继续运行,却已经不符合任务。软件工程要让变化有位置,而不是把旧假设藏在程序里。
接口让不同部分能够交接
系统变大以后,会把不同职责分开:界面收集输入,业务逻辑计算,数据库保存记录,权限模块决定访问。各部分通过接口交接。
接口规定能提供什么输入、得到什么输出、错误怎样表示。按钮和表单是人与软件的接口;模块之间也有接口。API是应用程序编程接口,常用来让软件以结构化方式调用另一个模块或服务。
接口隐藏内部细节,却不能消除需求错误。若“缺考”含义没有统一,界面、计算和数据库都可能按不同规则处理。可靠接口要写清数据类型、单位、必填项、错误状态、权限和版本。
AI工具调用同样依赖接口。模型产生一个结构化请求,周边应用验证参数,再执行API。模型写出工具名称,不表示接口已经调用成功。
测试提供有限证据
演示通常只展示正常路径。真实软件还要处理空值、格式错误、极端数据、权限不足、网络中断和恶意输入。
不同测试回答不同问题:单元测试检查较小模块,集成测试检查模块交接,端到端测试检查完整流程,安全和性能测试关注相应风险。用户试用则能发现需求和界面是否真正适合情境。
一组测试通过,只说明这些检查项下没有发现被检测的失败。[3] 未测试条件、真实数据差异和环境变化仍会产生问题。测试不是无错证明,是可重复的证据。
软件修改后还要回归检查。一个修复可能影响其他功能;版本记录帮助团队知道何时改了什么,出现问题后能否回到可用状态。
软件工程管理完整生命周期
软件工程使用系统化、可验证和可维护的方法处理软件需求、设计、构建、测试、运行、维护和退役。[1][2]
它不只是大型公司的流程。两人课程项目也需要决定谁维护数据,依赖库从哪里来,许可证是否允许使用,版本怎样交付,项目结束后是否继续运行。
软件上线以后,维护往往比初次编写更久。操作系统和依赖更新,安全漏洞出现,用户需求改变,原作者离开,都会要求软件继续演化。无人维护却仍影响他人的系统,是责任风险。
退役也属于生命周期。服务停止时,要处理数据导出、通知、权限关闭和替代路径,不能只让链接失效。
AI编码改变生产速度,没有替代工程证据
AI可以生成代码候选、解释错误、补测试、整理文档和比较方案。它降低了从想法到演示的成本,也让未经理解的代码更容易进入系统。
生成代码可能引用不存在的接口,使用不合适的依赖,遗漏安全检查,或者通过简单样例却不满足真实需求。提交者需要能解释关键行为,核对许可和依赖,运行测试并准备停止与回退。
速度提高会改变工作分配:更多时间可以用于定义问题、评审、测试和与用户验证。若节省的时间只用于生成更多功能,系统复杂度反而上升。
不写代码的人也能参与工程判断。面对一个需求,可以问:谁要完成什么,输入和输出是什么,异常如何处理,谁能访问和停止,怎样测试与恢复。这些问题往往比框架名称更早暴露真实距离。
计算机基础地图到这里已经形成:数据被表示和保存,程序借硬件运行,操作系统协调资源,网络连接服务,数据库维持状态,软件工程让系统在变化中可用。下一章进入人工智能,先看规则、搜索和机器学习为何长期共存。