【軟體工程底層邏輯系列】建模的底層邏輯

来源:https://www.cnblogs.com/88223100/archive/2022/12/28/Software-Engineering-Bottom-Logic-Series_The-bottom-logic-of-modeling.html
-Advertisement-
Play Games

建模對於大家來講並不陌生,而且建模的方法也有很多,如用例建模、四色建模、事件風暴等,但在日常工作中,大家又覺得建模挺虛的:怎麼把建模落到實際開發工作中。個人認為建模是分兩部分:第一部分是業務概念建模,對現實業務抽取核心概念構建出模型(知識層);第二部分是系統建模,系統建模是源於業務概念模型,遵循某些... ...


 

 

建模對於大家來講並不陌生,而且建模的方法也有很多,如用例建模、四色建模、事件風暴等,但在日常工作中,大家又覺得建模挺虛的:怎麼把建模落到實際開發工作中。個人認為建模是分兩部分:第一部分是業務概念建模,對現實業務抽取核心概念構建出模型(知識層);第二部分是系統建模,系統建模是源於業務概念模型,遵循某些原則最終形成開發可落地的模型(操作層)。在本文中,給出建模的底層邏輯:用圖形邏輯地表達現實業務的抽象,通過一些大家通識的技術案例講述建模的過程。

 

一、建模的底層邏輯

建模的作用不言而喻,它可以極大簡化大家對複雜事物的認識,讓人能在短時間內有全局視野看清楚業務,而且建模是用面向對象的思維分析事物,也容易轉化成類圖。用一個公式表達建模的底層邏輯:建模 = 圖形 + 邏輯 + 現實的抽象,用一句概括即是用圖形邏輯地表達現實業務的抽象,接下麵主要講述圖形、邏輯、現實的抽象這三部分的內容。

1.1 圖形

圖形即為UML圖形,下麵是6種對象間的關聯圖形,在建模中儘量遵循UML標準畫圖,方便大家理解。

  • 繼承:子類繼承父類的特性,有的語言僅支持單繼承。

  • 實現:子類實現父類定義的介面。

  • 組合:一個類包含另外的類,但它強調的是一種強關聯關係。

  • 聚合:也是表達一個類包含另外的類,但它的關聯關係比組合要弱。

  • 關聯:通過一個類可以關聯到另外一個類,可分為單向關聯和雙向關聯,一般以類的成員變數體現。

  • 依賴:比較弱的一類關聯關係,一般是以介面參數的形式體現。

圖片

 

1.2 現實的抽象

我們的現實業務有的是非常複雜的,如果涉及到專業領域概念,新手想入門是挺難的,當我們不清楚業務鏈路和邏輯時,直接看代碼實現時很難有全局的視野,不能夠串起全局業務間的內在聯繫。當我們切入到一個新領域中,並非短時間內就要成為該領域的專家,急需一種方法用20%的時間能夠掌握該領域80%的業務知識,一個可行的方法就是建模,通過對現實業務進行抽象,構建出全局業務概念模型,有了全局的認識,再去瞭解業務細節就會快得多。模型好比地圖,先做到心中有譜,再"按圖索驥",我們比較迷茫時,往往是看不到全局的"地圖",因此也就做不到心中有譜。我們要建模的對象即是問題域,我們並不需要覆蓋所有的點,而是基於核心的內容進行建模,Eric Evans 在建模書中提到一個觀點:建模是出於某種目的而概括地反映現實,這裡的概括就是抓住核心的意思。現實的抽象有三層意思:一類是直接映射,比如現實有一個杯子,那麼我們的模型中就有一個杯子;另一類是往上抽象一層映射,比如我們的組織中有一級結構、二級結構、三級結構等,那我們可以抽象成組合結構,形成父子節點的結構,這種抽象就更靈活了;最後一類是隱性抽象,前面兩類抽象比較容易做到,最難的是隱性概念抽象,它很大可能是之前不存在的,需要新造出一個概念,就像軟體設計中,通過新增加一層來實現解耦一樣,通過新造的概念串聯元素間的內在關聯關係,如下麵示例的中的"債權"概念。舉一個金融理財的案例,需要將投資的錢給到借款人那裡,然後借款人還款時將還款給到投資人,當投資人的錢給到借款人時,就產生了債權關係,因此有一個債權的概念,這記錄了投資人與借款人間的債務關係,債權就是一個橋梁。當借款還款時,對應的債權就會減少,當投資周期到了,債權就會進行債權轉讓,轉到下一個投資人身上,當前的債權關係就結束了,下圖雖然比較簡單,但對理解系統至關重要。

