主頁 > 軟體設計 > 淺談DDD(domain-driven design-領域驅動設計)

淺談DDD(domain-driven design-領域驅動設計)

2021-01-15 12:15:23 軟體設計

原文地址: https://juejin.im/post/6845166891670093838

劃了半年,現在開始接客!

?本篇文章存在大量干貨,建議調整姿勢反復觀看,所有技術堆疊通用,本文以vue專案為例?

「好代碼一定是設計出來的!而不是用多么牛逼的技術堆疊」

DDD

注意這不是大笑表情包,DDD(domain-driven design-領域驅動設計),大部分前端接到需求的時候都在思考這個原型我要怎么實作某塊功能細節(用哪個UI庫、該怎么寫),即使不了解業務也一樣可以開發,通常也能完成作業,這種情況稱為 ——「面向功能編程(沒有思考的前端資源)」

然而,隨著業務的深入、需求不斷地迭代和變更,我們(前端)仿佛在負重前行,為什么?

  • 業務不熟悉,不知道為什么要改需求,也不知道修改需求影響了原來哪塊代碼
  • 歷史包袱多,投入相較后端越來越重

領域怎么劃分?

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1030" height="284"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1030" height="284"></svg>)

差不多就是這樣抽象(就硬劃),建議和后端同學進行 「深入♂♂探討」(抽象能力個人認為需要學習思考+后天培養,也不能指望文章)

?我認為應該在了解產品(或行業領域)的前提下進行軟體開發,先根據專案抽象出業務邊界模塊,建立領域再動手開發,?

沙箱

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="570" height="374"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="570" height="374"></svg>)

?哎呀,你這個代碼怎么引數亂七八糟,方法全依賴在一起我都不敢改啊,怎么一個js有9000行?

我們先來康康什么是沙箱(sandbox),安全獨立的,隔離外界的,互不影響的環境結構,

看起來好像沒什么,我們再看看設計模式應該準許你的準則,

  • 單一原責
  • 迪米特(最少知識)原則
  • 開放封閉原則
  • 依賴倒置
  • 介面隔離
  • 里式替換

是不是覺得DDD和設計原則、沙箱環境都有相同想強調的地方?

好像又繞回來了,嘮了半天,盡和我搞文縐縐的文字游戲,是你需要30萬還是想爬山🧗了?

不是這樣的,如果

「「希望洗掉和新增一塊代碼(領域),并不影響原有代碼,并且不需要改動也不會報錯,怎么做?」」

接下來教大家如何運用在你的前端工程中,

結構

普通工程的目錄結構

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="552" height="490"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="552" height="490"></svg>)

很傳統的目錄結構,包括vue-cli3也是這么做的,按照功能職責劃分,想修改路由前往routes檔案夾里修改,修改vuex去store里找,

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500"></svg>)

按DDD劃分的目錄結構(非戰斗人員請迅速撤離)

ps: 這里的領域檔案夾名不大對,當作錯誤示范將就看了

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="588" height="658"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="588" height="658"></svg>)

貼一份新目錄結構的說明

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="876" height="816"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="876" height="816"></svg>)

優點

為什么要這樣做?

職責

假設一個專案多人開發,拆分需求一定是按照某塊業務功能劃分的(分配作業),這就是我們在無意識中利用DDD的思想拆分產品業務,

  • 清晰定位了每個同事的作業職責和邊界
  • 出現問題方便定位到問題的范圍
  • 減少代碼的沖突

效能

  • 維護成本低
  • 可復用某塊業務領域
  • 可拓展(在統一的模式下做自動化、基建等)

缺點

  • 代碼風格和編程思路的轉換
  • 老專案的兼容 (在歷史債上轉換)

領域內職責&細節

?因害怕篇幅過長(懶),所以本文使用了大量偽代碼(意識流裝逼)?

資料訪問物件 DAO (Data Access Object)

 static async getXxxList(api, payload) {
    const res = await api(payload);
    const { results, totalCount } = res.data.data;
    return { data: results, total: totalCount };
  }
復制代碼

沒什么好說的,處理領域內的介面,api 介面都放在這里,如果要處理資料建議也在這里完成,做到視圖與資料分離,不要在view里再做資料的封裝,

如果處理非常復雜建議再分層DTO(Data Transfer Object),把邏輯放在這里面,

?當你發現有介面重復的時候建議復寫,一般不會超過3個如果超過了思考是否領域拆分有問題?

引數/列舉 Model

里面一般有倆個檔案夾:

列舉 Enums

一些selecet的內容

[
  ["發布成功", 1],
  ["未發布", 2],
  ["等待中", 3],
  ["發布失敗", 4]
  ....
]
復制代碼

對應表物件 Vo

放一些對應表結構的資料,包括需要默認的內容、引數

{
  // 團隊 Number  teamId = null;

  // 應用 String  appName = null;

  // 申請人 Enums(Role)  role = 1;

  // 開始時間 dateStr  beginTime = null;

  // 結束時間 dateStr  endTime = null;
}
復制代碼

路由 Router

注意,通常我們都是寫在最外層一個統一的router檔案夾來注冊匯總,

「但是在領域里需要自己的路由,根據領域的實作和業務邏輯來規劃細分路由,」

視圖 View

類似路由的理念,可以在同一領域下拆分為多個視圖,畢竟有些龐大的業務需要很多頁面才能支撐起來他的流轉,

