Software Construction of HIT
文章目录
- Software Construction of HIT
- Chapter 3 Software Construction Process and Configuration Management
- 1 Software Development Lifecycle (SDLC)
- 2 Traditional Software Process Models
- 3 Agile Development
- 4 Software Configuration Management (SCM) and Version Control System (VCS)
- 5 Git as an example of SCM tool
- 6 General process of software construction
- 7 Narrow-sense process of software construction (Build)
- Chapter 4 Data Type and Type Checking
Chapter 3 Software Construction Process and Configuration Management
1 Software Development Lifecycle (SDLC)
1.1 Lifecycle of a software
From 0 to 1 From 1 to n
2 Traditional Software Process Models
2.1 Two basic types
- Linear 线性过程
- Iterative 迭代过程
2.2 Existing models
-
Waterfall (Linear, non-iterative) 瀑布过程
-
Incremental (non-iterative) 增量过程
-
V-Model (for verification and validation) V字模型
-
Prototyping (iterative) 原型过程
在原型上持续不断的迭代发现用户变化的需求。迭代:开发出来之后由用户试用/评审,发现问题反馈给开发者,开发者修改原有的实现,继续交给用户评审。循环往复这个过程,直到用户满意为止。时间代价高,但开发质量也高。
-
Spiral (iterative) 螺旋模型
非常复杂的过程:多轮迭代基本遵循瀑布模式每轮迭代有明确的目标,遵循“原型”过程,进行严格的风险分析,方可进入下一轮迭代。
3 Agile Development
敏捷开发:通过快速迭代和小规模的持续改进,以快速适应变化。
极限编程:
4 Software Configuration Management (SCM) and Version Control System (VCS)
4.1 Software Configuration Management
SCM 软件配置管理:追踪和控制软件的变化。
SCI 软件配置项:软件中发生变化的基本单元(例如:文件)。
4.2 Version Control System
- Local VCS:仓库存储于开发者本地机器,无法共享和协作
- Centralized VCS:仓库存储于独立的服务器, 支持多开发者之间的协作
- Distributed VCS:仓库存储于独 立的服务器+每个开 发者的本地机器
5 Git as an example of SCM tool
5.1 Managing changes in software evolution process
可能 考察git
的具体操作指令,但都是实验涉及到的。
详细的可以参考本人另外的两篇博客:Git基础小记——Chapter 1 起步 Git基础小记——Chapter 2 记录更新到仓库
5.2 Commits: nodes in Object Graph
- 每个子版本有0(根)、1或2(合并)个父版本
- 每个父版本可能有多个子版本
5.3 Managing changes in Git
- Traditional VCS:
存储的是局部的变化,看版本差异方便。
- Git:
存的是整体,看版本差异时间的复杂度高。
5.4 Git supports Branch and Merge
合并时要考虑他们的公共祖先版本,如果有冲突要人工解决。
# 切换分支
git checkout branch
# 创建并切换到新的分支
git checkout -b newbranch
# 合并HEAD分支和thisbranch
git merge thisbranch
6 General process of software construction
这一部分属于该课程的了解内容,就略提一下。
6.1 Programming
从用途上划分:
-
Programming languages:C, C++, Java, Python
-
Modeling languages (e.g., UML)
-
Configuration languages (e.g., XML, YAML, JSON)
-
Build languages (e.g., XML)
6.2 Review and static code analysis
6.3 Dynamic code analysis / profiling
6.4 Debugging and Testing
6.5 Refactoring
7 Narrow-sense process of software construction (Build)
粗略理解build:build-time→run-time 借助于工具,将软件构造各阶段的活动“自动化” (编译、打包、静态分析、测试、生成文档、部署、…) 尽可能脱离“手工作业”,提高构造效率。
-
General process of software construction:
Design→Programming/refactoring→Debugging→Testing→Build→Release
-
Narrow-sense process of software construction (Build): Validate→Compile→Link→Test→Package→Install→Deploy
Chapter 4 Data Type and Type Checking
1 Data type in programming languages
1.1 Types in Java
1.2 Hierarchy of object types
对象类型形成层次结构,是继承extends
关系。根是Object
,也即是说所有非基础数据类型都是objects
。
2 Static vs. dynamic data type checking
2.1 Conversion by casting
自动类型转换:整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。转换从低级到高级。
- byte,short,char—> int —> long—> float —> double
- boolean不能进行类型转换
- 低位数类型可以自动向高位数类型转换
2.2 Static Typing vs. Dynamic Typing
- Java是静态类型语言:在编译阶段进行类型检查。
- Python是动态类型语言:在运行阶段进行类型检查。
静态类型检查 >> 动态 >> 无检查。静态类型检查可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正确性/健壮性。
2.3 Static vs. Dynamic Checking
-
Static checking
- Syntax errors 语法错误
- Wrong names 类名/函数名错误
- Wrong number of arguments 参数数目错误
- Wrong argument types 参数类型错误
- Wrong return types 返回值类型错误
-
Dynamic checking
- Illegal argument values 非法的参数值:如除0错误
- Unrepresentable return values 非法的返回值
- Out-of-range indexes 越界
- Calling a method on a null object reference 空指针
静态检查:关于“类型”的检查,不考虑值
动态检查:关于“值”的检查
3 Mutability and Immutability
Immutability改变一个变量:将该变量指向另一个值的存储空间。
Mutability改变一个变量的值:将 该变量当前指向的值的存储空间中写入一个新的值。
3.1 Mutability and Immutability
- 不变性
-
Immutability
-
不变数据类型:一旦被创建,其值不能改变
-
如果是引用类型,通过关键词
final
也可以是不变的:一旦确定其指向的对象,不能再被改变。final定义常量,常量在定义时进行初始化后就不可再次赋值,再次赋值会导致编译错误。但是这里说的不能赋值是指不能改变它的指向,它的值还是是可以通过方法改变的,因为这样并没有改变它的指向。
-
Note:
- final类无法派生子类
- final变量无法改变值/引用
- final方法 无法被子类重写
-
-
不变对象:一旦被创建,始终指向同一个值/引用。
可变对象:拥有方法可以修改自己的值/引用。
-
String and StringBuilder:
String s = "a";
s = s.concat("b");
String t = s;
t = t + "c";
StringBuilder sb = new StringBuilder("a");
sb.append("b");
StringBuilder tb = sb;
tb.append("c");
Snapshot diagram:
3.2 Defensive Copying
-
使用不可变类型,对其频繁修改会产生大量的临时拷贝(需要垃圾回收) 。
可变类型,最少化拷贝以提高效率。但是也有风险:-
Risk:
- passing mutable values:它可能会不经意间改变了输入参数的值!这种错误非常难于跟踪和发现。
- returning mutable values:改变一个变量值的同时,另一个与之相关联的值也被改变了。
-
How to modify the code:
- 通过防御式拷贝,给客户端返回一个全新的该mutable对象。如:
return new Date(groundhogAnswer.getTime());
。大部分时候该拷贝不会被客户端修改,可能造成大量的内存浪费,如果使用不可变类型, 则节省了频繁复制的代价。
- 通过防御式拷贝,给客户端返回一个全新的该mutable对象。如:
-
Aliasing is what makes mutable types risky:
- 安全的使用可变类型:局部变量,不会涉及共享;只有一个引用
- 如果有多个引用(别名),使用可变类型就非常不安全
理想情况下,我们应该让用户只能调用内内部的操作(我们提供的)去改变值。
An Example of Defensive Copying:
下面是一个原始的不好的例子:
public final class Period { private final Date start, end; // 暴露点1 public Period(Date start, Date end){ this.start = start; // 暴露了 this.end = end; // 暴露了 } // 暴露点2 public Date start(){ return start; // 暴露了 } public Date end(){ return end; // 暴露了 } public static void main(String[] args) { Date start = new Date(); Date end = new Date(); Period p = new Period(start, end); end.setTime(88); // 暴露点1: 直接修改了p的内部值,导致了信息暴露 p.end().setTime(99); // 暴露点2: 直接修改了p的内部值,导致了信息暴露 } }
修改后的:
public Period(Date start, Date end){ this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); } public Date start(){ return new Date(start.getTime()); } public Date end(){ return new Date(end.getTime()); }
-
4 Snapshot diagram
As code-level, run-time, and moment view.
4.1 Primitive and Object values in Snapshot Diagram
-
Primitive values
-
Object values
4.2 Reassignment and immutable/mutable values
-
不可变对象:用双线椭圆
String s = "a"; s = s + "b";
-
可变对象:用单线椭圆
StringBuilder sb = new StringBuilder("a"); sb.append("b");
4.3 Unreassignable/Immutable references
- 不可变的引用:用双线箭头
-
An immutable/unreassignable reference to a mutable value whose value can change even though we’re pointing to the same object. 引用(指向的地址空间)是不可变的,但指向的值却可以是可变的。
final StringBuilder sb = new StringBuilder("abc"); sb.append("d"); // 该方法没有改变sb的指向 // sb = new StringBuilder("e"); // 编译出错,改变了sb的指向 System.out.println(sb); // 输出"abcd"
-
A mutable/reassignable reference to an immutable value, where the value of the variable can change because it can be re-pointed to a different object. 可变的引用,也可指向不可变的值。
String s1 = new String("abc"); List<String> list = new ArrayList<String>(); // list是mutable,String是immutable list.add(s1); s1 = s1.concat("d"); // s1的指向此时已经不再和list[0]一致 System.out.println(list.get(0)); // 输出"abc" String s2 = s1.concat("e"); list.set(0, s2); System.out.println(list.get(0)); // 输出"abcde"
-
immutable object VS immutable reference
- immutable object(like a String) :不变的是值,指向(引用)是可变的。
- immutable reference(like a final StringBuilder):**不能变的是引用,值是可以变的。**final不影响StringBuilder本身是mutable对象。
5 Complex data types: Arrays and Collections
5.1 Array
int[] a = new int[100];
char[] a = new char[100];
...
5.2 List
List
是一个interface
。
List<Integer> list = new ArrayList<Integer>();
...
5.3 Set
Set
是一个 abstract interface
,它无序且不允许出现重复值。
Set<Integer> set = new Hashset<Integer>();
...
5.4 Map
Map
类似dictionary (key-value)
,它是一个abstract interface
。
Map<String,ArrayList<Integer>> map = new HashMap<>();
5.5 Iteration
List<String> cities = new ArrayList<>();
// 隐式
for (String city : cities) {
System.out.println(city);
}
// 显式
Iterator iter = cities.iterator();
while(iter.hasNext()){
String str = (String) iter.next();
System.out.println(str);
}
An iterator has two methods:
-
next() returns the next element in the collection — this is a mutator method
-
hasNext() tests whether the iterator has reached the end of the collection
Mutation undermines an iterator:考虑删除以6.
开头的那个例子,使用remove
导致的错误。
6 Useful immutable types
-
The primitive types and primitive wrappers are all immutable. 基本类型及其封装对象类型都是不可变的。
-
The usual implementations of Java’s collections types — List, Set, Map — are all mutable: ArrayList, HashMap, etc.
-
The Collections utility class has methods for obtaining unmodifiable views of these mutable collections.这种包装器得到的结果是不可变的:只能看。但是这种“不可变”是在运行阶段获得的,编译阶段 无法据此进行静态检查。
List<String> list = new ArrayList<>(); list.add("ab"); List<String> listCopy = Collections.unmodifiableList(list); listCopy.add("c"); // java.lang.UnsupportedOperationException