关于软件工程中的银弹之我的见解
首先我要提一下这篇文章的作者 Fred Brooks,这位大师写了一本很经典的书是《人月神话》。
我粗略拜读了一点,当时是为了寻找软件工程里面的数学模型,有机会我要细细品味一下这本书。
我认为软件工程中不存在万能大杀器(银弹)
我们首先来看作者说为什么银弹他不行
1.软件工程中的复杂性
2.软件工程的一致性
3.软件工程的多变性
在这里我谈谈我为什么觉得他不行,这里主要谈一下软件工程的多变性。
首先来看如果有银弹会怎么样,有银弹的话,所有的软件工程问题都有特定的方法去解决
既然有特定的方法,那么必然会有人研究出如何让计算机去做软件工程。
这样的话程序员就只需要按照某种范式来撰写需求文档即可
但是我们看看现在的软件都是些什么,上到WINDOWS操作系统,下到一个小小的音乐播放软件
光一个用户体验需求,就不是可以用固定的语言描述清楚的,需要不断沟通修改
我们再来看看运行效率的问题,大家都不希望自己的软件用起来非常卡
把汇编语言抽象成高级语言,运行效率就下降了若干倍
把高级语言再抽象成更高级的框架引擎,运行效率不知又下降了多少
看看ZUN用汇编编写的东方系列弹幕射击游戏,和市面上一些随处可见用引擎写出来的弹幕射击游戏
玩起来游戏体验相差甚远
如果再加一层超高维度的抽象,也许必须人手一台天河一号了才能跑得起来扫雷小游戏了吧。
而用所谓“银弹”完成的软件,又能比这种计算机实现的软件高到哪里去呢
软件工程中对时间复杂度的要求,就把银弹的产生卡的死死的
程序员需要根据实际的需求来创造特定的架构,编写特定的代码。
这就像带兵打仗,不存在某种特定兵法,可以保证打赢所有战争(看看历史上尝试使用银弹的赵括吧)
光软件工程多变性这么一条,就导致银弹难以产生
何况作者还提到了复杂性和一致性
很多时候需要使用编程技巧和架构技巧,来同时满足需求的完整性和用户的体验
因此,我认为软件工程中不存在银弹
关于软件工程中的大泥球
在 Big Ball of Mud 一文中,作者用软件工程与建筑学作比,将软件工程的垃圾代码,质量低下的模块比作建筑中的一坨规模很大但是不能使用的泥,有种烂泥扶不上墙的意味。
然后作者给出了一些原因和解决方案
作者给出的原因大致有如下两点:
1.程序员优先实现需求,其次优化代码
2.刚开始进行项目的时候对架构的理解不是很清晰
3.不断更新的需求和技术
第三点属于客观因素,感触不是很深,这里主要说一下前两点
作者在文中发问,为什么优秀的程序员会写出垃圾一样的代码(THROWAWAY CODE)
这方面我和作者感触相同,主要是时间
我们往往被限定在一定时间内实现某种功能,而对代码风格和质量不作要求
然而不规范的代码,更容易隐藏BUG,同时也会加大debug的难度,可扩展性也会变得很差
时间一长,经过项目的不断扩展,这些不规范的代码会有很大概率暴露出问题,这时,我们整个架构中就出现了一坨泥
由于这样的代码往往会在一段时间之后才会出现问题,试想一下,如果一个BUG隐藏在一段一年前的远古代码里面,而且这段代码还不是自己写的(就算是自己也不知道),那么这段的修复代码将变得非常棘手。
所以,这就是代码不规范产生的泥
难道代码规范就可以了吗?
作者在文中也说了,刚开始对整个工程理解不深入的时候,是容易在最开始的实现上出现偏差,这里就拿我最近做编译遇到的一个例子来打比方
实现表达式检测的函数,需要调用项检测的函数;实现项检测的函数,需要调用因子检测的函数。实现因子检测的函数,需要调用表达式检测的函数,三者是一个递归嵌套的关系
我们的思维方式往往更习惯自顶向下,遇到这种A,B,C递归调用的需求,就会出现如下状况
实现完A,,B,再实现C的时候发现A需要修改以便兼容C,然后A做了修改,B也要做修改,这样改来改去,再规范的代码也容易变成一团烂泥
遇到这种情况,我认为最好的方式是实现之前就想清楚模块间的关系,注意协调配合其他人写的模块,这样才能减少类似的问题。
作者后面提出了很多减少泥球的方法,比如
灵活配合用户需求,而不是用某种模式来强硬实现需求。遇到泥球的时候可以考虑重构代码,等等……
我对减少大泥球确实也没有比作者更多的方法,我认为,如果规定时间内必须实现某种需求的话,那么在实现完之后,可以让程序员在一段时间内按照某种代码规范要求来维护/完善项目代码
这样既给了程序员修整的时间(连续加班太痛苦了),又能有效减少大泥球(只是企业利润可能会因此降低)
我的团队出现了不止一个大泥球,产生的原因主要还是对框架引擎不够熟悉(而且那个引擎坑真的多)
有的大泥球解决了,有的到现在也没有解决
关于大教堂和集市
- The Cathedral model, in which source code is available with each software release, but code developed between releases is restricted to an exclusive group of software developers. GNU Emacs and GCC were presented as examples.
- The Bazaar model, in which the code is developed over the Internet in view of the public. Raymond credits Linus Torvalds, leader of the Linux kernel project, as the inventor of this process. Raymond also provides anecdotal accounts of his own implementation of this model for the Fetchmail project.
这里我直接引用了原文,关于这两个概念,说通俗一点讲就是private和public的区别嘛
大教堂是团队内部有严格分工从而开发,集市是通过群众的力量开发(也许叫云编码比较舒服)
我们团队采用的是大教堂式开发
关于在集市中迷失,我们团队目前没有遇到过(因为现在还是大教堂模式开发)
关于Worse is better
这个观点我是赞同的,我还记得有一次软工课上提问,问有99%的可能性都用不到的需求,那到底还要不要加。我当时说的是不要
当时考虑的就是,既然大多数用户用不到,那么多加一个功能,既提高开发成本,又降低用户体验(功能冗余)
这个观点在软件设计里面我认为是很好的理念,只需要弄清楚这个软件是用来干什么的,那么就干好这件事,其余一概不管。
微信的成功就是很好的例子。
关于瀑布
瀑布模型(Waterfall Model) 是一个项目开发架构,开发过程是通过设计一系列阶段顺序展开的,从系统需求分析开始直到产品发布和维护,每个阶段都会产生循环反馈,因此,如果有信息未被覆盖或者发现了问题,那么最好 “返回”上一个阶段并进行适当 的修改,项目开发进程从一个阶段“流动”到下一个阶段,这也是瀑布模型名称的由来。包括软件工程开发、企业项目开发、产品生产以及市场销售等构造瀑布模型。
以上是百度百科对瀑布模型的解释
我认为瀑布模型有如下特点:
1.流程严格,产生的大泥球会比较少
2.开发时间较长,成本较高
这两个特点,一个优点一个缺点
我认为这个模型的适用性需要看应用场景
在操作系统设计这样的大工程中,软件对质量的要求很高,但是对时间的要求不高(看看WINDOWS多久更新一次,而且用户也没有更新的积极性)
瀑布模型是很合适的
在应用软件(游戏,视频,办公等等)中,往往用户有明确的需求,产品对时间的敏感度很高(可能晚发布一天就少了大量用户),BUG的容错率较高(相比于操作系统)
这类软件就不适合瀑布模型
关于敏捷
我认为敏捷开发时很适合做上述瀑布模型不适合做的软件类型,用户首先需要一个可随时运行的软件,敏捷开发可以满足。
用户又希望软件开发的比较快(谁想等一个产品等半年),敏捷开发这种切割式的软件开发确实会非常快。
所以,我相信敏捷未死,也不会死
我们的项目中全程应用敏捷开发
首先把架构写出来
然后并行实现这个架构下的若干功能
然后再并行实现这若干功能下的若干子功能
策划,美工,开发形成了一个流水线
关于软件工程的方法论
我认为以上争论是很正常的,作者站在不同的时间,不同的项目上,提出了不同的看法。
这恰恰说明了软件工程没有固定的方法论,如果有,那不就成了银弹?