可视化与领域驱动设计

从DDD的角度,领域逻辑的分析可以运用战略方法Bounded Context。可是,一个问题是:如何获得Bounded Context ?

我查看了许多关于Bounded Context的书籍与文章,虽然都着重强调了它的重要性,也给出了一些实例,却对如何从需求——>Boundex Context这一点上语焉不详。

一个初步设想

我的初步设想是通过绘制场景图(但并不成熟)。我认为有三种绘制场景图的方式:商业画布,体验地图和流程图。我认为,商业画布可以作为需求分析(尤其针对初创产品)的起点。商业画布如下图所示:

采用这种规范化的方式来推导商业模型,可以激发我们的灵感,理清我们的思路,以便我们思考为何要做这个产品,产品应该具备哪些功能。结合优点和缺点、成本等因素,我们可以藉此判断和决策功能的优先级,从而得到MVP。这个过程需要大量运用即时贴,让整个商业模型呈现。经过取舍后,就可以针对产品绘制场景图。此时,场景图可以采用Experience Map或流程图来体现。Experience Map的例子如下图所示:

由于商业画布本身提供了“客户”项,我们应该创建Persona,找准人物角色的特征来“搜寻”需求。绘制了场景图后,就能够确定用例了,此时,可辅以ATDD帮助确定Story。在确定了用例后,可以识别Bounded Context,并通过Context Map确定上下文之间的关系。

就我个人感觉,体验地图还是从Persona的角度设想系统如何使用,考虑它的用户体验。它其实符合“场景”的概念。这里可能还是要考虑:在一个完整的场景中,需要哪些参与者?但是,即使从粗粒度的角度出发,场景都可能存在多个,可能需要绘制多个场景图来逐步提炼Bounded Context。

关于如何运用Persona,熊子川在他的博客《XD关键字5:Persona》中已有详细介绍,同样在他的博客《Agile UX内容策略工作坊》中提出的“消费者建模”实践,指出:

为了更好的理解我们选择的目标消费者,我们需要对消费者进行完整的建模,即Persona。越接近于真实的Persona帮助我们更好的理解其用户目标……Persona的重要产出物是一系列用户目标,对于同一个Persona,用户目标可能有不同,有些目标是基础核心目标,有些则是衍生性的,例如一个访问网站潜在投资者的核心目标可能是了解成为投资者的过程,而衍生性目标可能是获得一些关于公司历史信息增加信任度。

说明:本图摘自熊子川博客

获得Context并划分领域

假设我们要开发一个电子商务网站,我们就可以通过商业画布来驱动出这个产品应该具有哪些功能,它的客户有哪些等,在绘制了场景图后,可以初步得到这样的Bounded Context:

然后,我利用Context Map得到了各个上下文之间的关系:

这样,一个包图的获得就水到渠成了:

六边形架构

在识别了Bounded Context以及Context之间的关系后,我们可以运用Hexagon架构(Cockburn提出的六边形架构)来展现系统的整体架构。Hexagon架构并不深入关注内部边界中领域部分,仅仅是简单的划分为Application与Domain两层。但它有助于我们获得基础设施层以及相关集成点的包结构。我们要合理地运用六边形架构。它更贴近应用逻辑架构,并可以驱动我们去发现诸多集成点,寻找集成模式。内外边界的分离也有助于我们将业务逻辑与应用逻辑分离开。这实际上符合“关注点分离”的架构原则。下图展现了六边形架构中常见的Port与Adapter:

所谓“可视化架构”,是一种利用多种交流方式实现架构知识共享的方法,因而需要团队成员均参与进来,并以Workshop的形式,更多通过即时贴、白板等工具实现可视化,而非通过绘图。至少,绘图不应该成为主要的驱动力,否则,开发人员很难接受。例如,下图就是我运用Hexagon架构,并结合可视化手段分析该电子商务系统得到的应用逻辑架构,它很好地一个展现了Hexagon架构的可视化手法。

在这个图中,直观地展现了如何与外部的支付系统以及物流系统的集成。例如,图中展现的Port实际上为防腐层(ACL)。为何要建立这样的一个防腐层呢,原因在于:支付与物流常常存在多个供应商,因而需要解除对供应商的绑定,并避免供应商系统的变化造成对电子商务系统的腐蚀。这是切合实际的决策。

