令人郁闷的开发---心得笔记一
一直幻想着,有一个快速编码的过程,几个月来,我们投入了大量人力与物力的研究,结果进展甚微。
从基本的代码模板到代码生成器,从简单的数据访问block到o/r mapping,简单建模到MDA,研究来研究去,发现一个怪圈:编写过程越是简单,生成的冗余代码量就越大,程序的灵活性就越低,同时,程序的bug以平方级增长。
编码与设计的关联度太高了,对于小型项目来说,采用代码生成工具,可靠性,连开发的人自己都有不少的疑惑,凡是代码均有bug,模块的复用度是一个折衷的值,高内聚低耦合在某些情况下,是很不实际的,至少,就目前计算机发展水平来说,就是这样。
最初,打算针对软件开发按照通常的方式,分割为设计、编码、测试、维护,采用迭代模型,不断地采用原型法来进行,仔细研究之下,发现这并不是一个好主意。
不知因为哪里的问题,设计、编码、测试,是一个融合得过于紧密的过程,人为地进行系统分割,还得看运气,包括面向对象思想中的复用,也是让人棘手不已。
做一个简单的计算,首先一个原则,凡是代码都不可能是万能的,遇到具体的问题时,必须更改,而且软件也是都有BUG的。
一个模块的错误机率假设是万分之5,那么它的正确率就是9995/10000,随着模块不断地被复用,假设每次复用时,针对模块都有或多或少的补充代码,那么每一次改变,正确的机率就是(9995/100)的N次方。如果复用20次时,系统的正确率就会降至98%,随着复用次数的增多,正确的机率将会越来越低。如果是一个大型一点的系统,其错误率可想而知。
上面指的或多或少的补充代码,我以简单的Label控件来说明:
Label一般使用的是Text属性,我们假设在任意输入组合数据的时候,最后的机器码无论如何搭配,Label控件都不出错(我们假设Label的Text属性的实现代码是100%正确的),那么,引用一个Label,设置一次Label属性,并且还更改了其它发生(如文字显示是否居中),这一部分代码就称为补充代码,它是对使用这个对象的描述,每一次采用了不同的描述方式,就要计算为一次改变,这样算下去,当然没有问题。但Label这个控件,假设有一点点错误,那么引起的后果也是灾难性的。所以,现在我们用的控件能够稳定到目前的程度,可以说是一个奇迹了。
所以,复用的提高,也往往意味着错误机率的提高,高内聚低耦合本身就是一个矛盾的,开发时,一般是想尽办法找一个折衷点,虽然目前没有一个很有效的寻找折衷点的办法(现在成功的软件,大多是靠高手们多年积累下的经验以及培养出来的敏锐直觉),但至少,有一个方向可以让人去摸索。可惜,令人不快的事情不是只有一件,软件不仅仅是模块设计,它往往还包含了数据设计,业务设计,用户设计等等,每个设计累积在一起,造成的问题是极度令人不快的。
有句话是这样说的:快速设计=快速死亡。此话不假,
还有令人郁闷的是,一般的可视化开发,在普通层面上看,好像只是拖拖控件之类的,其实根本不是那么回事,拖完控件后,还得写事件代码,写完事件代码,还得测试,测试完主要功能后,还要考虑用户习惯,这一步,常常会推翻即有的代码设计,所以,还得继续编码。
在网上看到有人说,为什么不事先设计好,这就是问题所在,大部分程序员并不清楚,自己做出来的东西的后果是什么,非要进行编译一次自己才能够知道编出来的东西是什么样子。这个问题当然是程序员的水平引起的,但现实生活中,不断更新的技术,一昧追新的老板,两者结合起来,程序员也不得不被迫努力学习那些并不成熟,甚至有可能只是昙花一现的技术,结果造成了整个行业的浮躁不堪。
测试先行,也许是一个好主意,它划出了一条线,告诉程序员,哪里不需要超过,避免了程序们因为技术的热衷而跌入的功能漫延之中。正如雕塑一样,已经给出了一个粗粗的轮廓。可惜时间往往不允许你这样做,客户需要的是精品,但公司要生存壮大,就不可能出精品,因为精品就像一块精美的宝玉,需要不断的琢磨才能出来,这是十分消耗时间与精力的,带来的,往往是不成正比的投入与收获。急急忙忙地去开发,客户急急忙忙地去使用,不断的维护与测试造成的修改,往往使程序员进入无底的深渊之中,这也是社会对程序员们的一种摧残,也是对程序们的天才的一种浪费与侮辱。
结对编程,呵呵,这个是好东西,与XP实践相结合,提供一个轻装上阵,把程序员们从无穷无尽的错误之中(文档也是错误之源,XP方法实践中,虽然也要求文档,但毕竟文档的约束力有所降低)往外拖出来一点,可惜的是,以目前的状况,结对编程是一个不令老板满意的东西,在国外也许会让程序员们不好意思偷懒,但在国内,结对往往会是程序员们偷懒的借口。国内的大多数老板们,估计永远不会考虑这样样式的开发,因为它造成效率下降的机率会更大。
人月神话里说:一个妈生孩子要十个月,十个妈来生,也要十个月。这个用来形容软件开发,确实恰当。想想各位项目经理都在做什么?划分出“看起来很美”的软件模块结构,看样子十分精密,结果却失去了软件的灵活性,出了问题时,修改问题的责任却还是落到程序员们的头上。不过,往往这样的项目却会成功,为什么?因为它满足了客户的第一步需求,以后的修改好不好办,这就是另一个问题了。
功能的扩展性,直接让代码的复杂度提高,按XP方法实践里的想法,不要去考虑目前用不上的功能,我觉得是一个好主意。因为交差才是第一的,以后如果要添加新的功能,把这个模块全部重写一遍都行。在对软件开发的熟悉程序未达到随心所欲前,最好少考虑什么扩展性,除非文档中明确指出此部分代码需要扩展。