建模對于大家來講并不陌生,而且建模的方法也有很多,如用例建模、四色建模、事件風暴等,但在日常作業中,大家又覺得建模挺虛的:怎么把建模落到實際開發作業中,個人認為建模是分兩部分:第一部分是業務概念建模,對現實業務抽取核心概念構建出模型(知識層);第二部分是系統建模,系統建模是源于業務概念模型,遵循某些原則最終形成開發可落地的模型(操作層),在本文中,給出建模的底層邏輯:用圖形邏輯地表達現實業務的抽象,通過一些大家通識的技術案例講述建模的程序,
一、建模的底層邏輯
建模的作用不言而喻,它可以極大簡化大家對復雜事物的認識,讓人能在短時間內有全域視野看清楚業務,而且建模是用面向物件的思維分析事物,也容易轉化成類圖,用一個公式表達建模的底層邏輯:建模 = 圖形 + 邏輯 + 現實的抽象,用一句概括即是用圖形邏輯地表達現實業務的抽象,接下面主要講述圖形、邏輯、現實的抽象這三部分的內容,
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/540909.html
標籤:其他
下一篇:淺談系統性能提升的經驗和方法