圖片

1.3 邏輯

邏輯即為因果,也即元素之間存在某種關係,如果兩個完全沒有關係的元素放在一些,就會顯得前因不達後果、風馬牛不相及,讓人不好理解。那麼對應到建模上,我們的模型應該是非常具有邏輯性的,從模型上能看出業務核心要素,要素與要素之間的關係是怎樣的。邏輯主要體現在時空兩個維度上:時間維度,一件事情節點完成之後,會影響後續的事情節點;空間維度,更多的體現在結構上,我們常說的空間結構就是這個意思。以時間維度為例,在電商結算中,當訂單支付成功後,結算收單,收單後接受到放款的執行指令,在放款之前需要計算出放款明細信息,如賣家應收到多少錢、公司應收到多少佣金等,最後是打款轉賬,這個過程就是按照時間節點不斷往後驅動,可抽象出如下圖的模型。

圖片

空間維度即是結構關係,比如下圖中的組織結構,像這樣的結構類型,我們還可以找到更多的實際案例,比如交易訂單有主子訂單結構,執行單包含多個執行明細信息,模型最終呈現出來的就是一個結構,從結構維度也可以將其分解出更小的粒度。

圖片

不管哪種建模的方法,最根本的還是體現出了建模的邏輯性,用例建模的邏輯性體現在能夠清晰地定義出用例場景,把所需要做的事講清楚;四色建模通過人、事、物、時間、地點維度描述清楚一件事;事件風暴通過時間軸勾畫出核心關鍵的事件。當我們構建不出模型時,並不是我們缺少建模的方法,而是建模的邏輯性上有問題,建模缺的不是方法而是經驗和實踐。我們不能神化建模,建模是很純粹的,就是為了簡化對複雜事物的認識,並且模型能夠映射到實際開發的模型中。

 

二、建模的方法

建模的方法有很多種,方法多並不意味著建模的難度會很低,相反建模的門檻很高,對抽象思維要求非常高,而且建模並沒有標準的答案,因此很多人覺得沒啥意思。其實這裡面有兩部分:一部分是源於業務概念的抽象,它需要對業務的理解和抽象,往往大家在這一部分覺得沒啥意思;另一部分是在業務概念模型的基礎上,結合設計原則,最終設計出合理的系統模型,這部分是考驗大家的設計功底。下麵列舉2種實踐中常用的方法,這些方法並非是新的方法,是在日常工作中不斷總結、實踐出來的,具有更便捷實用性。

2.1 定義法

定義法建模的核心思想是通過簡潔的一句話描述事物,然後根據定義進行建模,雖然方法聽起來很簡單,但真正用熟還需要大量的實踐。

2.1.1 命令設計模式建模

命令模型在23種模式中,相對還有點複雜的模式,有一句話描述命令設計模型:A下達了命令,B接受到命令後按要求執行。將A抽象成命令發起者,B抽象成命令接受者,因此很容易找出有三個對象:命令發起者、命令接收者、命令。接下來就分析這三個對象間的關係:

  • 命令發起者與命令的關聯:命令是命令發起者發起的,因此命令發起者是要感知到命令的,具體地表現就是命令發起者是要包含命令的。
  • 命令接收者與命令的關係:命令接收者是具體執行命令的對象,到底是命令接收者關係命令,還是命令關聯命令接收者呢?這個可以看誰變化的可能性比較大,應該用穩定的對象包含易變的對象,根據現實經驗,命令相對穩定,而命令接收者是易變的,比如做菜,今天是張三做,明天可能就換成了李四了。
  • 命令發起者與命令接收者的關係:它們之間是不會產生直接有關聯的,是通過命令進行解耦的,命令發起者定義做什麼,命令接收者完成具體的工作。

