@jtong
2017-07-19T16:38:43.000000Z
字数 1717
阅读 2179
教学
Graphic-Language
当我们把一个完整的功能拆解为一个个输入输出穷尽,互相独立的任务后,它是容易转化为代码了,可是这种方式并不容易思考规模更大的问题(光从哪来到哪去就够我们绕的)。把我们的大脑看成一台电脑,我们就是那种内存很低的电脑,问题规模一大,我们就会死机,然后就只能重启了。具体表现为我们思考时会觉得晕。每次晕的时候可能都重启了一下:)。
怎么办呢?其实也很简单,内存不够硬盘来凑。对我们的大脑来说,最常见的“硬盘”就是纸。而正如电脑的硬盘传输速度总是不如内存的,加了硬盘计算效率不一定快。我们需要一种对传输友好的编码方式,这种方式就是画图。
我们的画图方法受时序图启发而发明,具体的规则如下:
举例:
比如下列代码:
function c(){
}
function b(){
c();
}
function a(){
b();
}
a();
画成图是这个样子的
在这个图上我们可以清晰的看出来,函数a调用了函数b,函数b调用了函数c。而函数a自己,是在最顶层调用的,也就是所谓的程序入口。
整张图是从左往右表示时间顺序。
什么情况下既有从左到右,也有从上到下呢?比如下面这个代码:
function b(){
// b codes
}
function c(){
// c codes
}
function a(){
b();
//a codes;
c();
//a codes;
}
函数a先调用了函数b,然后再执行一段a里面的代码,再调了函数c,然后再执行了一段a里面的代码,然后返回。
我们正常使用这个实践的时候,这个过程是反过来的,我们可能先看画出了上面这张图。不过这回,我们要画的认真一点,为了后面可以导出任务列表,我需要加上标号,如下图:
然后从这张图里按照标号导出任务列表,如下:
#1 函数a
输入:
paramX: TypaX
输出:
bValue: TypeA
#2 函数b
输入:
paramY: TypeY
输出:
cValue: TypeB
#3 函数c
输入:
paramZ: TypeZ
输出:
aValue: TypeC
接着我们就可以照着任务列表写代码,如下:
function b(){
// b codes
return result;
}
function c(){
// c codes
return result;
}
function a(){
let bValue = b(paramX);
//a codes;
let cValue = c(paramZ);
//a codes;
return result;
}
最棒的是,我们可以照着任务列表写出测试
it("test case 1 for function b", () =>{
let paramX = // TypeX的测试数据
let actualBValue = b(paramX); // 调用b函数的实际返回值
let exceptedBValue = // 调用b函数的期望的返回值
expect(actualBValue).is(expectedBValue); //断言
})
// 以此类推...
所以,我们是在以测试驱动的方式做任务划分,你可以叫它测试驱动的任务切分。
如果要映射到测试,我们的任务列表就缺了一些东西,那就是所谓的测试用例。因为同一个函数可能有不同的测试用例,所以加上用例我们的任务列表应该长成这个样子:
#1 函数a
输入:
paramX: TypaX
输出:
bValue: TypeA
测试用例:
用例1:
inputValue1
----
outputValue1
用例2:
inputValue2
----
outputValue2
// 以此类推...
我们看到因为输入输出的顺序已经定好了,为了书写的速度,我们就省略了名字。如果你觉得不舒服也可以写上名字。如果你觉得这样太浪费时间,你可以把每组用例用一句话描述。毕竟一切为了实用嘛。
请把上一篇的任务列表,画成图,并补上测试用例。