fizzbuzz牛津英语树 fizzbuzz( 八 )

简单设计以及测试的量有很多人看到业务复杂到这个程度,总算该设计个机制了吧 。我见过很多人在这个环节把代码写得特别复杂 。然而我写的代码非常简单,如下所示:

fizzbuzz牛津英语树 fizzbuzz

文章插图
这种代码有什么好处呢?就是它的逻辑跟我们需求描述的逻辑几乎一模一样,我没有新增什么额外的机制 。这看起来不是很高大上的样子,很多人就想加个设计绘本 。我们要明白,所谓的设计就是加入一些约束,使得做一系列事的方便程度高于了做另外一系列事 。我们经常性的想约束想的都是代码,但实际上对代码的约束,本质上还是对人的约束 。
Rails的架构师DHH曾经说过约束是你的朋友,什么意思呢?就是说很多时候你对自己加了约束,那么你做事的效率可能比胡乱做、凭本能做更高 。从这个角度出发,我们加约束一定要提高我们的整体效率,所以我给自己加了一个约束,fizzbuzz翻译,叫做让我们的代码逻辑和业务逻辑最大可能性的保持一致 。虽然不是一种代码的设计,但是是一种行为的设计 。我们刻意要求自己按照这样的行为行事,会带来一个非常大的好处,那就是我们的业务逻辑的修改的难度和我们代码的修改难度保持一致 。业务上如果是什么改起来逻辑很复杂的话,你跟他多要一点时间来改我们的代码也比较容易要到,反之则不容易要到 。
如果我们刻意做了一些设计 。使得局面变成了,有时候业务上改起来很简单的事情,我们这边特别麻烦,而有时候业务上改起来特别麻烦的事情,我们改起来特别简单 。因为我会觉得我们设计在一定程度上提高了他们的效率吗?不会 。他们会觉得你今天心情好,所以你说简单,你哪天心情不好了就跟我说做不了 。所以你没有办法形成业务与技术的协同效应 。全局上来看,它是降低了效率的 。
所以要记得我们前面说过的这个原则:让我们的代码逻辑和业务逻辑最大可能性的保持一致 。细节上也要注意,要尽量采用业务名词,业务概念 。不要写那种写时候只有我和上帝懂,三个月之后只有上帝懂的代码 。我们想象一个场景啊,当项目上来了一个新人,他首先会学习业务知识,完了之后开始维护代码,我们尽量使用业务名词业务概念,对于这个新人来说,他的上手成本是最低的,如果业务逻辑又保持一致,那上手成本就更低了 。而新人这个概念不一定是新招了一个人,没有维护过你这块代码的,来维护过你这个代码,三个月后的你,可能都是这个新人 。所以善待新人就是善待自己 。
我们这些代码也是测试读音驱动出来读的fizzbuzz,下面是我新加的测试:
这些测试通过之后,由于实现的改变,会导致我们前面的测试用例会有很多的改变 。无形中制造了测试的麻烦 。这个时候我们可以采用测试替身技术 。把3,5,7的部分再摘出来测试,这样你就不需要关心3,5,7部分的输入了 。
不管我们是否使用了测试替身技术 。我们可能还是不太放心 。我想写一个测试用例很全的测试,也就是所谓的细粒度的测试,于是我就写了一个 。
fizzbuzz牛津英语树 fizzbuzz

文章插图
上面就是我用代码生成的数据,这个时候你会发现测试用例一点都不好准备 。测试成本很高 。这个其实是正常的 。测试代码也是需要花心思去写,花心思去维护的 。
但是这里面会延python伸出一个问题 。我写测试来保证实现的正确性,我拿什么来保证测试的正确性呢?
这事情要分两头看 。你写的一种测试代码是一种类库的形式,用于辅助测试的编写 。这种代码本身跟一般的程序没什么区别,所以你可以针对它单独测试 。在这个题里面,我根据不同的条件生成输入数据,就是这样一个类库一样的程序 。另一种测试代码就是我们平常的测试用例了,这种测试用例,它和实现是互相验证的,fizzbuzz是什么意思中文 。所以我们在写这个的时候有一个对自己的约束,那就翻译是写测试的时候绝对不写实现,写实现的时候也绝对不写测试,两者之间有一个非常明确的边界:执行测试 。也就是说我如果写测试,执行完了测试之后,确保是我预期的结果,我再去改实现 。反之我写了实现,如果执行完测试是我预期的结果,我再考虑去改测试 。这样写测试的时候实现就是我的验证 。写实现的时候测试就是我的验证 。主要在修改的时候作用更大一些 。

相关经验推荐