到底应该如何理解“设计“在敏捷开发中的地位?_big design up front-程序员宅基地

技术标签: 极限编程  TDD  重构  敏捷开发  软件设计  

声明:本文的主要观点翻译自Martin Fowler的https://martinfowler.com/articles/designDead.html。但在文章最后会抛出一些个人的理解和观点。

先讲几句废话

在敏捷上下文里,"(软件)设计"是一个让很多人感觉有点困惑的话题。不同于"文档"在敏捷里的地位,因为至少敏捷宣言里有一句话提到了敏捷对"文档"的态度是怎样的,但对于"设计",却让人有点摸不着头脑。在敏捷的主流框架里,比如Scrum, XP, Kanban等,都少有正式涉及"设计"这个环节的实践。所以直接给人的印象是,敏捷开发是不重视"设计"的。而最近由一个朋友介绍,读到一本书(已经是一本2020年出版的相对较新的书),不管从序言(非作者观点),还是从作者自己的正文里,都很好地印证了这种行业对敏捷的普遍印象。当然,作者原文里提到,"弱化设计"是一种"误区",并没有说敏捷本身弱化设计。另外,我几年前去国内一家互联网大厂面试的时候,也有被问到类似的问题。大意是问我之前的敏捷实践里,是如何对待"设计"这件事情的。我当时心里其实也是有一点点困惑的。只是把自己的理解,和实际怎么做的说了一下。但一直在想,对这个问题,到底有没有一个更好的答案。直到我翻到Martin Fowler在这篇文章……

但讽刺的是,Martin Fowler的这篇文章早在2004年就发表了!而且这篇文章的原始版本已于更早的XP 2000大会上发表。也就是说甚至早于2001年敏捷的诞生!这更让我觉得应该好好读一下这篇文章。下面是部分章节的翻译。原文有点长,就不全翻译了。网上也能查到更完整的翻译,但看了几个版本都感觉不怎么通顺,所以这里基本是我自己重新翻译的。


https://martinfowler.com/articles/designDead.html
作者:Martin Fowler

设计已死?(Is Design Dead?)

对于很多刚接触极限编程(Extreme Programming,XP)的人来说,XP似乎已经宣告了软件设计的死亡。不仅很多设计工作被嘲笑为"冗余的预先设计"(Big Up Front Design),而且类似于UML,灵活的框架,甚至于设计模式都被轻视,或者忽略。事实上,XP过程中是需要有很多的设计工作的,只不过它是以一种跟传统软件开发过程不一样的方式实现的。XP实际上让演进式设计(evolutionary design)重新焕发了青春,有的实践让演进过程真正成为了可能。但同时,XP也对设计人员提出了新的挑战和新的技能。比如说,需要学习如何做一个简单的设计(simple design),如何通过重构让设计保持整洁,如果以一种演进式的方式使用设计模式。

极限编程对软件开发的很多常见假设提出了挑战。其中一个最有争议的就是它反对大量的预先设计(up-front design),而是建议使用一种更为演进式的方法。对于XP的批评者来说,这就意味着回退到了"编码加修正"(code and fix)的时代——经常被讽刺为hacking。而对于XP的粉丝来说,这是在拒绝使用一些设计技巧(比如UML),原则和模式:别担心设计的问题,只要你倾听你的代码,一个良好的设计就会出现。

我发现我正好处在这个争论的中心。我职业生涯中的大量时间都在跟UML,设计模式等打交道。我还写过关于UML和设计模式的书籍。那么既然现在我已经拥抱XP了,是不是意味着我要收回我之前的这些观点,将这些反演进式的观点都抛弃呢?

简单地说,不会。至于详细的解释,就是这篇文章剩下的内容要说的了。

计划式的和演进式的设计(Planned and Evolutionary Design)

我将在本文中介绍两种软件设计的方式。可能其中最常见的一种是演进式设计(evolutionary design)。演进式设计实际上意味着随着系统的实现,其设计会不断成长。设计是开发过程的一部分,伴随着程序的演进,设计会不断地变化。

在它的常见用法中,演进式设计就是一种灾难。设计,最终成为了一堆即兴决策的结果,每一次都让代码变得更难以修改。很多时候你可能会说这根本就没有设计,当然会得到一个糟糕的设计。像Kent(译注:XP创始人)说的,"设计"是一个让你从长远的角度来看,保持软件容易修改的一个东西。如果设计变坏了,那么你有效修改软件的能力也会跟着变差了。软件也有熵(entropy)的概念(译注:个人很喜欢这种说法。如果你还不知道什么是熵,请搜索一下。我后面会用"软件熵"来翻译类似的语句),所以随着时间的推移,设计会变得越来越烂。这不仅仅让软件变得越来越难以修改,它同时也会让Bug更容易滋生,更难以查找,而且更难安全的修复。这就是我们说的"编码加修正"(code and fix)式的恶梦,修复bug的成本会成指数级成长。

