写点什么

Nuxt Apps 中的领域驱动设计实践

  • 2020-12-08
  • 本文字数:2479 字

    阅读完需:约 8 分钟

Nuxt Apps中的领域驱动设计实践

我在Vue StorefrontVue Storefront Next中实验 Vue apps 的领域驱动方法有一段时间了。使用这种方法能显著改善你的代码库的可维护性和复杂度。在这个系列,我想分享一些在 Vue Storefront 中对我们有效,且容易应用到任何 Vue 应用程序中的模式。


我将展示如何在 Nuxt 和“普通”Vue 项目中如何应用这些模式。本文中,我们将聚焦理论和 Nuxt 实现。


什么是领域驱动设计?


领域驱动设计(Domain-Driven Design,DDD)概念是,将业务概念优先于代码库的其它分类类型(例如,按文件类型分组)。这意味着,你应该基于你主要的业务领域(“问题”)及其子领域(问题的细分部分)来组织你的代码。例如,在电子商务领域,我们有产品目录、客户、订单、库存等子领域。


虽然 DDD 概念来自面向对象编程,依赖于类及其关系,但其核心理念可以很容易地应用到其它范式。


为什么领域驱动设计很棒?


领域驱动设计越来越受欢迎最简单的解释是,它是一种非常简单的模式,在大多数情况下,它都会在编程最困难和最痛苦的领域之一——代码维护性上带来显著改善。


我记得,我在思考组织代码库的最佳方式时度过的无眠之夜和漫长的淋浴。如果你曾经尝试过,你就会明白这项任务非常困难,而且结果永远不会完美,因为你必须考虑到你的项目在将来可能演变的所有可能的方式。随着时间的推移,我们对试图解决问题的理解不断增长,这会带来更有效的解决问题的方法,从而改变我们最初的方案。


我们都经历过并且知道,改变最初的架构会付出多大的成本。


这就是领域驱动设计的亮点。基于业务需求对系统进行建模要容易得多,因为这个方案不受技术限制和困难的影响。我们改变核心业务需求的频率比改变底层技术的频率要少得多。


此外,领域驱动设计推崇在编写代码时考虑实际的业务需求,这意味着我们根据业务功能(例如客户)而不是技术术语(组件、存储、服务),来组织我们的代码和文件结构。这种管理代码的方式让代码更容易维护。


下图显示了一个“标准的”Vue 文件结构 vs 基于业务领域的文件结构:




如果与某个功能相关的所有东西都放在一个地方,就会很容易理解它是如何工作的,因为不存在忽略某些部分的风险。完全删除某个功能也同样非常简单,因为这个功能相关的代码不会分布在整个代码库中。


另一个好处是,我们只需查看应用程序的文件夹结构,就能很容易地推断出其业务和功能。这也很容易找到一个开始上手的地方,因为我们的任务大部分时候是用业务语言编写的。我能够给出很多其它例子,但是我确信你已经明白为什么这个方案现在被认为是更容易维护的了。


领域驱动设计和根据功能组织代码的最大好处之一,就是限制了不同模块之间的关联数量。通常,我们在应用程序中有一组扩展点被所有模块使用。理想情况下,所有的连接都应该通过一个单独的地方进行,例如一个共享模块或事件总线。使用这种方法更容易维护这些模块,因为连接不同功能的部分通常是导致应用程序复杂性增加最多的地方。如果我们设法避免不必要的复杂性并简化连接,那么让你的代码库保持简单也就非常容易了。


弄清楚如何使你的模块独立并封装,是另外一篇文章(或者是一系列文章)的主题,因此现在如果你想要深入了解这一点,我建议你阅读hexagonal architecture,并应用这种方法中的大部分有用的理念。


那么,我们该如何在 Vue 中应用领域驱动设计理念呢?


Nuxt 中的领域驱动设计


我们从 Nuxt 开始介绍,它有了一个很好的内置机制,使得应用这个理念非常容易——模块。


Nuxt 模块通常用于在你的应用程序中包含第三方功能,例如授权或 i18n。虽然编写第三方代码是最常用的利用它们的方法,但是 Nuxt 模块也可以很好地在我们的内部架构中发挥作用。


因为 Nuxt 模块可以挂接到应用程序的不同部分,例如路由或 Vuex store,所以我们能很容易地使它成为一个特定子领域与我们的应用程序连接的唯一地方!


看看这个简单的 Nuxt 模块:

