領域驅動設計(DDD)【22】之限定建模技術

文章目錄

  • 一 限定初識
  • 二 限定識別
  • 三 限定實現

一 限定初識

  • 一個 員工 可以擁有多份 工作經驗,而各個 工作經驗時間段 不能相互重疊。可以得出一個推論:對于一個 員工 而言,每個 時間段 只能有一條 工作經驗
    在這里插入圖片描述

  • UML中第二種表述方式,如下圖:
    在這里插入圖片描述

  • 標有“: 時間段”的方框,叫做“限定符”(qualifier)。

  • 對于一個員工,任何一個時間段,要么沒有工作經驗,要么有一條工作經驗,但不能有多條工作經驗。換句話說,一個員工可以有多條工作經驗,但限定在一個時間段的話,那么最多就只能有一條工作經驗。

  • 限定機制起到兩個作用:第一,表達了更豐富的語義,把原來用注解說明的約束變成了更嚴格的符號;第二,簡化了關聯關系的多重性,把原來的一對多,在形式上,變成了一對一。

二 限定識別

在這里插入圖片描述

  • 在技能實體上,原來有一個“同一技能不能錄入兩次”的約束。現在由于增加對技能類別的限定,已經表達相同的意思。

  • 項目和項目成員之間的關聯,是否應該使用限定呢?
    在這里插入圖片描述
  • 雖然項目成員里面也有時間段屬性,但是項目和項目成員之間的關聯并沒有被時間段所限定。因為即使在同一個時間段,一個項目還是可以有多個成員。
  • 盡管項目經理和項目成員中都有時間段,但項目經理的關聯被時間段所限定了,而項目成員則沒有。現在的表示方法清楚地體現出了兩者之間的這種區別,而之前只能通過注釋中的文字來表達。

  • 項目成員“不必”用時間段來限定,而不是“不能”限定。這是因為,理論上其實也可以在項目一端加一個時間段限定。最終效果如下:
    在這里插入圖片描述

三 限定實現

  • 以工作經驗(work_experience)表和技能(skill)進行“限定”在數據庫里的實現。通過添加唯一索引,在工作經驗表上體現出時間段的限定,并且在技能表上體現出技能類別的限定。
    在這里插入圖片描述
