Day03-01|2.3.1 计算机软件概述
Day03-01|2.3.1 计算机软件概述:从程序到软件系统
对应教材:上篇·综合知识·第 2 章“计算机系统基础知识”·2.3.1 计算机软件概述
学习定位:高级系统架构设计师不能把软件理解成一组源代码文件。软件还包括数据、配置、文档、运行环境、构建和部署脚本,以及支撑软件持续演化的工程过程。本节建立软件分类、层次、接口和生命周期的整体认识,为后续学习操作系统、数据库、中间件、软件构件和应用架构打基础。
一、今日目标
完成学习后,应能解释程序、软件和软件系统的区别;区分系统软件、支撑软件和应用软件;理解软件的逻辑性、抽象性、复杂性、易变性和不可见性;能够说明操作系统、数据库、中间件、编译器、开发工具和业务应用之间的关系;在案例题中分析技术栈选择、运行环境依赖、软件质量和演进成本。
二、程序、软件与软件系统
程序是为完成特定任务而编写的指令集合,通常强调可执行逻辑;软件是程序、数据、相关文档和运行所需资源的总和;软件系统则进一步强调多个软件单元、硬件、网络、人员、流程和外部环境之间的协同关系。
| 概念 | 关注重点 | 示例 |
|---|---|---|
| 程序 | 指令和算法 | 一个排序程序、一个接口服务 |
| 软件 | 程序、数据、文档、配置和工具 | 操作系统、数据库产品 |
| 软件系统 | 软件与硬件、人员、流程和环境的整体 | 电商平台、银行核心系统 |
软件没有机械磨损,但这不代表它不会“老化”。需求变化、依赖升级、数据规模增长、漏洞暴露、运行环境迁移和团队人员变化,都会使原来可用的软件变得难以维护。软件架构的价值就在于控制复杂度,让变化被限制在可管理的边界内。
三、软件的基本特征
1. 逻辑产品与不可见性
硬件可以通过尺寸、材料和结构直观看到,软件的结构通常隐藏在代码、配置和运行时行为中。软件缺陷也不一定表现为某个零件断裂,而可能在特定输入、并发、时序和环境下暴露。因此软件需要模型、文档、测试、监控和可追踪性来“看见”它的结构与行为。
2. 复杂性
软件复杂性来自功能数量、状态组合、依赖关系、并发交互、外部接口和业务规则。增加一个看似简单的功能,可能影响数据库结构、权限、缓存、消息、日志、测试和部署。模块化、分层、构件化、服务化和领域建模,都是控制复杂性的手段。
3. 易变性
软件经常需要适应政策、业务、用户、设备和技术变化。易变性是软件的优势,也是维护压力的来源。若架构没有稳定的接口和清晰的职责,变化会通过共享状态、隐式依赖和复制代码扩散,形成“牵一发动全身”。
4. 可复制性与可修改性
软件复制成本低,但部署并不一定简单。不同操作系统、处理器、数据库、网络、权限和配置会影响运行结果。软件可以修改,却不能只看修改代码的成本,还要考虑回归测试、数据迁移、兼容性、灰度发布和回滚。
四、软件的分类
1. 系统软件
系统软件直接管理计算机资源,为其他软件提供基础运行环境。操作系统、设备驱动、编译器、链接器和系统工具通常属于这一类。系统软件关注资源管理、并发控制、权限、安全、设备和服务能力。
2. 支撑软件
支撑软件用于支持软件开发、运行、测试、管理和维护。数据库管理系统、中间件、集成开发环境、版本控制、构建工具、监控平台和测试工具都可以看作支撑软件。支撑软件不一定直接实现业务,但会显著影响系统的性能、可靠性、可维护性和交付效率。
3. 应用软件
应用软件面向特定业务或用户需求,例如财务系统、客户关系管理、电子商务、工业控制和内容平台。应用软件通常建立在系统软件和支撑软件之上,并通过配置、定制、开发和集成形成完整解决方案。
| 层次 | 主要职责 | 典型架构问题 |
|---|---|---|
| 系统软件 | 管理硬件与基础资源 | 资源隔离、权限、调度、驱动 |
| 支撑软件 | 提供通用技术能力 | 数据、消息、事务、构建、监控 |
| 应用软件 | 实现业务价值 | 领域规则、流程、用户体验 |
分类不是绝对的。同一个组件在不同系统中可能扮演不同角色。例如,一个规则引擎作为通用平台能力时属于支撑软件;如果规则本身就是业务产品的核心,也可以被视为应用系统的一部分。架构设计应关注职责和依赖,而不是机械记忆标签。
五、软件层次与运行时关系
一个典型的软件系统可以抽象为:硬件资源之上是固件和操作系统,操作系统之上是运行时、数据库、中间件和基础服务,最上层是业务应用与用户界面。上层通过接口使用下层能力,下层通过资源、调度、隔离和安全机制支撑上层。
这种层次关系体现两个原则。第一,抽象:上层不需要知道下层每个寄存器和磁盘扇区的细节。第二,约束:抽象会带来额外开销和能力边界。架构师选择虚拟机、容器、数据库、中间件和框架时,应明确获得了什么能力,又引入了哪些延迟、资源占用和迁移依赖。
软件运行还受到配置和环境影响。相同二进制程序在不同配置、数据规模、时区、编码、权限和依赖版本下,可能产生不同结果。因此软件交付物应包括版本、配置、依赖、数据库脚本、部署方式和运行说明;生产环境还应具备配置审计、密钥管理和可回滚能力。
六、软件接口与契约
接口是软件单元之间的稳定边界。好的接口应明确输入、输出、前置条件、后置条件、错误语义、性能目标、安全要求和版本策略。函数接口、类接口、系统调用、数据库接口、消息接口和 HTTP API 虽然形式不同,但都遵循“调用者依赖契约、实现者承担约束”的原则。
接口设计中要防止两个极端:一是接口过于具体,暴露大量实现细节,导致上层被某个数据库、框架或厂商绑定;二是接口过于抽象,缺少业务语义和错误信息,调用者只能通过猜测使用。面向架构的接口要满足最小知识、明确责任、可测试、可观测和可演进。
七、软件质量与架构关系
软件质量不是“没有 Bug”这一项指标,而是包含功能适合性、性能效率、兼容性、可用性、可靠性、安全性、可维护性、可移植性等属性。不同质量属性之间经常存在冲突:强一致可能增加延迟,高安全策略可能增加操作复杂度,高可用可能增加冗余和成本,快速交付可能积累技术债务。
架构决策应把质量属性转化为可验证场景。例如,“系统要可靠”过于模糊;“任一应用节点故障后,用户请求在 30 秒内切换完成,数据丢失不超过 1 分钟”就可以转化为设计、测试和监控要求。架构师要在需求阶段识别重要质量属性,并在设计、实现、部署和运行阶段持续验证。
八、案例分析:技术栈升级引发的连锁问题
某企业把单体应用的运行时和数据库版本整体升级,测试环境正常,生产上线后出现接口延迟升高、定时任务重复执行和部分历史数据乱码。请从软件系统角度分析。
参考答案:首先要区分应用程序、运行时、数据库驱动、连接池、字符集、操作系统和配置的版本关系,确认是否存在隐含依赖。其次检查数据库迁移脚本、时间区、字符编码和排序规则,历史数据乱码可能来自连接字符集或转换链路不一致。定时任务重复执行可能是集群节点同时执行、锁机制失效或调度器语义变化造成的。接口延迟则要观察驱动行为、SQL 执行计划、连接池、GC 和资源使用。
改进方案包括建立依赖清单和版本矩阵,使用兼容性测试与生产数据脱敏回放;把数据库迁移和应用发布拆分,提供回滚和数据修复方案;对集群任务增加分布式锁、租约或集中调度;通过灰度发布、分批切流和指标对比控制风险;为关键接口定义 P95/P99、错误率和吞吐基线。结论不能简单写“升级前充分测试”,而应说明测试对象、场景、回滚和验证指标。
九、综合知识练习
练习 1
下列关于软件的说法正确的是( )。
A. 软件只包括源代码
B. 软件没有物理磨损,因此不需要维护
C. 软件系统还包括数据、配置、文档和运行环境
D. 应用软件可以完全脱离系统软件运行
答案:C。 软件交付和运行依赖程序、数据、文档、配置、环境和过程;软件会因需求、依赖、漏洞和环境变化而产生维护压力。
练习 2
系统软件、支撑软件和应用软件如何区分?数据库管理系统通常属于哪一类?
答案: 系统软件管理基础资源并提供运行环境;支撑软件为开发、运行、集成和管理提供通用能力;应用软件直接实现特定业务。数据库管理系统通常作为支撑软件,为应用提供数据定义、存储、查询、事务和安全能力。
练习 3
为什么架构设计师需要把质量属性转化为场景?
答案: “高可靠”“高性能”“易维护”等表述缺少可测量边界,无法指导设计和验收。转化为包含刺激源、环境、响应和响应度量的场景后,才能选择架构策略、制定测试方法、配置监控并判断是否达标。
十、论文素材
在项目建设中,我没有把系统视为孤立的代码集合,而是从系统软件、支撑软件、应用组件、数据、配置和运行环境整体规划。通过稳定接口隔离技术实现,建立版本矩阵和依赖清单,并把性能、可靠性、安全性和可维护性转化为可测量场景。上线采用灰度发布、配置审计、自动化回滚和运行监控,确保软件在需求变化和环境升级过程中能够持续演进。
论文使用这段内容时,应补充真实项目背景、关键约束、取舍原因和量化结果。高级论文最忌讳把技术名词平铺直叙,必须体现从业务需求到软件架构、从架构决策到验证结果的闭环。
十一、今日复盘
- 程序、软件和软件系统有什么区别?
- 软件为什么具有复杂性、易变性和不可见性?
- 系统软件、支撑软件和应用软件如何分工?
- 软件层次化带来了什么收益和代价?
- 一个完整的软件接口契约应包含哪些内容?
- 为什么质量属性必须转化成可验证场景?
- 技术栈升级时,如何控制版本、配置、数据和运行环境风险?
本节核心记忆句是:软件不是代码的简单集合,而是运行在特定环境中的可演化系统。架构设计师要用层次、接口、质量属性和生命周期把复杂的软件整体组织起来,为后续学习操作系统、数据库和中间件建立统一视角。