策划总改需求怎么办?

这是我最近面试时经常会问的问题。这个问题很开放,并没有标准答案。有趣的就是,从求职者的回答几乎就能分析他对自己在团队中的角色定位。

比如“尽全力做吧,如果实在做不完就向策划说明原因。”——这位很可能是刚毕业的学生,踌躇满志想在工作中证明自己的能力,可是因为自己没有工作经验多少有些没信心。

比如“有时间就做,时间来不及就和策划商量砍掉不必要的修改。”——这位就不是唯唯诺诺的新人姿态了,工作一段时间的人会意识到程序和策划的关系是平等合作而不是指挥和服从,而且有保护项目进度的意识。

比如“同一个功能改一次两次没问题,我不能接受反复修改,特别是来来回回的改!”——这位可能有长久被策划迫害的惨痛经历,倒是在求职面试时能这么回答也是挺直率的。

比如“实现功能时使用设计模式把代码写灵活一些,这样需求变更时改动成本更小。”——听起来很有道理,但是经验丰富的程序都知道再好的设计也是顶不住策划的奇思妙想的……可能这位刚看过《大话设计模式》,想引诱我把话题转向设计模式吧。

这里我想讨论的话题是:面对策划需求的频繁变更,作为程序我们能做什么?也算是我个人针对这个问题的答案吧。

明确好需求后再开工

需求变更的根源是什么呢?是第一次的设计不够好。所以要遏制策划总改需求,最有效的方法就是一次做好,尽量做到没有改进的余地。

通常在一个游戏团队中,策划和程序的技能树是有差异的。策划的发散思维好,程序的逻辑思维更强;策划会考虑更多怎么让游戏好玩、怎么才能更优雅地坑钱,程序会考虑更多功能缺陷、玩法漏洞、边界条件。所以作为程序最好发挥自己的特长,参与进功能的设计和讨论。

当然了现在游戏团队一般的开发模式还是策划出文档->程序编码这个流程,那我们能做的就是拿到文档后仔细审查设计,遇到不理解的地方立刻与策划沟通。注意这里说的不理解不仅限于功能的具体实现细节,包括设计目的、与其他功能模块的关系、用户体验等都要全盘分析,只有当自己认需求是完善的、无可挑剔了再开始编码。一旦发现有策划没有想清楚的地方,一定要等策划想清楚讨论明白了再做。磨刀不误砍柴工。

举个例子。上周我们策划发给我一个关卡挑战的活动,因为这个活动会发放比较好的道具,所以限定为每天只能挑战5次,规则是进入战斗后成功或失败都扣一次次数,若是中途退出战斗则不扣次数。很明显的漏洞就是玩家可以在眼看着要失败的时候选择退出战斗,这样每天定能拿到5次奖励,战斗失败的设计就没了意义。这个问题向策划提出后马上做了修改。试想假如我当时直接就按文档做了,以后必定还是要改的。

再举个例子。依旧是上面那个关卡挑战活动,策划还设计了一个活动排行榜的功能,文档上写明了这个排行榜每天凌晨5点更新(显示昨天的排名)。我注意到很奇怪的一点就是活动数据并不是每天重置的,不理解5点更新排行的意义何在。向策划提出困惑后得到的解释是:这个排行榜并不需要很强的实时性,不做实时更新也能接受,程序实现起来会简单一些。而实际情况是我们的排行榜模块一开始就设计成可以高效的实时刷新,要做每天更新反而更麻烦……最后策划很高兴地赞成改为效果更好的实时更新了,皆大欢喜。试想假如我当时直接就按文档做了,费力不说效果还不好,以后可能还要修改。

达成共识的设计

策划和程序之间经常会出现一个矛盾:策划提出了一个小小的优化,程序却发现实现这个优化要大动干戈,难以短期内保质完成。于是演变成程序觉得策划真麻烦设计好的方案总是乱改,策划质疑程序的能力是不是有问题……

