日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【渐进】浅尝DDD,对试卷建模

發(fā)布時間:2024/8/22 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【渐进】浅尝DDD,对试卷建模 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

????? 領(lǐng)域模型是OO分析中最重要的和經(jīng)典的模型。領(lǐng)域驅(qū)動設(shè)計(DDD)則是有效的軟件復(fù)雜性的應(yīng)對之道。

??? 領(lǐng)域模型其實是一種語言,領(lǐng)域?qū)<遗c分析人員、開發(fā)人員之間交流的通用語言。?一開始,分析人員與領(lǐng)域?qū)<倚枰獙@個通用語言達成一致,雙方能熟練的運用領(lǐng)域模型描述問題,表達、分析、處理問題。
??? 1. 領(lǐng)域模型不是圖,圖只是讓核心、關(guān)鍵的概念清晰的呈現(xiàn)出來。圖的表達能力有限,模型必須配備描述(需求采集會議中的口頭描述,或文檔中的文字描述),將圖形所代表的意義,以及圖形中沒有呈現(xiàn)出來的規(guī)則、斷言、細節(jié)進行補充,才能完整地表述需求。
??? 2. 領(lǐng)域模型的UML或者類UML圖不能太細太完整,否則過于龐大的模型會干擾人的思維,阻礙對主要部分,或者復(fù)雜邏輯的梳理。業(yè)務(wù)總是被切分成一個個片斷進行分析,在每一個片斷里,畫出幾個主要的對象和交互邏輯,細節(jié)的部分用文字記錄、描述。
??? 3. 領(lǐng)域模型中不應(yīng)當(dāng)出現(xiàn)設(shè)計、技術(shù)方面的術(shù)語,也不應(yīng)當(dāng)出現(xiàn)開發(fā)人員不理解的業(yè)務(wù)術(shù)語。

????? 關(guān)于領(lǐng)域模型表達方法(UML圖Visio圖)的選擇問題,標(biāo)準(zhǔn)的形式是使用UML,但如果領(lǐng)域?qū)<一蜷_發(fā)人員根本無法對UML圖例形成清晰的概念(將UML圖映射到領(lǐng)域?qū)ο蟆⑦壿?#xff0c;或代碼實現(xiàn)),將注定DDD方式應(yīng)用失敗。因為沒有掌握語言就無法使用它正確交流。第三節(jié)中強調(diào)建模人員要直接與開發(fā)過程接觸,重要的一個作用是確認開發(fā)人員對領(lǐng)域模型這個語言是否正確理解,確保代碼實現(xiàn)保持了建模者要表達的意圖。因此DDD的一個關(guān)鍵思想是建模人員自始至終維護領(lǐng)域模型這個語言,以及它表達的內(nèi)容,向團隊的各個角色(領(lǐng)域?qū)<摇㈤_發(fā)人員等)詮釋各個建模元素的含義,讓各個角色掌握這個語言,運用它來表達、實現(xiàn)實際需求。這是分析人員最關(guān)鍵的職責(zé),貫穿整個過程。

????? 領(lǐng)域邏輯的表達不要受UML圖的約束,否則可能是問題所在,適當(dāng)?shù)拿枋鼍涂梢院芎玫慕鉀Q這個問題。

????? 關(guān)于DDD和UML相關(guān)的具體介紹可參考:

??? 《UML和模式應(yīng)用》(第三版)

??? 《.NET.Domain.Driven.Design.with.C.Sharp》

????? 從領(lǐng)域問題,場景中分析找出概念類,確定一組概念類則是OO分析的核心。以下就“試卷”這個領(lǐng)域來進行DDD的分析和設(shè)計嘗試。

  • 場景描述

????? 試卷由多個大題組成,每個大題下有多道試題,試卷還可以有多個分卷,如分卷I,分卷II,可以統(tǒng)計大題下的試題信息…

  • 概念類提取

????? 從上述描述提取出概念類:試卷,分卷,大題,試題。

  • UML概念類表達

  • 幾個設(shè)計方案

???? 方案一:按級聯(lián)關(guān)系相應(yīng)設(shè)計試卷結(jié)構(gòu),形成試卷->分卷->大題->試題的結(jié)構(gòu)。

???? 方案二:將試卷的分卷,大題,試題都認為是試卷分塊,試卷成為一個試卷分塊的線性列表。

