源码工程历经五年, 前后经历五六次人员变更, 20+人次左右的交接; 其中有应届毕业生到老鸟到脱坑, 也有中途其他部门调整岗位过来的同事; 二十多个模块的变更, 在公司相关规范不完善的情况下, 烙印下太多特行独立甚至堪称粗暴的痕迹, 最终成为现在的是一团即将再也看不到缝隙的大泥球,
而我----身处中心.
首先, 简述一下其模块内部结构:
1)模块接口:主要负责模块对外的接口
2)模块间通信类:主要负责同一抽象层模块间通信处理
3)底层通信类:主要负责与更底层模块的通信处理
4)界面类:主要负责界面效果处理
5)参数类:主要负责模块内部的参数处理
模块工程如下:
单纯的就上面的模块介绍以及工程, 是不是发现条理清晰, 结构合理, 无论再坏, 都不会糟糕到哪里去?
是的, 曾经的我也曾这么有自信的如此认同.
但是, 开场白就提到, 这里面经手的人员并不一定是如读者你这般有一定经验并且吃过苦头正在想找人一起探讨/吐槽以及苦思解决方案的人, 而是上述简述的文字提到的类型, 很有可能都是为了快速完成任务积累开发经验然后跳槽工资翻番之类的剧情(该种现象在天朝实在是太过普遍的常态), 自个都打定主意跑路的, 谁还会给你考虑可维护性, 可阅读性, 健壮性什么的?
当然, 一般的软件开发公司都会有完整的软件开发流程, 其中必不可少的会有代码审核(code review)的过程, 但----前文提到的相关制度不规范, 指的就是它并不是一般的软件开发公司 : )
所以, 本来一条道路上有一个坑, 有人遇到了, 从路的其他几处地方都挖了点土, 将这个坑填了起来, 然后继续往前走, 后面又有同样类型的人来了, 碰到了几个小坑, 于是再从路的其他地儿挖点填上, 于是乎, 较为讽刺的从反面佐证了"道生一, 一生二, 二生三, 三生万坑".
再来说说模块实现的业务逻辑:
不同模块实现的是不同功能的业务逻辑, 挑一个大家耳熟能详的播放器模块来剖析.
一般的播放器, 基本功能会有:暂停/播放, 上下一曲, 播放模式, 播放比例, 列表, 进度调节, 其他就是一些ID3信息的同步显示了, (当然现在的播放器基本都是插件化, 还支持各种插件的扩展, 当下介绍的播放器模块并无此实现, 所以不做阐述).
例如触摸界面上的播放器按钮进入播放器的处理, 理应切换对应的界面即可, 其他切换媒体通道/资源申请等的动作, 其他有对应的模块处理, 如果接口封装的好, 理论上就是一行代码的事情.
实际上, 最初的版本, 的确就是一行代码的事情搞掂了:
然后, 来了一个需求: 如果当前媒体已经是处于播放器媒体并且当前播放的是视频文件, 再次进入时, 进入全屏播放界面:
完了, 又有一个新版本的需求需要兼容:如果是当前版本的处理, 则需要根据另一个模块的一个状态判断, 是否可以进入全屏播放界面:
什么, 还需要兼容? 新来一个版本:如果是当前版本的特定系列, 则每次都是进入媒体播放器界面:
日复一日
年复一年
五年的迭代, 六十个月的轮回
五年的需求汇聚, 爆炸的代码量
各异的风格争锋
不明语义的定义争宠
以及
后来人的挣扎
这仅是一个模块单一功能点的状况, 无可以夸大. 现在修改问题, 一看记录, 我Bi____, 五年前的正在卖的产品代码诶, 算了, 看有无其他地方可以绕一下吧, 能不动这坨理不清里面到底有多少恩怨情仇在里面的代码, 要万一动出个问题, 那耗费的时间简直比重写一个模块来得更多.
大致总结一下以上代码迭代的问题:
1.代码风格不一致
2.魔数的使用
3.模块成员变量的公有化
4.耦合到其他多个模块
5.有违单一原则
6.嵌套太多
如还有其他, 请读者大大帮忙指出.
以上种种, 基本能覆盖当前所有模块的九成代码, 其中特别需要说的是关于耦合了其他模块, 这里只是耦合了两个其他模块的状态, 而有一些功能的实现, 可能耦合了超过五个的模块!
未完待续....