阅读 1493
前端中的领域驱动(DDD)

前端中的领域驱动(DDD)

随着我们解决的场景越来越专业化和复杂化,大型SPA应用的流行,前端承担的职责越来越多。很容易导致迭代着迭代着发现代码改不动了。最后只能新起炉灶,重新开发。归根到底在于 复杂度的失控 ,此时就需要一些理念来指导开发。

背景:

为什么迭代越来越难?原因在于:

  • 问题域本身错综复杂

    • 软件本身是为了管理复杂度,我们现在面对的问题域错综复杂。为了创建真正好用的软件,开发者必须有一整套与之相关的知识体系
  • 技术模型与领域模型不匹配

    • 一般我们很容易抽象出一个独立的类、函数来放通用逻辑,这个通用类、函数只有技术维度上的通用。技术维度上的通用 很容易被业务摧毁 。需求上的变动或者膨胀,技术维度的通用很容易被摧毁。根本原因就是我们设计的 技术模型领域模型 不匹配。于是每次需求的改动,映射到技术模型的改动可能就是极大的工作量。甚至根本改不动,在业务压力很大的时候,我们只能告诉产品经理,这个可以做,但是我们需要2个月。结局很可能就是需求方的妥协,牺牲用户的利益。导致产品越来越难用。
  • 知识的丢失

    • 任何项目都会丢失知识,外包出去的系统可能只交回了代码,知识没有传递回来。离职了,转岗了,一旦出于某种原因人们没有口头传递知识,知识就丢失了。

上这三个问题归根到底,就是我们没有在前端代码里把我们业务描述清楚。我们很多情况下是 视图驱动 ,而不是 业务驱动 。很多时候只关心页面长什么样子,发了什么请求拿了什么数据。于是在业务概念上每个人理解的深度都不同。解这个问题可能采用新的领域驱动设计的开发方式会比较合适。

什么是领域驱动设计?

在维基百科中定义:领域驱动设计是一种由 域模型 来驱动着系统设计的思想,不是通过存储数据词典(DB表字段、ESMapper字段等等)来驱动系统设计。 领域模型是对业务模型的抽象, DDD 是把业务模型翻译成系统架构设计的一种方式。

DDD中的模型

Model与传统的POJO(DTO、DO、DAO)类等对比,都是一个类中有属性、属性有Get/Set方法,并且做传输对象。 Model与传统MVC三层架构层的业务逻辑层中的Service对比,都是处理业务行为(Action)层。 模型(Model)承载着业务的属性和具体的行为,是业务表达的方式、是 DDD 的内核。是一个类中有属性、属性有Get/Set方法,并且业务的行为(Action)操作也是在模型类中(充血模型)即做业务逻辑处理,又做数据传输对象,模型分为Entity、Value Object、Service这三种类型。 前面说的都是服务端术语。 简单来说,将业务概念优先于代码库的其它分类类型(例如,按文件类型分组)。这意味着,你应该基于你主要的业务领域(“问题”)及其子领域(问题的细分部分)来组织你的代码。例如,在电子商务领域,我们有产品目录、客户、订单、库存等子领域。 虽然DDD概念来自面向对象编程,依赖于类及其关系,但其核心理念可以很容易地应用到其它范式。

前端应用领域模型(来自: 前端开发-领域驱动设计 · 语雀

领域模型很多情况下都是由后端同学建立的,前端同学如何指导开发呢?

  • 理解后端领域模型

    • 弄清他们的模块划分,我们可以直接借鉴他们的模型,这样也可以保证前后端对于业务模型的理解一致。
  • 建立前端领域模型

  • 分离领域层

强调的是领域层的建设一定不是两个页面同时发了个请求,于是把这个请求抽出来,给与一个领域的名字。他一定被 提前建立好 的。在开始进行前端设计之前就被设计出来的一层。 我们要将所有页面组件与模块内的业务行为都抽离出来,放在合适的领域模块中。只要是业务行为, 一定有一个领域模块可以落 。如果不行就是领域模型设计的不合理。 驱动领域层分离的目的并不是页面被复用,这一点在 思想上 一定要转化过来。领域层并不是因为被多个地方复用而被抽离。它被抽离的原因是:

  • 领域层是 稳定 的(页面以及与页面绑定的模块都是不稳定的)

  • 领域层是 解耦 的(页面是会耦合的,页面的数据会来自多个接口,多个领域)

  • 领域层具有 极高复杂度 ,值得单独管理(view层处理页面渲染以及页面逻辑控制,复杂度已经够高,领域层解耦可以轻view层。 view层尽可能轻量 是我们架构师cnfi主推的思路)

  • 领域层 以层为单位 是可以被 复用 的(你的代码可能会抛弃某个技术体系,从vue转成react,或者可能会推出一个移动版,在这些情况下,领域层这一层都是可以直接复用)

  • 为了领域模型的持续 衍进 (模型存在的目的是让人们聚焦,聚焦的好处是加强了前端团队对于业务的理解,思考业务的过程才能让业务前进)

  • 主导接口约定

接口约定尽量由 前端主导 ,毕竟接口是给前端使用,前端来设计接口比较合理。

  • 开发中注意业务含义

在类,方法,模块命名时要直指 业务核心 ,保持与领域模型的一致。

  • 实时同步

确保团队内部所有同学都要熟悉系统的模型。尤其是对于要熟悉并修改代码的新同学,先向他们分享我们系统的领域模型之后再介绍技术架构。工作开展的重点的不同会导致编程世界观的不同。这样子会让新同学养成习惯,在进行技术决断之前先判断是否符合现有的模型。不断的思考模型,才能够帮助我们业务成长。

在 react 中领域驱动设计?

按照业务划分好模块,组织结构,视图与逻辑分离,一般来说:src目录下应该只含有 assets,pages,layouts,app 四个。

  • 按功能划分文件夹,每个功能只能包含以下四种文件:Xxx.less, Xxx.tsx, useXxx.ts,useXxx.spec.ts , 采用嵌套结构组织,同时,结合 hooks 来做到相关状态逻辑收敛与复用

  • 一个文件夹包含该领域内所有逻辑(视图,样式,测试,状态,接口),禁止将逻辑放置于文件夹以外

  • 如果需要由其他功能调用,利用控制反转(依赖注入)SOA 进行组合

以上,也符合最小依赖,高内聚的原则,在 React 实践DDD,关键就是用好 hooks !

DDD 可以说是整个软件开发架构设计的趋势,前端中微服务实现其实也是依赖以此,把大的项目拆成相对独立的微应用,这就是划分为一个个的域。

参考

  1. www.yuque.com/mayiprotote…

  2. www.infoq.cn/article/a7e…

  3. Hexagonal Architecture by example - a hands-on introduction

  4. jishuin.proginn.com/p/763bfbd5e…

文章分类
前端
文章标签