软件构造第一章(考点总结)
1.1
软件构造的多维视图
软件系统主要由三部分构成:
1. 程序 (UI, Algorithms, Utilities, APIs, test cases, etc)
2. 数据 (files, databases, etc)
3. 文件 (SRS, SDD, user manuals, etc)
软件构造的流程:
计划——分析——设计——声明——测试——维护
一.软件的多维视图:
首先讨论在Build-time,即构造阶段的四种视图。
Code-level view:
指代码的逻辑组织such as functions, classes, methods, interfaces,etc
Component-level view:
指代码的物理组织 such as files, directories, packages, libraries
Moment view:
特定时刻的软件形态
Period view:
软件形态随时间的变化
第一种视图:Build-time, moment, and code-level view(源代码是以什么逻辑组织的)
可以看成如下三方面:
1. 词汇方面:近乎自然语言的风格+遵循特定的编程语法。
2. 语法层面:比如Abstract Syntax Tree(AST),彻底结构化,将项目表示成一棵抽象树。
3. 语义层面:比如Class Diagram(UML)一种建模语言(类图)
通常是图形化和形式化的,用于表达“需求”和“设计”思想。
第二种视图:Build-time, period, and code-level view
该视图描述的是Code churn,即文件版本更迭的过程中,代码的增加,更改或删除。
第三种视图:Build-time, moment, and component-level view
代码按照一定的物理结构组织成文件时,形成了目录。
包和其他的构成元素合乎逻辑的组织,就形成了文件。
复用模块以libraries的形式出现。
介绍Library:
Libraries:存于它们自己的磁盘文件中,能被不同的程序复用。
In build-time:可以被看作是标准语言的扩展,开发者像使用编程语言指令一样使用库中的功能。
Sources of libraries:
1. 操作系统提供的库
2. 编程语言提供的库
3. 第三方公司提供的库
4. 你自己积累的库
Library的链接:
编程时和build 时,需告诉IDE 和JVM 在哪里寻找某些库。
有两种方式将Library整合到可执行程序:
– Static linking (静态链接)
– Dynamic linking (动态链接)
由于讨论在Build-time的情况,构造阶段发生的是静态链接。Library被拷贝进入代码形成整体,执行的时候就无需提供库文件了。
此维度也可以在UML中展示(Component diagram)
第四种视图:Build-time, period, and component-level view
指各项软件实体随时间如何变化(files/packages/components/libraries)
VCS/SCM:管理上述变化
1. SCI:配置项(文件)
2. Version:版本
3. Baseline:版本相对稳定状态
4. CMDB:配置管理数据库
其次讨论在Run-time,即运行阶段的四种视图。
Code-level view:
指源代码的内存状态。
Component-level view:
软件如何配置在物理环境中(OS, network, hardware, etc)。
Moment view与Period view:
与Build-time中所述相同。
Run-time软件的高级定义:
1. 可执行的程序
2. 复用的库
3. 配置信息和数据文件
4. 分布式编程
下面讨论上述四个方面:
1. 可执行的程序
将可执行的程序完全转为CPU的原生机器码,这种执行代码速度最快,因为它与CPU相匹配,这样程序将源代码完全载入内存并且编译,解释型字节码与原生机器码相同,如果CPU不能读解释型字节码,将它翻译成原生机器码即可。 Perl or Python(run-time)就是被解释,但不被编译,执行脚本也会引发解释型字节码的生成。
2. 复用的库(在执行阶段链接库的方法是动态连接)
动态连接的情况下,库文件不会在build阶段被加入到可执行文件,仅仅做出标记,
程序运行时,依据标记加载库的内容。
发布软件时,要将程序所依赖的所有动态库都复制给用户。
优点:1.升级新的库,而无需重新建立可执行程序。
2.能够与其他的程序共享
3. 配置信息和数据文件
一般的程序如果使用额外的数据源,比如磁盘上的文件
程序在操作系统执行,需要把它的数据读入内存
4. 分布式编程
分布式程序的运行态:需要多个运行程序,分别部署于多个计算机物理环境。
言归正传:
第五种视图:Run-time, moment, and code-level view(指内存的状态)
查看内存的两种方式:
1. 快照图:描述程序运行时内存里变量层面的状态
2. Memory dump (内存信息转储)
第六种视图:Run-time, period and code-level view(程序执行时调用的关系次序)
查看调用的关系次序的两种方式:
1. UML中的 Sequence diagram(顺序图)
显示出程序单元之间的相互作用
2. Execution tracing 执行跟踪
用日志方式记录程序执行的调用次序
第七种视图:Run-time, moment, and component-level view
UML中的Deployment diagram(配置图)
第八种视图:Run-time, period, and component-level view
Event logging为系统提供需要的判断信息,event中的每个类都对应一个特别的“码”,统一格式化并输出可读的信息。
代码层面的跟踪Execution tracing与系统层面的日志event logging的比较
二.软件的构造可以看作不同视图之间的转换
1.2
软件构造的质量目标
一.软件系统的质量属性
外部质量指的是 速度和用户使用是否舒心。
内部质量指的是 软件本身可读性如何,针对的是它的开发者。
外部质量取决于内部质量。
1. 外部质量因素
(1)正确性:软件的行为要严格的符合规约中定义的行为。
①通过分层确保正确性(每一层保证自己的正确性,同时假设其下层是正确的)
②测试 和 调试 :发现不正确、消除不正确
③防御式编程:在写程序的时候就确保正确性
④形式化方法:通过形式化验证发现问题
(2)健壮性:出现规约之外的情形的时候,软件做出恰当的反应。
健壮性是对正确性的补充,出现 异常时不要“崩溃”。
“normal ”和“abnormal ”是主观而非客观,未被specification覆盖的情况即为“异常情况”,所谓的“异常”,取决于spec的范畴。
(3)可扩展性:随着程序规模越大,扩展起来越不容易,为了应对变化,需要遵从简约主义设计和*设计。
(4)可复用性: 一次开发,多次使用。关键是能够发现共性。
(5)兼容性:不同的软件系统之间相互可容易的集成。
方法:保持设计的同构性。
标准化:文件格式,数据结构,用户界面,协议
(6)性能:时间,空间,内存,带宽。
性能毫无意义,除非有足够的正确性。
对性能的关注要与其他质量属性进行折中。
过度的优化导致软件不再适应变化和复用。
(7)可移植性:软件可方便的在不同的技术环境(比如硬件、操作系统)之间移植。
(8)易用性:容易学习,安装,操作,监控,结构简单,
并给用户提供详细的指南。
(9)功能:程序设计中一种不适宜的趋势,即软件开发者增加越来越多的功能,企图跟上竞争,其结果是程序极为复杂、不灵活、占用过多的磁盘空间。
(10)及时性。
2. 内部质量因素
(1)代码的行数(LOC)
(2)复杂度
(3)耦合度与聚合度
(4)易读易理解
(5)整洁
3. 内部外部质量折中
完整性 与 易用性
经济性 与 功能
经济型 与 可复用性
性能 与 可复用性
性能 与 可移植性
及时性 与 可扩展性
正确的软件开发过程中,开发者应该将不同质量因素之间如何做出折中的设
计决策和标准明确的写下来。
虽然需要折中,但“正确性”绝不能与其他质量因素折中。
二.软件构造过程中五个关键质量目标
1. 易于理解
2. 开发的经济性(复用性)
3. 能够应对变化(可扩展性)
4. safe from bug(健壮性与正确性)
5. 运行效率
下面是不同的质量目标在不同视图中的体现