怎么才能做好一套软件系统
偶然翻到电脑里早前写的一篇帖子,转过来
引子
本周二,xxx系统一天内三次故障,报警短信频传。星期三一早,下去协助ABC一起分析zzz系统的事故,此时的PMD老大已经连续在公司待了24个小时,接着又跟我们一起做了一天的事故分析工作,然后他还要去向领导层汇报事故处理进展。
这让我想起了xxx系统刚刚上线后的情景,系统不断地冒烟,按下一处起来一处,商户的电话不断地打到业务人员的手机,快抓狂的业务人员不断地询问系统何时可以正常工作,CEO自己也坐到开发人员背后焦急地等待,被巨大的压力压到同样快抓狂的开发人员,一边擦汗,一边诅咒这见鬼的程序为什么一上生产就垮了。
商户有压力,因为他们接了快钱,但是收不到款了,买东西的用户买不了东西,住店的客户住不了店;公司业务人员有压力,因为商户在骂人,因为这个月的指标完不成,提成拿不到;公司高层有压力,因为商户可能流失,战略目标的实现受到威胁,投资人的利益无法得到保证;开发人员有压力,因为业务人员和高层很生气,后果很严重,因为自己觉得能力不差,怎么开发出来的系统这么不争气……所有的焦点都指向一个地方----怎么才能做好一套软件系统,它不需要多么出类拔萃,只要能好好干活别老添乱就行。
一套乱糟糟的系统
让我们来看一眼这套乱糟糟的系统吧----
虽然GRASP,SOLID,KISS,乃至SOA之类的设计原则和架构风格已经提出多年,这套系统还是像个大泥团,子系统跟子系统耦合,模块跟模块耦合,数据库表杂糅在一起;
几年的时间里,堆砌到系统中的特性代码交叉缠绕,新的修改需要很高的技巧才能进行,系统出点故障,也需要抽丝剥茧地去找原因;
质量堪忧的代码,性能极差的SQL,应用服务器和数据库服务器厂商或许从来没想到他们的产品需要面临这样系统的考验;
可以罗列的还有很多……
怎么会这样呢
要说当年开发这套系统的团队,以及几年里维护这套系统的团队,单从能力上讲,我觉得不算太差,有知名的架构师,有强力的管理者,有一群技术能力不错的开发人员,他们聚在一起,他们的每个人,最初的意愿,我以上帝的人格保证,绝对不是想做一套乱糟糟的系统逗大家玩儿的,因为我就是那个团队中的一员。
但是怎么会这样?事情是怎么被搞砸的呢?
成功需要千万行代码,失败只需要一个字节
好吧,大家都是程序员,有个原因是众所周知的:好的程序需要千万行正确的代码,而坏的程序只需要在其中有一个错误的字节。
因为少判断了银行返回结果的状态,当年的补单程序导致损失几百万,相关干系人降级处理;因为没有考虑多个节点上quartz的同步,当年的兑换程序一下子多给商户兑换了几百万,幸好及时发现才得以追回(这个bug出在我当时负责的产品中,如果没有追回,我的生活就会跟现在不同)。
一个软件项目从需求阶段就会有bug注入进来,到分析(做分析的是个新人)、设计(那个设计人员能力欠点儿)、开发(这个项目的程序员正集体跟女朋友闹别扭)、发布(发布人员资源太少,手脚并用地做着打包工作)、上线(凌晨一点,上线人员打着哈欠部署),各个环节那些让人痛恨的bug都有机会悄悄地爬进系统中,在代码中作怪;
乃至上了生产以后,应用服务器,操作系统,数据库,消息中间件,网络,路由器,机房电力,老化的硬件,这么多的因素都会导致我们的软件系统故障乃至瘫痪。
绝对地避免事故很难,事故出现之前怎么进行预判,事故出现之后又如何把影响降到尽量低。
这样掰着手指头一数,做一套并且运营一套能正常工作的软件系统,要求还真不是乍看起来那么低。
软件熵
熵定律告诉我们,一个封闭系统内的有效能力总是趋于变成无效能量,一切事物总是从有序趋于无序。软件系统是这样,软件团队也是这样。
当年那个xxx项目团队在项目之初,跟我们现在的任何项目启动之初一样,大家有对项目的责任心,有一套如何做好项目的想法----系统内有设计原则和思路,系统外有软件过程来护航。但是很可惜,软件系统的腐坏程度比想象中要快,一年的开发时间,系统还未上线,已经有臭味冒出来了。而经过几年高变化弱治理的维护,系统越来越显得乱糟糟;最初的雄心和好意与最终乱糟糟的系统之间的反差显得那么不协调,但这确实发生了,就在我们眼前。
历史总是在重复自己的,我们看到的xxx系统的故事,就在我们现在的系统/团队中悄然发生,只是它是那么地隐蔽,每天繁忙的工作中没人去关注它,让它得以不断积累,扩散,直到不可收拾。我甚至可以想象,如果没有有效的控制,一年后的我们,会像现在PMD的一些同事一样,被频繁的事故弄得压力重重,黑白颠倒。
据说把一只青蛙扔到热水中,它有机会一下子跳开,但是如果把它放在冷水中然后慢慢加热,它就没有逃开的可能了。
教训是什么
说到这里,还有个问题呢。上面这些所谓的道理,其实是如此地浅显,当年团队中的人,怎么会没有对策?对此,我看到的实际情况上,软件腐坏的问题,在很长的时间里,还真是没有被足够重视过,更别提采取严格的措施来阻止。
当然,不止是软件系统腐坏,团队也会。
要阻止有效能量变成无效能量,必须要有新的能量注入进来,比如,要组织软件系统的腐坏,需要有架构的治理工作,需要设计评审、代码评审;要阻止团队趋于无序的趋势,需要有合适的过程方法,氛围调和和激励工作,还有更多。
这些实践在日常的工作中显得无关痛痒,总会有更紧急的事情比这些更值得做,所以一个个团队一个个产品才会前赴后继地走着差不多的路。
我们要成为其中的一员,再走一遍么?
一辆车的感悟
一辆车,从设计到生产,从生产线到用户手上,一直到最后报废,粗略分为两个阶段。在生产线上的时候,生产线的质量决定着最终车子的质量;待到交付到用户的手上以后,车子自身内置的监控系统需要在汽油不足的时候提示用户,需要在水温过高的时候报警,即使安全使用的过程中,也需要定期地进行保养。
一套软件系统的一生,差不多也是这样吧。但等一下,软件系统好像少了点什么?
软件生命周期的延续
在刚入行的时候,许多的资料文档都是这样定义软件生命周期:需求-设计-开发-测试-上线,上线(或者发布)似乎是软件生命周期的终点,至少对很多软件团队来说都是这样,好多人也都是这么理解的。对照一辆车的一生,可以看到少了什么。
从需求到交付,软件系统只是度过了生产线的一段,在接下来的更长的时间里面,它要对外服务,要演进和变化。我们在软件的生产过程中,为软件系统运行期可能面临的问题做过什么吗?为软件的演进做过什么吗?比如,我们是否可以考虑为软件系统嵌入一个监控模块来检测系统的运行情况,是否可以考虑在软件出现故障的时候进行某种程度的故障隔离以实现优雅降级(Graceful degradation),是否可以在新的特性代码上线时只对部分指定用户开放……
如果把软件的生命周期看的长一点,延续到软件系统的运营,那么在分析设计和其他好多环节,有更多的事情需要做,这些和后来的运营工作一起,才能真正保证软件系统的良好运作。
架构藏在哪里
软件架构是一个出镜率很高的词汇,我有时候就会觉察到自己都有点“言必称架构”。但是架构这东西摸不着看不见,它在哪里,它真的在发挥作用吗?
如果单看一个软件项目的功能需求,还真是找不到架构的容身之处,需求让做把椅子,就做把椅子嘛,简单的很。直到把软件生命周期延续到运营之后,就会发现好多事情需要考虑,领导层关心系统可用性,业务人员关心系统伸缩性,运营人员关心系统的可操作性,QA关心可测试性,诸多的要求,汇总到一个项目中,分析设计的难度大大增加,突然发现生活不是电视剧中描述的那么简单纯粹,有太多的细枝末节柴米油盐的事情需要关注。
幸好,这里面好些工作不是需要在每个项目中都做一遍的,把其中可复用的东西汇总起来,就找到了架构;或者说,架构藏在对这一些“额外”需求的处理部分。比如上面提到的优雅降级,如果为特性模块加入超类型,使之可以监听特定的故障事件从而可以关闭部分特性,比如检测到资源紧张从而自动关闭部分非核心特性。这是架构应该考虑的东西。
软件产品从软件过程这个容器中被孵化出来以后,还应该有另外一套容器来照顾它在运行期的衣食住行吃喝拉撒,前面的容器是软件过程,后面的容器,我觉得除了更加外围的软硬件系统外,就是架构(更多的时候体现到框架中)。
也是基于这个认识,我觉得,我们日常工作中的设计少了点东西,当一个个本身并不存在设计问题的项目被加到一个产品中时,最终还是会导致作为整体的系统不可控,不满足需求。
我们的路,该怎么走
这一节,我想应该所有关心怎么做好我们现在的软件系统的大家一起来想。为了对抗软件熵,我们已经在渐渐引入敏捷方法,做设计/代码评审,做团队技术交流,但是在架构方面,我觉得我们还有好多事情可以做。