业务开发中的小心得之一

首次接触移动端网络游戏的开发,自己做的小模块是家具一般的功能。

伴随游戏周期始终,不会有太大的变动,功能与其他系统关联不大,但是颇多来往,所以必须保证数据处理的逻辑正确。

小小的升级功能,沿用架构的处理方式,也要沿用自己业务处理方式。

分为以下四点:

  1.代入场景思考

  2.这一行代码做什么?实际上有没有做?

  3.编写前,编写中,编写后分别要考虑什么?

  4.简化代码

一:

想准确的处理好升1级/升10级,应该先分开实现,再整合为一个接口。

这是必要的且收益高的复杂化,也是为了最终实现简单化的复杂化。

升级,无非扣除银两,操作等级。

但是这两句话本身就不是明确的。

  a.什么情况下要扣除银两=> 银两足够的情况下;

  b.什么情况下要操作等级=> 升级成功的情况下。

再退一步,

  c.你的操作数值是针对哪个大臣的=> 玩家是否存在这个大臣。

  d.而发起请求的玩家=> 传入的数值是正确的吗?Session正确匹配吗?时效过期了吗?

发起的请求是正常游戏流程产生的吗?

  e.有没有恶意发包的可能,那么参数有可能要屏蔽哪些情况?

一个升级功能,可以是流放的大臣恶意发包升级,也可以是玩家升了满级手快多误点了一下。

那么以a、b场景为例,银两不足的情况下,根据所在需求说明,假设大臣当前等级为99,99升100需要消耗银两100,000,玩家当前银两只有500的情况下,不予升级,但予扣款。

也就是玩家银两-500,并且保存升级银两进度,假设大臣等级为MinisterLevelConfig类型,其中有index表示等级,progress表示进度。则此时index值不变,progress=100,000-500=99,500

这个progress数值的意思是本级还需99,500才能升级。因此这种情况下不需要操作等级,升级过程不完整。

二:

当以上场景实际发生,那么再下一次升级这个大臣时,判断progress>0,因此正式扣款前,要先清空进度,本级升级金额应该为99,500,存在两种情况,一种是玩家银两足够,则进度清0,index++;

另一种玩家银两不足,则进度减去当前玩家银两,index还是不予操作。这两句话似乎没问题,但是脑袋瓜想当然的第二种情况,恰恰是我犯错的地方,当第二种情况,也就是当前大臣升级进度不为0,

那么此时玩家银两应该相对进度而言,还是相对本级升级银两而言,此时涉及到一个比较对象的变换。也就是每次玩家银两是否足够,取决于,相对于什么费用而言,然后才是数值上的比较。

因此,当我写this.m_UserMinister.OwnConfig.Upgrade<MinisterLevelConfig>(UnitOfWork uow(事务相关),int index,int progress)时,执行的效果并不一定是写出来的那样,还有细节上的变化。

三:

假设一、二都考虑到位的情况下。

编写代码前,要时刻检查命名是否正确区分了类的成员变量和方法的局部变量,命名看似无关紧要,但很有可能会造成难以排查的bug。

应对这一点的个人约束:当调用成员变量时,必须加上this。

编写代码时,可能为null的情况,和参数不满足操作的情况,发包的场景,需要用Throw new Exception的方式阻止代码继续进行。并且数据库的操作,都要在这些屏障之后,以免造成数据泄露。

编写代码后,复用的代码都整理为成员方法,不仅看起来优雅美观,排查问题时也能更有针对性,在进入和跳出某个成员方法时,测试用例报错,那么bug范围得到缩小,解决效率自然就提高了。

 四:

简化代码,减少代码量,但不改变执行的效果。

通过大佬的分享,获得了几个简化代码的方法。

Ⅰ.

a.foreach

可以改用Enumerable.range(min,max).Each(t=>{

  a[t]..

})

II.

if(a<100)

{

  ...A

}else if(a>=100&&a<200){

  ...B

}else if(a>=200){

  ...C

}

当if else 情况存在多种,代码看起来有点复杂,改用

IDictionary<int,Func<int>> aHandle=new Dictionary<int,Func<int>>{

  {100,()=>A()},

  {200,()=>B()},

  {300,()=>c()}

};

Ⅲ.

延迟加载

上文有MinisterLevelConfig对象,当我需要取其值如果不用延迟加载,每次都需要查询数据库,但在数值变化之前,查询的结果都是一样的。

因此可以这样写

private MinisterLevelConfig m_MinisterLevelConfig;

protected MinisterLevelConfig  MinisterLevelConfig {

  get{

    if(this.m_MinisterLevelConfig==null){
      this.m_MinisterLevelConfig=DB操作

    }

    return this.m_MinisterLevelConfig;

  }

}

这样可以只访问一次数据库。

但在数据变更后,缓存变量m_MinisterLevelConfig也要记得改变。

posted @ 2017-10-26 17:38  yahzi  阅读(203)  评论(0)    收藏  举报