一个实例:仓库管理流程控制系统

这个电子商务系统需要与仓库管理系统集成。恰好在《面向模式的软件架构》卷四的第35页,给出了一个仓库管理流程控制系统的案例。书中描述的非功能性需求,即所谓质量属性包括:

  • 分布性。仓库管理流程控制系统天生就是分布式的。
  • 性能。仓库管理流程控制系统不是一个“绝对的”实时系统,但性能仍与业务息息相关。对系统有整体的吞吐量要求,因此系统必须确保所有的运输指令能够被及时而有效地运行。
  • 可伸缩性。不同仓库其大小可能会有很大的不同,因此仓库管理流程控制系统必须能既支持只有几千个箱子的小仓库,又要支持超过一百万个箱子的大仓库。
  • 可用性。许多仓库操作采用三班倒的24/7模式工作,因此可用性是仓库管理流程控制系统对业务案例支持的关键因素。

假设要设计这样的系统以支持这些质量属性。对于分布式而言,书中提出的解决方案是传统的分布式系统解决方案,即引入Broker模式,在本地建立对远程对象的代理。而对于支持并发的领域对象访问而言,则采用了Active Object模式,并引入Leader/Followers并发模型来获得可扩展。

我没有打算引入这么复杂的模式,而仅仅是通过引入消息队列,并为消息队列引入路由的方式,来实现系统的分布式。这其中当然会用到经典的Publisher-Subscriber模式。我对领域逻辑进行了识别,将整个仓库管理流程控制系统的领域逻辑分为三个Bounded Context:

  • 库存管理
  • 物流控制
  • 拓扑管理

整个架构如下图所示:

对于库存管理而言,我认为它主要支持商品存放信息的数据管理,即获得商品数量、存放位置以及更新这些信息。对于该上下文而言,操作本身比较简单,且耗时较短。若出现大规模并发,其瓶颈也不在于获取或更新仓库信息(当然需要通过测试数据验证),而在于客户下订单后向仓库管理流程控制系统发起的发货请求。

我将发货请求放到了物流控制上下文中,除此之外,它还包括收货以及订单管理等。同时,对于物流控制与拓扑管理功能,基本上与具体的仓库形成了一一对应关系。此外,对于发货请求(或收货请求),并不要求很强的实时性,这使得对这些请求的异步处理成为可能。

物流控制由于牵涉到收货和运货,需要控制仓库的相关设备,并按照仓库的拓扑结构设定设备的路由。这说明物流控制与拓扑控制存在上下游关系,拓扑控制是上游。这两个上下文可以是Customer-Provider的关系。但它们之间不应该存在物理边界。因此,我将这两个上下文放到了同一个六边形中,而将库存管理放到了另一个单独的六边形中,以便于它们各自独立的可伸缩。

在库存管理与物流控制六边形之间,我引入消息队列来应对从库存管理子系统中转发而来的发货请求(发货请求实则又来自于E-Commerce的订单请求)。原则上,我针对一个物理的仓库建立一个单独的消息队列,因此库存管理在发送发货请求时,会根据商品的存放位置以及用户请求的IP地址,获得最优的仓库信息,然后通过Router将消息转发到正确的消息队列中。

一旦收到消息,物流控制系统作为消息队列的订阅者(或侦听器)就可以即使处理信息,进行后续的处理。

针对库存管理而言,我认为它是一个独立的物理边界,因此在可视化手段中,我展现为一个单独的库存管理六边形,如下图所示:

库存管理建立了如下端口:

  • 建立了针对REST服务的端口,对应的适配器为Controller,其目的是支持E-Commerce系统。事实上,我们对E-Commerce系统进行过分析,获得的六边形架构正好与此对接。
  • 建立了针对DB的端口,对应的适配器为DB Gateway,它负责访问库存管理自身的数据库。数据库持久化的消息包括商品的基本信息如SKU、商品名、数量等,以及商品存放的仓库名。
  • 建立了针对Queue的端口,对应的适配器为Message Router,负责将发货请求消息路由到正确的消息队列。