// index.jsmodule.exports = function ProductCatalogModule (moduleOptions) {  this.extendRoutes((routes) => {    routes.unshift({      name: 'product',      path: '/p/:slug/',      component: path.resolve(themeDir, 'pages/Product.vue')    });  );  // we can't register stores through Nuxt modules so we have to make a plugin  this.addPlugin(path.resolve(__dirname, 'plugins/add-stores.js'))}
复制代码


// plugins/add-stores.jsimport CategoryStore from '../stores/category.js'import ProductStore from '../stores/product.js'
export default async ({ store }) => { store.registerModule(CategoryStore) store.registerModule(ProductStore)};
复制代码


…有如下文件:


.├── pages|   |── Category.vue │   └── Product.vue├── components|   |── ProductTile.vue│   └── ProductGallery.vue├── plugins│   └── add-stores.js├── store|   |── category.js│   └── product.js└── index.js
复制代码

我们这里就是一个小的 Nuxt.js 应用程序,专注于我们的应用程序的某一个子领域。现在,当我们想要在应用程序中包含所有目录相关的功能时,我们只需要一行代码就可以做到这一点!


// nuxt.config.jsexport default {  modules: [    '~/modules/product-catalog/index.js',  ]}
复制代码


现在,每当我们在 Jira 中看到产品目录相关的问题时,我们就会立即知道从哪里开始改。而且,使用这种模块化方案,新来的人也能很快知道我们应用程序中有什么功能,因此可以更快地理解业务和技术背景!


.├── pages│   └── index.vue├── modules|   |── product-catalog|   |── orders|   |── payment|   |── shipping|   |── inventory│   └── customers└── index.js
复制代码


总结与展望


基于业务领域及其子领域来组织代码,是使应用程序更易于维护的最简单有效的方法之一。尽管还有一些已知的挑战,例如不同模块之间的通信,了解基础知识就足以为代码库带来巨大的好处。应用本文中的模式不需要高级编程技巧,这让所有层次的开发人员都可以使用它。


原文链接:


https://vueschool.io/articles/vuejs-tutorials/domain-driven-design-in-nuxt-apps/

2020-12-08 14:511710
用户头像

发布了 165 篇内容, 共 77.8 次阅读, 收获喜欢 343 次。

关注

评论

发布
暂无评论
发现更多内容

挖矿探索一:狗狗币-mac普通电脑

程序员架构进阶

比特币 区块链 28天写作 5月日更

架构实战营 - 模块三总结

凯迪

架构实战营

服务器又被挖矿了,怎么防?

运维研习社

挖矿 5月日更 Linux安全

架构实战营 模块三课后作业

iProcess

架构实战营

第三课作业

杰语

架构训练营模块3作业《消息队列架构设计文档》-江哲

江哲

applet跨域访问安全性问题(java.security.AccessControlException:access denied)

xcbeyond

跨域 5月日更 疑难杂症

架构师实战营 模块三作业(基于自研集群 + MySQL 存储的消息队列系统架构设计文档)

好吃不贵

业务架构

架构实战训练营 - 模块三课后作业

Johnny

架构实战营

架构实战营 模块三:学习总结

👈

架构实战营

一文看懂 Go 的数据类型

Rayjun

Go 语言

ARTS - week 8 补打卡

steve_lee

架构实战营 - 模块三作业

凯迪

GreenPlum的CURD

数据社

greenplum 5月日更

架构训练营——模块2作业

圆心角

MySQL索引原理浅析

逸少

MySQL 索引结构 索引

自研集群 + MySQL 存储详细架构文档

@oo?金樱子

初识Golang之err概述

Kylin

Go 语言 5月日更

作业三架构设计文档

大肚皮狒狒

优秀程序员都在注意的十个点

好好学习,天天向上

Java 设计模式 代码 技巧

消息队列详细设计架构文档

Hesher

架构 MQ Architecture 消息队列 架构实战营

前端百题斩[001]——typeof和instanceof

执鸢者

面试 大前端

霸气!这份清华学霸整理的Java线程池笔记,2小时从入门到入坟

飞飞JAva

Java

消息中间件详细架构设计文档

白发青年

架构实战营

【LeetCode】制作 m 束花所需的最少天数Java题解

Albert

算法 LeetCode 5月日更

模块三作业 - 消息队列系统架构设计文档

青鸟飞鱼

架构实战营

架构实战营模块三作业

冷大大

作业 架构实战营 模块三

假如只剩下canvas标签

执鸢者

大前端 canvas

自研集群+MySQL架构设计文档模板

9527

架构实战营

架构实战营-模块3-作业

笑春风

模块3作业 3

杨彬

#架构实战营

Nuxt Apps中的领域驱动设计实践_文化 & 方法_Filip Rakowski_InfoQ精选文章