> For the complete documentation index, see [llms.txt](https://weekly-essay.mikey.wang/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://weekly-essay.mikey.wang/zh/2020-nian/w27-ling-yu-qu-dong-qian-hou-duan-jiao-hu-mo-shi.md).

# W27-领域驱动 & 前后端交互模式

#### **关于领域驱动设计的一些思考** <a href="#id-guan-yu-ling-yu-qu-dong-she-ji-de-yi-xie-si-kao" id="id-guan-yu-ling-yu-qu-dong-she-ji-de-yi-xie-si-kao"></a>

**如何在快速变化中，保持我们项目核心的稳定。不至于在后续迭代中，复杂度失控直至重构。**&#x6211;们现在其实已经面临业务知识在团队传播中丢失的问题了，随着团队规模的扩大，人员的更替，问题只会越来越严重。那**核心是什么，就是对业务的理解与抽象，映射到软件设计中，我认为就是基于领域的设计。**

相比前端，后端往往在设计上做的更加详尽、更加深远。项目需要建立在对业务的深入理解之上，理解的越深刻，抽象的越彻底，项目的可维护性和扩展性越好。某种程度上讲，后端不做设计，可能根本没法开工。

前端就不太一样了，我们的技术方案，更多的体现在单纯的技术要点上，以及业务流程的实现上。真正在业务的深入拆解上，还做得不够。说实话，**我们的方案设计，基本上还是停留在面向页面的实现**。很少看到对业务进行抽象，进而设计组件和软件的结构层次。

好的后端项目，它的表结构和service层是相对稳定的，这得益于对于业务领域的深刻理解与抽象。商家端现在正处于业务快速迭代的阶段，相应地，在UI、交互上也会快速变化。如何最大程度地做到“以不变应万变”？如何在整体上，以更低的成本去支撑业务成长？我想在领域驱动设计中找到答案。

拿收银台举例，这次i版重构，是以容器组件和展示组件这个思路去组织整个应用的。容器组件负责状态管理和业务逻辑，展示组件是只负责数据与视图映射的纯组件。收银台前端的业务逻辑并不算复杂，但这样下来，容器组件也有600余行。现在来看还比较清爽，但马上就会加入贷款支付、理财金支付、营销等业务，容器组件会越来越厚。怎么办？必须拆。怎么拆？按领域拆。收银台前端的核心是对支付方式的处理，应该对不同业务属性的支付方式进行领域抽象。每种支付方式对应的资产提供方不同，所以可以理解为一个领域。不同的领域有其特有的属性与行为。比如，快捷支付，有卡列表的属性，有选择某张卡去输入密码的行为。贷款支付，有分期期数、金额的属性，有去人脸识别贷款的行为，有获取贷款合同的行为。这些是业务逻辑的底层，是相对稳定的。不管未来UI怎么变，项目的核心———领域层不会变。甚至前端技术栈从Vue转换到React，也可以做到核心的稳定迁移。

在设计这方面我之前也做的比较弱，对于领域驱动设计的构想还需要继续交流与碰撞，进而得到进化。

#### **前后端数据交互模式的一些体会** <a href="#id-qian-hou-duan-shu-ju-jiao-hu-mo-shi-de-yi-xie-ti-hui" id="id-qian-hou-duan-shu-ju-jiao-hu-mo-shi-de-yi-xie-ti-hui"></a>

与钱包的业务相比，支付这边的业务在前后端接口交互上，有着明显的设计差异。支付业务中，像收银台、绑卡、买单等业务。对前端提供的API，基本上是面向页面设计的。接口之间的关系，完全按照人机交互时的时序进行设计，前序接口会返回后序接口的url，请求参数，以及当前页面所需要的一切，就差直出渲染后页面了。

这样做的好处是，前端的职责基本上集中在人机交互上，看起来职责很单一。后端在接口交互上，可以有相对灵活的控制，可以自由决定后续接口，进而调用不同的下游，最终返回数据，避免了与前端协商的过程。

不好的地方也很明显，这种模式把API和视图，或者说人机交互流程，紧紧地耦合在了一起，在扩展性上其实是很脆弱的。这种协作模式之所以成立，是因为前端视图和业务流程足够稳定。事实上，支付业务确实比较符合这个前置条件。这种模式虽说普适性差了些，但既然支付业务在架构的时候就这么做，一定有一些比较深入的考量。目前来看，在支付的场景下，我说不上绝对的好与坏，还需要在做业务中体会。

**快捷支付项目中，A接口下发接下来的请求接口，决定后续接口。需要后端对前端版本有感知，要不通过版本号，要不通过以客户id为线索的全链路灰度。**