最終命令設計模式的概念模型如下圖所示。

圖片

2.1.2 導航欄建模

店鋪導航欄平時大家在瀏覽店鋪時常遇見,可以點擊不同的導航Tab看到不同的商品,比如新品、爆品等。用一句話描述導航欄:導航欄是由若幹個導航Tab組成,點擊導航Tab渲染出對應的頁面。很容易分析出有兩個對象:導航欄、導航欄Tab,但在導航欄Tab中還隱含了另外一個對象:導航欄Tab規格信息,這個規格信息描述了Tab的顏色、排序、跳轉鏈路等信息,因此我們可以很容易畫出導航欄的概念模型圖。

 

很可能有些人覺得這個例子太簡單了,如果你按照這種思路分析業務對象,是有別於傳統面向過程分析的,比如導航Tab該不該展示是由它自己負責的,並不是在一個大的方法里控制的。

 

2.2 因果法

因果法的本質同事件風暴建模一樣的,在用熟的基礎上按照自己的習慣進行運用,不管什麼方法,只有內化成自己的方法才有用。它的核心是基於一個對象不斷往前和往後找因果關聯對象,最終構建出完整的業務概念模型。

2.2.1 Spring容器建模

Spring IOC容器對大家並不陌生,以這個案例描述因果建模的方法。首先Spring IOC是一個工廠,因此有一個BeanFactory對象,同時它會包含業務Bean對象,因此最簡單的一個Spring IOC 概念模型如下圖所示。

 

接下來就需要不斷追溯了,Bean是怎麼到Bean工廠中的呢?應該有一個Bean註冊器,在上圖的基礎上,再完善下。

圖片

再想這個Bean是怎麼來的呢?即哪些業務對象會標識成要放到Bean工廠中的,會有一個掃描器掃描業務對象,發現有標識@Componet、@Service等註解的類需要放到Bean工廠中,因此這裡面就會有三個對象:BeanDefinitionReader、BeanDefinition、BeanDefinitionRegistry,迭代後的Spring IOC概念模型如下圖所示。

圖片

雖然這是一個簡陋的Spring IOC概念模型圖,但它還是把Spring IOC核心包含的對象展示出來了,結合現實需求,我們還可以加一些對象進來,比如考慮擴展性,會有BeanFactoryPostProcessor等。這裡僅僅是一個業務概念模型,具體到系統模型需要結合設計原則來設計,如Bean工廠在實際中會拆分成多級Bean工廠繼承的關係。

 

三、建模案例

根據第二節中講的方法,下麵通過三個技術案例描述在實際學習中的運用,通過模型可以快速讓我們理解技術涉及的原理,當我們有了基礎理解後,再去看技術框架源碼時也會快得多。

3.1 非同步事件建模

非同步事件對於開發來講並不陌生,將事件定義與事件執行進行解耦,用一句話描述非同步事件:事件發佈者發佈一件事件後,經由事件分發器分發後,找到對應的事件監聽器處理。這裡面就包含了四個對象:事件發佈者、事件分發器、事件監聽器、事件。事件發佈者是將事件發佈到事件分發器上,因此事件發佈者是需要關聯事件和事件分發器;事件分發器通過事件類型匹配,匹配上事件後調用對應的事件監聽器進行處理,因此事件分發器包含了多個事件監聽器。非同步事件的概念模型圖如下圖所示。

圖片

在Spring事件廣播器中,有添加事件監聽器,以及通過事件查找到對應的事件監聽器進行處理。

圖片

 

3.2 切麵建模

切麵編程在實際工作中應用得也比較多,比如在服務上增加橫切功能,如日誌列印、方法耗時統計等,接下來用因果建模法對切麵進行建模。最開始有一個目標對象,即為我們要增加橫切功能的對象,那麼怎麼表達這個橫切功能呢?至少要包含三種信息:誰需要被增強?;增強的邏輯是什麼?;什麼時候增強?,描述誰需要被增強的對象抽象成切點。增強的時間節點抽象成通知。因此可得出初步的模型。

