软件构造之软件构造基础
注意
虽然说标题是“软件构造基础”,但是实际上这一篇可以认为是后面几篇文章的一个绪论,主要内容由接下来的若干篇同系列的文章组成。
从多维视角看软件构造(Multi-Dimensional Views of Software Construction)
引言
既然我们要学习的是软件构造,什么是软件?
软件的概念最早由阿兰·图灵提出
在我们的生活中,有各种各样的软件,比如说操作系统和应用程序,有PC端、web端、安卓端、IOS端的各种程序等等,它们都被称为软件。
计算机的交互层级示意图 |
---|
用户 |
应用程序 |
操作系统 |
硬件 |
而同时,我们对于软件系统的理解也不断的在改变:从过去到现在依次是:
- 程序
- 算法 + 数据结构
- 程序 + 数据 + 文档
- 模块(成分) + 数据/控制流
如今,我们的coding愈发集成化,模块化编程也占据了主流。
关键
以下的内容都将围绕如上的表格展开
从哪些维度来看软件构造
- 编程时&运行时
说到运行时的话,就不得不考虑程序在靶机上的运行情况,比如如何从磁盘中载出程序,如何载入到内存中等等。内存占用量、运行速度等等因素将会成为注意的对象。届时,我们将使用“代码快照”等方式来进行相应的观测。 - 微观&宏观
代码的视角(源代码):①源代码如何逻辑组成或依赖程序块(如函数、类、方法、借口等等) ②内存中的程序及其之间如何运行与交互;
模块的视角(结构):①源代码如何物理构成或依赖结构(如文件、目录、包、库等等) ②各个程序包如何在物理环境下配置、运行与交互; - 时刻&时期
时刻:某一特定的时间点,代码或模块如何,程序如何运行;
时期:随着时间的推移,代码或模块如何变化,程序如何运行;
编程时、某一时刻、代码视角
在此情况下,我们从小到大有如下三个方面:
- 词义层面
- 语法层面
- 语义层面
编程时、某一时期、代码视角
即:程序本身如何变化?
增、删、改等等
编程时、某一时刻、模块视角
- 源代码组成文件,进而组成目录
- 文件封装为包,逻辑上,也叫子系统和元件
- 可复用的模块形成库
开发者通常并不是从头开发程序,而多是选择复用库中的模块。库存在于各处,来源广泛,我们可以将其看成是一种对标准编程语言的补充。
库的使用方式有两种:动态链接以及静态链接。详细内容可以回顾计算机系统。
编程时、某一时期、模块视角
每一个模块是如何随着时间变化的呢?为了描述这一种变化,我们引入了版本控制系统,也就有了我们常常说的版本号。
在发布软件之后,事情并未结束。软件是需要随着市场、技术等等因素而进化(Software Evolution)的,软件中的各个部分也将优胜劣汰,成为更好地软件。有的时候,维护的费用甚至将占到开发费用的90%。
运行时、某一时刻、代码视角
将采用代码快照(Code Snapshot)的方式对代码进行观察,将分析内存的占用情况等等。(将在第03章中详细介绍)
运行时、某一时段、代码视角
利用UML以动态的形式描述类
运行时、某一时刻、模块视角
模块分析
运行时、某一时段、模块视角
log日志
各个视角之间的关系
- Ф → Code
Programming / Coding (Chapter 3 ADT / OOP)
Review, static analysis / checking (Chapter 4 Understandability) - Code → Component
Design (Chapter 3 ADT / OOP; Chapter 5 Reusability; Chapter 6 Maintainability)
Build: compile, static link, package, install, clean (Chapter 2 Construction process) - Build-time → Run-time
Install / deploy (Another course)
Debug, unit / intergration testing (Chapter 7 Robustness) - Moment → Period
Refactoring (Chapter 9 Refactoring)
Version Control (Chapter 2 SCM)
Loading, dynamic linking, interpreting, execution (dumping, profiling, logging) (Chapter 8 Performance)
总结
描述软件系统的三个维度
- 时期视角:编程时(build-time)&运行时(run-time)
- 动静视角:时刻(moment)&时段(period)
- 级别视角:代码(code)&模块(component)
每个视角的元素、关系以及模型
软件构造:视角的转换
- Ф → Code
- Code → Component
- Build-time → Run-time
- Moment → Period
再放上最最关键的图
软件构造的质量目标(Quality Objective of Software Construction)
大纲
软件构造的质量特征:
- 外部和内部质量因素
- 外部质量因素(使用相关):与用户直接相关,比如运行速度、易用性等等
- 内部质量因素(编程相关):与编程人员相关,比如模块化、可读性等等
- 我们的目标在于外部特性,但是内部特性影响甚至从某种意义上决定外部特性。
- 重要的外部质量因素
- 各个质量因素的权衡
软件构造的五大质量目标:
- 易于理解
- 易于改变
- 易于拓展
- 健壮性
- 运行效率
外部质量因素
正确性
正确性:若输入正确,则输出正确
正确性是最重要的质量标准。
保证正确性:
- 条件性:因为上层模块需要依赖下层模块,所以要想保证下层的模块是正确的。也就是说自底向上,保证每层都正确,同时调用也没有问题
- 通向正确性的方法:测试以及Debug
- 形式化方法:数学才可能保证程序的正确性
特别注意:测试只能证明程序错误,但是不可能证明程序是正确的。
健壮性
健壮性:若输入错误,而程序依旧正常工作
健壮性与正确性相辅相成。正确性是正常的情况,而健壮性是异常的情况。异常与正常往往取决于程序的规定本身。
有以下几种保证健壮性的处理方式:
- 异常 → 提示
- 异常 → 退出
- 异常 → 降级技术
总之,最好是在异常的情况下可以让程序就像什么都没有发生过一样,只是发出提示或者甚至不(比如作为服务器或者卫星等等的系统)。如果做不到,也得“优雅地退出”。
拓展性
扩展性:软件易于调整变化以适应新要求的能力。
一般来说,软件的规模越大就越难以扩展。
由于人们的需求是在不断改变的,所以我们不得不不断改变软件的功能。当软件大到一定的程度,不再有能力修改的时候,软件的生命周期也就走到了尽头。
提高扩展性:
- 解耦合:模块之间尽量不要过于依赖,也就是说:要尽量降低模块与模块的耦合性
- 简单:体系结构越简单,越容易变化
复用性
减少无用功,为程序员省事情。
如何复用:
- 调用库:内部库或者第三方库
- 调用自己或者同事的代码
适配性/兼容性
适配性也就是使软件与软件易于合作。
软件与软件之间需要相互联系,其开发与使用之间并不是完全割裂的。
但是,毕竟人与人之间的想法难以做到相同,程序员也是人,所以程序员之间的想法也难以做到相同。那么不同的软件之间就会有不同的规则与定义。
解决适配性的方法就是标准化。
标准化的方式:
- 协议
- 借口
- ……
效率
这里的效率是指软件系统对硬件资源的需求程度。
- 时间效率
- 空间效率
实际上,二者相互制约,矛盾只可缓解,不可调和。
移植性
移植性是指是否便于将软件产品移植到种种不同的硬件和软件环境之中。
易用性
其实这里的易用性也局势我们常常说的“用户体验”的问题。
易用性的目的就在于让用户易于使用我们开发出来的软件,包括了安装、运行以及监听的容易程度。
Key:
- 用户手册:给新用户提供相应的手册以及解释,这样做可以不用让老用户感到厌烦。
- 简单:简洁就是美
- 用户视角:站在用户的角度上去理解用户、思考用户,从而了解用户需要什么。也就是所谓的换位思考。
功能性
功能性:系统尽可能提供更加全面的功能。
问题:在程序设计的过程之中,程序员不断地给软件增加功能,试图满足用户全方位的需求,但是却使软件不断复杂化,变得笨重,导致无谓的空间占用。也就是说,过多的功能将会导致软件易用性的缺失。
Key:
- 先实现核心功能
- 逐步按照需要添加新功能,同时保持功能性以及易用性的平衡,让用户有良好的用户体验。
及时性
及时性:在用户需要时或者需要之前开发出来。
其他
- 可验证性:是否易于验证
- 完整性:软件系统保护其各个组件(程序和数据)免受未经授权的访问和修改的能力
- 可修复性:促进缺陷修复的能力
- 经济性:同及时性相伴,是系统按照其分配的预算或低于预算完成的能力
内部质量因素
- 源码相关因素
- 代码量
- 圈复杂度:用来衡量一个模块判定结构的复杂程度。
- 结构相关因素
- 高聚合
- 低耦合。
- 可读、可理解、清晰
- 复杂度
- 规模
内部质量因素通常用作外部质量因素的部分标准。
质量因素之间的权衡
程序员需要在多个方面进行平衡,而大部分时候,效率会成为主导因素。
- 完备性 VS 易用性
- 经济性 VS 功能性
- 效率 VS 可移植性
- 效率 VS 复用性
- 经济性 VS 复用性
- 及时性 VS 扩展性
在软件构造的过程中,质量的目标应当有明确指出。
当然,正确性永远是首位的。
软件构造的关键
软件构造中的五大质量目标
我们将在课程中完整地学习如何实现这几个目标及其权衡。
归纳
- 易于理解
- 易于改变
- 易于拓展
- 健壮性
- 运行效率