计划式的设计(planned design)希望解决这种问题,它来源于工程学科的其它分支。如果你想搭个狗窝,你只需要弄些木头过来,然后搭出个粗略的样子。但如果你想建一栋摩天大楼,你就不能这样做了——因为在你搭到一半的时候可能就垮掉了。所以你开始画一些工程设计图,就像我太太一样在办公室里完成这些工作。在她做这些设计的时候,她会解决所有问题,这中间有一部分是通过数学分析做到的,但大多是借助于建筑规范。建筑规范都是基于一些成功的经验和一些低层的数学知识。一旦这个设计完成,她的设计公司就会把这份设计移交到另一家公司去实施搭建。

软件领域的计划式设计应该是以相同方式运行的。设计人员事先把主要的问题都想好。他们不需要写代码,因为他们是做设计的,不是做实现的。所以他们可以使用像UML之类的设计技巧,屏蔽编码细节,在一个更抽象的角度来工作。一旦设计完成,他们可以把这份设计移交到另一帮人(甚至是另一家公司)。因为设计人员考虑的问题更广,所以他们可以避免那些会增加软件熵的各种战术性决策。而程序员可以遵从这份设计,并且如果他们真的遵从了这份设计的话,他们就能构建出最终的系统。

这种计划式的设计方式在70年代到处可见,很多人都用过。在很多方面,它都比"编码加修正"式的演进式设计更好。但它也有缺点。首先一个是,你没办法把所有编码阶段会遇到的问题都考虑全。所以不可避免的,在进入编码阶段后,你会找到一些问题来质疑之前的设计。然而,如果设计人员觉得他的工作已经完成了,并且转到其它项目呢?程序员就只能硬着头皮实现,然后软件熵就开始生长了。即便设计人员没离开,我们也得要花些时间去整理设计的问题,重新画(设计)图,然后再修改代码。但通常都会存在一种更快的修复方式,并且还面临着时间压力,于是乎,又轮到软件熵登场了。

更进一步讲,我们通常都会面对一个文化问题。设计人员之所以成为设计人员,通常都是因为他们有更强的技能和经验,但他们通常都会忙于做设计,而没有时间写代码。然而软件开发的工作和资料都在快速地变化。你如果不写代码,不仅仅会错过那些技术变迁在编程一线带来的变化,也会失去那些写代码的人对你的尊重。

这种紧张的关系在建筑行业也存在,只是在软件行业更为强烈。因为两者有一个很关键的差异。在建筑行业,那些设计人员的技能和建造人员的技能之间有一条很清晰的界限。而在软件行业这条界限就不怎么清晰了。任何工作在高级设计环境中的程序员都需要很强的技能。强到可以对设计人员的设计提出质疑,尤其当设计人员已经不是很懂日常工作中的开发平台情况的时候。

现在,这些问题是可以被解决的。可能我们可以去处理一下紧张的人际关系。可能我们可以增强设计人员的技能,让他们能够处理大多的问题,并且有一个好的规范流程去修改设计图表。然而,另外还有一个问题要面对,就是需求变更。需求变更是我参与过的项目中,最让我头痛的一个问题。

解决需求变更的一个方法是,把足够的灵活性考虑到设计中去,当需求变更时,让修改来得更容易。但这取决于你预期的变更是什么类型的。一个设计可以做到处理一定领域的变更,但当它能够处理好这些变更的同时,它会处理不好另外那些没有预料到的需求变更,或者可能甚至带来负作用。所以你必须能够非常好地理解需求,从而把那些容易出现变更的领域区分好,而根据我的观察,这非常难办到。

有些关于需求的问题是由于没有清晰地理解需求导致的。于是有很多人关注于改进需求分析过程,以期得到一份更完美的需求,从而避免对设计的后续修改。但即便这样,可能也并不能解决问题。有很多预料之外的需求是由于真实的业务变化带来的。而这些变更是不管你多么小心地改进流程都没法避免的。

所有的这些都让计划式设计变得不可能。它们都是非常大的挑战。但我这里并不是想说,计划式设计就一定比那种做成"编码加修正"式的演进式设计更好。我其实倾向于认为计划式设计比"编码加修正"更好的。然而,我也知道计划式设计中存在的问题,所以想找找看,看有没有一个更好的解决问题的方向。

XP中的赋能型实践(The Enabling Practices of XP)

