我们同时维护着多个游戏项目,游戏内容大同小异,程序和策划基本上也是同一批人,难免一些功能,在A项目中开发完运行稳定,策划感觉效果不错,就要求把该功能迁移到B项目中去。于是,代码移植就在我们这里经常发生了,随着时间各个项目之间的差异越来越大,代码移植往往就没有策划想象的那么简单了。程序需要抽丝剥茧,小心翼翼地把代码复制来复制去,稍有遗漏就会出问题。
特别的,当策划同学在提出移植的时候,总是以为这是很简单的事情:“之前都不是已经实现了吗?照着抄不就完了?一天时间搞定如何?”。这时,心里真是一万匹草泥马在奔腾的感觉,在对功能需求不明确,时间有限的前提下来干这样一件事,这是让我们程序玩火自焚啊!
代码移植是怎么回事?
代码移植一般来讲与代码的可重用性有一定的区别,代码移植往往是将不同平台、不同编译环境的程序代码经过修改转移到自己的系统中运行,这与代码的可重用性有着本质的区别。(From:百度百科)
对于维护一个项目的同学来说,开发流程是这样的:
分支合并基本很少听见代码移植这样的事情。就算是新需求是抄其他项目的,提需求的人也需要提供详细的文档,经过严格的评审,程序才能介入然后实现。往往,想法COPY起来是很容易的,而代码COPY起来就没那么简单了:没有代码的,全部实现一遍;有代码的,只能仅作参考,系统架构差异已经决定了代码移植并非一件易事。
那对于差异不大的项目,或者后续项目是在之前项目的基础上改出来的,代码移植该怎样进行呢?困难又在哪里?下面会大概介绍一下。
代码移植代码移植的方式有那些?
-
工具
在B项目从A项目分裂前期,差异不大的时候,工具(如:
svn merge
)基本上完全可以胜任这件事情。代码冲突会比较少,这个阶段代码移植是一件可以迅速完成的事情,只需要把相应功能的版本号找出来,然后使用svn merge -c 版本号
进行合并,遇到代码冲突,修改一下即可。 -
手动复制
随着时间和版本不断的迭代,项目A和项目B的差异越来越大,工具合并起来冲突一堆,解决这些冲突的时间,还不如手动复制代码来的快一些。
-
两者结合
当某些功能的差异没那么大的时候,先用工具试着合并一下,如果冲突的文件数量大的可怕,那就手动复制;如果冲突量尚在可以接受的范围内,仅对于那些冲突特别严重的文件进行手动复制。工具和手动复制两者结合起来,比完全使用工具和手动复制效率要高一些。
总之,随着时间和版本差异变大,代码移植会越来越难进行下去!不过一定要记着:
移植代码必须在对功能理解和看懂要移植代码的前提下进行,否则出问题就抓瞎,没有对错的标准,就没法进行正确性测试。就算工具可以完全搞定,这样做也是必须的,因为出了BUG还得你来改。
困难在哪里?
高内聚、低耦合,是我们在写代码所追求的,因为遵守这样规则的代码重用性会比较好。但实际上,能做到的却很少,同一份代码被无数人改了又改,代码复审和代码质量监督的缺失,代码不光耦合性高,同一功能的代码片段还散落在项目源代码的各个角落,毫无内聚性可言。
那对于同根分支的不同项目之间代码的移植的困难又在哪里呢?
-
分支之间的差异
上面已经说过,分支之间的差异太大,会造成合并时各种各样的冲突。
-
功能代码的依赖
假设项目A开发功能X,依赖了代码Z,现在要把X功能移植到B项目主干,而代码Z是项目B之前所没有的,那么在移植功能X的时候,需要同时把代码Z移植过来,那么问题来了:Z代码还有其他依赖不在项目B中吗?Z代码提交的记录又要如何去找出来?(这让我想到了linux下面源码安装一些包的痛苦,编译不过缺少依赖项,结果依赖的那个包拿过来,又依赖另外一个)
对此,我们又能做些什么呢?
提高代码的模块化程度。功能代码尽量集中放在相关的一两个文件里面,尽量新建相应功能的.h和.cpp文件,提高代码的内聚性。功能代码也不大可能不动到其他相关文件,但应该尽量减少在其他文件中修改代码的行数。这样在移植的时候,工具冲突的可能性会比较小,就算手动复制也会比较快找到所有代码。
网友评论