目录链接
这次笔记我们学习一下软件构造课程的第一部分,代表着软件构造的基础内容。
一、软件构造的多维度视图和质量目标
1.1软件的多维视图(Multi-dimensional software views)
1.1.1软件的概念及结构
软件是由计算机之父艾伦·图灵(Alan·Turing)提出的概念。国标中对软件的定义为:与计算机系统操作有关的计算机程序、规程、规则,以及可能有的文件、文档及数据。
对于软件的概念定义经历了如下演变:
可以看到,软件的定义先是程序和代码,之后变成了算法+数据结构,最后演变成了现今的主流认知:程序+数据+文档,或是模块+数据+控制流。
软件的成分如下:
软件的结构包括了用户端、软件、技术环境、硬件网络、社交网络等等,其中用户端是商业目标的执行者,而软件的执行结果就是商业目标的实现。从图中可以看出,软件就像一个黑盒一样,里面的程序可见但数据与文件不可见。
软件又有其SDLC,即生命周期。生命周期内容如下图所示:
从图中可见,程序的生命周期包括计划、分析、设计、填充、测试、维护等,包含很多子内容,在此不加赘述。
1.2 软件的多维视图(重点)
这张图就是软件的多维视图。可以看到,它将软件分成了两个阶段:构造阶段和运行阶段,并将其中内容分为四类,它们分别是代码级视图(Code-level view),组件级视图(Component-level view),瞬时视图(Moment view)和阶段视图(Period view)。其中阶段视图和瞬时视图是一对,代码级视图和组件级视图是一对。
1.2.1 软件的构造时视图
软件的构造时视图内容如下:
代码级视图:代码的逻辑组织,如函数、类、方法、接口等;
组件级视图:代码的物理组织,如文件、目录、包、库等;
瞬时视图:特定时刻的软件形态,如源码、类结构等;
阶段视图:软件形态随时间的变化,如代码变化等。
1.2.1.1 目录
目录属于组件级视图和瞬时视图,内容如下:
源代码被物理组织成文件,进一步按目录组织;
文件被封装到包中,并且在逻辑上封装到组件中和子系统。
可重用模块以库的形式出现。
库存储在磁盘文件中,可以在各种程序中重用的函数。
库就是在编辑java语言时的package,其中涉及到的方法可以直接由开发者调用。库的种类也有很多,如外部库、操作系统库、自己编写的库等。
这些东西就是我们在编写java程序时的目录界面。
1.2.1.2 静态链接
编程时和build时,需告诉IDE和JVM在哪里寻找某些库。
链接分为动态链接和静态链接,构造时视图发生的是静态链接(static linking)。静态链接是发生在构造阶段的,在此阶段中静态库被拷贝进代码形成整体,因此执行的时候无需提供静态库文件,只需用代码即可。
1.2.1.3 代码变化
代码变化(code churn)属于阶段视图和代码级视图,指的是从一个版本到另一个版本的文件中添加、修改或删除的行。
1.2.1.4 版本控制
版本控制属于阶段视图和组件级视图的内容,如图所示:
版本控制是给计算机软件的不同状态分配唯一的名字或者编号的过程,这个过程我们在之后会说到,此处不再赘述。
1.2.2 软件的运行时视图
软件的运行时视图是程序被载入目标机器,开始执行的过程,其内容如下:
代码级视图:逻辑实体在内存中如何呈现,如代码快照、内存转储等;
组件级视图:物理实体在物理硬件环境中如何呈现,如包、库、动态链接、数据库、网络、硬件等;
瞬时视图: 逻辑/物理实体在内存/硬件环境中特定时刻的形态如何,如代码快照、内存转储等;
阶段视图:逻辑/物理实体在内存/硬件环境中的形态随时间如何变化,如堆栈轨迹、并发线程等。
1.2.2.1 动态链接
在运行时发生的链接叫做动态链接(Dynamic linking)。动态库文件不会在build阶段被加入可执行软件中,仅仅做出标记,而在程序运行时,根据标记装载库至内存,因此我们在发布软件时,要将将程序所依赖的所有动态库都复制给用户,而这也正是我们向git提交作业时要提交外部库的原因。
相较于静态链接,动态链接的优点如下:
1.类库变化时,不需要重新生成可执行程序
2.多个运行中程序可共享同一类库,优化内存的使用
1.2.2.2 分布式程序
分布式程序描述了一种情况:需要多个运行程序,分别部署于多个计算机物理环境。
这时候我们就需要采用分布式程序的运行态:不同节点上可运行同样的程序或者不同的程序(C/S),需要不同的build策略。
1.2.2.3 代码快照图(Code snapshot)
代码快照图属于代码级视图和瞬时视图,它可以描述程序运行时,某时刻内存里变量层面的状态。
1.2.2.4 内存信息转储
内存信息转储同属代码级视图和瞬时视图,它代表了一个硬盘文件,这个文件包含进程内存内容的副本,当进程因某种内部错误或信号而中止时产生。调试器可以加载转储文件并显示其中信息,包括寄存器的内容、调用堆栈和所有其他程序数据(计数器、变量、开关、标志等),以便于分析程序的状态。
程序员可以通过查看内存缓冲区来查看在程序中止时正在处理哪些数据项。
1.2.2.5 执行跟踪
执行跟踪属于代码级视图和阶段视图,它能用日志方式记录程序执行的调用次序,如图所示:
1.2.2.6 事件日志
事件日志属于组件级视图和阶段试图,属于系统层面,它为系统管理员提供了对诊断和审计有用的信息。
1.3视图转换
▪ 产生代码
– 编程/编码 (ADT/OOP)
– 审查、静态分析/检查
▪ 代码级视图到组件级视图
– 设计(ADT/OOP;可重用性;可维护性)
– 构建:编译、静态链接、打包、安装等
▪ 构建时视图到运行时视图
– 安装/部署
– 调试、单元/集成测试(稳健性和正确性)
▪ 瞬间视图到周期视图
– 版本控制
– 加载、动态链接、执行(转储、分析、日志记录)
– 并发线程
1.4 软件质量
软件质量涉及的方面分为内部质量和外部质量。
1.4.1 外部质量
1.4.1.1 正确性
最重要的指标,按照预先定义的“规约”执行。
测试和调试:发现不正确、消除不正确
防御式编程:在写程序的时候就确保正确性
形式化方法:通过形式化验证发现问题
1.4.1.2 健壮性(鲁棒性)
健壮性是针对异常情况的处理,是对正确性的补充:
正确性:软件的行为要严格的符合规约中定义的行为
健壮性:出现规约定义之外情况的时候,软件要做出恰当的反应
健壮性保证了软件出现异常时不要“崩溃”,即出现了规约之外的情形时要做出恰当反应。
1.4.3.1 其他重要性能
可扩展性
对软件的规约进行修改,是否足够容易
可复用性
一次开发,多次使用
兼容性
不同的软件系统之间相互可容易的集成
性能
程序的效率
对效率的要求要建立在正确性的基础上,对性能的关注要与其他质量属性进行折中,过度的优化会导致软件不再适应变化和复用。
可移植性
软件可方便的在不同的技术环境之间移植,包括硬件和操作系统
易用性
对用户而言容易学、安装、操作、监控
功能性
程序功能的多少
程序设计中一种不适宜的趋势,即软件开发者增加越来越多的功能,企图跟上竞争,其结果是程序极为复杂、不灵活、占用过多的磁盘空间,忽视整体质量,失去可持续性。
及时性
在用户有对应需求前放出新版本
其他性能还包括可验证、完整性、可修复性、经济性等。
1.4.2 内部质量
源码方面:行数(LoC)、逻辑复杂度。
结构方面:耦合、内聚。
除此之外还有代码可读性、易于理解、清晰、大小等。
1.5 总结
质量的核心因素如下:
其分别设计的部分如下: