GMTC全球大前端技术大会聚焦前端、移动、AI应用等领域15个热门专题方向,购票立减¥960 了解详情
写点什么

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

2020 年 12 月 08 日

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:51616
用户头像

发布了 124 篇内容, 共 40.6 次阅读, 收获喜欢 219 次。

关注

评论

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

华为不能代表中国开源,请勿捧杀鸿蒙、方舟

小智

华为 开源 鸿蒙 方舟

我的内容创作方法论

小智

原创 内容 创作

2020,你怎么看?

池建强

2020 疫情 黑天鹅

看似努力,或许你是在浪费生命

泰稳@极客邦科技

学习 深度思考 读书笔记 高效工作

团队提拔人,要讲究先“实至“再”名归”

泰稳@极客邦科技

创业 团队管理 人力资源

世界很大,你不必抗下全部

泰稳@极客邦科技

创业 身心健康 生涯规划

我一个做内容的人,为啥要研究西贝?

郭蕾

极客时间

胡夕:阅读源码,逐渐成了职业进阶道路上的“必选项”

极客时间

kafka 极客时间 源码

Gary的唠叨(一):我们每个人都要提高自己的综合免疫力

郭蕾

Gary的唠叨 今日头条

徐明强博士亲述:如何像微软一样建设企业文化,渡过至暗时刻

TGO鲲鹏会

微软 TGO鲲鹏会 企业文化

苏宁云商向江旭:是时候让技术成为新司机了!

TGO鲲鹏会

刘超的创作故事:“趣谈网络协议”专栏是怎么生产出来的?

极客时间

吴咏炜:人生漫长,走点弯路在所难免

极客时间

学习 极客时间 编程

郭忆:数据中台,是陷阱?还是金钥匙?

极客时间

极客时间 数据中台

王天一:如何成为机器学习工程师?

极客时间

学习 极客时间

人啊,永远是得自己成全自己

郭蕾

读书笔记

比尔·盖茨:事了拂衣去

池建强

微软 慈善 比尔·盖茨

PingCAP CEO 刘奇:如何聚集精英技术人才

TGO鲲鹏会

巨头过处,寸草不生

池建强

创业 互联网巨头

那个忽悠了马云的“骗子”王坚,私下里是什么样的?

小智

云计算 阿里巴巴 阿里云

我看罗辑思维&得到简史

池建强

创业 产品 罗辑思维 得到

秦粤:说来说去,到底Serverless要解决什么问题?

极客时间

极客时间 Serverless

领导者应该承担一切责任,这才是领导力

郭蕾

读书笔记 团队管理 领导力

易宝支付 CTO 陈斌:如何做一个好的 CTO

TGO鲲鹏会

周爱民:捡豆吃豆的学问(上)

极客时间

Java 学习 极客时间

四火:聊一聊程序员学英语

极客时间

学习 极客时间

雷蓓蓓:“学习”到“实战”的距离,到底有多远?

极客时间

极客时间 项目管理

聊聊宿华:利他、活在当下、做大梦

郭蕾

周爱民:捡豆吃豆的学问(下)

极客时间

Java 学习 极客时间

裁缝铺里开始创业,340亿美元卖身IBM,红帽创始人的传奇故事

小智

开源 红帽

中年程序员都在想什么?

小智

程序员 中年 人生

大数据技术升级脉络及认知陷阱

大数据技术升级脉络及认知陷阱

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