圖片

目標對象與切麵是怎麼關聯上來的,相當於在目標對象的方法前後要額外增加一段邏輯,可以通過代理來實現,因此有一個代理對象,它會鏈接目標對象和切麵,最終切麵業務概念模型如下圖所示。

圖片

當熟悉了切麵業務概念模型後,再去看Spring AOP的源碼會容易些,模型就是簡化認識,提煉出核心關鍵的事物要素。

圖片

3.3 ORM框架建模

ORM是將傳統SQL映射到對象上,更符合面向對象的習慣。同樣我們使用因果建模的方法,ORM框架在底層最終還是要執行具體的SQL,因此將SQL語句抽象成Mapper,資料庫配置信息抽象成配置信息,有了這兩個配置信息,自然有對應的解析配置的類,初步的模型如下。

圖片

將執行SQL的過程抽象成會話,會話會執行SQL,將執行SQL的對象抽象成SQL執行器,在SQL執行過程中,需要做兩件事:一件是參數解析;另一件是結果解析。最終的ORM框架概念模型如下圖所示。

圖片

在執行器中,我們可以看到有配置信息、參數信息。

圖片

 

四、建模經驗總結

4.1 能清晰地描述事物建模就成功了一半

建模是將混沌的事物抽象成有序關聯事物的過程,混沌到有序,因此我們需要梳理清楚事物間的關聯關係,如果我們都不能夠清晰地描述事物,是很難建模的。不能夠描述清楚事物,說明我們自己都還沒有理清內在的關聯關係,也就做不到抽象出有序的模型。在日常工作中,可以嘗試用幾句描述一件事,看大家能不能理解到。在學校老師經常讓我們概括文章的中心思想,就是鍛煉這種建模能力,通過幾句話把文章的核心內容勾畫出來。我們在軟體建模也是一樣的,通過幾句話把業務的涉眾、業務結構、業務目標、核心關註點表達出來,然後通過業務概念模型呈現出來。

4.2 通過描述事物的結構是建模常用的方法

模型最終呈現出來的是一個圖,這個圖往往是有清晰的結構,比如房屋模型,它就有自己的結構:坐北朝南,有大廳、睡房、廚房、洗手間等,軟體模型也是一樣的,在2.1.2節中舉了一個店鋪導航欄的例子,如下圖所示,當我們看到店鋪導航欄時,可以想像下它是怎樣的結構。

圖片

在實際的業務中,有兩類模型:一類是偏結構型的模型;另一類偏行為型的模型,從個人接觸到的業務看,結構型的模型偏多,比如訂單有主子訂單模型。我們也可以嘗試從結構的角度去定義事物。

 

4.3 建模要區分知識層和操作層

模型一般有兩層:一層是知識層;另一層是操作層,知識層中包含的概念是通識的概念,往往是面向使用者,比如我們在使用AOP切麵編程時,可以用@Aspect、@PonitCut、@Before等註解時,它們就是屬於知識層,知識層的內容抽象層次比較高,大家比較容易理解,我們所做的業務運營工作台也是做的知識層的內容,比如配置頁面模板、站點配置等,這些可枚舉的維度都是知識層。另一層是操作層,操作層是支撐知識層的,還是AOP為例,底層有對註解的解析、動態代理的生成等;再比如Spring IOC中,有各類Bean的註解,在操作層中,有BeanDefinition的載入、識別、解析、Bean實例化、Bean初始化等,操作層中的實現也並非面向過程的設計思維,它也包含了抽象設計和遵循某些設計原則,這一點在下一節中會專門講到,同樣的設計,張三和李四可能不一樣,正所謂"文無第一,武無第二",大家的設計理念、角度不一樣,技術設計本應如此,就像一百個廚師做同樣的菜,做出來的菜也有一百個樣。如果知識層偏表達,那麼操作層就是偏實現支撐,這兩類的視角也是不一樣的,知識層更抽象,而往往我們開發人員更關心的是操作層中的具體實現類,缺乏抽象意識,這也是我們自己心中非常清楚,但別人很難理解,需要轉換視角,思考通識的知識層有什麼。

 