???? 方案三:將試卷的分卷,大題等歸屬于結(jié)構(gòu)相關(guān)信息,對試卷抽象出試題列表和試卷結(jié)構(gòu),

  • 方案比較(略)

???? 方案一完全依賴場景描述設(shè)計層級結(jié)構(gòu),固化了試卷結(jié)構(gòu),方案二,三的設(shè)計思路都是將試題列表設(shè)計為線性,屏蔽業(yè)務(wù)和呈現(xiàn)需求的差異。

  • 最終方案

???? 試卷(Paper)主要由試卷結(jié)構(gòu)(PaperStruct)和試題列表(PaperQuestionList)構(gòu)成,試卷結(jié)構(gòu)包含試卷分塊列表,試卷分塊用于表示試卷中的大題概念。

???? 試題列表是為此場景而特化設(shè)計的集合,僅僅是對試卷分塊(PaperPart)中試題列表的邏輯映射,僅公開部分集合相關(guān)操作。

???? 試卷分塊主要包含試題索引范圍(QuestionIndexRang)和 分塊試題列表(QuestionList)的定義以及相關(guān)統(tǒng)計屬性。

???? 最終方案的優(yōu)勢:即保證了結(jié)構(gòu)和業(yè)務(wù)的剝離,又使得呈現(xiàn)可以以直觀的層級進行。

  • UML詳細設(shè)計模型

  • 基本代碼成型