上面已经提过了,再灵活的设计也顶不住策划的奇思妙想,我的体会是对修改最友好的设计并不是一定要灵活,最重要的是策划、服务器程序、客户端程序要在解决问题的模型上达成共识。

以我们游戏开发中的实际案例来说明。游戏中的PVE战斗分好几种:副本(关卡依次解锁,可以反复挑战)、经验副本/金钱副本(每天只能挑战3次)、爬塔(只能依序挑战)。对于这几个功能,不同的人会用不同的模型分析:

  1. 这几个功能都属于PVE模块,只是挑战限制和次数限制有所不同,需要在模块内特殊处理。
  2. 这几个功能分别是不同的模块,只是恰巧都要打怪而已,应该分别独立实现。
  3. 这几个功能分别是不同的模块,它们都包含挑战关卡的过程,应该提炼出关卡模块由这几个模块分别引用。

这几种模型没有显然的对错之分,具体情况具体分析(实际在我们的游戏中使用模型3较为合理)。重点是不论选哪种模型所有人都应该形成共同的认知。如果选择模型1,那么服务器和客户端都使用单独的PVE模块来处理这几个功能,策划将所有数据填入单一的PVE配置中,引入PVE类型来进行标识。如果选择模型2,那么服务器和客户端都将三种PVE挑战完全分开,策划将数据分别填入三份配置中,只是三份配置有一些相同的列是关卡信息。如果选择模型3,程序这边使用3个独立模块分别引用关卡,策划针对3个模块分别配置,这3份配置再引用关卡配置。

这样一来,大家在相同的语境下讨论问题会更顺畅,需求变更时所有人对工作量的评估是相当的,策划做优化时很自然就会规避大动干戈的方案了。

正如优秀的程序会去审视策划的设计,优秀的策划也会去主动审视程序的实现,以保证大家解决问题的模型是相同的,团队达成共识需要所有人去一起努力。实际上前面说到的排行榜就是一个很好的反例,如果我们让策划了解到程序原本设计的就是实时更新的排行榜,那么一开始每日刷新的方案就不会被提出了。

大刀阔斧地修改

经常看到有的程序在修改代码时选择把旧代码注释掉而不是删除,原因是“万一过几天策划又要求改回来呢?”

我的观点是,如果你不确定以后会不会再改回来,说明你没有理解好需求,你需要与策划沟通。如果策划也不确定以后会不会改回来,那么先不要做,等策划先想清楚。前面说过,避免总改需求最有效的方法就是一次做好,既然第一次失败了没做到最好,那么第二次就更应该确保做到最好了,不可能是“做着试一试”的心态,即使做不到最好,至少也应该保证绝对不可能不如第一版。

一份优秀的代码一定是简洁、直接、有力的,重构代码时一定要有魄力,该删的就删,该调整的结构就果断调整,永远让版本里的代码像新写出来的一样。我曾经的主程关于重构有过一个很形象的比喻:代码仓库就像一间房子,在房间中生活又不加以收拾,必定会越来越杂乱,最后没办法了只好整个推掉重建。爱整洁的人一定会每天打扫卫生,把东西收纳整齐,不要的东西扔掉,要买新家具了重新好好规划一下房间布局,没空间了落了灰了旧家具也得搬搬放到合适的位置,勤劳的人才能安居乐业。

最让人头痛的代码就是那种一眼看上去历经沧桑的、历史气息扑面而来的。试想过几年以后新入职的员工请教某段代码,你是想回答“哦,这段代码对应游戏中的X功能”,还是想回答“呃,这段代码大体上对应游戏的X功能,因为最初设计时还包含了现在已经废弃的Y模块,所以遗留了处理A逻辑的代码。去年有一次处理Z模块引发的B问题时时间太紧特殊处理了一下C逻辑,没想到引发了D问题所以又用E代码做了下适配……现在确实挺复杂,看不懂也没什么的,你可别乱动这块儿!”