五、小結

在文章中主要講述了建模的一些方法,方法雖然簡單,但用熟還是需要大量的實踐經驗,建模分為兩個階段:第一個階段是業務概念建模,它無關於技術,是通識的建模(知識層);第二個階段是系統建模,基於業務概念建模的基礎上,考慮具體的技術實現(操作層),遵循某些設計原則構建可落地的模型。建模的確會簡化對複雜事物的認識,以學習技術框架為例,如果一頭扎進源碼中,很難有全局觀,相反如果我們從全局對技術框架有一定的理解,再去看源碼也會快很多。

 

作者:高福來(不拔)

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/Software-Engineering-Bottom-Logic-Series_The-bottom-logic-of-modeling.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 摘要:不知道大家在生活中有沒有見過一些非常酷炫的可視化大屏應用? 本文分享自華為雲社區《老闆要的物聯網可視化大屏,我30分鐘就搞定了》,作者:華為雲社區精選 。 不知道大家在生活中有沒有見過一些非常酷炫的可視化大屏應用? 隨著數字化經濟的發展,我們對數據的呈現形式要求也越來越高,很多老闆動不動就讓我 ...
  • 摘要:為了持續打造核心競爭力,英克康健聯合華為雲,基於雲資料庫RDS for PostgreSQL全新打造了一個高性能、大容量、高可用的SaaS醫葯管理系統,助力萬千藥企業務邁上新臺階。 乘借數字化東風,醫葯行業呈現出一片欣欣向榮之景。作為一家高新技術企業,北京英克康健科技有限公司(簡稱“英克康健” ...
  • 熟悉Taier的小伙伴們應該都知道,在11月7日發佈的Taier1.3新版本中,我們融合了「DataSourceX 模塊」。這是十分重要的一個變化,移除Taier外部插件依賴,新增數據源插件相關特性,支持後續Taier對接更多的RDBMS類型的SQL任務。 本篇文章,就帶大家詳細瞭解一下DataSo ...
  • 作者:劉鄧忠 Mysql 是大家最常用的資料庫,下麵為大家帶來 mysql 索引下推知識點的分享,以便鞏固 mysql 基礎知識,如有錯誤,還請各位大佬們指正。 1 什麼是索引下推 索引下推 (Index Condition Pushdown,索引條件下推,簡稱 ICP),是 MySQL5.6 版本 ...
  • 好家伙,好家伙,本篇為《JS高級程式設計》第八章“對象、類與面向對象編程”學習筆記 1.原型鏈 原型鏈是JS實現"繼承"的方案之一 ECMA-262把原型鏈定義為ECMAScript的主要繼承方式。其基本思想就是通過原型繼承多個引用類型的屬性和方法。 重溫一下構造函數、原型和實例的關係:每個構造函數 ...
  • 一.概述 傳統許可權管理: 類似於這樣,每新增一個人都要重新給她一些許可權,是針對每個人單獨設置的,這種方法已經不適用於高效管控許可權的 基於此,RBAC許可權模型就誕生了,Role-Based Access control也就是基於角色的許可權控制,相對於傳統模式,這套方案強調一個==role角色== RB ...
  • 標簽 tag 基礎標簽 div 塊元素 介紹:沒有任何含義,主要用於 div 進行模塊佈局 類型:塊級元素 block,盒子占用寬度為一整行 屬性:沒有屬性 <div>我是模塊</div> 我是模塊 span 行內文本元素 介紹:沒有任何含義,主要用於展示文本內容 類型:內聯元素 inline,盒子 ...
  • 這個問題作者認為是所有從後端轉向前端開發的程式員,都會遇到的第一問題。JS前端編程與後端編程最大的不同,就是它的非同步機制,同時這也是它的核心機制。 為了更好地說明如何返回非同步調用的結果,先看三個嘗試非同步調用的示例吧。 示例一:調用一個後端介面,返回介面返回的內容 function foo() { v ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...