或许我们做错了,但绝非一无是处

是的,过度设计的现象普遍存在。回到90年代中期,当我开始入行开发者行业时,我的目标就是成为一个架构师。任何认真的开发者都不会在选定自己喜欢的设计模式之前就开始写代码。我们会在选好设计模式之后才开始思考怎样将业务需求融合进去。是的,我们会先弄出架构,然后是宏设计(层)和域模型(包括UML图表),接下来才思考业务需求和详细的用例。没错,那个时代,用例真的不是什么大事。我们的基本流程和众多可选流程中有一长串的用例。

90年代是开发者们群情振奋的时期。70和80年代还在学术论文层面上的一些结构化设计,以及互联网,最终都在90年代实现了。那个时期里,还出版了基本面向对象编程的书,至今在很多领域里还是新鲜的概念。

我依然记得我们扑在画类、序列、组件、部署和很多其他图表上的无数个月,我们总在尝试想出未来某天我们将打造出的软件的最佳设计。我们也建立了一些原型,因此我不能说在规划阶段我们没有做任何的编程或试验。当然,所有来自于原型的经验教训最终都会反馈到我们的图表中。

除了内部设计,90年代还是分布式系统大爆炸的时期。我们有了CORBA(公共对象请求代理体系结构)和DCOM(分布式组件对象模型),有了客户端/服务器(C/S)和多层级架构。我们在使用数据库作为应用程序间通信点上学到了单点故障。是的,我们在这上面栽过大跟头。我们学会了怎样创建“服务”——SOA(面向服务架构)概念迅速兴起。我们学会了考虑可扩展性和安全性。很多政府和银行以外的项目也变得非常巨大和复杂了。

大多数充满激情的软件开发者的目标,都是创造出一个超棒的设计;这也是通往架构师和职业升华的道路。我们必须学习,要在软件设计上做到最好。我们必须对结构化设计和面向对象设计都有着深度理解。我们必须了解分布式系统的基本原则。我们必须非常熟悉所有层级的内聚和耦合。我们必须理解协变与逆变。我们必须学会设计包含了契约与不变量的组件边界。我们必须学会理解业务语言中的动词和名词,并将它们映射进软件中。如果不知道怎样在关系数据库中对数据建模,不知道怎样让查询表现良好,那就根本过不了入职面试那一关。我们必须能在合适的粒度定义自己的专有协议,以便能让其他系统更容易地使用它们,同时,还要能处理输入输出(I/O)和带宽问题。是的,我们花费大量的时间来干这事儿。

90年代 的软件开发基本围绕设计和架构展开。而且,还必须用UML来完成。

但是,虽然我们学会了怎样设计,却败在了很多其他方面。我们开发得不够快。事实上,在某些项目中,我们根本没能产出任何东西。大多数时候,我们花费在拿出一份完美设计上的所有脑力劳动都完全打了水漂——缺乏快速反馈以及对业务发展的无力应对。我依然记得在一行代码都还没开始写之前就用来控制需求变更的巨大电子表格。是的,我们报销了大量的时间。很多很多次地报销掉了。

快进20年,我们中的有些人意识到了之前所做的是错的。于是,我们在工作方式中引入了敏捷开发(Agile)、精益开发(Lean)和其他多种开发原则和实践。我们的工具包中加进了很多新的设计和架构技巧。我们引入了新的技术。我们融合了与业务协作的不同方式,开发团队构建方式也有了创新。我们认识到,尽管设计非常重要,但没有什么东西比持续推出软件更重要的。我们学会了怎样获得反馈并进行迭代。我们明白了自己有责任测试自己的代码。我们懂得了必须在生产中为软件提供支持。我们知晓了创建原型再摒弃的价值。我们了解了实验的重要性。但是,我们同样深深领会到,即便要以更好的方式工作,这些年来我们所获得的所有设计技巧也不用全都扔掉。我们没必要放弃我们那个时代,70、80、90年代软件设计上的众多出色成果。但,我们学到的最重要的一课,就是:上下文才是决定性的,软件设计就是在权衡而已。没有产品,设计毫无意义。那么,我们就要不断产出没有坚实的设计基础的代码吗?我可不这么认为。

今天的软件设计中,我所看出的最大的问题,就是二元思维。如果X不行,那么Y必然很好。如果X适用于A公司,那我们也一定能用。如果某个著名人物在一场45分钟的演讲里说了什么东西,或者我们在博客里看到了什么东西,那肯定是真的。例子太多,不胜枚举。

二元思维引发的另一个常见错误,就是坚信软件项目的所有功能都具有同等的复杂度,一个设计选择就能通吃。但真相是:某些功能相当简单,某些十分复杂,其他跟多的则处于两者之间。有时候,复杂性存在于实现阶段;其他时候则会在理解和建模阶段出现。有时候复杂性在于弄清我们应该做出个什么东西。其他时候则在于与别的系统的集成上。就算是同一个功能,不同部分在复杂性上也有很大的区别:一些部分可能很小,可以快速实现,而其他部门有可能极端复杂,需要预先考虑很多。某些功能很浅,几行代码就搞定,其他则很深,要用到多个模块,上千行代码。非功能性需求也会让简单功能的部署变得相当复杂。而有趣的是,以上种种都在同一个软件项目中碰上。因此,如果我们认同软件项目中不同功能有着不同的复杂度和规模,那么,我们就不能将二元思维应用到软件设计上——一个相当复杂的软件项目是不可能用单一设计方法搞定的。