XP这么有争议是有原因的。其中一个关键问题就是XP倡导演进式设计,而不是计划式设计。我们已经知道,由于大量的即兴式决策和软件熵的问题,演进式设计可能根本无法工作。

理解这个争议点的一个核心问题是如何处理软件变更曲线(software change curve)。变更曲线说的是,随着项目的进行,软件变更的成本将会成指数级增长。正如一句话所说的:分析阶段只需要花费1美元的修改,在生产阶段将会花费数千美元。

这非常具有讽刺意味,因为很多项目使用即兴式流程,根本没有所谓的设计阶段,但依然能够工作,可是指数级问题仍然存在。这个指数级曲线问题意味着演进式设计根本没法工作。同时它也告诉我们,为什么计划式设计需要非常小心,因为任何设计的问题都将面临着同样的指数级问题。

而XP底层的一个很基础性的假设是,它能够使这个变更曲线变得更平坦,从而让演进式设计变得可行。XP既赋能了这个过程,又把这个过程利用到了极致。这正是XP实践相互配合性的一种体现:具体地讲就是,你如果不使用赋能平坦化曲线的那部分实践,就无法使用另一部分充分利用平坦化曲线的实践。这个地方其实正是很多针对XP争议的来源所在。很多人批评XP"利用"曲线的那一面,但他却没有看到"赋能"的那一面。通常这些批评都源自于他们自身的经验,他们并没有使用"赋能"的那部分实践,却就已经使用了"利用"的那部分。结果搞得引火烧身,然后导致他们一看到XP,就想起了火。

XP的赋能型实践有很多。其核心部分是测试相关的,以及持续集成。没有测试部分提供的安全性,XP的剩余部分是不可能顺利实施的。而持续集成则能让整个团队保持同步,这样当你做修改的时候就不用担心会破坏到别人的工作。这些实践放到一起,就能够对修改曲线产生巨大的影响。在Thoughtworks的经历让我再一次体会到了这一点。引入测试实践和持续集成极大地改善了我们的开发工作。这种改善的程度已经大到让我对XP的一个断言产生了怀疑:你需要所有的实践来收获巨大的改善。

重构则有类似的效果。那些按XP建议的那样,以一种很严格的纪律去重构的人,他们工作的有效性跟那些只是偶尔地,即兴式地调整代码的人相比,有非常明显的不同。而这正是在Kent教会我如何正确地重构之后所经历的。毕竟,仅仅就这一个巨大的变化促使我写了完整的一本书出来。(译注:没有去求证,但猜应该就是大名鼎鼎的《重构》这本书了)

Jim Highsmith(译注:也是敏捷宣言签署者17人之一),在他的一篇文章中对XP做了一个总结,用到了一个天平的比喻:天平的一边是计划式设计,另一边则是重构。在更传统的开发流程里,计划式设计是胜出的。因为这里的假设是你不能在之后来修改之前的决定。而随着修改的成本降低,你就可以借助于重构,把设计放到更靠后的阶段来做。这个时候,计划式的设计并没有完全消失,我们可以在两种设计方式中找到一个平衡。对于我来说,在正确地使用重构之前,感觉就好像我一直只是在用一只手做设计。

这些赋能型实践——持续集成,测试,重构——提供了一个让演进式设计变得可靠的环境。不过还有一个我们没搞清楚的点是,这个平衡的点到底在哪里?我可以肯定的是,不管外部观点如何看待,XP都不只是测试,编码,然后重构。在编码之前,还是会有一定的空间留给设计的。其中有一些会发生在所有编码之前,而大多数则会发生在迭代中,针对某一个特定任务的编码之前。然后会在预先设计(up-front design)和重构之间找到一个新的平衡

简单的价值(The Value of Simplicity)

