美文网首页
一个前端项目中能用上的领域模型

一个前端项目中能用上的领域模型

作者: ltaoo | 来源:发表于2021-06-08 11:57 被阅读0次

关于「领域驱动设计」在前端的应用,断断续续都能看到一些博客,但大部分看完后不明觉厉,转眼就忘记了,最重要的原因是无法应用在自己项目中。

其实有一个大部分前端同学每天都接触的领域模型 - 「列表领域」。

领域模型是公共认知的体现

我们说到列表时,都知道它在 PC 端一般是表格形式,移动端是列表形式。

  1. 表格形式下它有页码,可以点击切换页码,表格显示当前页数据
  2. 列表形式它是无限滚动加载或点击加载更多,列表显示当前页及之前所有页数据
  3. PC 端移动端都有搜索功能,搜索时需要将页码重置到第一页

不仅仅是上面的描述,还有更多对于「列表」这个概念的「公共认知」就不赘述了。这个公共认知不仅对于研发,对于产品也是一样的。
产品经理在 PRD 中对于列表功能从不会详细描述,不会写出这样的 PRD

... 该页面展示客户表格,默认请求第一页数据,下方展示可以点击的页码 1 - n,点击页码时,将当前表格数据更新为点击页码对应的数据;根据关键字对客户进行搜索时,不使用当前已点击的页码而是第一页;点击重置按钮时,清空所有搜索条件,页码和表格数据回到第一页。

只需要一句「该页面展示客户列表,支持分页和搜索」,研发就知道怎么做了。对于某个业务逻辑大家有一致的认知,它就是领域模型。

领域模型在代码上的表现

下面假设存在 fetchCustomers 函数,它是一个支持分页、搜索的客户列表请求方法。

// 声明领域模型
class List {
  constructor(fn) {
    this.fn = fn;
  }
  async fetch(params = { page: 1, pageSize: 10 }) {
    const response = await this.fn(params);
    this.response = response;
    return response;
  }
}

const customerList = new List(fetchCustomers);
// 初始化时这样调用
customerList.fetch().then(({ list, total }) => {
  // 获取列表数据成功
  console.log(list, total);
});

// 点击页码时这样调用(后面均省略 .then)
customerList.fetch({ page: 2 });

// 搜索时这样调用
customerList.fetch({ page: 1, name: "ltaoo" });

List 虽然有方法有属性,但它没有表达「业务逻辑」所以不能算领域模型。

class List {
  constructor(fn) {
    this.fn = fn;
  }
  async fetch(params = { page: 1, pageSize: 10 }) {
    const response = await this.fn(params);
    this.response = response;
    return response;
  }
  init() {
    return this.fetch({ page: 1, pageSize: 10 });
  }
  goto(page) {
    return this.fetch({ page, pageSize: 10 });
  }
  search(params = {}) {
    return this.fetch({ page: 1, pageSize: 10, ...params });
  }
}

const customerList = new List(fetchCustomers);
customerList.init().then(({ list, total }) => {
  // ...
});
customerList.goto(2);
customerList.search({ name: "ltaoo" });

将业务逻辑以合适的方法名封装在 List 中,调用时无需关心逻辑内部实现,只需要调用对应方法,这才是领域模型。
除了这几个方法,我们还可以有 loadMore 实现移动端加载更多、reset 重置列表等。

有生命力的领域模型

其实上面的逻辑写成一个 react hook 是完全没有问题的,类似这样

function useList(fn) {
  const [response, setResponse] = useState({ list: [], total: 0 });
  async function fetch(params = { page: 1, pageSize: 10 }) {
    const newResponse = await fn(params);
    setResponse(newResponse);
  }
  return [
    response,
    {
      init() {
        fetch({ page: 1 });
      },
      goto(page) {
        fetch({ page });
      },
    },
  ];
}

// 使用时
function CustomerMangePage() {
  const [response, { init, goto }] = useList(fetchCustomers);
  useEffect(() => {
    init();
  }, []);
  // 渲染客户列表
}

写法上仍然简洁清晰,不过写成类的好处是不和框架耦合,无论框架怎么变更,只要仍使用 js 开发,这个 List 类是可以一直使用的。
当然,不和框架耦合,不意味着写法只能固定,我们可以创建一层框架与领域的粘合层,仍以 react hook 为例

function useList(fn) {
  const list = useRef(new List(fn));
  const [response, setResponse] = useState({ list: [], total: 0 });
  useEffect(() => {
    // 这个需要 List 内实现每次调用 fetch 后调用 onChange
    list.onChange = (nextResponse) => {
      setResponse(nextResponse);
    };
  }, []);
  return [
    response,
    {
      init: list.init,
      goto: list.goto,
    },
  ];
}

和直接实现为 react hook 用法是一样的,但它还可以在 vue 等框架中使用。

当然,说了这么多,这里是一个可运行的示例,实际上手体验下吧


点击体验

相关文章

  • 一个前端项目中能用上的领域模型

    关于「领域驱动设计」在前端的应用,断断续续都能看到一些博客,但大部分看完后不明觉厉,转眼就忘记了,最重要的原因是无...

  • “领域驱动设计”答疑(四)

    问题:代码如何和领域模型保持一致?C语言能清晰的表达领域模型吗? 第一个问题:代码和模型保持一致,需要掌握用编程语...

  • GROW模型(1)-及早发现“自嗨”,避免陷入低水平勤奋。

    今天介绍一个万能的模型,GROW模型,没错,就是grow,用好这个模型,你在各个领域都能如竹笋搬实现提升。 参考:...

  • 2018-09-25

    奇舞推荐 奇舞推荐 美菜无线前端架构模型 “防守姿态的前端驱动模型已经无法支撑一个前端人、一个前端团队在未来的生存...

  • DDD原则模式和实践 读书笔记 三

    领域模型实现模式 领域模型 领域模型是一个面向对象模型,它同时囊括了行为和数据。该模式基于没有数据库前提的。优点:...

  • 广告行业中那些趣事系列10:推荐系统中不得不说的DSSM双塔模型

    摘要:本篇主要介绍了项目中用于商业兴趣建模的DSSM双塔模型。作为推荐领域中大火的双塔模型,因为效果不错并且对工业...

  • 领域模型

    领域模型 领域模型是对领域内的概念类或现实世界中对象的可视化表示。又称概念模型、领域对象模型、分析对象模型。它专注...

  • 关于前端请求的那些事

    引言 前端是一个快速发展的领域,而在前端的技术栈当中,前端请求又是最见的一个领域,通过请求接口数据,才能将一个静态...

  • 前端工程化

    前端是一种技术问题较少、工程问题较多的软件开发领域,一切能提升前端开发效率、提高前端应用质量的手段和工具都是前端工...

  • GROW模型——很好用的自我教练工具

    在培训领域有很多耳熟能详的概念:SPIN、SMART、GRIT和GROW教练模型。 今天说说GROW教练模型|| ...

网友评论

      本文标题:一个前端项目中能用上的领域模型

      本文链接:https://www.haomeiwen.com/subject/yhgdeltx.html