@jtong
2017-07-19T08:38:43.000000Z
字数 1717
阅读 2483
教学 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 codesreturn result;}function c(){// c codesreturn 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// 以此类推...
我们看到因为输入输出的顺序已经定好了,为了书写的速度,我们就省略了名字。如果你觉得不舒服也可以写上名字。如果你觉得这样太浪费时间,你可以把每组用例用一句话描述。毕竟一切为了实用嘛。
请把上一篇的任务列表,画成图,并补上测试用例。