你曾听说过一名专业软件开发人员应该掌握一种驱动方法吗?这些驱动方法可能是:领域驱动设计(Domain-Driven Design)、测试驱动开发(Test-Driven Development)、行为驱动开发(Behavior-Driven Development)、数据驱动设计(Data-Driven Design)、数据驱动开发(Data-Driven Development)、用例驱动设计(Use Case-Driven Design)、用例驱动开发(Use Case-Driven Development)、架构驱动设计(Architecture-Driven Design)、架构驱动开发(Architecture-Driven Development)、模型驱动开发(Model-Driven Development)、敏捷模型驱动开发(Agile Model-Driven Development)等等。我确实听说过这样的要求。
我们期待这些驱动方法(或者我称之为心理框架, mental framework)具有某种魔力,是因为我们喜欢框架。我们常常忘了对于我们的技能,它们只是扮演支撑角色,而不是软件专业的唯一目标。但是这种对框架的热爱,使我们产生了一些认知上的偏差,让我们进行深入分析。
心理框架是如何产生的?
这些所谓的驱动方法是一类被称为心理框架工具的例子。心理框架,正如软件框架,是一种构造(一些想法或者过程),能够用于开发活动,例如以有序的方式进行建模、设计、编程或者测试。我们将分析三种心理框架:领域驱动设计、测试驱动开发和行为驱动开发。它们是社区中非常流行的驱动方法。
这些框架的创建者的假设是它们能够通过以下途径促进开发工作:
- 让通用的想法(例如对象建模和测试)更具体;
- 引入有序的工作方法;
- 以可重复的步骤形式展现复杂的活动。
这一切都归结为一个承诺和吸引人的文化基因
当作者提出一个心理框架,这意味着一个承诺,从现在起所有事情都将变得更好、更有效率、更快、成本更低,一切都将很好。通常,承诺与开发人员在运用某个特定概念的过程中遇到的问题有关系,而且它武断地假定,当使用了这个建议的框架后,这些问题都将得到解决。测试驱动开发就是一个很好的例子。它的承诺包括:“你将不再需要调试器”,“你将有简单和高质量的代码”,“你的代码在产品阶段的 bug 会更少”。我并不是说这些是空头承诺。我的意思是这些承诺并没有在早年TDD 中得到明确的、可验证的数据支持。先有对TDD 的热情追捧,然后才有一些度量来验证它的承诺。
是什么让这些心理框架的承诺如此“吸引人”?毫无疑问,其中一个因素是我们希望解决所有问题。因此,当问题越大,我们就越可能采用它。另一个因素是有感染力的文化基因(contagious meme)。就像基因是遗传信息的单位,字节是数字信息的单位一样,文化基因是文化的基本单位。这个词是由英国进化生物学家和作家Richard Dawkins 创造,他将其视为一种复制器(replicator)。
每种框架都定义了自己的文化基因,有感染力的的口号,这让开发人员将它与特定框架及其承诺联系在一些。通常,这个文化基因描述了框架所促进的一个主要概念。TDD 文化基因就是一个很好的例子,即红- 绿- 重构(Red-Green-Refactor),它与计划- 执行- 检查- 处理循环( Plan-Do-Check-Act cycle,缩写为 PCDA 或称为戴明循环)没有什么不同。PDCA 循环是持续改善产品和服务的一种迭代和适应性过程。红 - 绿 - 重构,这个简短的口号有以下特点:
- 它用三个词表达了 TDD 基本技术;
- 它很容易记住;
- 它描述了可视化工具来支持 TDD。
这三个词使你用简单的文字描述了 TDD。你不需要提出精心设计的概念、详细的定义和区分特定的案例或复杂的步骤。它很简单,就是红 - 绿 - 重构。
在表 1 中,我列出了心理框架的例子,它们的承诺以及它们的吸引人的文化基因。
表 1
框架 它的承诺 吸引人的文化基因 TDD 你的产品将几乎没有可见的 bug,同时除了必须的代码外,不会生产过多的代码。 红 - 绿 - 重构,单元测试 BDD 你将 TDD 与功能需求关联起来 Given, When, Then DDD 应用的架构完全反映现实业务,因此后续需求的实现将非常自然;没有变通方法,没有秘密路径,只有纯粹的、不受影响的以及独立的模型。 组成部分(Building Blocks),无歧义的语言(Unambiguous Language)和策略设计(Strategic Design)## 谁创建了它?
在建立他们的突破性概念时, Ken Beck 、 Dan North 、 Eric Evans 、 Steve Freeman 、 Ivar Jacobson 和其它心理框架的作者们已经在各类项目、不同人群、领域和技术上积累了多年的经验。那些生搬硬套使用这些框架(认为它将改变他们的生活)的人有哪些经验呢?本文后面将再回到这个问题。
如果让我改述一个关于建房子的流行说法,我会说我们的第一个系统是给敌人建的,第二个系统是给朋友建的,只有第三个系统才是给我们自己的。想想你的职业生涯,最初的编码留下了多少坑。接下来你的代码使用了很多润滑和工程相关的东西,以至于你自己都不理解。再经过一段时间,你终于做到了中庸之道(有趣的是你无法平分成黄金比例)和实用主义。
根据Singley 和Anderson 的著作 The Transfer of Cognitive Skills以及 Woltz、 Gardner 和 Bell 的文章 Negative transfer errors in sequential cognitive skills,当你在一个项目上工作,又开始另一个项目的工作,你通常会体验到知识迁移,意思是迄今为止你所掌握的技能能够用于另一个项目,并且能让你更有效地开发新的、有用的技能。这种迁移被称为正迁移,是我们最需要的。然而,负迁移也是有可能的,因为掌握了一种技能可能使另一种技能更难掌握。
所有这些心理框架的作者已经转战于各种项目并有丰富的经验。因此,他们体验了学习的正迁移并获得特定的知识、技能和专业技术。在某个时刻,他们经历了我所说的“启迪”(或者更常用的说法,灵光一闪、啊哈!效果或模式转变)。这常常是偶然发生的,有时候是在梦里,触发了思维过程的整个链条,启迪了这些作者。基于经验、思考和总结,他得出了一种思想,例如红 - 绿 - 重构。这种思想把有序带入现有知识中,并给它灌输更深入和更普遍的意义。从技术上讲,这是归纳概括(如图1)。基于他的专业知识并通过归纳推理的方法,作者建立了一个概括其个人经验的理论。然后他开始向世人介绍这个新的心理框架。他或她开始写书。
图1 心理框架是如何建立的?
归纳的结果
归纳有一个问题:它不能保证结论是正确的。这不是大问题,因为框架没有必要逻辑“正确”,它只需要“在给定的上下文环境中是有用的”。现在我们来到了这个点,即上下文环境是个关键,它就是概括出新想法的那些经验。当作者想分享他的探索,并开始写书,新的未曾预料的问题出现了。如何在他不熟悉的其它上下文环境中使用框架?如何将框架应用于他不了解的项目、架构和技术中?他接下来该怎么做呢?他使用推论(如图2)。
图2 如何在别的上下文环境中使用框架?
基于他自己的经验和想出来的这个框架,他进行推理和论证并得出结论,在这个新的上下文环境中,应该以特定的方式使用框架。在这个阶段,不同类型的论证是必要的。归纳推理使框架能够基于实际经验。通过逻辑思维演绎推理该框架,避免其与现实冲突。当然,冲突是有可能的,但它可能要数年时间,并且竞争从未停止。
演绎推理在有些情况下能够得出正确的结论。而另一些情况下,结果可能有所不同。有时候只需要重温和回顾就能得出结论。Eric Evans 的书《领域驱动设计: 软件核心复杂性应对之道》就是个例子,特别是战略设计这部分。当我们观察Evans 先生的活动,我们将发现当他使用DDD 时,他的结论是书中的部分观点应该更准确或者应该换种方式突显出来。我们发现了一些更新:介绍了 Domain Language Model Exploration Whirlpool 过程,特别强调有边界上下文( Bounded Context )角色、领域事件( Domain Event )的更准确定义以及它与有边界上下文更准确的关系。
谁能使用它?
当作者遇到新的、未知的环境,他的框架不起作用时,他会怎么办?他将依赖自己的经验,做一些小的尝试,跟踪其效果,然后对其想法做一些小修正。绝大多数情况下,心理框架的作者拥有丰富的经验和相当专业的知识,知道如何面对新情况。换言之,作者明白如果框架的教条越多,则其价值将越少。基于他利用的是自己的经验(这总是很方便)这个事实,如果他认为它是没有意义的,他可能会立即停止使用他的框架。他会根据自己的经验选择别的解决方案,或者修改框架。
现在让我们想像一下这样一个场景。一个缺乏经验的开发人员使用某种驱动方法,结果会怎么样呢?当他按书中和网上的教程开始编程,一切看起来好像很顺利。但事实上,我们几乎不会去开发一个教程那样的系统,很快问题就会出现。开发人员马上就要面对下面的问题:如何在新的、未知的环境中使用这种驱动方法?我们的这名开发人员经验很少,正在不断犯错误,也在不断取得成功。他没有足够的专业知识,他孤立无援。面对时间压力,他可能会做以下事情:
- 寻求有经验人士的帮助(这是最好的选项);
- 开始努力尝试并最终得出正确的方法(成本有点高,但可接受);
- 在互联网上寻找解决方案(不一定正确);
- 以教条的方式使用心理框架,即使它没有任何意义,也排除万难完成任务;
- 停止使用框架,回到他的老习惯。
以上 5 种情形中,有 3 种情形的结果是令人沮丧的,框架相关的承诺并未实现。也许你认为这并不意味着该驱动方法没有效果。开发人员只是没有相关的经验来正确地使用驱动方法。心理框架的典型特征是他们是非常通用的。很难写一个适用于任何场景的详细过程。我甚至认为这是不可能的。心理框架需要解释。当你开始使用它们,并期望只收获好处,你就需要在给定的上下文环境中解释它们。而这种解释依据的就是你自己的项目经验。
当然,有些开发者已经具备了某个心理框架所需的经验。他们会采用什么样的方法呢?他们通常有自己的思考和属于自己的框架。当他们有些人看到一个新的“革命性的”驱动方法时,会发现它的有趣面并意识到他们已经在使用它的一些元素。他们会从新框架中汲取他们想要的长处,或者完整地使用它,毕竟它有一个简洁又好记的名字。框架将会丰富他们的资源,使他们的工作更加有序。
根据我的粗略观察,我发现刚才提到的这些开发者有以下特征:
- 他们具有超过 10 年的经验;
- 他们具有各种各样的经验:不同的公司、不同的项目、不同的技术和不同的人群;
- 他们具有从独立的、看似无关的经验中概括一些模式,创造出广义概念的能力;
- 他们具有很好的工作方法,能够准确区分接口与实现,因此他们更多地关注要实现的目标,而不是实现目标的具体手段;
- 他们回顾性地评估自己的资源;
- 他们花时间拓展自己的知识面、提升自己的技能;
- 许多情况下,他们从自身行为中寻找失败的原因,而不是归因于外部环境;
- 他们有能力控制任务的规模。
最后两个特征通常是最大的挑战。要掌握它们,你需要不同寻常的巧遇,或者通常是多年广泛领域的强化训练。在我们看来,这些特征是每个开发者夯实他的心理框架的关键因素,对于推出他自己的驱动方法来说则更加重要。没有这两个特征,他也能获得大量关键知识和技能,足以轻松工作。这样的人很少关心心理框架,因为他通常更加了解。
所以,现在你知道为什么所谓的驱动方法没有改变任何事情了?因为当开发者没有所需的经验时,框架没有什么帮助,它在产生干扰。他认为自己在做专业的开发,但实际上他得到了更多的知识和更少的技能。因为他无法在特定的上下文中创新性地解释框架,因此他以不同的方式使用框架。如果开发者有所需的经验,他已经设计了自己的框架或者对它不感兴趣,因为他认为它不适合于自己的场景。
有什么替代的选择?
诚然,开发者的各类驱动认证似乎是有吸引力的团队开发策略。对此我不下结论。这是一个策略选择的问题,如果它带来预期的结果,也没什么好说的。接下来我将介绍一些也许你会认为有价值的替代选择。
打好基础
如果让我用三个词总结整个软件工程,我认为是:职责、封装和组合。每个词都能写成一篇独立文章甚至一本书。遗憾的是,当我们挣扎于各类驱动方法时,我们忘记了这些词可能才是我们应该关注的最重要的概念。我们常常问自己,该使用什么模式?选择什么心理框架?相反,我们应该问:这个方法、类和模块的职责是什么?职责、封装和组合是每一种软件工程技术的基础。
如果你已经很熟练地运用这些概念,模式将会水到渠成。如果你忽略这些概念,你很快将要结束一个糟糕的软件工程。与此同时,这些概念非常通用,与你的经验无关,你始终可以在更深的层次上去理解它们。
因此,你的第一阶段应该是集中精力打好基础。当你掌握这些概念后,你可以继续往前到一些更复杂的任务,包括:
- 使用职责、封装和组合;
- 以接口的视角思考,即“人们如何使用我的组件?”;
- 使用相关技术写好代码,包括可读性、信息性、简洁、自描述,尽量避免显式地使用模式;
- 有能力回答特定业务的“本质”;“本质”是一个模型,但不意味着类和方法,它意味着回答问题“这个业务如何真正地工作?”
有趣的是,按照这些规则写的代码也许不是“最佳”的,但它一定是“易于重构”的。我们能够以相对容易的方式修改其结构。这与那些难以重构,甚至当发生变化时,有时候要完全重写的代码形成了鲜明对比。
技能管理
在开发过程中,另一种比痴迷于各种驱动方法更有效的策略是团队中技能的告知管理(Informed management of skills)。很久以前,你要进入雇主 - 熟练工的关系才能得到一份工作。它最新的名字叫做老师(教练)- 学徒。现在,每个开发者在起步阶段,都有一堆文档,简单、重复的工作要做。有些人数月、数年的时间都投入其中。某些情况下,这减少了他在就业市场中的成功机会。我要大胆地声明,这份新工作抹杀了他的潜力,对其开发毫无帮助。从技能开发管理的角度来看,如果说每一个专业人士都能够被一定数量的学生取代,那么也就等同于说每一个 CEO 都能被一定数量的顾问取代。
通过以下行动,组织能够管理好开发者的技能:
- 教会有经验的工程师成为老师和教练;
- 为新员工指定一个关心并帮助其提升技能的人;
- 为开发者提供机会,让他们有可能工作于各种不同的项目、技术、客户和同事(当然,不是同时);
- 对员工设定额外的技术设定,不匹配的人不能录用;
- 一旦录用了某人,就认为他具有开发的潜力;
- 与开发者构建双向信任。
可替代的人力资源
至少一或多种方法是与技能开发管理背道而驰的。也许这是开发者最不欢迎的方法。公司不明说,却在实际使用的方法。这就是为什么它很重要,我要在这里进行说明的原因。它的主要目标是建立一个架构,让公司能够以快速、廉价的方法替换大多数开发者。这样的组织会做以下事情:
- 雇用一定数量具有丰富经验的工程师,剩余的开发者则只需要普通技术水平和平均薪酬;
- 一小组开发者构建系统架构,使得后续开发能以重复的模式进行,从而将执行成本降到最低;
- 系统架构的调整由开发专家进行,关键变化和创新变革始终由那些具有丰富经验的专家团队和高薪工程师完成。
总结
正如之前所说的,本文并非要批评任何人或任何事。它只是谈论优先级并寻求平衡。首先关注于我们的基础技能,这能够帮助正确地使用某种驱动方法,特别是在未知的上下文环境中。我真的感谢所有这些心理框架,他们做了非常棒的工作。但我认为如果软件开发是由某种东西驱动的话,这是股东的需求和我们的简单认识。被任何其它东西驱动都可能会影响简单性。
关于作者
Michał Bartyzel是 BNS IT 的教练和顾问。他分析和开发编程模型的心理学,帮助软件开发者更好地工作。他目前为 conversation-patterns.com 软件专业工作。可通过以下方式联系: m.bartyzel@bnsit.pl 、mbartyzel.blogspot.com 和 @MichalBartyzel。
评论 1 条评论