第一章 软件构造的多维视图和质量目标
第一章 软件构造的多维视图和质量目标
软件构造三个维度
-
build-run
-
code-component
-
moment-period
Buildtime Views
Code-level view代码层面
代码的逻辑组织
-
moment views
-
词汇层面:源代码
- 半结构化:近乎自然语言的风格+遵循特定的编程语法。前者:方便程序员;后者:方便编译器
-
语法层面:流程图Abstract Syntax Tree(AST)
- AST:彻底结构化,将源代码变为一棵树,对树做各种操作==对源代码的修改
-
语义层面:类图 Class Diagram
-
语义:源代码具体想实现什么目标?
源代码—现实世界 -
通常是图形化或形式化的
-
用于表达“需求”和“设计”思想,再转化成code(在设计阶段进行)
-
-
-
period views
- Code churn 代码变化
Component-level view构件层面
代码的物理组织
-
moment views
-
源代码-》文件-》包
-
可复用模块——库
-
像编程语言指令一样使用库中的功能
-
库的来源
-
操作系统提供的库
- 如文件和网络 I/O、GUI、数学、数据库评估
-
编程语言提供的库
- language SDK
-
第三方公司提供的库
-
你自己积累的库
-
-
默认搜索库的位置
- javac -classpath ./lib/*.jar
-
链接的两种方式之一
-
静态链接(Bulid阶段发生)
- 将需要的目标文件拷贝到可执行文件中形成整体,执行的时候无需提供库文件
-
-
-
构件图:Component diagram
各个子系统之间的链接方式
-
-
period views
-
软件实体随时间如何变化
-
Software Configuration Item (SCI ,配置项)
- Evolution Graph (of a SCI or a Software)
-
Version ( 版本 )
- Version Control System (VCS)
-
Runtime Views
Code-level view代码层面
逻辑实体在内存中如何呈现
-
Moment
-
Snapshot diagram(代码快照图:描述程序运行时内存里变量层面的状态)
-
Memory dump (内存信息转储)
- 内存转储:硬盘上的文件,包含进程内存内容的副本,当进程因某些类型的内部错误或信号而中止时产生。 调试器可以加载转储文件并显示其中包含的有关正在运行的程序状态的信息。 信息包括寄存器的内容、调用堆栈和所有其他程序数据(计数器、变量、开关、标志等)。 用于分析程序的状态,程序员查看内存缓冲区以查看失败时正在处理哪些数据项。
-
-
Period
-
Sequence diagram: UML中的序列图:程序单元(对象)之间的交互(函数级别调用图)
-
Execution tracing 执行跟踪
- 用日志方式记录程序执行的调用次序
- 给程序员看的
-
Component-level view构件层面
物理实体在物理硬件环境中如何呈现
-
Moment
-
Deployment diagram: UML 中的部署图
- 各个主机部署什么系统,怎么通信
-
-
Period
-
Event logging:事件日志:系统层面
-
为系统管理员提供了对诊断和审计有用的信息,有助于本地化并允许系统管理员更轻松地获取有关发生的问题的信息。
-
在开发周期中会考虑将记录的不同类别的事件,以及事件消息中将出现的详细信息。
-
每类事件都被分配一个唯一的“代码”来格式化和输出人类可读的消息。
-
对比
-
-
运行时软件的高级概念
-
Configuration and data files(配置和数据文件)
- 这些不是可执行文件; 它们提供程序可以从磁盘加载的有用数据和配置信息。(例如音乐软件使用的音频文件)
-
Distributed programs(分布式程序)
- 这种类型的软件由多个可执行程序组成,它们通过网络相互通信,或者只是作为在同一台机器上运行的多个进程。这与具有单个整体程序映像的更传统的软件形成对比。
- 例如,软件系统可能使用客户端/服务器模型,在一台计算机上运行单个服务器程序,在许多其他计算机上运行大量客户端程序。 在这种情况下,构建系统可以创建两个发布包,因为不同的人将安装服务器程序和客户端程序。 或者,可以使用相同的发布包来安装两个单独的程序。
-
Executable programs
-
Native Machine Code ( 原生机器码 )
- 将可执行程序完全转换为 CPU 的本地机器代码
- 这是执行代码最快的方式,因为程序完全访问 CPU 的功能
-
Full Program Interpretation ( 程序完全解释执行 )
- 运行时系统将整个源代码加载到内存中并对其进行解释(如 BASIC、UNIX shell 等)
-
Interpreted Byte Codes ( 解释型字节码 )
-
字节码类似于本地机器码,只是 CPU 不直接理解它们。 因此,字节码环境需要与程序一起加载额外的解释器或编译器。
-
Java
-
Perl 或 Python:它们被解释而不是编译,但在运行时使用字节码。执行 Perl 或 Python 脚本的简单行为会自动触发字节码的生成。 -
-
-
Libraries
-
动态链接(发生在运行阶段)
-
含义
- 不加入可执行文件中,只是记录程序需要哪些库
- 当程序开始运行时,库作为单独的实体加载到内存中,然后与主程序连接
- 发布软件时,记得将程序所依赖的所有动态库都 复制给用户
-
优点
- 升级库无需重新创建可执行文件
- 优化内存使用,多个程序共享库
-
-
软件系统的质量特性
关系
- 外部质量因素(用户可以检测到它们在软件产品中的存在与否)影响用户, 最后,只有外部因素才重要
- 内部质量因素 影响 软件本身和它的开发者:只有有权访问实际软件文本的开发人员才能察觉
- 外部质量取决于内部质量
外部质量
-
Correctness(正确性)
-
正确性:最重要的质量指标
-
按照预先定义的“规约”执行
-
每一层保证自己的正确性,同时假设其下层是正确的
-
确保正确性
- 测试和调试:发现不正确、消除不正确
- 防御式编程:在写程序的时候就确保正确性,例如使用断言
- 形式化方法:通过形式化验证发现(数学方法论证)
-
-
Robustness(健壮性)
-
健壮性是对正确性的补充
- 正确性:软件的行为要严格的符合规约中定义的行为
- 健壮性:出现规约定义之外的情形的时候,软件要做出恰当的反应,出现异常时不要崩溃
-
未被specification覆盖的情况即为“异常情况”, 所谓的“异常”,取决于spec的范畴
-
-
Extendibility(可扩展性)
-
对软件的规约进行修改 ,是否足够容易 ?
-
规模越大, 扩展起来越不容易
-
为什么要扩展 :应对变化
-
提高扩展性的两个原则
-
简约主义设计
- 架构简单
-
分离主义设计
- 模块独立自治
-
-
-
Reusability(可复用性)
- 发现共性,一次开发,多次使用
-
Compatibility ( 兼容性)
-
不同的软件系统之间相互可容易的集成
-
例如,文件格式的兼容,一个程序直接使用另一个程序的结果作为输入。
-
设计的同质性(保持设计的同构性),以及程序间通信的标准化约定
- 标准化文件格式,如在 Unix 系统中,其中每个文本文件只是一个字符序列。
- 标准化的数据结构,如在 Lisp 系统中,所有数据和程序都由二叉树表示(在 Lisp 中称为列表)。
- 标准化的用户界面,如在各种版本的 Windows、OS/2 和 MacOS 上,所有工具都依赖于单一范式与用户进行通信,基于标准组件,如窗口、图标等。
-
-
Efficiency(高效性)
- 性能毫无意义,除非有足够的正确性
- 对性能的关注 要与 其他质量属性进行折中,如可扩展性和可复用性,过度的优化导致软件不再适应变化和复用
- 过早优化是万恶之源
-
Portability (可移植性)
-
Ease of use (易用性)
- 容易学、安装、操作、监控
- 给用户提供详细的指南
-
Functionality(功能性)
- 每增加一小点功能,都确保其他质量属性 不受到损失
-
Timeliness (及时性)
- 是软件系统在用户需要时或之前发布的能力。
-
可验证性 是准备验收程序,尤其是测试数据,以及在验证和操作阶段检测故障并追踪错误的程序的容易程度。 完整性是软件系统保护其各种组件(程序、数据)免受未经授权的访问和修改的能力。 可修复性是促进缺陷修复的能力。 经济性,与时效性相伴,是一个系统在其分配的预算内或以下完成的能力。
内部质量
- Readability
- Understandability
- Clearness
- Size
质量属性之间的权衡
-
Integrity vs. ease of use
-
Economy vs. functionality
-
Efficiency vs. portability
-
Efficiency vs. reusability
-
Economy vs. reusability
-
Timeliness vs. extendibility
-
虽然需要折中,但“正确性”绝不能与其他质量因素折中。
-
正确的软件开发过程中,开发者应该将不同质量因素之间如何做出折中的设 计决策和标准明确的写下来
-
最重要的几个质量因素
-
Correctness and robustness: reliability
- • 软件构建的系统方法
- • 正式规范
- • 开发过程中的自动检查
- • 更好的语言机制
- • 一致性检查工具
-
Extendibility and reusability: modularity
-