我们生活在一个信息触手可及的世界。谷歌搜索一下,我们就能搜到很多现成的解决方案。我所恐惧的是,作为一个产业,我们正在丧失思考的能力。我们正在丧失研究并作出我们自己的选择的能力。我们越来越多地依赖于现成的解决方案。我们总是在走捷径。要我说的话,我会把这些所谓的捷径称作“Stack Overflow(一个与程序相关的IT技术问答网站)”解决方案。

对某些人而言,软件设计就是过度设计的同义词,这让我很伤心。另一个让我伤心的认知是,“根本没有设计”正成为敏捷开发、精益创业和快速交付的同义词。我不觉得良好软件设计、敏捷开发和精益原则的发起人和倡导者们的本意是这样的。过度设计不是件好事,但没有设计不也很糟么?简单不意味着扯淡。简单代表的是我们当下所知道的刚刚好的设计,而不是少到可怜或者根本没有的设计。套用爱因斯坦的话:软件设计应该尽可能简单,但不能过于简单了。或者,另一种表达方式:代码应该是良好设计的,而不是过度设计的。

过去几年里我与很多开发者聊过,也复查了很多的代码,我主要担心的是,我们正在发展一种黑客文化。我见过的从业不足10年的很多开发者,都几乎没有什么良好软件设计的知识。当然,他们自己不那么认为。如果你觉得我是在夸大其词,那就去让你团队中的开发人员解释一下什么是内聚,以及内聚的不同层级。问问他们共生性、协变、逆变的含义。问他们耦合的不同等级和类型。问他们什么是契约式设计和不变量设计。对那些听说过面向对象设计SOLID原则的人,问他们SOLID原则的出处。今天的很多开发者认为设计模式不好。那就让他们描述几个模式,说出它们的异同,以及什么情况下应该或不应该用某种模式。问问他们不同的模式分类法。让他们说出桥接模式、适配器模式和中介模式的差异。访问者预期要解决什么问题?问问他们什么是备忘录模式。如果他们解释不出,那他们又怎能称设计模式不好呢?

今天的很多开发者都没有意识到软件设计基础都是在70、80、90年代铺设的。其他开发者则倾向于无视这一事实:这就是过度设计,我们不需要。好吧,我尊重个人意愿。那我们为什么依然保留了那些糟透了的软件呢?难道今天的做出的软件就真的比20年前做出的好吗?为什么开发者今天依然在用测试驱动开发模式(TDD)艰难设计代码?为什么我们依然在讨论遗留代码?对我而言,遗留代码就是设计很烂、难以测试和维护的代码的代名词。

我绝非在为过度设计或浪费时间画UML图表辩护。我想说的是,我不会花几个小时去设计核心领域内部类,也不会试图在开始编码之前不考虑整体设计就去打造一个企业应用并一次次测试。设计是软件开发中的重要一环。如果我要打造一个与其他很多应用共存于同一个生态系统内的应用程序,或者一个背负沉重非功能性需求的应用,又或者一个需要遵从很多规则的应用,好吧,我当然会在动工之前认真考虑它的整体架构(宏设计),但我也会边开发边测试它的功能(“微层级”)。设计存在于各个层级:从前期的架构层级,到即时的作为我TDD流一部分的微层级。决定设计的量是个技术活儿——关键就在找到拐点。

软件设计是软件开发中最重要的技术之一。好的设计能让开发者相互协作,业务功能可以随时增加和改变,还能拥有可靠的自动化测试。随着经验的积累,我们会学会怎样快速找到问题点,估算出应该花费在解决问题上的时间。我们还明白,大多数设计决策应该在最后时刻再做出,这意味着,在还没掌握问题的足够情报前,我们尽量不过早地绑定到某个设计上。

这就是为什么我说我们90年代所做的是并非都是无用功的原因。尽管我们过度设计,尽管我们产出不多,但我们学会了怎样设计。我们学会了怎样为我们自己考虑。我们学会了怎样研究。我们学会了怎样思考权衡。花了些时间,但我们确实学会了怎样避免二元思维,节制我们对于新潮流的过度兴奋。强大的软件设计基础和敏捷开发及精益开发原则和实践的结合,让我们不仅可以快速拿出软件,还能持续推出软件。

我们的目标是支持业务敏捷性,而这能通过可以持续部署到产品中的软件来达到。一次性部署软件没什么难的,但想要几个月甚至几年时间里保持每天都往产品中部署软件,就没那么简单了。我们需要很多守则和工程设计来达到持续部署的目标,也就让软件设计和TDD成为了我们必须掌握的两大重要技术原则。

作者:桑德罗·曼卡索(Sandro Mancuso),软件工艺师,作家,伦敦软件工艺社区(LSCC)创始人。幼年即开始写代码,但直到1996年才正式入行。曾为初创公司、软件作坊、产品公司、国际咨询公司和投资银行工作。
其职业生涯中曾有机会参与多种多样的项目,用过不同编程语言、技术,跨越很多不同行业。桑德罗在向不同规模的公司企业引入软件工艺理念和极限编程实践上有着丰富的经验。由于在发展和传播软件工艺上的杰出工作,桑德罗蜚声国际,常被邀请参与各种全球性会议并发表演讲。他的职业抱负,是通过帮助开发者进一步关注和改善自身技艺,来促使软件产业向前发展。

 

 

原文地址:http://www.lindukj.cn/news/archives/829

posted on 2016-04-27 15:09  clschen  阅读(141)  评论(0编辑  收藏  举报