物流控制与拓扑管理放在同一个边界中,它是高度可伸缩的独立系统,为展现它的可伸缩性以及它与库存管理之间的集成,我在可视化手段中,展现出两个独立的六边形,如下图所示:

物流控制与拓扑管理建立了如下端口:

  • 针对Queue的侦听器端口,对应的适配器为Message Handler。若有必要,如为了更好的支持并发,也可以在此引入Active Object甚至Leader/Followers。
  • 针对REST的端口,对应适配器为Controller。它主要是为了支持移动终端设备、Web应用,以便于相关人员直接发出发货或收货请求。
  • 提供了DB的端口。这个数据库是对应仓库的专有数据库,与库存管理数据库无关。
  • 提供了针对设备(指仓库的设备,如叉车,箱子,运输车等)的端口,对应适配器为South Gateway。
  • 提供了针对配置文件的端口,对应适配器为Configurer。此功能是为了支持拓扑信息的动态配置。
  • 提供了针对外部物流系统的端口,这里为其建立了Shipping的防腐层,使其能够更好地支持各个不同的物流供应商。

目前,我针对可视化架构与设计的手段仍在完善之中,并已经尝试在真实项目中实践以进行验证,并希望能够找到足够简单的方法,为架构师与开发者提供直观而又具有体验价值的沟通方式,并能形成行之有效的设计手段。

原文发布于微信公众号 - 逸言(YiYan_OneWord)

原文发表时间:2016-05-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开源项目

项目推荐 | 逗视 IOS 客户端

本项目是基于 IOS 的逗视客户端,逗视在发现页面有排行榜功能,看看哪些视频大家都在看! 逗视中的视频可以分享到QQ,微信,微博等社交平台,与你的朋友一起欢乐...

3697
来自专栏用户2442861的专栏

前端工程——基础篇

https://github.com/fouber/blog/issues/10#issuecomment-271133674

651
来自专栏AI研习社

Github 项目推荐 | Scikit-learn(sklearn)官方文档中文版

官网地址:scikit-learn(sklearn): http://scikit-learn.org

1052
来自专栏魏艾斯博客www.vpsss.net

DNS 解析和 CDN 加速的区别与联系

6394
来自专栏工作随笔

改VB.NET“偷懒”技巧

【开篇胡侃】虽然搞软件开发很多年了,但似乎从没有动手写过什么(很丢脸的感觉),因为,我的精力都献给了我的其他爱好,比如健身、美食、旅游等等,反而把自己最该专注的...

28613
来自专栏WeTest质量开放平台团队的专栏

提升iOS审核通过率之“IPv6兼容测试”

在WWDC2015大会上苹果宣布iOS9将支持纯IPv6的网络服务。2016年6月1号,所有提交到AppStore上的应用都必须支持IPv6,否则将通不过审核。...

1703
来自专栏ytkah

微信公众平台多客服新增自定义客服头像和消息转发接口功能

  多客服一般是开放给微信认证服务号的一个便捷功能,可以将消息转发到多客服方便回复。对有些“选择综合症“的客服,看到那一层不变的客服头像就想吐槽。现在好了,多客...

4984
来自专栏编程微刊

做前端技术方案选型的时候,你是怎么做决策的?

最近在知乎上看到的一个提问做前端技术方案选型的时候,你是怎么做决策的?想起一年来自己所做的项目,全都是一个人在做选型,能力也在一步步中培养起来。

881
来自专栏IT派

高级工程师的晋升之路:如何用 JavaScript 打造十亿级的应用

我以前开发过超大规模的JavaScript应用。现在我不做了,所以我觉得应该回顾下我学到的东西。昨天我在宴会上喝啤酒时有人问我,“嗨Malte,你为什么要来讲这...

702
来自专栏知晓程序

如何在微信群里发通知?这个方法特别好用

今天,「知晓程序」推荐的小程序「群里有事」,也许能解决这个问题。在这里,你不仅可以发布通知、活动,而且它有一种强大的魔力,吸引大家去查看。

731

扫码关注云+社区