// domain.orgmng.emp;
//imports ...
public class Emp extends AggregateRoot {// other fields ...// protected List<Skill> skills = new ArrayList<>();protected Map<Long, Skill> skills = new HashMap<>();// protected List<WorkExperience> experiences;protected Map<Period, WorkExperience> experiences = new HashMap<>();// other methods...public Collection<Skill> getSkills() {// return Collections.unmodifiableList(skills);return Collections.unmodifiableCollection(skills.values());}public Optional<Skill> getSkill(Long skillTypeId) {// return skills.stream()//         .filter(s -> s.getSkillTypeId().equals(skillTypeId))//         .findAny();return Optional.ofNullable(skills.get(skillTypeId));}public void addSkill(Long skillTypeId, SkillLevel level, int duration, Long userId) {skillTypeShouldNotDuplicated(skillTypeId);Skill newSkill = new Skill(tenantId, skillTypeId, userId).setLevel(level).setDuration(duration);//skills.add(newSkill);skills.put(skillTypeId, newSkill);}private void skillTypeShouldNotDuplicated(Long newSkillTypeId) {// if (skills.stream().anyMatch(//            s -> s.getSkillTypeId().equals(newSkillTypeId))) {if (skills.get(newSkillTypeId) != null) {throw new BusinessException("同一技能不能錄入兩次!");}}//    public List<WorkExperience> getExperiences() {//        return Collections.unmodifiableList(experiences);//    }public Collection<WorkExperience> getExperiences() {return Collections.unmodifiableCollection(experiences.values());}public void addExperience(Period period, String company, Long userId) {durationShouldNotOverlap(period);WorkExperience newExperience = new WorkExperience(tenantId, period, LocalDateTime.now(), userId).setCompany(company);//experiences.add(newExperience);experiences.put(period, newExperience);}private void durationShouldNotOverlap(Period newPeriod) {// if (experiences.stream().anyMatch(//                 e -> e.getPeriod().overlap(newPeriod))) {if (experiences.values().stream().anyMatch(e -> e.getPeriod().overlap(newPeriod))) {throw new BusinessException("工作經驗的時間段不能重疊!");}}// other methods...
}
  • 把Emp類的skills屬性的類型改成Map。Map的Key實際就是 技能類別ID,就保證了對 技能類別 所限定的唯一性。
  • getSkills() 方法,我們取了Map的 values(),并把方法的返回值類型改成了Collection。
  • getSkill(Long skillTypeId) 方法,我們直接從 Map 里取值,而不是像以前那樣通過遍歷 List 來搜索。
  • 當寫程序的時候,如果發現從 List 里搜索比較麻煩,可能就已經想到改成 Map 了。我們就可以“反推”出模型中很可能應該使用限定。這其實是在編寫代碼的過程中,以優化代碼結構為啟發,反過來促使模型演進的一個例子。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912208.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912208.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912208.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《P6492 [COCI 2010/2011 #6] STEP》

題目描述 給定一個長度為 n 的字符序列 a&#xff0c;初始時序列中全部都是字符 L。 有 q 次修改&#xff0c;每次給定一個 x&#xff0c;若 ax? 為 L&#xff0c;則將 ax? 修改成 R&#xff0c;否則將 ax? 修改成 L。 對于一個只含字符 L&#xff0c;R 的字符串 s&#…

macOS,切換 space 失效,向右切換space(move right a space) 失效

背景 準確來講&#xff0c;遇到的問題是向右切換space&#xff08;move right a space) 失效&#xff0c;并向左是成功的。 在鍵盤-快捷鍵-調度中心中&#xff0c;所有的快捷鍵均可用&#xff0c;但是“向右移動一個空間”總是失效。 已經檢查過不是快捷鍵沖突的問題&#x…

網飛貓官網入口 - 免費高清影視平臺,Netflix一站觀看

網飛貓是一個專注于提供豐富影視資源的在線平臺&#xff0c;涵蓋國內外熱門電影、電視劇、動漫、綜藝等多種類型。它不僅整合了Netflix的獨家內容&#xff0c;還提供了大量高清、藍光畫質的影視作品&#xff0c;支持多語言字幕&#xff0c;滿足不同用戶的觀影需求。網飛貓的界面…

Hyper-v-中的FnOs--飛牛Nas虛擬磁盤擴容(不清除數據)

在Hyper-v下的飛牛Nas要怎么在不刪除原有虛擬磁盤數據的情況下擴容呢 OK下面開始教學&#xff08;適用于Basic模式的虛擬磁盤擴容&#xff0c;Linear沒試過&#xff09; 先關閉飛牛Nas系統 找到飛牛Nas虛擬機&#xff0c;在設置下SCSI控制器找到要擴容的虛擬磁盤&#xff0c; 點…

掌握 MySQL 的基石:全面解讀數據類型及其影響

前言 上篇文章小編講述了關于MySQL表的DDL操作&#xff0c;在那里我多次使用了MySQL的數據類型&#xff0c;但是我并沒有去講述MySQL的數據類型&#xff0c;想必各位讀者已經很好奇MySQL的數據類型都有什么了&#xff0c;今天這篇文章我將會詳細的去講述MySQL的數據類型&#x…

buildadmin 如何制作自己的插件

官方文檔指引 提示&#xff1a;若不計劃發布到應用市場&#xff0c;可省略圖片等非必要功能 參考文檔&#xff1a;https://doc.buildadmin.com/senior/module/basicInfo.html 目錄 官方文檔指引開發說明模塊開發流程模塊包結構示例安裝開發工具 總結 開發說明 目標&#xff…

【數據標注師】關鍵點標注

目錄 一、 **關鍵點標注的四大核心原則**二、 **五階能力培養體系**? **階段1&#xff1a;基礎認知筑基&#xff08;1-2周&#xff09;**? **階段2&#xff1a;復雜場景處理技能? **階段3&#xff1a;三維空間標注&#xff08;進階&#xff09;**? **階段4&#xff1a;效率…

創建網站的基本步驟?如何建設自己的網站?

創建網站是一個系統化的過程&#xff0c;涵蓋規劃、設計、開發、測試和發布等多個階段。以下是詳細步驟及關鍵工具推薦&#xff1a; 一、規劃階段&#xff1a;明確目標與內容 定義目標 1、確定網站目的&#xff08;展示信息、銷售、博客、服務等&#xff09;。 2、分析目標…

FreeSWITCH配置文件解析(2) dialplan 撥號計劃中xml 的action解析

在 FreeSWITCH 的撥號計劃&#xff08;Dialplan&#xff09;中&#xff0c;使用 XML 配置。其中&#xff0c;<action> 標簽用于指定要執行的操作。這些操作通常是應用程序&#xff08;applications&#xff09;或設置變量等。下面列出常見的 <action> 類型及其含義…

MCPA2APPT:基于 A2A+MCP+ADK 的多智能體流式并發高質量 PPT 智能生成系統

&#x1f680; MCPA2APPT / MultiAgentPPT 集成 A2A MCP ADK 架構的智能化演示文稿生成系統&#xff0c;支持多智能體協作與流式并發&#xff0c;實時生成高質量 PPT 內容。 &#x1f9e0; 項目簡介 MultiAgentPPT&#xff08;又名 MCPA2APPT&#xff09;采用 A2A&#xff…

Maven 多模塊項目調試與問題排查總結

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

debian國內安裝docker

先升級apt和安裝依賴包 apt update apt upgrade apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates添加存儲庫的GPG密鑰&#xff08;阿里云&#xff09; curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg…

vue網頁中的一個天氣組件使用高德api

今天寫了一個天氣組件效果如下&#xff1a; 實現代碼如下&#xff1a; <template><div><span click"getLocation" style"cursor: pointer"><span style"color:white;">{{ weatherInfo.area }}</span></span&g…

5 手寫卷積函數

5 手寫卷積函數 背景介紹滑動窗口的方式代碼問題 矩陣乘法的方式原理代碼結果 效果對比對比代碼日志結果 一些思考 背景 從現在開始各種手寫篇章&#xff0c;先從最經典的卷積開始 介紹 對于卷積層的具體操作&#xff0c;我這里就不在具體說卷積具體是什么東西了。 對于手寫…

vue3+element-plus,實現兩個表格同步滾動

需求&#xff1a;現在需要兩個表格&#xff0c;為了方便對比左右的數據&#xff0c;需要其中一邊的表格滾動時&#xff0c;另一邊的表格也跟著一起滾動&#xff0c;并且保持滾動位置的一致性。具體如下圖所示。 實現步驟&#xff1a; 確保兩個表格的寬度一致&#xff1a;如果兩…

Mysql架構

思考&#xff1a;Mysql需要重點學習什么&#xff1a; 索引&#xff1a;索引存儲結構、索引優化......事務&#xff1a;鎖機制與隔離級別、日志、集群架構 本文是對Mysql架構進行初步學習 1、Mysql鏈接 Mysql監聽器是長連接 BIO(阻塞同步IO調用)&#xff0c; 不是NIO. 為什么…

使用deepseek制作“喝什么奶茶”隨機抽簽小網頁

教程很簡單&#xff0c;如下操作 1. 新建文本文檔&#xff0c;命名為奶茶.txt 2. 打開deepseek&#xff0c;發送下面這段提示詞&#xff1a;用html5幫我生成一個喝什么奶茶的網頁&#xff0c;點擊按鈕隨機生成奶茶品牌等&#xff0c;包括喜茶等眾多常見的奶茶品牌如果不滿意還…

WOE值:風險建模中的“證據權重”量化術——從似然比理論到FICO評分卡實踐

WOE值&#xff08;Weight of Evidence&#xff0c;證據權重&#xff09; 是信用評分和風險建模中用于量化特征分箱對目標變量的預測能力的核心指標。 本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關…

js遞歸性能優化

JavaScript 遞歸性能優化 遞歸是編程中強大的技術&#xff0c;但在 JavaScript 中如果不注意優化可能會導致性能問題甚至棧溢出。以下是幾種優化遞歸性能的方法&#xff1a; 1. 尾調用優化 (Tail Call Optimization, TCO) ES6 引入了尾調用優化&#xff0c;但只在嚴格模式下…

vue界面增加自定義水印 js

vue整個界面增加自定義水印 需求&#xff1a;領導想要增加自定義水印 好不容易調完&#xff0c;還是想記錄一下,在.vue界面編寫 export default {mounted() {this.$nextTick(() > {this.addWatermark()})},methods: {// 關鍵&#xff1a;添加水印// 動態添加水印addWaterm…