一、No Silver Bullet 和 There is silver bullet
没有银弹这篇文章的作者认为在未来的十年之内,不会有任何单一的软件工程上的突破,能够让程序设计的生产力得到一个数量级的提升。
这里面的软件开发的主要困难有两种,一种是叫本质性:软件如何从抽象性问题,发展出具体概念;另一种叫附属性,就是将概念上的构思运行在电脑上所遇到的困难。
作者认为,附加性的困难会随着工具的改善而逐渐淡化,反而是本质性的困难最难以解决,因为大部分的活动是发生在人们的脑海里,缺乏有效的辅助工具。这里还提出了以下四项:
- 复杂性(complexity):软件要解决的问题,通常牵扯到计算步骤,这是一种人为、抽象化的智能活动,多半是复杂的。
- 隐匿性(invisibility):尚未完成的软件是看不见的,即使利用图标说明,也常无法充分呈现其结构,使得人们在沟通上面临极大的困难。
- 配合性(conformity):在大型软件环境中,各子系统的接口必须协同一致。由于时间和环境的演变,要维持这样的一致性通常十分困难。
- 易变性(changeability):软件所应用的环境常是由人群、法规、硬件设备、应用领域等,各因素所汇集而成,而这些因素皆会快速变化。
不过之后另一篇文章写的是有银弹,里面指出采取再利用(reusable)、可替换组件的方式来对付属于概念本质性部分的问题。以及越来越多的软件开发模式及方法论的出现,都是对本质性工作困难进行的优化。
个人觉得,附加性的问题的确是在逐步被解决的,所以根据工具的完善而逐渐淡化我觉得是很对的。现在的确有了很多工具帮助我们解决了许多附加性的问题,最直白的例子就比如我们的编辑环境,编辑环境极大地辅助了我们的软件开发。然后在我们本次一轮迭代中,我们后端开发使用的ruby on rails的架构,更是极大地简化了大量工作。不过实际上在我个人开发的感觉中来说,我觉得本质性的困难好像并没有遇到很多,因为就感觉怎么做都是可以解决的,只是解决的效率有一定区别,相反,附加性的问题仍然是最大的困扰。比如很多功能在实现的时候,因为某些语言的特性,或者是某些平台的问题,比如我们这次开发的网页,就是因为平台的问题出现了很多bug。比如火狐浏览器在http请求中会嵌入大量的无关信息,这就导致我们后端解析http请求出错,没有办法实现功能,这些都是要一个个去测试去发现问题然后再想方设法解决的。所以实际上来说,我觉得附加性的问题虽然得到了一定程度的解决,但仍然是我们需要解决的大头。
另外我觉得,本质性问题其实并不是说那么难以解决的。就个人而言,我发现在经过数据结构,使用过一些高级语言,然后在学会面向对象面向过程的一些思想之后,这些都对于我在思考解决问题都有很大的帮助。比如一些抽象问题,就可以直接将它具象到对象,然后就具象到数据结构,然后就很好去思考出来一种解决方案。然后这里的问题其实大部分都在于如何去更好地实现它。
二、big ball of mud
通过阅读文章和查找资料(文章全英文的而且那个页面看起来实在是太蛋疼......),对于大泥球这个概念有了一点点的肤浅的理解...
大泥球,是指杂乱无章、错综复杂、邋遢不堪、随意拼贴的大堆代码。
然后这个东西在我们的开发过程中还是很常见的。先说我们的这次的第一轮开发,在我们第一轮开发的时候,前端的html代码就有一点点大泥球的问题,主要就是因为初学并不了解,然后不懂得如何模块化,这个问题暂时我们还没有解决,我们是把这个放在了第二轮迭代的任务中。另外对于后端来说,后端有的代码也存在这样的问题,不过后端这个也是因为不够了解,然后导致写出来的东西看起来特别别扭。后端的开发实际上分成了三个人来开发,所以代码风格确实差的很远。不过我们尽量去解决一定的这个问题,就比如用户验证我们就是使用的模块化方法去解决的,就是在具体调用某个接口之前会进行用户验证,比如修改删除新建等操作,然后对于不同的操作用户验证部分是一样的,所以就有注意把这些都放在一个地方,然后通过一个东西实现。然后刚开始的时候三个人写的时候,有的同学还专门在他的代码那边自己写了自己的验证,后来统一了一下。
在个人项目中,的确也是有这个问题出现。主要就是因为,在码代码的时候写着写着就发现有的地方没有考虑清楚,没有考虑全之类的,然后就去接着在另一个地方加上一些代码,然后增增减减什么的。我觉得这个问题的出现最大的原因就是刚开始的设计没有做好。刚开始的设计做好,对于需求思考清楚之后,然后仔细想好如何实现,有没有漏洞等,自然而然就可以解决这些问题,也就是说设计好。不过这让我想起来了另一个方面,就是在我们软件工程一轮开发的过程中,后端在开发的时候,有时候会因为前端的某些功能的变化而需要修改,添加等。添加其实还好说,修改有时候会比较麻烦,然后这个时候就会经常出现改了一个地方,然后这里改改那里改改的情况。换句话说,就是前期设计好了,需求变化了,也是经常会出现这样的问题。我觉得这个方面就不是特别好解决了,也不可能刚开始就考虑清楚需求会不会变化什么的,而且就算去考虑这些问题,需要消耗的时间也太多了。
三、Cathedral and the Bazaar
这里主要讲了世界上的建筑可以分两种:一种是集市,天天开放在那里,从无到有,从小到大;还有一种是大教堂,几代人呕心沥血,几十年才能建成,投入使用。当你新建一座建筑时,你可以采用集市的模式,也可以采用大教堂的模式。一般来说,集市的特点是开放式建设、成本低、周期短、品质平庸;大教堂的特点是封闭式建设、成本高、周期长、品质优异。
在开发中,这个分为两种,大教堂模式(The Cathedral model):源代码在软件发行后公开,但在软件的每个版本开发过程中是由一个专属的团队所控管的。市集模式(The Bazaar model):源代码在开发过程中即在互联网上公开,供人检视及开发。
大教堂模式的软件开发中,测试环节等都是耗时会比集市模式大,因为毕竟并不是所有人都了解这个程序。
我们使用的是大教堂模式,整个开发过程都是由我们的团队专门控制的。我们就是属于封闭式的,源代码没有对外公开,最起码后端的没有对外公开,前端的真想看的人倒也都能看...所以我们测试等如果出现问题都是自己处理,而且像这个在团队中由于前端后端的区分,相当于只有后端可以调试修改后端的东西,也就是只有少数人可以参加到测试和修改中。
四、Lost in CatB.
作者主要讲了开源导致的一系列问题如,软件质量会大大下降。比如说,有一个开源软件然后这个软件是有bug的。然后假如有10个人使用了这个软件,然后可能里面有5个人改了这里的bug,然后其他人就会就这么用着了...然后写的软件就这么流传下去,然后如果还有别人使用这部分的代码,然后就接着错然后就错误就这么一直流传下去了。而且实际上很多开发者并不是真的那么专业的,就我个人了解,很多人就只是那么用着,然后就放进去自己的代码了,就是只是用着,而不是说懂得原理什么的。这就会导致很多问题,就比如错误流传什么的。然后实际上还有别的问题,比如到处引用然后就很混乱等等。
所以说,开源虽然创造了史无前例的全民编程热潮,但也导致了无责任、非专业、凌乱的软件开发。从这个角度讲,也可以解释为什么大教堂模式的优点是品质优异(与集市模式相比)。
这个问题在我们的软件开发过程中也有一定的体现。
我们的前端开发中,设计UI时用到了当下很时兴的semanticUI。里面涉及到了弹窗的设计啊按钮的设计啊等等,然后弹窗会需要引用一些网络上的开源jQuery包来支持相关html代码。但我们根本不了解它的具体实现,只是作为用来实现功能的工具使用,其实这个也就是属于不专业了...很有可能我们就会导致出现什么问题之类的。这样的问题很有可能对第二轮迭代造成潜在的影响,且不利于软件的稳定与完整。而且这样的东西都属于定时炸弹一样的感觉,就是因为不了解,所以不能掌控,所以就不知道到底有没有问题,然后这样的情况下,如果出了问题,都经常很难解决。
五、Worse is Better
首先提到了普遍认为是“好”的设计原则:
- 简单性:在实现和接口中,设计必须简单。接口的简单性比实现更重要。
- 正确性:在所有可观察的方面,设计都必须正确。一丝的错误都是不允许的。
- 一致性:设计不能不一致。为了避免不一致性,可以稍微减少一些简单性和完整性。一致性和正确性同样重要。
- 完整性:实际上,设计必须覆盖许多重要的情况。应该覆盖可能出现所有情况。简单性不可以过度地削弱完整性。
然后又提到了“更坏是更好”的设计原则:
- 简单性:在实现和接口中,设计必须简单。相对于接口而言,实现的简单性更为重要。简单性是设计中最重要的注意事项。
- 正确性:在所有可观察的方面,设计都必须正确。正确性的重要程度仅次于简单性。
- 一致性:设计不能过于不一致。在某些情况下,为了实现简单性可以牺牲一致性,但放弃设计中处理非常见情况的那些部分比引入实现复杂性或不一致性更好。
- 完整性:实际上,设计必须覆盖许多重要的情况。应该覆盖可能出现所有情况。为保证其它质量,可以牺牲完整性。实际上,只要危害到实现简单性,就必须牺牲完整性。如果保证了简单性,可以牺牲一致性以实现完整性;尤其是在接口的一致性没有价值的情况下。
也就是说,简洁是最重要的,其他的东西都是可以为了简洁而让步的。同时作者还提到了,c和unix,甚至还有c++,都应用了这种理论。
个人认为,这种思想是很有价值的。比如,在敏捷开发中,我们先拿出一个成果,然后再与用户交流继续改进我们的成果。就这样一个过程,就很可以体现简洁的重要性。这就有个很吸引人的地方,就是把注意力集中在比较重要的功能上,就是专注先做好一个东西,然后再去做优化,完善,就是先把大体框架和主要的部分实现了,然后其他的慢慢添加。
在我们的软件开发过程中,尤其是这种两轮迭代的方式,第一轮的开发就很明显地用到了这个思想。在我们最初的设计中,我们的工程是很庞大的,提供了特别特别多的功能。然后第一轮开发的过程中,我们实际上是删去了大量功能,在这里就只是提供了最最重要的功能,就是社团和学生最需要的交流的功能,社团管理参加学生的功能。当然我们还需要完成许多大量其他的部分,但是先做好一部分,搭起框架,然后再调整,其实也是有这种方式的价值的...吧...最起码给了我们学习的时间,也给了我们和第一轮的社团用户交流的时间。我觉得这个还是挺好的。
六、瀑布模型
瀑布模型是1970年出现的,一直到80年代早期,它都是唯一被广泛使用的软件开发模型。
瀑布模型将软件的开发分为,制定计划,需求分析,软件设计,程序编写,软件测试和运行维护的六个不同的部分,并且规定了必须要从上一个一直到下一个,这个就和瀑布流水一样,一级一级往下面走。所以叫瀑布模型。然后作者还提出了回溯增加等概念,比如回溯就是在每个过程中都会有反馈,然后如果到哪个过程中有什么问题发生,就可以返回上一个阶段然后进行修改。
瀑布模型的中心思想是按照工序,流水线一样的活动,就可以将问题简单化,然后将实现和设计分开,就可以很方便地分工合作了。还可以联系数据库里讲的,就是逻辑和物理的分离。这里还有张图。
我觉得瀑布模型有这些特点:
1、从开始到结束,每个阶段都分布的比较合理,然后就可以保证整个过程很完善。就比如,如果踏踏实实按照这个流程走下来,就可以比较好地开发出来软件。
2、有个问题,就比如,如果在中间部分或者是某个地方,用户的需求改了,那么按照回溯的说法,就需要一直回溯到最前面,重新去设计什么的,那这样是不是就得重新走一遍?如果真的要重新走一遍的话,我觉得这个应该很不适合敏捷开发= =
3、对于这样的模型,的确很适合分工...
七、关于敏捷开发
在我们的开发过程中,用了敏捷开发的这样东西:
1、我们每天都有开scrum meeting,每天汇报今天干了啥,然后明天打算干啥之类的,还有遇到的问题等等。虽然现在上课有点忙,但是每天都还是可以干一点,就比如学习一些后面开发可能会用到的东西等。虽然可能暂时没用到
2、然后我们有使用过结对编程,在实现数据库设计的部分。
3、我们有很大的自主性,多学习或者多做一些东西等,会对自己的任务进行调整。就像之前写的那样...
4、对于成员之间的东西,比如我们在后端开发的时候,经常会一起讨论,然后看对方写的东西,然后对他写的那部分进行调整改进等。
5、我们的规格说明书,测试什么的都是大家一起写的。
6、我们时刻随着需求的变化而变化...
八、软件工程的方法论到底有多少用处?
个人觉得,这些方法论肯定是有用处的。举个最简单的例子,就比如我们现在的开发过程,我们就是按照敏捷开发的方法在做的。这个方法给了我们一个学习的模式,一个开始的框架。对于我们初学者而言,这种方式,这些开发的方法,一定都是有帮助的。但是这种东西,我个人觉得,它的价值就在于,这是别人的经验。别人的经验,也就是,有可能对你有用,也有可能对你没用,但是你了解了,你就有了个认识,然后懂得该注意什么,哪里应该干什么了,哪里又应该怎么怎么样,又比如遇到什么事情应该如何处理等等。这是经验,但是并不是真理。也就是说,这个东西并不是一定就是这么回事,换了参数条件就有可能不一样了。所以,一定不能盲信,一定要自己有思考,然后自己懂得根据不同的情况调整不同的方式和方法。也就是要学会灵活。就比如,两篇文章中都说过,方法论在预测需求和度量项目方面都是不可行的,然后有的人说,代码行数已经没有什么价值了,因为也么有办法度量你的能力了,然后就进一步怀疑方法论(之前已经因为方法论没法预测需求然后度量项目而怀疑过了),然后也有的人说,代码复审等等都是对于软件开发有很大帮助的。所以我觉得,对于这样的方法论,就是应该去学习,而不是盲从。其实某种程度上来说,我们稍微哲学一点,对于这种经验总结的得出的结果,就比如科学,都是需要有一种怀疑的精神,科学理论也是不停地被推翻的。所以我们更应该抱有一种学习的态度。我觉得从这角度上来理解,软件工程的方法论和科学的用处是很像的。我们使用这种东西都可以帮助我们去完成某些东西,但是我们有时候都需要调整。