碰到过一个面试题:升级某卡牌=A+B+C(三个材料数量固定只能是 1)。简单说就是三个数量为 1 的材料可以升级某卡牌(不需要额外金币或者其他资源)。并据此说一下协议测试用例。
由于现在所在项目原因,我很自然代入了 PB 数据作为通信协议数据,然后回答的时候有个点和面试官冲突了:他认为需要测试 A+B+C+D,也就是数量为 4 的情况,我认为不需要去测试这个情况。我本人不是很擅长被面试,临场发挥是弱项(面对别人说话就脑子有点紧张),但是我觉得我没有问题。这里事后总结一下想法,不谈面试问题,只谈由面试引出的协议测试设计问题,同时也希望行业老大哥交流一下。
面试官想要缩短考的范围,指定了固定数量是 1。但是我表达的是,item1:count1,item2:count2,item3:count3(这个涉及到我为什么认为不需要测试 A+B+C+D)。
首先说下协议内容为啥要有 count,即使你指定数量 1,协议内容也必须要有 count,这是因为扩展性原因。在涉及诸如卡牌升级系统的时候,往往不能因为需求指定了数量 1,就少了必须的 count 参数,这非常不利于以后的扩展。万一以后升级材料数量不是 1 了呢?
现在我们承认了 count 参数存在的意义,这就又引出了另外一个问题:那么是不是要考虑 item4:count4 的情况,万一以后多了材料 4 呢?这就非常没有必要考虑了,因为多了材料 4,理论上你的系统就要重新迭代,包括 UI 设计,布局设计(你得设计多一个格子,去给玩家把材料放进去了)。
接下来用 pb 数据来说下我设想的可能的协议结构数据:
message item {
required int32 itemid = 1;
required int32 count = 2;
}
message updatecard {
required item material1 = 1;
required item material2 = 2;
required item material3 = 3;
}
面试官给我预先设想的结构,居然是List
(协议内容为 [A+B+C])。当然,proto3 现在也支持ListValue
和map<K,V>
此类json mapping
。但我认为此类卡牌升级指定了三种材料,协议数据设计就不应该用List
,因为这样你不知道列表长度,不知道带了多少种材料了,就需要多一个len()
去判断长度了。如果需求是要给不定数量的玩家发奖励,这种带有不定数量的情况,协议是可以用列表的。
基于以上想法,以及我设想的协议结构数据,我认为协议测试重点是itemid
和count
参数,而没有必要考虑 A+B+C+D,这种多了一个 D 材料的情况。客户端多了一个 D,服务器处理协议数据可能就出问题了:明明说好三个材料,你多发了一个,事先没声明,服务器根本不知道怎么去处理,会因为协议没对上直接报错或者返还 “错误内容” 给客户端了。我甚至认为itemid
不需要测试空的情况,但是很遗憾,又和面试官冲突了。(在实际测试中,看到 required 字段,我很自然就不会去测试空的情况)
现在我又多了一个结论:不看具体协议数据结构设计去谈协议测试,有点脱离实际了。
@jiazurongyu 还请老哥指教
---------分割线----------
抱着疑问查了一下,又多了解了一些东西。
https://stackoverflow.com/questions/31801257/why-required-and-optional-is-removed-in-protocol-buffers-3
https://capnproto.org/faq.html#how-do-i-make-a-field-required-like-in-protocol-buffers