1. DDD原型:扩展技术 - 业务协作
2. 介绍无代码API
3. 建议:将可视化API对外发布
无论如何,你都会未雨绸缪。——《人月神话》,弗雷德里克·布鲁克斯
1. DDD原型:扩展技术 - 业务协作
什么是协作障碍
协作障碍是业务应用开发项目的时间线中,最终结果的主要贡献者从业务设计团队到软件开发人员转移的一个时刻。
协作障碍通常发生在已经充分理解领域模型,可以认真开始编码的情况下。在那一刻人们相信,颠覆性思想改变的可能性已经低到可以接受的程度,因此领域模型可以开始在代码中冻结。
图1“编程开始后,业务人员的贡献度就开始下降”
图1显示了一个纯粹的定性模型,表明技术人员和业务人员在项目进展过程中如何共同参与确定最终结果。协作障碍左侧有一个弯折。在此弯折之前,业务人员正在向技术人员讲解业务。在弯折之后,他们开发了普遍存在的语言,并且正在完全协作地描述领域模型。在协作障碍的右侧,业务人员对最终产品的贡献变得微乎其微。
改变的代价
如果团队发现他们必须返回并修改领域模型,则可能会改变。在协作障碍之后,实际返回和更改领域模型的成本开始上升,并且随着时间的推移它继续上升并且必须撤消更多的工作。换句话说,在协作障碍之前,改变主意的成本(就最终项目延迟而言)是低而平的。在协作障碍之后,成本通常单调上升。因此,在协作障碍之后,如果实现了需要改变的设计,决策过程可能会变成产品质量和项目进度之间的价值权衡。
图2“提交的代码越多,更改的成本越高”
图2再次定性地显示了随着时间的推移而变化的成本。这个成本是进度延迟和质量损失的某种组合,这取决于如何处理变更。
显然,你希望在协作障碍之前就得到正确设计。难题,尤其是如果这是需求的第一次实现,(直截了当地说)就是在构建需求之前,您不知道要构建什么。IBM构建OS/360的经验使弗雷德·布鲁克斯的课程登顶。
业务参与原型设计的案例
那么,答案就是建造一个既便宜又快捷的东西,你可以用它来学习你真正需要建造的东西。我把这个叫做原型。原型的目标应该是以可控的成本最大化学习。
我在这里的前提是,为了使学习机会最大化,业务人员必须充分参与构建原型。如果是这种情况,将原型阶段引入开发的效果就是将协作障碍向右移动,如图3所示。
图3“让业务人员参与原型设计,能将协作障碍推向右侧”
如果我们接受原型是一次性的(此时没有理由怀疑这一点),那么构建原型的工作不会对最终代码产生影响。这项工作是“损失”,它增加了项目的总成本。这要花多少钱?引用布鲁克斯的话[1]:
因此,管理层的问题不在于是否要建立一个试点系统并扔掉它。你之后会这么做。唯一的问题是,是提前计划建造一个一次性系统,还是承诺向客户交付一个一次性系统。
我冒昧地将布鲁克斯的话,解释如下:
构建原型所购买的是避免不得不废弃和重建交付的系统,或者更乐观地说,它第一次购买构建更可用的系统。自从布鲁克斯身上,我们学到的是如何把它小块小块扔掉而不是一下子扔掉。
为什么业务人员完全参与的原型设计会引导出更可用的系统?因为业务人员是衡量可用性的唯一可用的预备资源,他们就在那里参与其构建。他们一直在考虑可用性。
因此,我们提出了一个问题:我们如何才能以一种我们认为不是程序员的业务人员完全参与流程的方式构建原型?
划分工作
我在这里提出的答案是将原型分为开发人员构建的部分和业务人员构建的部分。下面是这种划分任务的方法的一些要求。
双面原型模型
双面模型(图4)是一个结合了传统构建的领域对象和非程序员构建的图形化用例描述的环境。可视化APIs使这两个部分能够协同工作,同时保持各自的优势。
图4“双面原型模型”
无代码用例
无代码用例执行包含价值传递的用户交互。它们不仅仅是简单地描述用户界面,因为它们与领域对象通信,使用直接从它们派生的值,并适当地响应用户事件,也可能是状态更改。
我开发了一种单向对象流连接语言,它似乎足以根据上面的需求,用符号列表描述用例。我并不认为这是唯一的解决方案,但它是一个存在的证明。
这种连接语言本身并不是强大的,但是它通过可视APIs被无缝地扩展到包含领域对象的业务流程中。连线是一种图形化、非程序化的流程语言,它不执行算术,甚至不执行涉及循环或分支的最简单算法。它在能力和可访问性(即非程序员可用性)之间占据了一个有利位置。它不需要变得更复杂,因为在需要更多力量的地方,这些力量都是特定于领域的,属于领域对象,并且可以通过可视APIs访问,如以下部分所述。
图5说明了连线语言如何适应能力可访问性的权衡。它能够处理功能组合(通过连接有线组件)和集合(在连线上流动的业务对象)、呈现用户界面、响应用户事件等。据我观察,在这些连线用例描述中发生的大部分事情是组装和分解集合。沿导线向下流动的对象可能很复杂,例如,记录其元素具有特定于领域的行为。
图5“简单的连接语言不那么强大(如果单独使用),但会更容易访问”
可视化APIs
可视化APIs取代了对生成器的要求,即通过显示对话框窗口中显示的选项来构造语法文本。它使业务人员能够访问领域对象并向其参数化消息,而不必离开舒适区。这些消息是由有线组件发送的,它们的返回值沿着连线向下流动。
图4显示了可视化APIs是由开发人员构建的。这项工作的回报是技术人员和业务人员之间的沟通容易,并延长了他们充分参与开发过程的时间。这些是双面模型原型化带来的业务收益。
介绍无代码API
本节将多个现有的区别合并到一个概念框架中,以便扩展这个框架。图9将这些概念放在一个地方。
A.对称性/灵活性区别
每个API有两个维度。
一旦API发布并开始使用,根据生产者和消费者之间的关系,更改它可能是可以接受的,也可能是不可以接受的。这种区别将API分为两类,可协商的和固定的;请参见图6。
图6“一旦API投入使用,API契约就可以协商或定型”
这与一般API文献中的区别相对应。本文献几乎总是假设生产者和消费者都是程序员,或者至少可以使用正式规范的技术细节。然而,上面关于DDD原型的讨论与这一假设相矛盾,因为消费者、业务人员通常不是程序员。所以我们需要把这个1x2变成一个2x2;参见图7。这个数组的“对称”维度与API的规范方面相对应;数组的“灵活性”维度与API的契约方面相对应。
图7“对称/灵活的API”
请注意,长期以来被认为是编程语言中一些不容易分类的电子表格就属于这个分类方案。电子表格可以看作是一个API,如下所示:
为什么在这里提到电子表格?因为描述它的应用模型将允许我们稍后转向双面模型。
B.构建/运维区别
任何一个软件单元的开发都有两个不同的阶段,即构建阶段和运维阶段。为了让我们充分理解可视化API是什么,这两个阶段需要引入到相同的概念框架中,并被视为同一事物的两个方面:软件单元的生命周期。为了简单起见,我们将此讨论限制为根据API开发客户端-服务端交互。
图8的生命周期/角色图为可视化API捕获了这一区别。注意,有一个新的元素:公共VAPI发布。这对于消费者的工具是可见的。它管理与使用者的交互;这个交互在客户端中生成并存储请求代码。所有这些交互和代码生成功能都是由生产者预先构建的;这项工作是额外的成本,其好处是消费者的极简体验。
图8“可视化API的生命周期/角色图”
图9总结了迄今为止提出的概念。
图9“概念总结”
3. 建议:将可视化API对外发布
产品概念
现在让我们重温图7,用一个尚不存在的示例替换电子表格示例。我会称之为DIY应用程序生成器,简称为“DIY应用程序生成器”。它属于图7中的不对称/固定象限。也就是说,它的API契约是不可协商的,它的客户端可以由非程序员创建。图10简单地将图7中的“电子表格”替换为“DIY应用程序”。
图10“DIY App Builder以非对称/固定的方式替换电子表格”
什么是DIY应用程序生成器?把它看作是构建符合双面模型(图4)的业务应用程序的东西,并且它不要求其API的使用者是程序员。DIY应用程序生成器API的愿景是,它们可以像Web API和电子表格那样对外发布;它们将允许非编程人员构建某些类型的业务应用程序。这看起来像是下一节的主题。
图11“DIY App Builder的生命周期/角色图”
启示
至少在最初,这个概念可能会局限于中小型业务的软件市场。在这个市场上提供产品的一种方式是通过本地顾问为客户定制现有产品包。一些例子包括:零售收银机/库存/订购、非盈利捐助者管理和客户项目管理/计费。该产品应使这些增值顾问更具生产力,并构建专有的领域对象,以增加其增值。一些小部分业务用户可能会涉足去构建自己的应用程序。
如果这个产品有适当的管理之后,它将建立一个用户社区,这些用户将互相交流和支持。从长远来看,我可以想象会变成一个自由和开源软件社区,现在主要局限于开发人员,分成两个分支(对应于双面模型的两部分):现有的开发人员分支和新的最终用户分支,其成员交换封装的连线图。开发人员分支中的一些开发人员将为此产品构建领域对象模板,从而扩大其市场。