首先在宏观上软件的生命周期基本可以划分为:需求收集和分析,可行性分析,系统分析,软件架构设计,编写代码,测试代码,整合代码,打包交付,运行和维护。但在具体实现过程又有不同的方式,比如传统的瀑布模型和现在比较流行的敏捷开发。
对于瀑布模型,其核心思想是按工序将问题化简,将功能的实现与设计分开,便于分工协作,即采用结构化的分析与设计方法将逻辑实现与物理实现分开。并基本严格按照上述的软件生命周期来自上而下的分工,具有相互衔接的固定次序,如同瀑布流水一样逐级下落。
而敏捷开发以用户的需求为核心,采用迭代、循序渐进的方法进行开发。在敏捷开发中,把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。其核心原则是主张简单,只基于现有的需求进行建模,并时刻准备着迎接新的变化,同时保证项目的可持续性。由于在实际开发时用户的需求不可能在一开始就完全确定,因此这样的敏捷开发原则更加实用,效率更高。
一、ADT1. 如何设计ADT?
设计ADT:设计规约Spec->表示不变性Rep->实现Impl
1.1 规约Spec的写法
- 方法注释
- @param 参数说明
- @return 返回值说明
- @throw 抛出异常
1.2 规约Spec的强度和评价1.2.1 规约Spec的强度:
- 前置条件越弱,规约强度越强;
- 后置条件越强,规约强度越强;
- 其他情况无法比较。
1.2.2 规约Spec的评价:
- 内聚的:一个好的规约Spec应该功能单一,易于理解;
- 信息丰富的:不产生歧义;
- 足够“强”的:使开发人员应该考虑足够多的异常情况并进行处理;
- 足够“弱”的:为开发人员减轻工作负担并降低开发成本。
1.3 抽象函数AF和表示不变量RI1.3.1 抽象函数AF:
- 表示R(表示空间)和A(抽象空间)之间关系的一个映射;
- AF:R->A;
1.3.2 表示不变量RI:
- 描述什么是合法的表示值;
- 是所有表示值的一个子集。
1.4 ADT实现Impl(表示泄露)
通过防御式拷贝,给客户端返回一个全新的对象,即使客户端修改了数据,也不会影响自己。然而大量的拷贝会占用内存空间,因此很多时候会使用不可变数据类型以节省频繁复制的代价。
2. ADT测试Test
需要注意的是,由于测试时开发者也相当于用户,因此不能直接访问ADT内部的数据域,只能调用其他方法测试待测的方法。
- 针对creater:构造对象后,用observer观察是否正确;
- 针对observer:用其他方法构造对象,调用被测observer,观察判断结果是否正确;
- 针对producer:produce一个新的对象,用observer观察结果是否正确。
二、OOP1. OOP的基本概念1.1 接口(Interface)
接口是一系列方法的声明,是一些方法特征的集合。
- 接口之间可以继承与扩展;
- 一个类可以实现多个接口;
- 一个接口可以有多个实现类。
1.2 抽象类
在类中只有一些方法声明,没有具体的方法(即未被实现,等待子类实现)。
- 抽象类至少有一个抽象方法
1.3 类
每个类包含数据说明和一组操作数据或传递消息的函数。
- 类必须实现抽象类中所有未被实现的方法。
1.4 继承(Inheritance)与重写(Override)
类与类之间是继承与被继承的关系; 类与接口是实现与被实现的关系。
登录后复制
重写:
- 参数列表必须与父类完全相同;
- 访问权限不能比父类中被重写的方法的访问权限更低;
- 声明为 final 的方法不能被重写;
- 构造方法不能被重写;
- 当需要在子类中调用父类的被重写方法时,要使用 super 关键字。
1.5 多态(Polymorphism)与重载(Overload)
多态:
多态是同一个行为具有多种不同表现形式或形态的能力。
- 可以消除类型之间的耦合关系;
- 可替换,可扩充;
- 灵活性,简化性。
重载: - 多个方法具有相同的名字,但具有不同的参数列表或返回值类型;
- 无法以返回值类型作为重载函数的区分标准;
- 被重载的方法可以声明新的或更广的异常。
三、 ADT和OOP中的等价性
1. 不可变对象
- “==”是引用等价,即两个引用指向了相同的内存空间;
- “equals()”是对象等价,即两个对象的域相同。
1.2 如何判断两个不可变对象相等
如果AF映射到同样的结果则等价。在自定义ADT中,如果要判断等价,需要重写equals()方法和hashCode()方法。
2.可变对象
2.1 观察等价性与行为等价性
- 观察等价性:在不改变状态的情况下,两个可变对象看起来是否一致;
- 行为等价性:调用对象的任何方法表现出一致的结果。
对可变数据类型,往往倾向于实现严格的观察等价性,但有些时候可能导致bud,甚至破坏RI。对于可变数据类型,无需重写equals()f方法和hashCode()方法,直接继承自Object即可,而如果一定要判断两个可变对象看起来是否一致,最好定义一个新的方法。
3.总结
- 等价性应该是一种等价关系;
- 抽象函数AF是等价性的基础。