XP的两个最著名的战斗口号是:"只做可能可行的最简单的事情"(Do the Simplest Thing that Could Possibly Work)"你不会需要它"(You Aren't Going to Need It, YAGNI)。它们是XP的简单设计(Simple Design)实践的两种表现形式。

YAGNI通常是以这种方式表达出来的:今天编写的代码不要包含任何明天才会被使用到的特性。表面上看,这条规则非常简单。但当我们开始考虑类似于框架(frameworks),可重用组件和足够灵活的设计的时候,问题就没那么简单了。要把这些东西做出来是比较复杂的。你会有一些额外的预先的花销在上面,并期望能够在后期得到足够多的回报。这种预先考虑灵活性的思路,看起来是有效的软件设计的一个关键部分。

然而XP的建议是,不要为第一个需要此功能的用例去构建灵活的组件和框架。先让架构自由地生长。比方说,我现在打算写一个Money的类,它需要能够处理加法,但暂时不需要剩法,那么此时此刻,我只需要实现它加法的行为即可。即便是我很肯定在下一个迭代(iteration)里我会需要剩法功能,并且知道如何既简单又快速地实现它,我仍然要把它留到下一个迭代去实现。

这样子做的第一个原因是考虑其经济效益。如果我当下做的工作只有在明天的特性里才用得上,那么我一定会损失一部分精力去实现当下需要实现的功能。而发布计划已经说明了现在应该做什么,那么如果去实现将来才需要的功能就是有悖于开发人员与客户之间的共识的。这个时候存在一种风险,就是有可能当前迭代的用户故事会做不完。即便不存在这个风险,那么当前可以做哪些额外的工作也是由客户决定的,而客户的这个决定有可能并不是实现那个剩法功能。

这种经济效益上的限制可能还会进一步加重,因为我们还有可能会弄错一些东西。不管我们有多么肯定某一个功能是如何工作的,我们都有可能搞错——特别是当我们还没有更进一步的需求的时候。提早的考虑错误方向的解决方案比提早考虑正确方向的解决方案更浪费。XP专家们基本上相信,我们更有可能弄错方向。而我是认同这一点的。

那么第二个原因则是复杂的设计会比简单的设计更难懂。所以在提升了复杂度的系统上做修改,当然会比简单的系统更难。这个成本主要体现在,当这个复杂设计刚被做出来开始,一直到我们真正需要用上这个复杂设计的时候截止。

这个建议让很多人觉得是无稽之谈。我觉得他们是对的。对就对在在通常情况下,我们的开发过程里并没有使用XP的赋能型实践。然而,当且仅当我们在计划型设计和演进式设计之间找到平衡的时候,YAGNI就会成为一个很好的实践。

下面稍微总结一下。你不需要去花精力实现那些在将来的迭代才需要的功能。即便这个实现的成本为零也不要做,因为它会带来额外的修改成本。然而你只能在引入XP实践的情况下才能做好这件事,或者是借助于其它类似的,可以降低修改成本的技术

到底怎样才算简单(What on Earth is Simplicity Anyway)

下面假设我们都已经愿意尽量做到简单了。这貌似是个不太需要去争论的观点,毕竟谁会愿意变得更复杂呢?但这里其实非常取决于我们如何定义简单。

在Kent的《解析极限编程》(Extreme Programming Explained)中给出了满足简单系统定义的四个条件。按重要程度排序是:

  • 所有测试都跑通。Runs all the Tests
  • 没有重复。No duplication
  • 代码意图被清晰表达。Reveals all the intention
  • 尽可能少的类和方法。Fewest number of classes or methods

所有测试跑通,很好理解。没有重复,也很直截了当,只不过有很多开发人员会需要经过一些指导才知道如何做好这一点。代码意图被清晰表达,这一条则值得好好讨论一番。那么它到底是什么意思呢?

这里基本的价值观就是保持代码清晰易懂。XP非常重视代码可读性。在XP的世界里,"聪明的代码"(clever code)是个贬义词。但对于有些人来说,清晰地表达代码意图就是对聪明的代码的另外一种解读。

Josh Kerievsky在他的XP 2000大会发言上给出了一个很好的例子。他查看了可能最广为人知的XP代码:JUnit(译注:作者就是本文反复提到的Kent)。JUnit借助装饰器模式给测试用例添加可选功能,比如并发同步,批量准备(batch set up)。把这部分代码拆分出来之后,可以使通用代码更加清晰。

但你必须得问一下你自己,这样的代码真的更简单吗?对于我来说确实是的,但这是由于我对装饰器模式很熟悉了。但对于很多不熟悉装饰器模式的人来说,它就是复杂的。类似的,JUnit使用了可插入式方法(pluggable methods),我发现也有很多人根本找不到有效代码在哪里。所以我们能够就此下结论说,JUnit的设计对有经验的程序员来说更简单,但对不那么有经验的人来说却是更复杂吗?

我觉得单讲如何消除重复这个问题的话,XP的"有且仅有一次"(Once and Only Once)和《程序员修炼之道》(The Pragmatic Programmer)的"不要重复你自己"(Don't Repeat Yourself, DRY)都是非常好的建议。单单遵循这一点,就已经能够帮助你朝"简单"的方向迈出一大步了。但它不是全部,如何做到简单仍然是一件很复杂的事情。

最近我参与了一个可能被过度设计的项目。我们重构了它,去除了它原本的一些灵活性。但就像其中一个开发人员说的:"对一个过度设计的系统进行重构,比对一个没有设计的系统重构会更容易。"能够设计得简单一点当然最好,但如果稍微复杂一点也不是什么很严重的事情。

我听到过的最好的建议是来自于Bob大叔的(Robert Martin)(译注:另一位敏捷宣言签署者,包括Clean Code, Clean Agile在内的Clean系列书籍的作者,XP拥护者)。他说,不要过于纠结到底怎样才是一个最简单的设计。毕竟你可以,应该,也一定要重构。所以我这里最终的结论是,有意愿重构远比马上知道怎样才是一个最简单的设计要重要得多

 【译注:第一次看到这里(其实原文在这中间还有两小节),我不知道你会不会跟我有同样的疑惑。作者一直讲的"设计",跟我们在传统认识上的希望花比较多时间去做的"架构设计"到底是不是同一回事?请注意,原文中到这里,一直没有出现"架构"(architecture)这个词,只有"设计"(design)。请继续看下去,下面的内容刷新了我的个人认知。不确定会不会有同样的效果给到你。】

培养一个架构(Growing an Architecture)

当我们说软件架构(software architecture)的时候到底是什么意思?就我个人而言,架构是这个系统的核心元素,是一些比较难发生改变的东西。系统其它部分的搭建都将基于这些东西。

那么在演进式设计中,架构将扮演一个什么样的角色呢?XP的批评言论认为,XP是无视架构的,XP的套路就是尽快开始编码,并且相信重构会解决所有的设计问题。有意思的是,他们说对了,而且那也很有可能是一个弱点。那些最激进的XP实践者们,Kent Beck, Ron Jeffries, 和Bob Martin(译注:三位全是敏捷宣言签署者中的XP阵容代表)正在把越来越多的精力放在避免预先的架构设计上面。在你真正确定需要之前,不要把一个数据库给整进来。先使用文件系统,在后续的迭代中重构的时候再把数据库引入进来。(译注:这句话跟Bob大叔的《架构整洁之道》,Clean Architecture这本书里的观点一模一样)

我被认为是一个XP界的怂人,所以我必须得否定一把。我觉得对于大量的初始架构来说,它们应该还是有一席之地的。比如说,如何给系统分层,如何跟数据库交互(当你需要一个数据库的时候),用什么方式去处理web服务器等等。

实际上,我觉得经过多年的工作经验之后,这里的很多领域我已经总结出来一些套路了。当你自己总结的套路越来越多的时候,你应该有足够的理由首先去使用它们。关键问题是,这些早期的架构决定不应该成为板上钉钉的事情。而应该认识到,人都是会犯错的。重要的是错了之后,我们应该有勇气去修正它。听别人讲过一个故事,当时已经临近部署阶段,但发现已经不再需要EJB了,所以就把EJB给去掉了。这是一次工作量可观的重构,到很晚才做,但那些赋能型实践不仅仅让它成为了一种可能,更让它变得有价值。

如果我们从另一个方向来看这个问题会怎样呢?你先是决定了不使用EJB,那么在后期再加入它会不会更难?你是不是不应该从一开始就使用EJB,直到你发现你真的需要它呢?回答这个问题,要考虑的因素很多。在一个更简洁的系统下工作当然会让事情进展得更快。然而有的时候,去掉一个东西比加入一个东西是更容易的。

所以我的建议是,开始的时候还是要评估一下最可能的架构是怎样的。如果你已经预料到了有巨大的用户数据量,那就尽管把数据库给用上吧。如果你预料到了复杂的业务逻辑,那么就用上领域模型。然而,根据YAGNI原则,一旦你担心判断错误,那么请选择站在简洁性的一边。另外,只要你看到那些没用的东西,请随时准备给架构做减法

当你成长起来之后,你会想成为一个架构师吗?(Do you wanna be an Architect when you grow up)

在最近的十年里(译注:请注意开头说的,本文的初始成文时间大概在2000年左右),"软件架构师"的说法变得流行起来。这个词语对我个人来说,要使用它是有一定的心理障碍的。我太太是位建筑工程师。工程师与架构师之间的关系是……有点意思的。我最喜欢的一句话是:"架构师很善长三个B:奇思妙想(译注:原文是bulbs。但以我有限的英语能力来说,倾向于翻译成奇思妙想,而不是灯泡。理由是前者与后面两个B,以及后文都有一种很微妙的逻辑关系,同时与架构师的定位也有很微妙的关联,但灯泡却没有这些效果),灌木(bushes),鸟类(birds)"。这背后的思想是,架构师负责画出那些漂亮的画,而工程师们则保证这些画能够站立起来。所以我是避免使用"软件架构师"这个词语的,毕竟如果我太太都不认可我的专业性的话,我又如何在其他人中找到立足之地呢?

在软件行业里,"架构师"这个词语有很多种解释。(在软件行业里,很多词语都有很多种解释)通常来讲,虽然下面这句话很严肃:"我不只是位程序员,我还是位架构师"。它却可以被翻译成,"我现在是架构师了,别再叫我写什么代码"。那么问题就变成了,当你想成为一个有技术领导力的人,你是否会要跟那些做平凡的编码工作的人划清界限呢?

这个问题估计会让人很上头。我看到人们当被剥夺掉架构师的头衔之后变得非常愤怒。"XP里根本就没有给有经验的架构师留下任何生存空间",这是一句我经常听到的话。

在如何对待设计这个问题上也有同样的情况。我不觉得这是由于XP不重视个人经验,或者好的设计能力所导致的。确实,我从很多XP的支持者——Kent Beck, Bob Martin, 当然还有Ward Cunningham(译注:又一位敏捷宣言签署者中的XP阵容代表)——身上学到了很多关于设计的东西。然而它的确意味着,这帮人的技术领导者的角色发生了变化。

作为一个例子,我聊一下我们Thoughtworks的一位技术领导者:Dave Rice。Dave已经经历了好几个完整的项目研发,并且承担了一个50人项目的非正式技术领导者角色。他的这个角色意味着要花大量的时间和所有程序员一起工作。他一旦发现某位程序员需要帮助,就会走过去跟他一起解决问题。一个明显的标志就是看他坐在哪里。作为一名长期在Thoughtworks工作的人,他完全可以拥有一间他喜欢的办公室。他曾和Cara,一位发布经理,一起共用过一段时间的办公室。然而在过去的几个月里,他搬到了外面的开放式格间,跟其他程序员坐到了一起(使用了XP喜欢的那种开放式"作战室"风格)。这对于他来说是很重要的,因为这样他就能看到现场正在发生的事情,并且可以提供一些必要的帮助。

了解XP的人会发现我说的其实就是XP里的教练角色。确实这是XP的几个文字游戏里的一个,它管技术领导者叫"教练"。这想表达的意思是很明显的:在XP里,技术领导是需要能够帮助程序员做出有效决策的人。这同时需要好的人际关系处理能力和技术能力。Jack Bolles在XP 2000大会上有提到,当下的时代已经没有多大的空间给到那些孤胆英雄了。合作与教导才是成功之道

在一次会议聚餐上,Dave和我跟一个声称反对XP的人聊了一会。当我们说起我们自己的日常工作的时候,发现大家的作法是非常相似的。我们都喜欢演变式的(adaptive),迭代式(iterative)的开发方式。我们都认为测试是很重要的。所以我们很不理解他为什么会激烈地反对XP。然后他说,"我最不希望看到的就是,我的那帮程序员们拿着我的设计瞎搞什么重构"。我们就明白是怎么一回事了。后来Dave跟我说,如果他不信任他的那帮程序员,那为什么要招他们进来呢?在XP里最重要的是,那些有经验的开发人员能够尽可能多地把他的技能传递给其他初级的人员。你需要安排一个教练去教那些开发人员如何做出重要的决定,而不是找个架构师去把所有重要的决定都做了。像Ward Cunningham说的,这样做可以让他的技能带来的收益放大,对一个项目的贡献会大过任何一个孤胆英雄。

那么设计到底死了没有?(So is Design Dead?)

没死,不管从任何角度来说都没死,只是设计的性质改变了。XP中讲的设计是需要如下技能的:

  • 要有一种持续的欲望,去尽可能地保持代码简单和整洁。
  • 掌握重构技能,这样在需要的时候,你就能自信地改进代码。
  • 对模式的良好认知:不只是一些特定的方案,还要知道什么时候使用它们,以及如何朝它们演进。
  • 在做设计的时候对将来可能的变动留一个心眼,同时认识到当下的决定,将来可能不得不改变。
  • 知道如何把设计跟别人讲明白,可以使用代码,画图,或者最重要的:沟通。

这些技能其实是有点可怕的,但要作一名合格的设计人员从来就不是一件容易的事。XP并没有让它变得更容易,至少对我来说是如此。但我觉得XP确实给了我们一个新的思路,到底怎样才能有效地做设计,因为它重新让演进式设计变得可靠。而且我本身是进化论(evolution)的忠实粉丝——否则鬼知道我会成为个什么东西?


译文完

下面聊一下个人的理解

首先,这里只翻译了原文15个小节中的7个小节,只有一半不到。有可能由于这一部分的缺失,会让原文的某些观点变得没有那么有说服力。所以还是强烈推荐去读一下完整的原文。完整看完原文,应该会对你的认知的提升更多更彻底。

然后我个人理解到的作者的核心观点如下:

  • 敏捷开发仍然需要做设计。而且对设计人员的要求并没有降低。
  • 早期根据设计人员(请注意我这里也按Martin的意思,特意避免使用架构师这个词)的经验,可以做一个粗略的(starting point)设计。绝大多数设计将在后续迭代中演进。
  • 把上一点做好的前提是,我们能够用好类似于XP里那些相互配合的实践,从而降低软件变更曲线。

另外总结几点跟本文主题不直接相关,但我觉得也很重要的内容是:

  • 技术领导者(technical leadership,或者我们中文好像一般叫技术经理?)需要跟一线开发人员工作在一起。
  • 仍然建议设计人员编写代码,以保持对一线技术变更,以及具体障碍的敏锐度。
  • 我们需要的是一个既懂技术又懂合作的教练,而不是一个高高在上的架构师。
  • 像Martin Fowler这种大咖,是很务实的。这并不是拍马屁(因为没必要),只是觉得,我们想讨论出一些真正有价值的结论,就应该如此。

文章写到这里,其实我感觉还是会有些人对此表示不理解,还是会怀疑"设计"这个东西真的能够自我生长出来吗,或者稍改一下措词,能够健康地生长吗?对此,我只能班门弄斧地再补充一下。有这个疑惑,可能是出于两个原因:

  1. 还是没有理解文章的一个重要观点,XP的实践是分赋能型实践和利用型实践(exploiting practices,个人对后面这个翻译不是很满意,但一时没想出更好的)的。它们相互配合,相互成全。而赋能型实践通常被人忽视。
  2. 或者可能是没有太多XP的实践经验,可能最缺的是TDD的经验。而XP是一个实操性非常非常非常强的框架。如果有兴趣,请先动手实践一下。它会改变你的认知。

我最近正好看了Bob大叔新出版的一个Video Book的部分章节。他在其中TDD的章节里做了一个演示,是实现保龄球的计分算法。简单描述就是,他先像模像样的做了一个粗略的设计(有UML图),然后开始用TDD做实现。结果程序在一条预料之外的路径上完成了。算法写得很成功,但与最初的设计完全不一样。这基本上就是"传说"中的涌现式设计了。而且我忘了是不是这个例子了,反正记得其中有个TDD的例子完了之后,Bob大叔自己cos了星际迷航里的Spark(相当于自己给自己的一个托,哈哈),发表了一个评论,大概意思是:"神奇!你只需要严格按TDD的规则小步往前走,算法就自己完成了!不可思议!"原文的感叹词可能没这么多,我可能夸张了一点。但大概意思就是这样。

那么,万一,如果,可能,你还是觉得这一套玩法很好很天真。也没关系。因为我必须得承认,我的认知也是有限的。而且考虑到TDD以及XP的现实状况,可能确实存在一些情况,是不适合这样玩的。《卓有成效的敏捷》这本书(《代码大全》作者2021年的新作)的观点基本也是如此。那么在这些情况下,如果我也想跑敏捷,那这个时候应该怎么做设计呢?我尝试给出的建议是:应该问题不大。你就尽管去做那些up-front的设计就是了。请注意,我是认真的!up-front在这里不包含任何负面的意思。仅仅意味着它会更多地发生在所有编码之前。但Martin Fowler原文中的这条建议,我猜可能仍然适用:"在做设计的时候对将来可能的变动留一个心眼,同时认识到当下的决定,将来可能不得不改变。" Designing with an eye to future changes, knowing that decisions taken now will have to be changed in the future.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yzj_000/article/details/124730190

智能推荐

HTML ISO-8859-1 参考手册(实体字符)_参考手册是哪个符号-程序员宅基地

文章浏览阅读1.5k次。HTML ISO-8859-1 参考手册Previous PageNext PageHTML 4.01 支持 ISO 8859-1 (Latin-1) 字符集。ISO-8859-1 的较低部分(从 1 到 127 之间的代码)是最初的 7 比特 ASCII。ISO-8859-1 的较高部分(从 160 到 255 之间的代码)全都有实体名称。这些符号中的_参考手册是哪个符号

结对项目——四则运算GUI项目-程序员宅基地

文章浏览阅读120次。一、项目地址:https://git.coding.net/lvgx/wsz.git二、PSP:PSP2.1任务内容计划共完成需要的时间(min)实际完成需要的时间(min)Planning计划1515Estimate估计这个任务需要多少时间并规划...

PhotoZoom Pro 3 无损放大你的照片_photozoompro3-程序员宅基地

文章浏览阅读1.6k次。今天去番薯窝逛 了逛,发现番薯窝发布了一个可以无损放大图片的软件 PhotoZoom Pro 3,一下子对这个软件来了兴趣,以我的常识,只有矢量图放大才不失真,一般的图片放大的话,都要失真的,而这个软件却利用一些算法来弥补失去的像素,让图 片达到不失真放大的效果,真的不错。没经过番薯窝的同意就先转藏一下。一会再去和番薯说一下,应该不会怪罪我吧?PhotoZoom Pro 是一款新颖的、技术_photozoompro3

How to Use the Nslookup Command-程序员宅基地

文章浏览阅读412次,点赞14次,收藏8次。#Linux #Command #Nslookup #DNS

头条分库分表与分区的区别和思考,王者笔记!_mall-swarm b2b b2c-程序员宅基地

文章浏览阅读116次。1、Java基础Java基础务必要有一个非常牢固的根基,尤其是对于JVM和并发编程的掌握情况**(属于进阶内容,但也是Java最为重要的基础内容)**,不论是面试还是工作,基础不好,写不出高质量、漂亮的代码;面试估计刚开始就会被面试官给拍死。基础不好的话,《Java编程思想》和《Java核心技术》这两本书一定要好好看一下,同时再搭配学习笔记等资料,能让你更好的打稳基础!同时,大家可以对照下面这份学习路线梳理一下自己的知识体系,需要获取高清完整版Java学习路线的话,可以在文末免费领取Java架构师筑基_mall-swarm b2b b2c

macOS下 弹出无法保存文件,请检查权限或文件是否处于只读状态_mac 修改系统文件无法保存-程序员宅基地

文章浏览阅读6.5k次。首先打开问题文件所在文件夹的显示简介 将下面权限全部更改为读与写 一定要先解锁然后点击应用到包含的项目 更改完成后记得把小锁锁上 这样就完成啦_mac 修改系统文件无法保存

随便推点

imazing 3.0.0.3官方中文破解版2024最新imazing 3百度网盘免费下载-程序员宅基地

文章浏览阅读896次,点赞27次,收藏14次。imazing 3.0.0.3官方中文中文破解版是一款专业又好用的苹果IOS设备管理工具。imazing破解版百度云下载安装后,用户就可以轻松在Mac、PC以及其他任何iOS设备之间自由传输文件了,一键管理、备份、恢复和克隆iOS设备上的内容或软件,实现一端管理多端的便捷服务。imazing 3.0.0.3官方中文中文破解版可以在任何地方用任何电脑,一键传输、管理、备份全部的数据内容,不用受iCloud限制,也不需要提前同步数据或备份,只要安装imazing破解版并连接到iOS设备即可。

一个简单的HTML篮球网页【学生网页设计作业源码】-程序员宅基地

文章浏览阅读804次,点赞21次,收藏16次。精彩专栏推荐 文末获取联系 ️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 作者主页: 【主页——获取更多优质源码】 web前端期末大作业: 【毕设项目精品实战案例 (1000套) 】 程序员有趣的告白方式:【HTML七夕情人节表白网页制作 (110套) 】超炫酷的Echarts大屏可视化源码:【 echarts大屏展示大数据平台可视化(150套) 】 免费且实用的WEB前端学习指南: 【web前端零基础到高级学习视频教程 120G干货分享】 关

用Python表白,把爱和情书写进程序里_python pillow 库 表白 程序-程序员宅基地

文章浏览阅读345次。这不已经十一月了,22年马上就过完了,各位兄弟有对象了吗,现在就是缺钱还缺对象退一步来说,有心仪的人吗啊,如果有的话,看看这篇 程序员的表白小妙招吧安装完成后,我们先来简单介绍几个常用示例新建及保存图片。_python pillow 库 表白 程序

Struts2学习笔记(3)-如何访问Web资源_strust2 如何访问resources文件下html-程序员宅基地

文章浏览阅读257次。一、web资源是什么? web资源是HttpServletRequest、HttpSession、ServletContext等原生的Servlet API。二、为什么要访问web资源? B/S的应用的controller中必然需要访问web资源,比如:向域对象中读写属性、读写Cookie、获取realPath等...三、怎么访问web资源? 访问web资源有两种方式:和Servle_strust2 如何访问resources文件下html

银河麒麟(Linux)磁盘做逻辑卷——LVM_银河麒麟分区vg为空-程序员宅基地

文章浏览阅读1.7k次,点赞8次,收藏9次。Linux银河麒麟v10制作逻辑卷_银河麒麟分区vg为空

python opencv cv2.resize()函数-程序员宅基地

文章浏览阅读2.9k次。**def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None): # real signature unknown; restored from __doc__ """ resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst ..._python opencv cv2.resize(

推荐文章

热门文章

相关标签