耗时近两个月才完成售后系统的构建附带上对商品状态的完全重构。之前由于商品状态上有售后状态的问题,导致重构难度极大。好几次我都因而觉得找不到这套东西的突破口而抓狂。但是能完成这个项目对于我来说也意义重大,做任何事情都会要先踩坑后来才会了解哪些地方有坑。做重构和设计新系统并行这件事情本身就需要极大的耐心,这也是让我感触最深的一点。没有仔细的思考边界条件,没有耐心的进行解耦就不会有被重构系统的新生。
上面莫名其妙就先鸡汤了一波,可能是被这种项目折磨得太惨的怨念爆发。。。。下面就分两部分对我在整个项目进行推进的时候遇到的难题进行一一分析和总结:
重构部分:
1. 重构系统的话,一定要考虑到以前系统的传参逻辑。
这个感受来自于,由于以前的系统已经在线上跑了很多年了,你必须要考虑到以前传递的那些参数是不是现在还是有用的不能闭着眼睛随便进行删除。
2. 重构系统的时候,在查找旧函数是否已经删除完或者在系统需要并行的时候,是不是每个需要并行的地方都有处理到有两个方法。或者要么在以前的通用入口函数中加入新的逻辑,这样不容易遗漏。还有一个方法,一步到位,在每个旧系统入口函数的外面加新的逻辑,但是一定要仔细搜索旧的入口函数所在的位置。要把所有的旧的入口函数都找到。并且加上新的逻辑。另外还可以使用注释打tag的方式来制造新代码的统一tag,这样直接搜自己写的注释的关键词可以方便的查询新代码和修改还有定位。
另外如果还涉及到有洗数据的需求的话,最好在新系统上线并行之前把数据洗一遍。这样的话可以保证类似于自增id这样的字段连贯。避免了以前代码里面有一些类似于order by id 这样的代码出现不应该有的错误。
对于重构一个系统来说,如果这个系统很大无法一次性全部替换掉,或者中间有很多需要洗数据的情况存在的话,可能两套系统会并行一段时间是最常见的情况之一了。这样既能保证新系统现有功能可以稳定运行一段时间,也能保证避免使用过于激进的一口气全部替换系统引起的系统不兼容,数据不一致,前后系统逻辑改动太大导致很多细节问题的集中爆发。到时候可能真是加班一个通宵夜无法解决完所有问题,还会冒着系统停机的风险,得不偿失。
另外第二点里面谈到的一个打注释tag的方法是我在重构系统的时候摸索出来的一个有效搜索新代码的方法。因为我们给代码取名字的时候往往会有很多重复的情况存在,在定位自己最新改动代码方便直接在代码里面查看除了求助于git这样的工具,直接搜索自己打的注释tag也能方便的帮你定位到你的最新修改。
3. 在重构系统或者在写已经有一些逻辑的地方做新的设计,一定不要局限于以前设计者的想法,要跳出来重新看待需要些什么字段做更详细的设计,想得更周全。
这个在代码被review的时候感受特别深,因为最先做的是两套系统并行,所以很多代码其实都是依照着以前的系统逻辑来写的,就是为了在以前系统执行的时候,能把最新的数据写入到新建的表里面去,为后面整体数据迁移做准备。但是当在设计最新的系统的时候,你不仅需要考虑到老系统的字段要全部能存能解析,还要考虑到有了新系统之后,老系统哪些地方的特判,或者逻辑发生了变化。站在新系统成型之后的逻辑角度去思考,可以帮助我改掉以前的一些特判或者是再无意义的判断。更好的完成新系统的构建。 千万不要再局限于老系统的思路,去构建新系统,既然要重构,肯定就是要解决以前麻烦的地方和痛点。不然可能没有解决太多问题,还把自己绕进去。
4. 每次重写功能或者重构 都应该删除掉没有使用的功能的代码。否则下次再进行重构的时候简直寸步难行。
这个体验主要还是以前老代码给的,因为以前特别多的老代码就是被重构之后,没有地方引用了,也不删除干净。变量名字跟我新系统这边特别相近,逻辑什么的绞在一块儿特别难处理,搜索起来特别费劲。这次重构为了不再给后面人留坑,删了特别多以前的老代码。
5. 数据迁移涉及到 创建时间更新时间之类的东西。并且自增长id会被破坏。排序数据的时候最好用create_time数据迁移只要能迁移create_time 就不会破坏原来的代码。
这一点跟上面第二点里面提到的有点像,所以平时order_be的时候可以考虑使用create_time。
6. 在迁移的时候如果会有很多中间状态的话,迁移可能无法一步到位。而且在跑数据迁移的时候一定不能掉以轻心,一定要真实的测试几次,如果上线再出问题 那可真是要了亲命。所以要多考虑线上正在发生的事情会不会跟迁移这件事情本生产生冲突。
这个也是。。。。一把鼻涕一把泪的诉说。因为商品状态本来本身就有许许多多的状态正在进行,那个脚本考虑到了这件事情进行迁移,把各个对应不同状态的商品状态上对应的售后状态都映射上了,然后一切看似都很成功。迁移完了之后发现,虽然新系统可以正常跑了,但是旧的商品上的状态却永远停留在了原地,无法再走向完结了。。。。。这个大坑导致了未来一两个星期都在断断续续的手动改这些状态。所以在迁移的时候一定要仔细耐心,多思考边界条件,多思考线上正在发生的事情。专注的想这些事情,做好规划可以帮你在完成操作之后,更少的修改bug。
7. 千万不要轻易重构别人的代码,特别是在你权限还不够的情况下。除非你对整个系统极其了解,可以即使不看以前代码也能再造一套这样的系统。当然如果你可以做到这样,那么我还是建议你不要重构了,直接重写吧。
这个可以说是本次感受最最最深的点。因为既然你要重构代码,踩坑,那么多多少少都可能会出一些bug。特别是在以前的代码还写的不是那么优雅的情况下。或者逻辑混乱的情况下。现在重构就是为了造出拥有更优雅的逻辑和结构的代码。那么如果你对这套系统还没有那么深的理解,你最好主动承认能力不够。如果你觉得可以挑战一下(我就是这样)那么一定要仔仔细细把控好每个细节。权限不够指的是,你对代码最终走向何种级别算是完结没有话语权,而且没有办法自己控制代码的合并提交和bug修改。这会给你的重构工作带来巨大压力和不便,所以也要三思而后行。
其他感受部分:
1. 在进行表或者重要变量命名的时候,先参考著名前辈级产品有没有类似描述。命名很重要。
2. 写代码的时候也要考虑一下在测试环境下 能不能尽可能兼容。
3. 考虑有更新的数据库的地方一定要充分考虑并发会造成的同时发生的问题是否能够绝对避免,一般在使用orm获取到当前值更新之后,一定要返回self本身,如果重新get值乐观锁将会毫无意义。
4. 在考虑这种有一定保密型单子的时候,一定要事先考虑好加密的东西,并且用unique字段来保证。例如订单号,服务单号,最好不要使用自增id,如果要使用自增id也不要在应用层面暴露这个自增id。可以做一个加密算法,把这个加密后的订单id 和自增id都存在订单表里面,这样查起来也方便,也不会在应用层暴露真实数据。
5. 需要快照的地方比方说一张表上要能取到所有信息的时候,存储的信息一定要存全。不能拿个id跑到以前的地方去取。
6. 以后写测试不要一边接口一边测试,而是将所有接口和东西都弄好之后再补充测试,否则稍有改动要改测试 非常耗时 成本非常高。
7. 扫描之前创建的数据库以及其字段,能最快速度的了解业务逻辑和功能。
8. 以后像类似需要json序列化字段的时候 即使是空,也应该使用空的字典obj,这样能进行平滑的loads字典判断 而不是如果是空的话需要特殊的判断。
9. 文件命名也要注意单复数啊。
10. 两个人在进行同步合作的时候 开一个 分支跟上对方的分支 然后要测试 使用rebase 合并之后上传到测试服务器进行测试。这样可以时刻保证拥有两方最新的代码,而且删除方便不用大量rebase。
11. 每次都需要做的重要操作最好抽象到一个 每次都要调用的函数里面,这样就不用到处找该函数的入口了
12. 在写const的时候注意,其实const也可以写函数来计算想要的东西。只要计算的是常量都没有什么问题。
13. 在调用第三方api 如退款的时候没有办法进行本地事物保证的时候,一定要先操作 最后调用。
14. 并发 并发问题 一定要考虑好,多服务器 同时 负载均衡的时候太容易出现并发情况了。
15. 做东西之前多思考边界条件。
16. 耐心。
其他感受部分很多,也是平时编码时候需要注意的所以都在一起写了。另外鉴于交易系统的并发性,书写代码的时候都要特别注意处理并发的问题,该上乐观锁的时候打上乐观锁,该用悲观锁的时候就用悲观锁。
最后 耐心!
以上。