二十年前的我,还在学校里抱着一台DIY机(德州486+大众主板+16M内存+3.5inch软驱+昆腾320M硬盘,当时全校最快主机没有之一),揣着一本《Undocumented DOS》,沉迷在Pascal、C以及汇编混合编程的世界里无法自拔。二十年后,软件开发已远不是当初几张简单流程图可比,软件开发的方向由简至繁,各式的开发工具更是层出不穷,不仅让新出道的人们深感乱花渐欲迷人眼,也让我等备感跋涉之不易。所幸爱好不外有二,读书实中其一。也唯有不断学习,才不至被拍死在沙滩之上。
学习BDD,实属偶然。在学习ES+CQRS的过程中,我认识到必须要转变观念,把传统单一结构的领域模型一分为二,将其中反映系统状态发生变化的部分封装在写模型里,而将查询或呈现的部分封装在读模型里,分别设计、分别实现,再以领域事件为纽带,实现整个业务的最终一致性。因此,发掘领域事件、理解最终一致性成为个中的关键。因此,我开始寻求发掘领域事件的方法学支撑。
在搜索引擎帮助下,我很快找到了一些社区和Blog上关于发现和挖掘领域事件的文章,而它们的观点最终都归结为了一点:讲好故事。讲好了故事,才能清楚我们究竟要什么,才能帮助我们划清边界,才能发现边界间的联结关键。于是,很自然地,BDD进入了我的视野,然后是Specification by Example,继而是Impact Map。它们都可以帮助我们把故事讲好。
这一篇,先总结一下这段时间的学习成果。之后再争取学以致用,用一个具体的项目进行DDD+BDD的综合实践。
既然是要在原有开发方法里掺入新的东西,那就说明现有方法必定有其缺陷,需要加以完善和改进。所以,先说说我们在此之前是怎么做DDD的。
在整个开发流程里,如果说建模、实现、测试等等,都还在我的控制之中,那么在与客户交流时,我不知道有多少人象我一样,时常感到引导话题或者讨论方向时那种深深的无力。客户总会认为你是专家,他说的你都能理解、都能实现,无论其表述是如何的天马行空。而这种信马由缰式的讨论,也对我划分子域、切分BC带来了很大的困扰。可能有的人会说,你为什么不每次都拟定一个讨论的主题和大致的提纲呢?而我能说的是,嗯,是的,我准备了,可是客户思维的发散性和跳跃性永远会给你带来意外的“惊喜”。另一方面,是伴随系统模块逐渐增多后迅速膨胀的各类测试,以及繁琐的UI测试,给我们的维护与迭代带来的巨大心理和工作压力。
所以,我希望有一种方法学的指引,帮助我们更加专注于每次讨论的主题,帮助我们更好地发现和切分BC。在张逸的《如何识别Bounded Context》一文中,我找到了方向。在文中,他倡导以领域中的Who-What-Why-When-Where-How为媒,以Actor为驱动,不断堆砌出系统的关键用例,再以对用例的分类划定问题的边界,最终由此催生不同的BC切分。
这更加深了我对“讲好故事、划好边界”的认识,并由此引导我迅速地转入了对BDD、Specification by Example的学习。
关于BDD,我在前一篇《行为驱动开发BDD概要》中已经做了一份《BDD in Action》的书摘,并按图索骥尝试了.NET平台下的Specflow+NUnit组合。由于有TDD的基础,所以这个过程的后半实现部分并没有想象中的困难,反而是在前半分析部分——理清Specification并写出Feature文件,由于找不准Why-Who-How-What,而让我犯了不少迷糊。
起初,我的想法很简单,只要能搭出这个Why-Who-How-What的框架,剩下的工作将只是往里填充内容而已。所以我在使用Impact Map这个脑图工具时,一开始就拘泥于BDD in Action作者在第三章的阐述,只能教条式地从该书第72页列举的4点主题去寻找Why:
于是,我得到了一张象下面这样的图。这显然与我们的目标相距甚远,因为这样的Business Goal并不够明确具体,不是完全可量化的,也无法直接作为验收标准。但这并不是说这样的做法是错误的,只能说是仍不够精确的。因为它对于我们理解用户需求还是有一定帮助的。
而且在这个过程中,如果说找出Why和Who还不算难事,那么要挖出How与What则让我大费周张。在书中,作者对How的部分引入了Capability的概念,并建议参照Liz Keogh的观点,以”to be able to”的形式来描述。而对What的部分,作者则引入了Feature的概念,强调这里描述的应该是系统能以何种方式帮助特定角色实现相应的Capability。
于是当我按图索骥时,却再一次陷入了教条主义的泥沼,搞不清什么应该放在How、什么又该放在What里。而致使我陷入被动的另一个因素,则是我发觉中英文在表达How与What时语义上存在的混淆。比如”它会怎样改变?(How should it change?)“与”它会发生什么样的改变?(What should be the change in it?)”,你能分得清这两者有什么真正的区别吗?
尽管我反复阅读BDD in Action第3章和第4章,但我那可怜的英语阅读能力并未能帮助我顺利摆脱How与What的纠结。
好在网络是强大的、墙外的风光总有美好的。在email、twitter以及group的轮番轰炸下,一切开始出现转机。首先是Julian May向我推荐了Gojko Adzic所著的《Specification By Example》一书,然后是作者Gojko、网友ChrisMatts等人的回复,为我指明了学习的方向。
在此有点题外话,一是BDD in Action著书于Specification by Example之后,其第3、4章的内容已经撷取了后者的精华,却不知为何没有使用Gojko所提倡Impact和Deliverable的概念。二是Specification by Example已有中译本《实例化需求:团队如何交付正确的软件》,由人民邮电出版社出版,我的英文书摘亦将另行整理,以作对照。
Specifications by Example为我呈现了一个全新的视角:以Specification、Automation Test以及Living Documentation等文档为中心的交付模型(Documentation-centric model),以及一个由下图所示的交付模式。
随着阅读的不断深入,Why-Who-How-What被Goal-Actor-Impact-Deliverable所代替,其含义也越发地清晰起来:
之前那种依赖于语言本身对How和What进行的讨论,此时便显得如此拙劣。对此,Gojko有这样一段精彩的阐述:
But now I advise people not to think about that, instead to think about impacts and deliverables. Deliverables are stuff you do in your zone of control, impacts are how those things influence actors in your sphere of influence. You can call these questions "what/how" or "how/what" or not think about the questions at all, depending on what the group in the room understands better.
它回答了之前一直困扰我的问题。即What是在开发团队控制范围内的,能对Actor产生影响的那些事物。这些是我们努力就一定能做到的,比如系统能提供的具体功能。而How则是我们期望的、能对Actor产生的影响。这种影响相对开发团队而言,是间接和被动的。对此,Gojko用一个手机App进行了形象的比喻:
Impacts - this is your sphere of influence - things you don't control directly, but things you think you can influence. Deliverables - this is your zone of control. The big question to differentiate between the two is: is there an assumption here, or are we guaranteed to achieve it if we decide to do it. Eg if we decide to build an iPhone App, we will. But if we decide to get people to buy the app on the appstore more, regardless of all our efforts that might not happen. The first one is in our zone of control, the second is in the sphere of influence.
期间我对Business Goal也重新进行了认识。BDD in Action曾用Specific(特定的)、Measurable(可量化的)、Achievable(可实现的)、Relevant(相关的)、Time-bound(有期限的)对其进行说明,而发掘Goal的工具真的是如此简单——不停地问Why……然后,我又重绘了之前的图:
再补上MelvinPerezCx对Impact Map与各种产出件之间关系的一张好图:
解决了Impact Map的问题,下一步就是思考如何将DDD的战略思考与BDD的战术实现结合起来,引导整个开发的方向。这一切当然地需要用实践来解决,在前进中才能解决遇到的问题,所以暂且只得到以下的一个思路。
这是我近期学习的一些收获,不仅思考很不成熟,亟待实践的检验,而且文中也难免有个人认识上的谬误之处,还请各位看官批评指正。另一方面,由于BDD是一种战术意义的Development方法学,需要时间去掌握相关的一些工具,所以我会尝试用一个相对简单的项目练手,届时再来补充完善此篇所述之内容。