软件构造的视角和质量
软件多维视图
build time & moment | build time & period | runtime & moment | runtime & period |
---|---|---|---|
code level | AST/SourceCode/class Diagram | Git(代码变化) | Snapshot |
component level | File/Package/library component Diagram | 软件部署 | 系统层面的事件日志 |
软件构造的质量指标——在不同质量指标之间进行折中,并明确记录
第一章
内部质量指标—>开发者
外部质量指标—>用户
开发者高于用户
★正确性——spec
五大质量
- 健壮性(chapter7)——对于正确性的补充,处理spec中没有明确的情况
- 可拓展性(chapter6)——应对变化的能力(可维护性)主观地判断
- 可复用性(chapter5)——1.一次开发 2.多次使用
- 可理解性 (chapter4)
- 效率(chapter8) 性能必须建立在正确性的基础上(过早的优化是万恶之源)
外部:
- 正确性
- 健壮性
- 可拓展性
- 可复用性
- 兼容性(不同软件系统之间可互相容易集成)
- 性能
- 可移植性
- 易用性(易学,易安装,易操作)
- 功能性(每增加一点功能,能确保其他属性不损失)
- 及时性(及时发布)
- 可验证性,完整性,可修复性,经济性等等
内部:
Loc 耦合性,聚合性,可理解性,clearness
第二章软件开发遵循的过程(从无到有,从有到优)
软件的声明周期(SDLC)
需求——设计——构造——测试——部署——运维
构造与测试是SC重点关注的
编程——代码评审——性能分析——测试——调试——重构——build
(以上为线性过程)
第3章 ADT和OOP的相关技术
数据类型分为两种,第一个是基本数据类型:有值无ID,在栈中存储,不可变
第二个是对象数据类型:有值有ID,在堆中存储
静态 | 编译阶段:与类型相关 (Java) | 语法错误、类名、函数名错误(final变量不可变) |
---|---|---|
动态 | 运行阶段:与"值“相关(python) | 非法参数(除0)、越界、空指针、不变类型的不变 |
(change a variable)
改变一个变量:将该变量指向另一个存储空间
(change a value)
改变一个变量的值:将该变量空间写入一个新的值
Immutability : final 值不可改,引用不可改
可变对象:拥有方法可以修改自己的值/引用 stringBuilder
不可变对象:一旦被创建始终指向同一个引用/值
Risk of mutation
- 传递可变类型的参数(可以改变其中的值,再次使用问题)
- 返回可变类型的数据(如果接收方进行修改,或影响到程序内部)
常见的不变类型:基本类型包装类。Collecions。unmodifiablexxx
specification :用于人与人之间的交流
代码中蕴含设计策略——>final 关键字的使用
注释形式documenting——>给人读 pre-condition post-condition
contract(合同):明确责任,解耦,隔离变化
输入输出数据类型
功能性和正确性 ====》只讲能做什么,不讲怎么做 ===》行为等价性
性能
设计规约:易于理解的,内聚的 ,private 可以不用前置条件,内部自用,public,必须使用前置条件
ADT 的特性;不变量,表示泄露,抽象函数AF,表示不变量RI,★通过封装来避免客户端获取数据内部表示,
数据抽象:由一组操作所刻画的数据类型,与内部的具体实现无关
可变数据类型:有操作可改变内部值(mutator)
不可变数据类型:操作不能改变内部值,而是构造新对象
工厂
creator : t*-》T; producer: T+,t* -》T;
observer:T+,t*-》T; mutator(变值器):T+,t*->void|t|T
CT是抽象数据型,t是其他数据型,其余语法类比Re
设计ADT:
- 设计简洁,一致的操作
- 需要支持所有的操作
- 要么具体,要么抽象
表示独立性:
- 客户使用时无需考虑内部的实现
- ADT内部变化不影响外部spec和客户端观察
RI(Rep Invariant)表示不变量
表示某个表示是否合法,表示所有表示值的一个子集
对immutable ADT —》Beneficent mutation
检查不变量的三个标准
- 创建时确保
- 改变/观察时博爱吃
- 没有表示外泄,利用参数中的ADT来维护pre-post-condition
ADT invariants 取代 (利用参数中的adt来维护pre-post-condition)
ADT 的一种实现技术: OOP(Object-oriented-programming)
object state:field(属性Java中)
behavior: methods(方法,Java中)
static 类成员变量,类方法 《===》实例成员变量,实例方法
Interface -》定义ADT : class—》实现ADT
避免客户端直到该接口的实现类的名称:工厂函数
封装与信息隐藏
- 使用接口类型声明变量
- 客户端仅使用接口中定义的方法
- 客户端代码无法直接访问属性
继承和重写(Inheritance and Overriding)
Override :完全相同的signatur(参数列表,返回值);实际执行调用的方法运行时决定
抽象类:至少包含1个抽象方法,可以有fields
抽象方法:必须没有实现体(abstract修饰)
三种多态
- 特殊多态,Overload
- 参数化多态,泛型
- Subtyping(多类型多态,包含多态)
Overload:根据参数列表进行最佳匹配
如下
Java中的泛型(参数化多态)
- wildcards(通配符) 只能在使用时出现,不能定义
- 不能用instanceof检验泛型(类型擦除)
- 不能构建泛型数组
子类型多态:LSP原则,子类型的规约不能弱于父类型的规约
静态分派:编译阶段确定执行操作
动态分派:编译阶段可能绑定到多态操作
Object 中重要方法
toString(),equals(),hashcode()(其中equals和hashcode()必须同时override)
ADT和OOP中的等价
3种方式判断等价
- AF:AF映射到同样的结果,则等价
- relation:等价关系(自反,对称,传递)
- 利用observation:站在外部观察者角度看等价性
引用等价性:对于基本数据类型(==)
对象等价性:对于对象,使equals (Object种缺省判断引用等价)
可变数据类型的等价性
观察等价性:在不改变状态情况下,两个mutable对象是否看起来一致
行为等价性:调用对象的任何方法都展示一致结果
Collections=》观察等价性=》mutation改变hashcode
stringBuilder=》行为等价性=》引用等价,继承Object