其实我很久以前就想写这一份报告了,但是项目真的很紧,没有什么时间去整理去总结,但是这个过程是非常重要的。这份报告总结了远东一期项目在整个开发过程中的一些弊端,其中也会谈一些
CMMI
在远东一期中的应用中存在的缺陷。好了,我们现在就开始吧!
第一、
分层开发。
远东项目应该是从真正意思上我们公司第一个完全分层开发的项目,之前我们虽然做过一些练习,但是经验远远不够,也没有完全理解分层开发的精髓,基本上将分层开发的所有缺陷都暴露出来了。
在我们谈分层开发的之前,我们先联想一下这样一个场景:假如我们公司不是开发软件的,而是搞新型汽车研发的,现在要研发一种会飞的汽车,外型时髦,功能强劲,而且还会飞。由我们公司最有实力的设计师小祥子设计,设计方案经过公司各个专家的评审通过,可行性达到
90%
。
接着公司联系了各个组件的厂商,比如说发动机,轮胎,底盘等等。我们就用发动机这个组件来举个例子。
小祥子:“小马呀!发动机的设计图纸你看过了吧?你们厂商研发这个没有什么问题吧!”
小马:“没问题!小
CASE
。”
数日后,小马分析完设计图纸后,联系了各家发动机零件厂商。
小马:“小洪,根据我给你需求,你做这些零件有什么问题吗?”
小洪:“
No problem!
小
CASE
。”
时间一天天的过去了,首先是小洪交付了一批零件,由于时间进度非常紧,这批零件并没有去检验,接下来是小马根据这些零件,并按着设计图去组装这批零件,组装后发动机也没有经过测试,就发给了小祥子。
接下来小祥子收到了各个厂商的各个部件,比如说发动机,轮胎,底盘等等,组装成了一辆“会飞的汽车“,然后按下了启动按钮
………..
。这时候,有的人要问了,你们这整个过程什么测试检验都没有,这能行吗?
看了上面的例子,我们应该都有所感悟,知道这样的一个过程,十有八九是不会启动。其实软件的分层开发何尝不是这样,如果不能保证每一个方法,每一个服务都是正确的,那将会带来毁灭性的灾难。现在我就总结一下软件分层开中经常遇到的问题。
1、
查错与沟通。
刚才说到哪里了?哦!对了,当小祥子按下了启动按钮,这时只发出“轰”的一声,冒出一股黑烟,之后什么反应都没有了,到底哪里出了问题,于是他一个一个组件的去查,最后发现了发动机有问题,于是马上打电话给小马。
小祥子:“小马,你不是说这是小
CASE
吗?怎么搞的,你的发动机都没有反应!你如果在这样,今后我们就不用你们厂商的发动机了!”
小马听了电话之后,感觉事情不妙,马上召集全体发动机设计人员,到底是哪里出错了。经过一天一夜的检测,终于发现是引擎盖子出了问题,并不是发动机的设计上有什么问题。于是小马打电话给小洪。
小马:“小洪,你到底还要不要做生意了,你都给我的是什么破烂玩意,你去看看你的引擎盖子。”
错误终于检测到了,原来是发动机的一个零件除了问题。错误是检测到了,但是想想我们到底花了多少人力物力。为什么当初不把每个零件都检验一遍,为什么!
当然在汽车制造业是不太会发生这样的事情的,但是在软件行业,不管是分模块开发还是分层开发,经常存在这样的问题而且还不被重视。在分模块开发时,自己造成的恶果,当然自己先尝了,然后再去补偿,但是在分层开发时,是谁造成的恶果,我们必须要查出“真凶”,才能“对症下药”。
举个例子,负责表示层的小金按下了一个保存按钮,“咚”一下系统强制关闭了,怎么回事,于是找负责服务层的小岑。
小金:“小岑,我刚才调用你的服务,然后就系统强制关闭了,怎么回事?”。
小岑:“是吗?我看看代码”。
于是小岑仔细的查了一下自己写的服务方法,发现在自己的服务方法里面调用了小花写的服务,而且自己的调用数据访问层的方法都是对的,于是他便叫来了小花;
小花:“小花,在我的
XX
服务方法里调用了你的服务方法,你看一下你的服务方法到底出现了什么问题。
接着,小花根据小岑的提示,找到了那个服务方法,仔细的看了一遍,发觉在调用小洪写的数据访问层的时候,出现了问题。
于是小花问小洪:“你的数据访问层的
XX
出了差错,你仔细查查有什么问题!”小洪老老实实查了自己写的方法,终于发现了问题。
我们对比一下汽车制造业,几乎一摸一样,都是花了大量的时间和精力去查错,但是有一点实业和软体业是不一样的,就是对质量的控制。在市场经济,实业的竞争非常激烈,如果你的零件,或者说发动机做的不好,那你就会受到制裁,甚至就失去这个客户,所以我们就关心我们的每一个步骤,发动机厂商就会检验每一个零件是否没有问题,汽车制造厂商就会去留意每一个组件是否完好。每一个环节出现问题,将直接导致产品失败,造成的损失将无法挽回,我们不是常常听说有些厂商集体召回某些批次次品的汽车,然后还要赔偿大量金钱去平息这些风波。
那软件行业的,特别是分层开发,因为分层开发从某种意义上模仿了社会上各种制造业,但是软件行业各层人员怎么去控制自己代码质量呢?因为没有制度和经济的制约,难道你说数据访问层写错了一个方法,就让写保证书,说我以后保证不在发生这样的错误。那怎么办?
这绝对不能放任不管,这些沟通和差错的成本远远超出了想象,也可以说是埋下了一个个“地雷”,不知道那天被人踩到,“死伤一片”。
我认为要解决这个问题,首先要是意识上必须要注意质量的问题,你要认识到你的一个差错,并不是影响你一个人,而是对这个团队带来的影响,意识的问题的严重性,这样你才会认认真真的看设计文档,看需求,认认真真的编码,而不是别人去强迫你。
再次,我发觉我们在做项目的时候,差错
50%
来自数据访问层,
30%
来自服务层,
20%
来自表示层,而数据层的差错,不是什么严重的问题,都是一些字段的
SQL
组装差错,数据组装差错,逻辑理解差错等,一般数据访问层问题的解决都在
2-5
分钟之内,但是整个团队可能花了半个小时,甚至更多时间,数据访问层人员必须意识到自己就是最基本的零件加工商,如果自己的零件出了问题,那将是致命的,对自己每一个发生的错误都要深刻的反思,预防自己再次发生这样的事情,这样你才能是被称的上是合格的“零件加工商”。
之前我们的所有项目都没有做数据访问层单元测试,如果换个大公司的话,可以说这是不可想象的,也许有的人要抱怨,写测试代码很累的,而且会影响进度的。那你就错了,现在测试代码的框架可以自动生成,而且影响进度的恰恰不是这点,而是上面我所说的差错和沟通,这里花的时间远远要比你想象的多,也许你都可以写
20
遍测试用例代码了。所以我坚持要在中心血站的加入单元测试用例代码。
至于服务层,由于我们公司现在做的项目业务逻辑并不是很复杂,导致服务层更多像一个“皮包公司”,而不是“零件加工工场”,但是这并不是说没有导致服务层出错,编程人员的逻辑严密性、业务理解能力、需求分析能力,这些都将导致提供错误的服务,就像你拿到了一堆完好的零件,但是由于你的失误,导致向表示层提供了错误的服务。
最后表示层,我觉得表示层要像一个客户,表示层人员的侧重点要关注在人机交互,数据采集的正确性、页面美化及细节处理等,必须意识到自己不需要关注任何业务上的细节,如果你在代码中有通过调用服务层来返回一个状态,接着再去处理你的另外一个逻辑的话,那就说明你的页面层做的不称职,从另一个角度也说明了服务层人员提供的服务不专业,属于二流水平。
小结:我苦口婆心的说了这么多,就是为了表达一个意思,各层人员在编码实现与设计阶段必须保证质量,要像制造业一样有产品质量危机意识,有问题的“零件”千万不要出厂。
2、
瓶颈现象
这个问题在分层开发中的“上镜率”也是相当的频繁,对软件研发进度造成的资源浪费相当的严重。从制造业我们可以轻松的想象到这个问题的严重性,举个例子当研发发动机时,在组装的过程中少了一个零件,于是小马怒气冲冲的拨打了小洪的电话:
小马:“小洪呀,小洪,上次你给我的破烂零件我还没和你算账,这次你干脆就不给我零件了,还要不要在道上混了。”;
小洪:“小马哥,万分抱歉,我马上就查!”
与是小洪看看小马零件需求单,
MYGOD
,少了一个核心的零件,加班加点也要
2
天,这次篓子桶大发了。
于此同时,小祥子也万分火爆的打了小马的电话:
小祥子:“小马,发动机呢?你到底要拖到什么时候,还让不让我活了,整部车就等你一台发动机。”
于是,这三个郁闷的男人,就白白的等了好几天
……
我们回过来看软件行业,这样的现象尤其严重,打个比方,表示层开发人员小金要调用某个服务的
GET
方法,这时候他发现服务层并没有这个方法,于是:
小金:“岑哥,你怎么没有给我
GET
方法呀,你不提供我怎么获取数据呀?”
小岑:“我看看,哦?真的没有哟?马上就写一个!”
但是在小岑在
GET
方法的时候,发现数据层开发人员小洪并没有提供这个方法,于是
小岑:“我的洪爷,你怎么连
GET
方法也没写呀?表示层等着用呢?”
在最先我们开发通用权限模块和最近的远东项目,这样的问题是经常的发生,我们可以想象一旦一个流水线断了之后,那对资源的浪费是多么的庞大,只有把流水线修好之后,才能继续开工,软件行业分层开发也存在这个问题,而且要严重的多。
那要怎么解决这样的问题呢?这里我像了很多,我觉得要真正的解决这个问题,必须要回溯到需求过程,首先必须要把需求做好,任何违背需求的设计,不管你功能做的多么的强大,界面多么的优美,客户都是不会签收的。在保证需求质量之后,在系统设计阶段,要采用原型开发,而且必须不能是废弃型原型,原型的需求满足度没有
95%
而要有
90%
,你要知道每少一个百分点,就有可能少掉一些数据访问层方法和服务方法,通过界面来充分满足需求,化抽象为具体,这样在我们画交互图的时候才会尽量的趋势完整,尽量的减少业务逻辑理解的错误,在整个分层开发中,致关重要的就是交互图设计的质量,可以这么所当交互图非常完美时,编程人员都可以不用去理解业务,照着图编码就
OK
了,但这只是理想状态,我只是为了说明交互图的重要性而已。
实事上,当我们项目开发的时候,画交互图确实难倒了我们,一方面是我们经验上欠缺,另一方面,也是最主要的对需求理解的不够深入,不够彻底。所以我才提出将抽象需求变成具体的界面,而且尽量的不要遗漏需求。这样,在设计交互图的时候才会做到真正的完整。
小结:我觉得开发人员在实现阶段,整个就处在“猴急”状态,想到什么写什么,这里写一点那里也写一点,没有规划,所以我们必须要记住“磨刀不误砍柴工”的道理哦!
3、
BUG
归属
BUG
归属问题更像是软件过程的管理问题,但是这个问题我之所以提出来,是因为如果处理的不好,那将会对团队的管理带来相当的大的影响,软件的质量也会一泻千里。
打个最简单的比方,一个善于伪装的杀人狂魔逃入了一幢大厦,然后伪装起来找不到了,但是能确认就是在这幢大厦里,于是政府的某一高官说:“宁可杀错一万,也不能让他活着踏出一步。”于是这整幢大厦的无辜百姓全倒了大霉,陪他升天,最后引起公愤、民变
……
。
其实分层开发的
BUG
就想善于伪装的杀人狂魔的道理一样。但是做起来相当的复杂,应该说是分层开发的一大弊端。打个比方,项目现在进入测试阶段,测试人员进行测试,基本上测出
95%
的问题和异常来自页面。接下来怎么办呢。只能说将所有的
BUG
发给负责人先,然后由负责人再分发给各层人员。但是这里有几个问题要特别值的注意:
A.
负责人怎么知晓到底是哪一层出现了问题,难道他要将这个
BUG
从表示层测到数据层,然后在具体定义这是谁出现的错误。
B.
告知具体层的负责人错误后就完事了吗,他怎么去重现这个错误和异常,难道他还要再做一遍从头到下调试,再定到自己的错误?
所以说,这么做是非常不合理的,而且对资源的浪费相当的严重。但是如果不去找到那些“地雷”的制造者,不给他们“严厉”的惩罚,那他们就会继续制造
”
地雷
”,
这和放纵凶手基本雷同,公理何在,制度何在?
我对这个问题我想了很久,对待分层开发的
BUG
问题,我们必须要开宣判大会,软件行业叫
BUG
会议,将各层开发人员召集起来,将各个
BUG
统计起来,一个一个的审讯,在众目睽睽中将它的带头大哥领出来。
我们来模拟一个场景,在测试部测出了
50
个
BUG
后、于是老余【部门经理】、小金、小岑、小花、小洪决定在
X
月
X
日开
BUG
会议。
老余:这次项目第一版测试的结果并不是很理想、超出了指标
XXX%
,我非常的不满意,为了端正大家工作态度,提高软件的质量我决定开这次会议,会议上我会记录
50
个
BUG
的归属,按公司规定的严重、一般、轻微错误进行归类,做到公正,不会冤枉一个好人,也不会放过一个坏人,各层开发人员注意,必须详细记录自己的错误信息,做到直接修改
BUG
的程度。
”
首先老余开始宣读第一个
BUG
:“
XX
模块的
XX
页面,点击【保存】按钮跳出异常。”
于是小金开始重新这个错误,并将每个层都设了断点:
表示层逻辑没有问题
服务层逻辑没有问题
数据层出现问题,发现原来是没有写测试用例,导致字段异常。
老余发话了:“小洪,记录你的错误信息,这个
BUG
按照公司的规定属于严重
BUG
,记严重
BUG
一处”。
……
经过四小时的
BUG
会议,老余做了总结:“这次
BUG
会议,小洪一共
25BUG
,严重
8
个,一般
10
,轻微
7
个。小岑一个
6
个
BUG
,严重
1
个,一般
4
个,轻微
1…..,
这些
BUG
将记录到公司的项目绩效考核软件中。大家对自己的
BUG
分配的不对的可以提出来。如果没有那将给大家二天时间修改这些
BUG
,并在大后天开这
50
个
BUG
的重审会议,如果再在这
50
个
BUG
中出现
BUG
,那将列为公司定义的特大
BUG
处理,纳入考核。我希望大家都认真对待这些
BUG
,想想为什么会出现这些
BUG
,一次怎么去避免这些
BUG
。小洪留一下。”
接下来,老余给小洪谈了分层开发的概念,为什么分层开发,而小洪负责的数据层起到了怎样的角色,让小洪从意识上重视软件质量。
小结:分层开发的
BUG
处理真的比较特殊,不像分模块开发,只要是这个模块的就是你的
BUG
,你怎么也赖不掉,直接记入考核。目前我想到的只有
BUG
会议这个方法,别的暂时还没想到。
分层开发总结:完全分层开发的项目我经历的不多,可以说就是这十个月吧,以前都是分模块开发的,在这
300
天的时间里我想了很多,也经历了很多。在这里我不想谈,到底是分模块好,还是分层开发好,就像谈论使“刀”的厉害呢,还是使“剑”比较强呢。这没有什么意义。但是每一个合格的项目负责人和软件架构师,在决定使用分层开发时,就要非常谨慎的去选择每一层的开发人员,就像制造业选择每一级的服务厂商一样,只要选择了一个不合格的厂商,那必定注定了坎坷,甚至失败。可以说越是大型的项目,就越要注意团队的建设。分层开发中除了我说的以上
3
点外肯定还有值得总结,也希望大家把自己的想法交流一下。其实,上面的观点或者理论毛经理在教我们分层开发的时候,都提醒过我们,可能还不只一次,但是人就是这样,当别人说:“小心!前面有个大坑!”总是不以为然,直到有一天你载到在这个大坑前,摔倒了,痛了,你才会真正的意识到,这里真的有大坑嘢!而且还这么大。只有“痛”过,经历过,才会真正的领悟。这里非常的感谢毛经理,是他教会了我们很多很多。
第二、
高质量编程
我之所以把这点放在第二,我感到我们公司没有重视它。不管在技术交流,还是在平时的交流里,都透露了轻视编码这个过程,或者鄙视编码这个工种,常常听到:“设计都做的这么详细了,编码应该不成问题。”“最没有技术含量的就是程序员了”甚至“你到底编的是一堆什么垃圾呀”等等,我真想质问那些发表这些言论的人:“你们到底有没有编过码,到底有没有理解过编码,知不知道每一行代码都是程序员的汗水,有没有尊重过程序员的劳动,我们先姑且不论它的质量的好坏。”虽然说程序员的能力并不是要求要达到多少水准,但是的的确确他们的工作,确定着软件的质量。很有可能会由于他们的编码风格而导致难于维护,可能会因为他们的代码重构而导致连锁
BUG
,甚至系统崩溃等等。在我们进入系统实现阶段,负责人要提醒程序员:“你们是程序创造者,是你们从真正意义上实现了这个系统,要记住每一行代码都是你们智慧的展现,系统的质量是否过硬,性能是否优良,是否可维护,可扩展,都要靠你们对每一行代码的控制。”研究表明程序员在受到重视和受到轻视的
2
种不同环境下,是完全不同两种状态。
以上的说了这么多,首先是在意识要重视代码编写这个过程,接着就从几个方面来说明代码编写要注意的地方。
1
、代码风格
程序员编写代码的过程是属于创造性劳动,代码里常常含有每个人的使用思路和习惯,即使在同一个项目中,一个程序员也不一定能够完全看的懂和理解其他人的代码。所以这也是我们为什么采用分层的思想来开发的原因之一。在远东项目里,整个表示层由我和马腾负责,而我又给了马腾我的代码模板和页面设计要求,要求他按照模板来写代码,所以说远东里所有的表示层代码的风格都是一样的,没有太多的出入,及时在我离开项目组的情况下,组员再看我写的代码也不会太多的陌生感。
然而分模块开发的时候就要注意了,一定要统一风格,不要太有英雄注意,太注重个性,任何你的个性都是别人的对你的嘲讽。
2
、代码重构与复用
这一点,我真的很惭愧,做的很不到位,里面有太多的教训了。
首先没有标准的基准页,在做远东项目时,为了赶进度,胡乱的做了个页面,什么命名空间,引用,控件命名,
GIRDVIEW
字段定义、样式应用等等全都没有考虑,其实开发我们这种数据库系统,页面的应用和相似度非常的大,就拿远东打个比方,在这个流程里面,相似页面就达到
20
多张,但是由于我的疏忽,导致到后期每张页面的改,真的是太多的工作量花在这里了,反正延缓了进度。事后我想了很久,一定要定义基准页,真的花不了多少时间,就是花多一点的时间也是值得的,我想最好能将相似代码体也抽象出来,做成基准代码,这样效率将更高。
其次没有做业务控件,这也是一个重大的失误,大家都知道业务控件是对某类业务功能的抽象和复用,是软件编程阶段最实用的复用手段之一,但是因为自己的一念之差,导致了无法返回的地步。比如说远东的下一步人员选定,差错数据录入,文件上传,
OWC
业务数据读取,都是可以做成业务控件的。就拿远东的
OWC
控件来说,远东的核心数据处理,都在里面,但是当时自己没有抽象出来,导致每张页面代码过于冗长和重复,多的甚至达到了
3000
行代码,所以每次当需求改到这一块,我都痛苦无比,看的眼都花了。事后,我做了一下研究,如果将这块逻辑做成业务控件的话,页面代码将缩短
10
倍,变成
300
行,可能还要少。哎!一失足而成千古恨呀。这一段时间自己恶补了自定义控件的制作,以及事件、委托的概念与应用,决定在今后的项目里一定要将复用逻辑做成业务控件。
最后,别的层我参与的并不是很多,所以我个人不在总结什么,我想各层编码人员都有自己的深刻体会吧。“家家有本难念的经”。
3
、异常处理
我想大家可能有疑问,异常处理,不就是
TRY CATCH FINALLY
吗,这有什么好谈的,但是真正的编程高手也许并不是这么想,异常处理机制就像是一把“双面刃”。我想远东项目组的成员应该都会有这个深刻体会,当我们在处理
OWC
控件导出
XML
实体文件时,发生了一个错误,当初他就抛出了个异常,是一个内容地址信息,这时所有人都傻眼了,到底怎么错哪里,怎么错的,于是所有项目成员花了
5
个工作时去处理这个问题。最后终于知道是服务没有开文件权限。大家可以想象如果
OWC
当时就能抛出这个异常那我们就不会花这么多的事情了。在我们的项目中也一样,如果我们能正确的去处理异常机制,那我们的程序将更富有智能化,而且它自己去检测业务数据的正确与否,大家都应该我写的
if{}if else{} else{}
语句吧,写的非常死,所以导致后期数据类型发生错误了,也没有检测出来,后来毛经理更我们说,如果你在最后的
else
里写上抛出异常,那这时候程序相当与自动去检验数据类型,当超出数据类型范围了,程序就自动提醒你。这时我才恍然大悟,原来异常处理是这么的灵活。事后,关于异常处理我想了很多,如果当复查的服务层方法逻辑里,加上异常处理,那改是多么好,随时能定位到导师那个调用,那个服务出错,在差错和调式阶段效率将相当的高。关于异常处理我们真的应该要想的更多,看的更远。
4、
代码互查及单元测试
这
2
块,我们没做好,从某从意义上我们走了形式,然而我们也为我们的行径付出了我们应有的代价。这时候我想起了几句言语“种的是什么果,开的就是什么花”、“出来混的,总是要还的”。没错,就是这两块没做好,从而到后期翻天覆地的
BUG
漫天飞舞,原先计划的一周试用期翻了
6
倍时间,原因就是
BUG
。
很可笑的是当初我们自己找了很多理由
:
A.
这简直就是在浪费时间嘛,没什么用嘛!
B.
软件开发人员不应该参与单元测试的,仍给测试部去做吧。
C.
我编写的代码的质量应该比较高,单元测试也查不出来的。
D.
如果真的做单元测试吗,填这么多表格很影响进度的。
到了最后,我们才知道我们是多么的无知,大家可以翻阅软件测试的相关书籍,来看单元测试的用途,多说也没什么用途,我还是那句话:“你如果不是自己亲自被这个坑跌掉,是不会长记性的”,但是我希望大家在“跌倒”之后,重视这个坑,不要在跌一次。
第三、
CMMI3
过程规范
在谈这个问题之前,我们先做一个游戏,名字叫做“话语传递”,规则很简单,
5
个人,在游戏中每个人都听不到对方在说什么,只能看到他的动作和口型,有第一个人看到面板上的字,然后动口型和肢体,由第二个猜他说的是什么话,依次下去,由最后一个人说出面板上的话,结果常常让人哭笑不得。我们想象这个游戏是这样的:
老余看了面板上的字,于是他拼命的喊并表演着:“天上有架飞机。”
小金听不到老余说的话,但是他拼命的看他的口型和猜他的动作,转头和小马说:
“天上要下雨”。
小马看了之后想了想,和小花说:“明天要杀鸡”。
小花看了小马的口型和动作后,想了半天也不知道是什么意思,于是和小洪说:
“杀鸡做饭吃”。
最后,主持人问小洪,小洪说了一句
:
“我想喝排骨汤”。
从一开始的“天上要下雨”竟然能演变到“我想喝排骨汤”,有的人可能会觉得不可思议,不信的朋友可以玩一下这个游戏嘛,保准比这个更离谱,原因就是没有控制过程,当发生偏差的时候没有更改,任由发展,当然最后也就面目全非了。
其实我讲这个故事的目的很明确,在
CMMI
过程规范里,有高质量的需求就会有高质量的设计,有高质量的设计就会有高质量编码,因因果果,果果因因。
其实远东项目在
CMMI
施行上就像上面的游戏,没有的控制好,但是这是我们第一次,谁都不能保证第一次不会犯错,可贵的时候第二次不犯同样的错。
CMMI
我就不在这里详细的说了,我怕
3
天
3
夜也写不完哦。
总结:晚上
10
点了,洋洋洒洒的写了这么多,整个人都肌肉酸痛了,但是心情很亢奋,成充实,就像充满能量的感觉。自己从上到下细细的品读这篇总结,呵呵,没想到自己发现了这么多大大小小的“坑“,而且几乎每个“坑”都跌到过,都留下了伤疤。看着满身的伤疤,立刻感到自己又“强壮”了许多,“彪悍”了许多。在这里再次感谢整个项目组成员,还有毛经理,是你们造就我一天天的“彪悍”,我更希望我们整个团队变得更“彪悍”。