中臺系統的某個領域內可能需要2-3套crud才能支撐起來,那其中的View檔案夾下可能就要放2-3套對應的crud檔案夾,檔案夾內部才是視圖的結構(搜索表單、表格、詳情等按需細分),

Vuex

正常用法,領域內不同單元之間需要流通資料可用,不建議跨領域使用

領域注冊 Main.js

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1280" height="641"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1280" height="641"></svg>)

這里考慮到每個領域需要賦予的能力都不一樣,所以需要針對單個領域模塊提供可選松耦合的能力,

有點發布訂閱模式內味了,注冊了什么東東?先上一段神奇的代碼

import routes from "./router";
export { routes };

// 領域模塊名稱const MODULE_NAME = "Doctor";

// 注冊模塊能力export default ({
  registerRouter,
  registerStore,
  registerApi,
  .......
}) => {
 // 使用模塊能力  registerRouter(MODULE_NAME, routes);
  registerStore(MODULE_NAME, store);
};

復制代碼

看到了很多register開頭的引數這些是自定義的能力,從能力中心拿出注冊,

「能力分析」

能力的訂(相當于注冊能力的名單封裝),在最后會用到這里

  • registerRouter 把路由注冊到Doctor模塊下
 Doctor: {
    path: "/doctor/",
    name: "doctor",
    redirect: "/doctor/goodDoctor",
    component: () => import(/* webpackChunkName: "goodDoctor" */ "../view/Main"),
    children: [
      {
        path: "/doctor/goodDoctor",
        name: "goodDoctor",
        component: () =>
          import(/* webpackChunkName: "goodDoctor" */ "../view/goodDoctor/Index")
      },
      {
        path: "/doctor/badDoctor",
        name: "badDoctor",
        component: () =>
          import(/* webpackChunkName: "badDoctor" */ "../view/badDoctor/Index")
      },
    ]
  }
復制代碼
  • registerStore 把doctor的store注冊到vuex里
 Doctor: {
    goodDoctor:{
        namespaced: true,
        state,
        getters,
        mutations,
        actions
    },
    badDoctor:{
        namespaced: true,
        state,
        getters,
        mutations,
        actions
    }
 }
復制代碼

還有很多就不細說了

「擴展」

  • 針對單個領域的埋點
  • 針對單個領域的性能監控
  • 針對單個領域的錯誤監控

還有很多遐想(瞎想)空間......

中心化-領域匯總 Module.js

問:整了那么多領域,怎么讓他實體化把專案跑起來?

答:將領域匯總掛載到vue上

// 獲取src下的領域import 領域1 from "@/領域1/main";
import 領域2 from "@/領域2/main";
——————————————————————————————————————
/*
也可以用
require.context('@', false, /\\main.js/)
匹配所有src下領域內的main檔案注冊
*/

const modules = [領域1,領域2,領域3....];
new Center(modules).mount("#app");
復制代碼

這個中心函式Center到底做了什么了什么?

import Vue from "vue";
import App from "../App";

class Center {
  constructor(modules) {
  
    // modulesCenter做了層遍歷,注冊的所有內容放進函式以便獲取    modulesCenter(modules);

    Center.store = this.store = modulesCenter.createStore();
    Center.router = this.router = modulesCenter.createRouter();
    Center.vue = this.vue = new Vue({
      store: this.store,
      router: this.router,
      render: h => h(App)
    });
  }

  mount(mountEl) {
    this.vue.$mount(mountEl);
    return (Center.currentCenter = this);
  }
}

export default Center;
復制代碼

大致做了什么,估計你們也猜到了

  • createRouter
 const router = new VueRouter({
    mode: "history",
    ...modules.router
 });
復制代碼
  • createStore
 const store = new Vuex.Store({
    ...modules.store
 });
復制代碼

共享領域資料

說白了就是跨領域呼叫,其實都在本地了,代碼和呼叫vuex modules是一毛一樣的

computed: {
    //都在 Doctor 內    ...mapAction('Doctor',[
      '/goodDoctor',
      '/badDoctor',
    ])
}
復制代碼

將來的composition Api 可能會更加輕哦,

?當然是不建議有耦合資料的,如果出現跨領域了依賴,說明拆分有問題,反推后端這里是否可以進行改變,防患于未然,面向未來的需求提前編程,?

基本能力講完了是不是覺得這么做的意義和消耗的時間不成正比? 讓我們把能利再升華一下,看看如何擴展成架構反哺業務......

[data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="400"></svg>](data:image/svg+xml;utf8,<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="400"></svg>)

擴展基建中臺

  • 代碼統一規范
  • 領域代碼復用(也能跨專案)
  • 提升效能,結合webpack5+vite可以只coding個別領域
  • 搭建微前端體系前的技術籌備統一

領域gui化

https://user-gold-cdn.xitu.io/2020/7/2/1730fb84f701ebd5?imageView2/0/w/1280/h/960/format/webp/ignore-error/1

使用某個領域

直接拖拽,low code或者微服務都可以,不限于輸出形式

https://user-gold-cdn.xitu.io/2020/7/2/1730fb4213072566?imageView2/0/w/1280/h/960/format/webp/ignore-error/1

配套設施

需要管理后臺進行收集與輸出,其它配套設施一大堆就不過多描述了

總結(人話時間)

  1. 思考業務
  2. 可插拔
  3. 提效

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/249053.html

標籤:其他

上一篇:Go常見并發模式

下一篇:java 支付寶支付

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more