???? 試卷:

  • ??/// <summary>
  • ??/// 試卷
  • ??/// </summary>
  • ??public class Paper : ICloneable
  • ??{
  • ??????private int _paperId;
  • ??????/// <summary>
  • ??????/// 獲取試卷標(biāo)識
  • ??????/// </summary>
  • ??????public int PaperId { get { return this._paperId; } }
  • ??????/// <summary>
  • ??????/// 獲取或設(shè)置試卷結(jié)構(gòu)
  • ??????/// </summary>
  • ??????public PaperStruct PaperStruct { get; set; }
  • ??????/// <summary>
  • ??????/// 獲取試卷分塊列表
  • ??????/// </summary>
  • ??????public PaperPartList PaperPartList
  • ??????{
  • ??????????get { return this.PaperStruct.PaperPartList; }
  • ??????}
  • ??????/// <summary>
  • ??????/// 獲取試卷試題列表
  • ??????/// </summary>
  • ??????public PaperQuestionList QuestionList
  • ??????{
  • ??????????get { return PaperQuestionList.Create(this); }
  • ??????}
  • ??????/// <summary>
  • ??????/// 清理試卷內(nèi)部結(jié)構(gòu)
  • ??????/// </summary>
  • ??????public void Clear()
  • ??????{
  • ??????????//重設(shè)分塊的試題索引
  • ??????????//重設(shè)試題列表索引
  • ??????}
  • ?
  • ??????#region ICloneable 成員
  • ??????/// <summary>
  • ??????/// 返回一份當(dāng)前試卷的副本
  • ??????/// 副本將完成可靠的拷貝邏輯
  • ??????/// </summary>
  • ??????/// <returns></returns>
  • ??????public object Clone()
  • ??????{
  • ??????????Paper clone = this.MemberwiseClone() as Paper;
  • ?
  • ??????????//引用處理
  • ??????????//...
  • ?
  • ??????????//標(biāo)識置0
  • ??????????clone._paperId = 0;
  • ?
  • ??????????//拷貝引用
  • ?
  • ??????????return clone;
  • ??????}
  • ??????#endregion
  • ?
  • ?
  • ??}
  • ?

    ??? 試卷分塊:分塊將維持試題索引范圍

  • /// <summary>
  • /// 試卷分塊
  • /// </summary>
  • public class PaperPart : ICloneable
  • {
  • ????//構(gòu)?
  • ?
  • ????public PaperPart()
  • ????{
  • ????????this.QuestionRang = new QuestionIndexRang(-1, -1);
  • ????????this.QuestionList = new List<QuestionInfo>();
  • ????}
  • ?
  • ????/// <summary>
  • ????/// ?取或?置分塊下的??索引?圍 ?不存在??則索引??為-1
  • ????/// </summary>
  • ????public QuestionIndexRang QuestionRang { get; set; }
  • ????/// <summary>
  • ????/// ?取或?置?分塊下的??列?
  • ????/// </summary>
  • ????public List<QuestionInfo> QuestionList { get; set; }
  • ?
  • ????#region ICloneable 成員
  • ?
  • ????public object Clone()
  • ????{
  • ????????PaperPart clone = this.MemberwiseClone() as PaperPart;
  • ?
  • ????????//處理引用
  • ?
  • ????????return clone;
  • ????}
  • ?
  • ????#endregion
  • }
  • ?

    ??? 試卷試題列表:此設(shè)計用于映射分塊中的試題,并控制對其的調(diào)用,使得對它的相關(guān)操作能映射至實際的試題。

  • /// <summary>
  • /// 試卷的試題列表
  • /// </summary>
  • public class PaperQuestionList : CustomList<QuestionInfo>
  • {
  • ????/// <summary>
  • ????/// 所在的?卷
  • ????/// </summary>
  • ????public Paper Paper { get; private set; }
  • ????/// <summary>
  • ????/// 初始化
  • ????/// </summary>
  • ????/// <param name="paper"></param>
  • ????private PaperQuestionList(Paper paper)
  • ????????: base()
  • ????{
  • ????????this.Paper = paper;
  • ????}
  • ????/// <summary>
  • ????/// 生成試卷的試題列表
  • ????/// </summary>
  • ????public static PaperQuestionList Create(Paper paper)
  • ????{
  • ????????PaperQuestionList list = new PaperQuestionList(paper);
  • ?
  • ????????//拼接
  • ????????list.Paper.PaperPartList.ForEach(o => { list._list.AddRange(o.QuestionList as IEnumerable<QuestionInfo>); });
  • ?
  • ????????return list;
  • ????}
  • ????/// <summary>
  • ????/// 重載索引器
  • ????/// </summary>
  • ????/// <param name="index"></param>
  • ????/// <returns></returns>
  • ????public override QuestionInfo this[int index]
  • ????{
  • ????????get
  • ????????{
  • ????????????return base[index];
  • ????????}
  • ????????set
  • ????????{
  • ????????????bool flag = false;
  • ????????????int count = 0;
  • ????????????for (int i = 0; i < this.Paper.PaperPartList.Count; i++)
  • ????????????{
  • ????????????????if (flag) break;
  • ?
  • ????????????????for (int j = 0; j < this.Paper.PaperPartList[i].QuestionList.Count; j++)
  • ????????????????{
  • ????????????????????if (count == index)
  • ????????????????????{???
  • ????????????????????????//修正實際引用
  • ????????????????????????this.Paper.PaperPartList[i].QuestionList[j] = value;
  • ????????????????????????flag = true;
  • ????????????????????????break;
  • ????????????????????}
  • ????????????????????count++;
  • ????????????????}
  • ????????????}
  • ????????????base[index] = value;
  • ????????}
  • ????}
  • }
  • ?

    • 更多考慮

    ???? 對于模型的接口和屬性暴露:本文所提及的設(shè)計并非采用貧血模型,模型內(nèi)部需維持主要邏輯,對于對外接口和屬性應(yīng)慎重,如對于引用類型的屬性,應(yīng)考慮使用者有可能并不總是按照設(shè)計者的預(yù)期來使用,因此最小化設(shè)計原則和按需暴露接口,或者返回接口而非真實引用尤為必要。

    ???? 領(lǐng)域模型并非為傳輸而設(shè)計,若希望模型同時能夠支持跨層傳輸和序列化,則需額外注意相關(guān)屬性和字段的設(shè)計和暴露。

    ???? DDD是從業(yè)務(wù)出發(fā),關(guān)注業(yè)務(wù),以業(yè)務(wù)價值為導(dǎo)向的設(shè)計方法,測試和業(yè)務(wù)的實現(xiàn)均是由它出發(fā),以對象而不是關(guān)系數(shù)據(jù)庫作為模型基礎(chǔ),而對于存儲則不是業(yè)務(wù)人員需要過多關(guān)心,通常web開發(fā)者習(xí)慣了數(shù)據(jù)驅(qū)動設(shè)計,總是希望實體和數(shù)據(jù)庫一一映射,那么您恐怕需要換個思路思考了,因而一個強有力的ORM框架支持也是DDD的執(zhí)行的保證。

    ?

    ???? 篇后語:學(xué)習(xí)和實踐中,請多多指正。歡迎拍磚。

    轉(zhuǎn)載于:https://www.cnblogs.com/wsky/archive/2009/10/27/1590873.html

    總結(jié)

    以上是生活随笔為你收集整理的【渐进】浅尝DDD,对试卷建模的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。