OceaBase开发者大会落地上海!4月20日共同探索数据库前沿趋势!报名戳 了解详情
写点什么

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

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

关注

评论

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

2020年3月云主机性能评测报告

博睿数据

云计算 运维 机房 数据中心 主机

快速入门 Nacos 作为配置中心操作

zhuoqianmingyue

nacos SpringBoot 2

代码刚提交暂存区,组长突然要我把新增代码 Commit另一分支怎么办?

zhuoqianmingyue

git

玩转SpringBoot2.x之缓存对象

zhuoqianmingyue

redis springboot

使用Spring Boot和Docker构建微服务架构(三)

Tux Hu

Docker 架构 容器 微服务 Spring Boot

程序员的修行之路-关于编程语言

牧马人

程序员

爬虫框架Scrapy应用实践-淘宝保险频道数据抓取【1】-前期准备

hadesxiong

Python 爬虫 保险 Scrapy

卡巴斯基产品本地化用时能缩短 77%,怎么做到的?

葛仲君

项目管理 软件开发 本地化 开发流程

程序员的修行之路-保持良好的心态

牧马人

程序员

产品周刊 | 第 16 期(20200524)

Herbert

产品 设计 产品经理 产品设计

微信gif图片大小的规则

石云升

微信 GIF

使用Spring Boot和Docker构建微服务架构(四)

Tux Hu

Docker 架构 容器 微服务 Spring Boot

企业微信机器人在大型财务共享中心的应用实践

DT极客

后台定时统计任务太耗时如何优化一下

zhuoqianmingyue

线程池

微软:正式发布针对 .NET Core的 Winform 设计器

葡萄城技术团队

.net 微软 Win .net core

游戏夜读 | 世界两大游戏评论!

game1night

ARTS第一周

困到清醒

ARTS 打卡计划 起跑

Jsp页面报错后如何找到提示信息中的_jsp.java文件

阡陌r

Java | @Override 不要再把它当成可有可无的了

YoungZY

Java 注解 Override annotation

是什么在背后支撑起“带货一哥”李佳琦?

博睿数据

负载均衡 APM 压测 秒杀 并发

数据产品经理实战-DMP搭建

第519区

产品经理 营销

linux 账户及安全管理(一 账户管理)

牧马人

Linux

短视频时代下的知识摄取

Neco.W

学习 知识管理 知识体系 短视频

足不出户“逛”银行,37家城商行、农商行手机银行App性能大比拼

博睿数据

APM App 评测 网银 银行

使用Spring Boot和Docker构建微服务架构(二)

Tux Hu

Docker 架构 容器 微服务 Spring Boot

配置国内的pip源以提高使用pip安装python软件包的速度

良少

Python pip

zookeeper到nacos的迁移实践

捉虫大师

架构 nacos

使用Spring Boot和Docker构建微服务架构(一)

Tux Hu

Docker 架构 容器 微服务 Spring Boot

Spring Cloud 和 Dubbo 哪个会被淘汰?

程序猿DD

Spring Cloud dubbo

2020年3月北京BGP机房网络质量评测报告

博睿数据

运维 APM 机房 数据中心 拨测

程序员的修行之路-关于编程语言

牧马人

程序员

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