软件构造总结

第一章 基础

按照阶段划分

  • Build Time:构思算法、需求、设计、写代码,例如configuration,static link
  • Run Time:运行时,程序被载入目标机器,开始执行,例如dynamic link

按动态性划分

  • moment:时间点,例如snapshot,memory dump
  • period:时间段,例如log,stack trace

按构造对象划分

  • code:代码层面
  • component:组件层面,如log

衡量指标

  • 外部指标有:正确性(分层,防御式,形式化验证),健壮性,可扩展性,可复用性,兼容性,性能,可移至性,易用性,功能性,及时性。
  • 内部指标:LOC,圈复杂度,耦合度,内聚度。

第二章 软件生命周期

  • 瀑布过程

  • 增量过程

  • V字模型
  • 原型过程
  • 螺旋模型

敏捷开发

git

git仓库三部分:

  • .git 本地的CMDB
  • 本地文件系统
  • 暂存区

pull = fetch + merge

第三章 ADT设计

静态类型检查

在编译阶段检查。

你所有能想到的Compile Error

1
2
3
int a = "10";
Math.sin("10");
...

检查”类型”的错误

动态类型检查

  • divide by 0
  • 数组越界
  • 空指针

检查”值”的错误

1
2
3
int a = 10;
int b = 0;
System.out.println(a / b);
1
2
Exception in thread "main" java.lang.ArithmeticException: / by zero
at test.TestLock.main(Abc.java:16)

-> 动态类型错误

1
2
3
double a = 10;
double b = 0;
System.out.println(a / b);
1
Infinity

Mutable vs. Immutable

对象的引用

final

  • final类无法派生子类
  • final变量无法改变值/引用
  • final方法无法被子类重写

不变对象:一旦被创建,始终指向同一个值/引用
可变对象:拥有方法可以修改自己的值/引用

Immuatable类没有mutator。

Safe:

对于mutable类进行防御性拷贝。

Specification

1561364447298

行为等价性:站在客户端视角看。

1561364647015

前置条件 requires …

设计规约

规约强弱

S2 >= S1 当S2比S1前置条件更弱(宽松),后置条件更强(严格)。

S2可以代替S1。

Trick:更强的spec让programmer编程更困难一些。

ADT设计

creator:构造器,如Integer.valueOf()

producer:生产器,如concat()

observer:观察器,如size()

mutator:变值器,如List.add()

选择某种特定的表示方式R,进而指定某个子集是“合法”的(RI),并为该子集中的每个值做出“解释”(AF)——即如何映射到抽象空间中的值。

具体设计AF和RI:

AF:解释合法的表示值,如AF(field1, field2…) = graph (V, E)

RI:一个条件,描述了什么是“合法”的表示值

Safety from rep exposure:表示泄露安全声明

例子:

面向对象编程

继承

重写/重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
public Object function(Object t) {
return "1";
}
}

class B extends A {
@Override
public String function(Object t) {
return "1";
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.function(new String("1")));
}
}

== vs. equals

a equals b 充要条件:AF(a) == AF(b)

重写equals必须重写hashCode

equals的hashCode一定要相等

第5章 复用

Guava/Apache Commons

在java中:

  • 子类型可以增加方法,但不可删
  • 子类型需要实现抽象类型中的所有未实现方法

  • 子类型中重写的方法必须有相同或子类型的返回值

  • 子类型中重写的方法必须使用同样类型的参数
  • 子类型中重写的方法不能抛出额外的异常

LSP原则

强行为子类型化

  • 更强的不变量

  • 更弱的前置条件

  • 更强的后置条件

即子类型的Spec要父类型Spec强。

1
List<Integer> list = new ArrayList<>();

java里没有协变、反协变,都是重写

1
2
3
4
5
6
Number[] numbers = new Number[2];
numbers[0] = new Integer(10);
numbers[1] = new Double(3.14);
Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;
myNumber[0] = 3.14; //run-time error!

泛型

  • ArrayList<String> is a subtype of List<String>
  • List<String> is not a subtype of List<Object>

类型擦除

通配符

  • Class<?>
  • Class<? super A>:A 或 A的父类
  • Class<? extends A>:A 或 A的子类

List<Number> is a subtype of List<? extends Object>
List<Object> is a subtype of List<? super String>

设计模式

  1. visitor设计模式

    看个例子

  2. Iterator模式

    Iterator接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
    }

    public interface Iterable<T> {
    ...
    Iterator<T> iterator();
    }

    Iterator模式让自己的集合类实现Iterable接口。

    并自定义MyIterator实现Iterator接口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class MyIterator<E> implements Iterator<E> {
    private Iterator<Map.Entry<Track, Set<E>>> iter;
    private Iterator<E> iter2;

    public MyIterator(Map<Track, Set<E>> map) {
    iter = map.entrySet().iterator();
    }

    @Override
    public boolean hasNext() {
    return iter.hasNext() || (iter2 != null && iter2.hasNext());
    }

    @Override
    public E next() {
    if (iter2 != null && iter2.hasNext()) {
    return iter2.next();
    } else {
    iter2 = iter.next().getValue().iterator();
    return iter2.next();
    }
    }
    }
  3. Strategy模式

第六章 可维护性

正则表达式

第七章 异常

针对健壮性优化