Thinking-关于项目
背景
去年做了一年偏管理类工作,感觉不喜欢目前公司的管理模式。给我的感觉整个就是一个效率低下的笨重机器在缓慢爬行,负重还在逐渐增加,整个笨重的身躯随时有可能塌下来。
感觉是太多人只考虑自己的利益。其实工作中考虑自己是没有问题的,但是在公司利益和个人利益之间需要有一个合理比例以达到某种平衡。比例太小,人就比较自私;太大了别人会觉得你很蠢。现在的感觉是有些人这个比例接近零。悲伤的故事。
在这种情况下就换了一个部门,做回研发工作。也接触了算是公司目前最“畅销”项目的代码,从比较偏研发的角度说一下自己的思考,或者叫乱想。
项目本身
这个项目本身是个支付平台。在接触这个项目之前,我认为这个项目的重点应该在于支付渠道、对账、数据监控等。但是了解了之后,才知道我的认知只是其中的一半。
这个项目最初是两个项目合起来的:支付平台和预交金平台。所以除了支付本身,另一半主要是和院内业务的交互。而且,院内业务在日常开发的比重尤其大。
观察部门人员的周报,感觉其实很大一部分人在做的都是和his系统对接的工作。支付平台项目中的大部分开发在做的其实是对接院内系统,这有点本末倒置。在这部分,其实需要做个解耦,把项目主要功能拆成三大部分来处理:支付、院内和整合。
模块
主要模块
支付模块就专门处理支付渠道,主要考虑和钱有关的订单业务,把自己当作一个收款方或者首款渠道的前置,负责连接用户和微信支付宝等,只负责到收款。至于为什么收款以及收款之后做什么,这部分不需要考虑。
院内模块就专门处理和院内的对接,这部分不涉及任何渠道。简单来说,就是一个和his交互的模块,而不考虑其他。
整合模块就需要考虑完整的流程,主要负责调用前两个模块来实现整个业务完整流程。比如在患者进行处方结算这个环节:患者首先进行查询处方并进行预算,这部分是his业务,整合模块调用院内模块,获得预算信息。然后根据预算金额,整合模块调用支付模块进行下单收款。当整合模块收到支付告诉他已收到款之后,就再告诉院内模块这个款已收到,需要告诉his这个处方已结算完成。
分成三部分之后整个项目更加的容易排查和扩展。首先是可以拆分给不同团队或者部门来做,避免一个改动影响整个项目,这可能会造成灾难性后果。其次,可以方便新人熟悉项目。一个新人只需要理解他自己做的其中一部分,做院内的不需要知道收款情况,他要开发的接口就是假设钱已经收到,他甚至不需要其他部分的配合,专注于实现自己的接口并提供出去即可。当第一次看到这个项目有一万七千多个文件的时候,内心是感到很不可思议的。还有就是可以减少项目的维护成本。按照这种结构来说,支付模块只有在对接新的渠道时候才需要改动,整合模块只有在院内流程改动的时候才需要调整,院内模块只有在院内接口改动的时候才需要开发。每一次的改动就意味着有一定几率引入新的bug,因此,越少的改动就意味着越少的维护。如果一定要改,那就尽量减少受影响的模块数量吧。
其他模块
后台管理也是不可缺少的一部分,这部分来说主要是一些配置与业务查看。这部分的接口应尽量由整合模块来提供,以保证数据链路完整性的同时保证其他两个模块功能的纯粹性。
除了以上,我觉得还需要做一些“边角”。比如数据监控与数据展示。以我所在公司的水平来说做专门的数据处理可能有点吃力,但是简单的数据整合以及展示还是可以做的,而且很有必要。虽然现在我们的项目都是私有化部署,但是不排除未来有一些很小的医院,私有化部署对他们和对我们都是没有必要的。对他们来说增加了开支,硬件成本和网络成本都是很大的;对我们来说则增加了维护成本。这时候saas化就很有必要。这个我看到目前的团队和产品经理也有在考虑。
假设我们已经做好了一个云平台,那这个云平台上面要展示的数据其实应该更多,要尽量把那些私有化部署医院的一些非敏感数据整合进来。好的数据对公司的管理层以及市场人员都是很有用的,退一步来说,部门对上层汇报成绩的时候数据是最好的表达方式。
模块开发
项目叫支付平台,而最大的工作量是对接院内his,这应该是很不合理的情况。针对这种情况,我觉得应该出一份标准的文档,由院内his按照标准文档提供接口,只有实在没有办法提供的时候才由我们适配,不然的话这个问题永远无法解决。
基础数据
还有一个问题就是关于基础数据的问题。比如有A和B两个module同时需要访问一张表x,那正常应该做的是A或B提供访问x的service,或者单独一个模块C用来提供对x的增删改查之类的操作。而现在项目的处理方式是在A和B单独处理,就导致多份dao层的出现。目前我想的是单独出来一个module然后把dao和xml先移进去,然后A和B先直接把这个包进去,后续再改由新module提供dubbo服务出去。
代码质量
其实最初想写这篇文章,就是因为这部分。但是没想到啰啰嗦嗦写了这么多其他内容。支付平台算是公司的核心产品了,我觉得我以前在代码质量方面高估了对它的期望。不知道是项目发展到一定规模必然质量下降还是其他原因,反正情况不是很好。
由于本身的水平所限,我想说的都是很简单的,一般初级软件开发人员都应该做到的。
300行的函数。相信这种函数每个开发人员看到之后感受到的只有绝望吧。面对一个屏幕都无法展示完整,包含层层叠叠if语句的函数,有时候真的无从下手,我是配合onenote边做笔记逐行查看,才大致理解了整个函数,这个函数几乎不可维护。这种一般就是后来开发人员没有很好的及时对函数就行梳理以及重构引起的,越积越多,最终几乎没人愿意主动来处理他,处理不好很容易出错。对这种情况,我的建议是当函数超过50行的时候就强制要求拆分。每个人的所有提交进行自动扫描,如果包含超过50行的函数拒绝提交。而且要求对每个函数进行功能说明。这样一个300行的函数会被拆成6-7个小函数,而且是有功能说明的小函数,对代码阅读性有很大提升。
重复的查询。在业务逻辑比较复杂的情况下,有时候会出现很多层调用:入口函数A调用B,然后B调用C,然后C调用D。这个时候就会出现如下情景:A里面需要使用数据库的数据a,此时BCD都不需要。当某一天某一个开发人员改动逻辑发现在D中需要数据a的时候,他可能并没有去从入口一步步从A看到D,他只是关心了D中需要什么,于是他再一次在D中查询了数据库。同样的,假设这个逻辑很长,这个数据可能被查了很多遍。在没有做数据缓存的情况下,会导致同样的数据库查询一遍遍执行,很不合理而且影响程序性能。对这种情况首先应该增加数据缓存,其次还要提高开发人员的基本素质,当更改某个流程时,应对整个流程有充分的了解,避免重复性工作。
代码冗余。只说一句,sonar插件让我看到一个if-else if-else中,第一个if和最后一个else中的代码块是完全一样的,表示很无奈。
复杂或者奇怪的sql。其实很多人并没有系统的学过数据库这门课程,所以他们设计表结构的时候有些随心所欲,这部分就不说了。但是有些人喜欢在网上搜一些有些奇怪或者说很复杂的sql语句用在代码中,对不同数据库的兼容性就会很差。其次,数据库的性能相对于程序一般都不是很好,复杂的sql对整个项目的性能有很大影响。还有就是,sql进行要符合常人的思维习惯。我曾经看到数据查询接口的入参叫callCount,值为2,我觉得我肯定发现了一个隐藏的bug,因为这个查询应该查的是callCount为1的值。但是当我启动项目执行的时候发现返回值并没有出错,让我百思不解。我只能用断点一步步执行,最终发现在sql中他写的是 CALL_COUNT < ${callCount}。看到这里我的内心真的五味杂陈。我不知道为什么开发的时候要把等于1这么正常的情形反常的写成小于2,可能有我不知道的故事吧。
还有其他的小问题就不说了,逼死强迫症。
命名规范
这部分在我来这家公司之前是完全没有思考过的,直到我看到了在一张表中各个字段的奇怪命名方式。一个人对一张表的字段竟然可以添加不同的前缀,这是很不可思议的。至于单词拼错的情形,不说也罢。
真正想说的其实是整个公司的命名统一问题。比如身份证字段,所有项目都应该有个统一的名称,比如:idNo,那么前端在需要身份证号的时候就直接取idNo字段,而不是每个项目起一个名字。实际项目开发中,有看到一个类表示同一种id的字段竟然有好多个,就是因为命名不统一,后面的维护人员并不知道前人写的那个名字和自己的是同一个,无形中就增加了代码维护成本。针对这种只能定义公司自己的命名仓库,每个人需要定义一个新的名字之前都要去查询,如果没查到才能提交新的名字给命名库,只有在命名库采纳之后才允许使用。这当然会增加一些额外的工作量,但是我认为是可以接受的。
关于前端
其实现在的我是没什么资本来讲前端的。所以可能讲的不对或者不合适,不过我自己的博客,应该只要不违法都可以说。好久没大量写过前端了其实,应该接近三年。
在上个公司有写过很多,还用react-native开发过完整的一个网站,并在H5/iOS/android多平台上线,曾经也算是略有心得。其实我们公司的前端页面更偏向于后端的增删改查,大部分也不需要很复杂的前端技巧,这个时候组件化或者说可视化我觉得是完全有可能做到的。不要一讲到可视化就觉得很高端,如果我们只需要实现简单的首页功能与菜单排布,列表预定样式选择配置,我觉得是很容易实现的。
针对首页,开发很多模块出来,比如轮播模块,菜单模块,列表展示模块,然后定义好数据格式。这样的话在后台通过拖拽排布然后配置,就可以定义好一个首页,至于背景色这些就更加简单了。
至于列表页,可以预设几种样式,然后同样通过配置决定加载哪一种,我觉得这些是完全可以实现的。这部分配合一些参数转化,前端根本不需要关心是医院列表还是医生列表,只需要知道数据源,数据转化,列表模版即可自动展示列表。
至于表单页详情页更加不用说了。虽然真正的可视化编程很难,但是配置化的可视化并非不能实现。完全可以遇到新的需求时就以组件的形式做出来,然后入库,随着一点点的扩充,是有可能实现大部分功能的。这并不会很难实现,而且实现过程也不会增加很大额外工作量,但是后期真的可以减少很多前端的工作量。
最后
整篇说是思考,最终更偏向于吐槽。项目在发展过程中还是需要花一些时间定期做些代码方面的优化和重构,不然越积越多,最后整个项目很可能变成一个shit mountain。至于公司层面,我不知道怎么说,应该是我的眼界或者阅历不够。树木还不够大就已经开始生虫子了,需要真正有权利的人来做一些修剪的工作。