本来想在周末写完,结果周末打扰,到现在才开始。要加班了,不然写不完。……
任何产品都有迭代,有周期,有版本,版本是一个阶段工作的里程碑和产出。 对于应用开发者,更新版本可能是件很开心的事,因为说明在不断的优化和改进。然而对于SDK开发者来说,对于版本更新的感觉却是复杂的,开心又心塞。
开心是因为又修复了不少问题,或者出了新的功能,做了新的优化。但是更多的是多版本维护带来的压力和成本。SDK一个版本的生命周期并不像应用那么短,而且他带来的问题的影响也会更久远。
本来想和关于版本号的那篇一起写完,发现有点多,先发了,写的过程思路有偏差,把他们两篇的耦合关系降低了,所以可以独立开来了。
这个其实不用考虑,一个还算合格的SDK肯定都有两个版本:一个稳定版用于大面积的推广;一个开发版用于一些急于使用新功能的游戏试用。
稳定版本和开发版本的存在是为了提高SDK的版本质量,同时结合版本发布的一些策略,降低SDK版本质量对使用者的影响以及SDK的bug的影响范围。
这里对开发版再增加一点说明。这里的开发版不是说开发临时出的版本。任何只要对外提供的版本,都必须要经过标准的版本发布流程,无论是开发版还是稳定版都是对外正式发布的版本。而开发通过本地环境打的包或者自己临时出的包是不可以包含在版本计划中,更是绝对不能提供给游戏。
任何流程,只要是人完成的就总会有问题,而且这里也被坑过,因此才有这个也算严格的规范。这样即可以杜绝游戏使用有问题的包上线的风险,而且不会让别人觉得很不专业(PS:接过的某SDK,经常随意给版本,甚至给过100%crash的版本………………)。
对于我们目前的SDK的发布的策略或者版本的周期,我觉得还是不错的。这里也做一个简单的说明吧。
推荐做法:
SDK从开发完成到最后对外提供,建议包括以下过程:开发自测、专项测试、发布开发版(或者叫内测、小范围灰度)、转为稳定版、下线版本这样几个周期。
测试我会在下面继续说。这里说下其余的几个环节。发布开发版,也就是灰度我觉得是至关重要的一环。我们的使用者除了外面的开发商还会有自研的游戏。因此当我们的新版本发布以后,我们会优先提供内网的下载地址供内部游戏接入,同时我们从后台观察具体的数据;当有游戏通过新版本上线而且没有问题,我们就会正式推出这个版本。
对于转为稳定版,一般是在我们某个有重大功能更新的版本在很多游戏已经验证过没有问题以后。一些重大功能版本之间的小版本,一般即使他很稳定,我们也不会用它替换我们的稳定版,因此会发现我们的开发版是不停的变,但是稳定版每次变化都会很大,版本也是跳跃的。
最后一个环节不是非必须的,当我们推出新版的时候,我们会下线旧的版本。我们是为了限制推动游戏升级和更新版本,所有我们不会提供游戏老版本的下载链接,这个因实际需求不同而不同。
就一个原则:所有新功能的开发只能排期到最新版去开发,绝不能为了尽快的推某个版本而简单的在稳定版拉个分支去支持新功能。(当然老大非让你上也没办法,说明厉害关系)
就说说我们的故事吧,我们在稳定版1.7,开发版1.9的时候,某平台想推出新功能。然后有个游戏想急用,同时平台也很着急。迫于多方压力,我们在1.7增加了一个新功能版本加入这个功能。由于1.7以上的版本太多了,我们不可能在所有版本都假如新功能,所以只在目前外发的稳定版和开发版的最新迭代以及正在开发的主干版本同时加入了这个坑爹的功能。然后噩梦就开始了,他们的版本和接口中间都有变动,为了向上兼容每一次我们就要把对外发布的1.7和1.9以及我们正在开发中的2.0对应的地方同步改动,同时出三个版本……这个问题的后遗症一直持续了半年,有段时间每天疲于应付各种版本……
其实因为类似的问题,我们遇到过一个更坑更坑的问题,这次低版本调整涉及到了本地数据库的变更,我会接下来讲故事说明,这一次在某个老版本插入新功能直接影响了我们超过5个大的版本。那段时间游戏问的最多的是,我们是x.x.x,我们现在要升级,应该升级到哪个版本呢?让你苦死,苦逼到极致的经历……
因此一定要和产品、测试、老大约定好,不要随意在低版本增加新功能,尤其是变动交大的功能,这个对接下来的生活来说是致命的。
对于android的向下兼容,专门聊聊本地数据库的版本的问题吧。这个问题让我们心碎了不久。问题的起因是没有规划的在低版本中增加新功能,结果引来一系列悲剧的问题就。这里我随便用三个版本来描述吧。我们当时稳定版1.1.1的DB版本号是14,开发版1.3.3的是17(中间还有别的版本是15,16);然后1.1.1版本临时要增加新功能,而且这次功能调整了DB,这个时候就要升级DB的版本号了,那改到多少呢?
最终选择了升级到17以上,然后重载了SQLiteOpenHelper的onDowngrade函数,当DB降级的时候,就直接删除了DB,重建一个。这样变为:1.1.2是18,新功能也没加入1.3.3,所以他的版本保持17,我们开发中的1.4.0升级到19。
你以为这样就完了,太天真。这次以后有很长时间我们没有更新过DB,所以就忘了这件事。然后有一天更新的时候,开发版本想变为稳定版,就把这个功能也加上,此时
然后当他变成稳定版以后,原来1.1.2的大批游戏升级到1.3.4以后就发现又跪了,而且是必现的crash。当时都要疯了,因为忘了1.1.2的那回事,用了一样的DB版本号,虽然新增的表改了,但是1.3和1.1本来就有差异的表没变…………。
最终只能是彻底把所有版本的DB版本号都梳理了一遍,有问题的版本全部升级并把一批版本列为不可用于正式上线的版本以后才解决。导致的结果就是我们中间的5个版本是不能用于上线的,游戏等了很久才换了一个可用的版本……
这里废话太多了,而且估计还看不懂。总结下:
在SQLiteOpenHelper中,一定要覆写其onUpgrade和onDowngrade函数。做到对应用DB升级和降级的处理。
慎重修改表字段,修改以后一定要记得整理DB版本号。
不要把高版本的内容往低版本加!!!
这里主要说从版本排期到最后发布过程中个人认为比较重要,我们做的也还不错(那是因为坑了太多次)的要点吧。直接用标题列举吧。
对于一个版本来说,每次提交测试前需要确认的问题肯定很多,例如功能验证、开发过程中一些临时增加的一些断点、为了配合开发做的一些调整等等。每次提测的时候这些问题很多总会被遗漏,或者某一类问题的某一个点总会被遗漏。因此,我们对于一个版本提测,要有一个专门的提测流程。对于一些重点项还该有具体的说明(结合自身实际制定一个提测前的版本checkList)
这部分内容我会再SDK开发经验之测试(点击阅读)中来详细说明我们的流程是什么样,踩过什么坑等。
只要人参与的总会有问题
,编译环境,配置文件等等的差异有时候很容易被忽视。另外,只要能用工具、能自动的就绝不手动。
拿我们的SDK来说,之前因为是手动出包,有时候会经常遇到遗漏文件、忘记修改配置中的版本号、SVN填写错等问题。带来的结果就是:
对于android应用来说,通过ant和批处理(win)或者shell脚本,我们可以完成代码编辑、jar包生成、自动化测试等所有的工作,大大降低人为工作引起出错的成本。
本来,客户端的向下兼容是最轻松的,因为客户端开发的时候其实是不用考虑向下兼容的,因为他是一个独立的个体。如果非要考虑,可能也只是考虑安装、签名等这些,开发中本来是最轻松的。但是!!!当你是一个SDK的客户端开发的时候,一切就都变了。
对于SDK的客户端开发,虽然你可以任性的在不同版本随意的优化和调整而不会招致什么问题。但是这对于接入你SDK的开发来说,却绝对是噩梦,你绝对是他们认为神一样的存在。尤其是你老的版本的覆盖范围已经非常大的时候。
我们的SDK目前被吐槽的最多的很多方面其实我们也知道。而且我们比来吐槽的人更想改掉。但是……目前接入我们MSDK的游戏的量太大。我们的一次改动,可能意味着增加了无数游戏的版本更新的难度,这势必会影响游戏的开发周期和版本进度。所以很多问题尽管我们知道他们的存在,而且也一直想改,但是一直没有动。我们会在问题暴漏的足够多的时候一次改变了,而不是一点点去调整,然游戏一直阵痛,每次更新都来骂一次。
SDK也是产品,只是用户比较特殊。如果有些时候不能拿定注意,就和你的用户做一次比较大范围的访谈,另外做一些测试。
目前我们遇到的回调太多、模块太多、常量和错误码定义太混乱等问题其实不但困扰游戏也困扰我们自己,在2.0的时候我们本想修复这些问题,但最终被否定了。后来在和各种类型游戏开发进行了多次交流沟通以后,我们才下定决心会在3.0解决。同时我们用另一个使用范围比较小、更新比较简单的SDK对我们的想法做了一些验证,最总确定了修改的方案。
SDK存在很重要的一个价值就是方便开发的接入。当SDK接入、更新的成本超过甚至逼近开发直接对接的成本时,这个SDK其实是失败的,而且也失去了应有的意义。