面向對象分析與設計的底層邏輯

来源:https://www.cnblogs.com/88223100/archive/2022/08/22/The-underlying-logic-of-object-oriented-analysis-and-design.html
-Advertisement-
Play Games

在面向對象出現之前,已有面向過程的分析方法,為什麼面向對象被提出了呢?究其本質原因,人們發現面向過程並不是按照人正常認識事物的方式去分析軟體,那麼人究竟是怎麼認識事物的呢,Yourdon 在《面向對象的分析》一書中提到,人類認識事物是遵循分類學的原理,分類學主要包含三點:區分對象及其屬性;區分整體對... ...


1 面向對象是符合人認識事物的基本方法

 

01 人是怎麼認識事物的

 

在面向對象出現之前,已有面向過程的分析方法,為什麼面向對象被提出了呢?究其本質原因,人們發現面向過程並不是按照人正常認識事物的方式去分析軟體,那麼人究竟是怎麼認識事物的呢,Yourdon 在《面向對象的分析》一書中提到,人類認識事物是遵循分類學的原理,分類學主要包含三點:區分對象及其屬性;區分整體對象及其組成部分;不同對象類的形成及區分

 

我們現在可以回想下我們認識事物的過程,是不是和分類學所提到的 3 個要點很相似,看到一個事物,大概會感知到它的組成結構是怎樣的,形狀是怎樣的,屬於什麼分類。所以,人認識事物是以對象的視角切入的,然後賦於對象具體的概念,比如蘋果、梨子、汽車等等概念名稱。

 

 

 

02 分類與分層的兩種思維

 

我們面對的現實世界是非常複雜的,應對複雜事物的有一個重要的方法即是抽象,抽象在實際應用過程中,又體現在兩種方法上:分層和分類。分類即是將有差異的事物歸類到不同的分組中,正如我們常聽到的"物以類聚、人以群分"的道理一樣,產生分類的原因有兩點:一點是事物間的關聯緊密程度,不需要將所有的事物都耦合在一起;另一點是人掌握事物是有局限的,只能掌握少量的要點,比如 5~7 個要點,超過了容易忘記。

 

 

 分層是通過不同的視角看事物,每一層的關註點是不一樣的,這種關註點不同是由自己的視角造成的,比如我們理解電腦,並不需要深入到二進位電信號去理解電腦。層次特性在軟體設計中我們經常遇到,比如電腦體繫結構、TCP 七層協議等,層次特性有一個特點:越往上越具體、越往下越抽象,越往上的內容越不穩定,也即是容易變化。

 

 

 

03 問題域到解空間的映射

 

我們把需要解決的問題稱之為問題域,或者問題空間,把解決方案稱之為解空間。正向上一小節中提到的事物有層次特性,不同的人理解的事物是站在各自理解的視角,這樣大家的理解、溝通並不一致的。如果我們看到的問題空間是表層的,那麼基於淺層次理解設計出來的方案就會不穩定,可能下次有一個小變化導致方案需要重新設計。

 

 

 我們可以把一個軟體劃分成三層:場景、功能和實體,場景層是經常會變的,比如發放優惠券場景就非常多,比如有天降紅包領取優惠、分享有禮領取優惠券、新人註冊領取優惠券等,這種場景的更迭隨著業務的調整變化得非常快,因此場景層是不穩定的。功能支撐某一些的場景集合,對比場景,功能相對而言穩定些,就像前面提到的發放優惠券場景,本質就是給用戶發放優惠券,只需要提供發放優惠券的功能即可,至於哪些場景來調用它並不關註,但功能還是基於場景的集合抽象出來的,如果場景場景類型變化了,功能也就隨之變化,比如擔保交易和預售交易就不一樣。實體是穩定的,以擔保交易和預售交易為例,它的訂單模型大致是一樣的,只是新增加了一些信息而已。

 

 

因此,我們希望從問題空間到解空間,大家看到的、理解的是一致的,而且看到的是問題的本質而非表象,往往場景、功能是不穩定的,而面向過程又是以功能驅動的,所以在易變化的場景下,它面臨的問題就比較多。比較穩定的是問題空間中的實體對象,所以面向對象分析是現實的需要。面向過程和麵向對象是兩個不同的視角的分析方法:面向過程是一種歸納的分析方法,由外到內的過程;面向對象是一種演繹的分析方法,由內到外的過程

 

04 三個一致性

 

軟體開發會經歷需要分析、概要設計、詳細設計、編碼、測試、上線主要階段,我們不希望每塊是割裂的,比如分析做完之後,做設計階段又要重新去做分析的工作,那麼這裡面就涉及到一致性的問題,即需求到分析的一致性、分析到設計的一致性、設計到編碼的一致性。這樣做的好處可以保證無信息失真,因此我們急需求一種分析設計方法能做到這一點,面向對象分析與設計就能做到,因此全流程是以對象作為分析與設計的目標,在最終編碼中也都是對象。

 

 

05 面向對象的底層邏輯

 

提到面向對象,有部分人會提到封裝、繼承、多態等特性,然後這些並不是面向對象的本質特性,比如封裝,面向過程中也有封裝,多態面向過程也有體現,這些特性算不上面向對象特有的特性。面向對象的底層邏輯是基於現實事物做的抽象映射:現實事物對應軟體中的對象,我們討論解空間能對應到問題空間中的對象,兩者是一一直接映射的,其它的分析方法是問題空間到解空間的間接映射。

 

 

2 面向對象分析與設計的全景圖

 

01 我們面臨的問題是什麼

 

從頂層看,我們要完成需求到編碼的工作,然而從需求到編碼又會經過多個階段,如需求分析、方案設計等,從大的層面講,我們主要遇到三個問題:

 

1. 做什麼的問題

 

看似這是一個簡單的問題,但在複雜的業務場景下,對做什麼的理解太重要了,因為不同的人對需求的理解是不同的,比如最近做了一個項目,有一個業務判斷規則是只針對跨境訂單計稅,最開始開發同學的理解是判斷賣家類型是否是跨境賣家,然而到了測試階段,發現大家對這個業務規則判斷理解是不一致的,跨境訂單跟賣家類型是沒有關係的,真正的跨境訂單計稅場景是 shipTo(收貨地址)和 shipFrom(發貨地址)國家地址是不一樣的。在大項項目中,涉及到多個團隊之間的協同,這樣的問題異常突出。而且從業務訴求到產品需求,再到技術方案,這其中是經過了 2 次變換,每次變換是不同的角色在裡面,大家的認識也會不一樣。

 

2. 怎麼做的問題

 

落實到事情具體要怎麼做時,往往大家並不會出大的問題,怎麼做偏具體執行階段,程式員往往在邏輯嚴密性上沒多大的問題,往往出問題是在第一個問題上,相當於方向弄錯了,所做的工作也是無用的。

 

3. 方法指導的問題

 

我們往往希望不勞而獲得到一種萬能的方法,能夠應對所有的問題,同時又看不起低級的方法,比如大部分人對用例分析方法嗤之以鼻,想要能體現技術水平高大上的方法。其實自上世紀 70、80 年代,軟體的分析設計方法並沒有太大的變化,而且在我們大學期間都學過,只是大家並不認為它是一種高大上的方法而已。

 

 

02 分析到設計的過程

 

在本節中,我們推導軟體分析到設計的過程,由粗到細,最終落實到我們接觸到的 UML 知識上。從需求提出到編碼實現,這中間有兩個關鍵問題:一是界定目標,即是定義清楚要做什麼的問題,相當於是我們做事的方向、目標;二是具體如何做的問題,即通過怎樣具體的方案支撐需求目標實現。因此,我們需要一種方法能夠幫助我們界定目標和表示具體方案,而且是大家互認的一種通用的方法。

 

 

通過用例圖可以幫我們界定目標,用例中有三個關鍵要素:用戶、場景和目標。比如交易下單是一個用例,它的用戶是買家,場景包含下單成功和下單失敗兩個場景,用例的目標是買家可以購買心儀的商品。當用例目標確定了,相當於界定了目標,知道需求要做什麼,這個過程要反覆和業務方確認好,至到最終大家對目標的理解是一致的,方向對了,具體怎麼做就好辦了。

 

具體怎麼做用時序圖表示,畫時序圖需要註意的一點是頂層的對象層次要一致,不能有的對象表示具體的實體對象,有的表示系統對象,即對象的層級是一致的,要麼大家都是系統,比如導購系統調用交易系統,交易系統調用支付系統,要麼大家都是對象,比如商品、訂單等。通過時序圖可以看到一個完整功能的執行步驟,它就包含具體執行的細節,如正常流程、異常流程。

 

 其實在上面有一個問題,在畫時序圖時要確定好對象,那麼這個對象是怎麼來的呢?它是由健壯性圖分析出來的,它裡面有三個關鍵的對象:一個是邊界對象,這個比較好理解,比如UI界面就是邊界對象;另一個是控制對象,即是控制業務流程的對象,如下單服務就可以看作是控制對象;實體對象即是問題空間中的業務對象,比如訂單。畫健壯性圖是有規則的,一般是邊界對象調用控制對象,控制對象產生實體對象,比如用戶下單界面是邊界對象,下單服務是控制對象,訂單就是實體對象。

 

 

3 尋找對象之路

 

01 對象從哪裡來

 

在本文第一部分第三小節中已經提到,問題空間到解空間是一一映射,我們討論解空間中的對象時,其實它映射到問題空間中的對象,而問題空間中的對象主要來源於業務概念、業務規則、關鍵事件。大部分的對象是顯現的,我們通過理解業務能發現,有的對象是隱性的,需要我們持續對業務有更深的理解才能發掘出來。好的對象模型是需要經過多次迭代打磨出來的,並非一次就能設計得十全十美。

 

02 發現對象的方法

 

在本文第二部分第二小節中已經提到尋找對象的方法,不過那還只是關鍵顯現的對象,在本節中主要講述完整對象發現的方法,主要方法分成四個步驟:

 

1. 通過健壯性圖找到關鍵的實體對象;

 

2. 通過結構分析方法找出更多的實體對象;

 

3. 將對象組成有機的對象模型;

 

4. 最後通過用例走查對象模型是否完備。

 

 這裡以一個案例來說明發現對象的過程,案例是用戶在下單時,在訂單上展示稅的金額。首先畫出健壯性圖,這裡的邊界對象是下單界面,控制對象有兩個,一個是下單服務,另一個是計稅服務,實體對象也有兩個,一個是計稅單,一個是訂單。有了計稅單和訂單這兩個實體對象後,接下來通過結構分析方法,分析出更多的對象。

 

 

對象都是有結構的,只要我們掌握了對象的結構,基本上就能掌握對象的概貌,因此我們從對象的結構入手,去分析對象內部的結構、對象關聯的結構,實質上是從兩個維度出發:一是從自身的角度出發,看自己內部還包含了哪些對象,如主訂單包含了子訂單;另一個是從外部的角度出發,看自己還與哪些對象相關聯,如計稅單與訂單是有關聯的。這種找對象的方法我稱之為結構分析方法,因為本身結構又是事物本質的一種表達方式,比如化學分子結構決定化學現象。

 

為了更好地表達出對象的結構,我的一個經驗是給對象下好定義,下定義可以從不同的維度,比如功能性維度、價值性維度、目的性維度、結構性維度等,這裡可以從結構性的維度去給對象下定義。以計稅單為例,可以給它下一個定義:計稅單是將訂單金額信息轉成若幹個標的物計稅的單據模型,從這個定義中,我們可以看到計稅單是與訂單有關聯關係的,另一個是計稅單是包含了若幹個標的物,我們可以畫出計稅單的對象模型。

 

 

 

當對象模型畫出來後,後續我們討論業務基本上圍繞這個對象模型去討論業務問題的,比如商品標的物哪些金額要參與計稅、計稅金額的計算口徑是怎樣的,到這裡,大家再體會下"問題空間到解空間一一直接映射"這句話,業務上的訴求也無非是哪些訂單費用項要計稅,計稅的邏輯是怎樣的,有可能在這個場景下要扣減金本位優惠,在另外一種場景下金本位優惠不需要扣減,基於對象模型與產品、測試同學討論問題,大家都是處於同一個維度的視角看問題,溝通理解成本會少很多。

 

對象模型是一種可視化的表達,我們大部分的溝通問題是缺乏顯性表達造成的,這句話可以這樣理解,也可以那樣理解,導致大家理解有偏差,現在用模型的形式溝通問題,很多偏差、歧義就消除了。

 

03 組織對象結構

 

當我們分析出一堆的對象後,還需要經過一定的組織,正如前面提到,人對事物理解是有局限的,不能一下子接受太多的事物,因此可以將它們分成一個個小的域,比如商品域、訂單域、稅務域等,這樣當聚集一個問題時,可以只看某個子域里的對象模型即可。

 

 

4 如何分配職責

 

01 職責是怎麼來的

 

面向對象最難的點有兩個:一個是找出對象;另一個是分配職責。UML 把職責定義為"類元的契約或義務",因此職責的劃分從本質來講還是類元本身決定的,比如訂單,它要提供訂單渲染、訂單創建、訂單修改、訂單查詢的義務。

 

職責分為兩類:一類是認知職責;另一類是行為職責。

 

  • 認知職責包含:

 

    • 對私有數據封裝的認知。
    • 對相關對象的認知。
    • 對其能夠導出或計算的事物的認識。

 

  • 行為職責包含:

 

    • 自己執行的行為,包括創建對象或計算。
    • 初始化其它對象的動作。
    • 控制或協調其它對象的活動。

02 分配職責的邏輯
上一小節中提到的職責有兩類,認知職責是對象自身的認知範圍,即它只能基於自身屬性完成相應的職責,舉一個例子,假如一主多子的訂單,要計算總的訂單金額,怎麼分配職責呢?首先商品只能查到自身價格的信息,它的認識是基於商品 price 屬性,一個子訂單可以有多個商品,那麼它也只能計算出子訂單的金額信息,它的認知是基於 item 和 quantity兩個屬性,主訂單包含所有子訂單的信息,那麼就可以計算出總的訂單金額。

 

 從上面的例子中我們可以看出,認知職責是基於對象屬性的,正所謂"不在其位、不謀其政",認知職責一定不會超過它的認識範圍的。
行為職責是偏領域服務的,有的時候一個職責不屬於某一個對象,比如轉賬,就是一個行為,讓其它的職責承擔並不合適,這類行為職責往往是一個顯著的業務活動,比如訂單渲染、訂單創建就是行為職責而非認知職責。
分配職責一定要遵循"信息專家"模式,它的含義是將職責分配給具有完成該職責所需要信息的那個類,也即上面提到的認識產生職責。


03 驗證職責分配的合理性
我們期望分配的職責滿足"高內聚、低耦合",怎麼檢驗呢?我們再回過頭來思考職責的定義:類元的契約或義務,換句話講,職責是滿足其它對象來調用的,這個就與我們畫時序圖的目的是一致的,每次發生一次調用,即意味著其它的對象要提供一個職責出來,因此我們可以在時序圖中看對象間的調用頻次,如果一個對象被調用得非常頻繁,有可能這個對象承擔了太多的職責,是不是可以對其拆分,把職責分配一部分出去。因此,對象職責分配並不是一蹴而就的,需要不斷審視、檢驗。
分配職責是要遵循一定的原則,如創建者模式、信息專家模式、純虛構模式等,這些原則會在下一篇中單獨去講。


5 案例
01 案例背景
這裡舉一個例子,說明面向過程和麵向對象在分析、編寫代碼的差異性,計稅需要判斷是否滿足計稅規則,比如虛擬商品不計稅(手機充值之類)、有些免稅地址不計稅、小 B 買家也不計稅等,因此需要提供一個計稅過濾判斷邏輯。

02 常規面向過程實現
面向過程的思路很簡單,提供一個過濾方法依次處理下麵邏輯:過濾虛擬商品計稅請求、過濾免稅地址計稅請求、過濾小 B 買家計稅請求。

 

 

public void filter(List<TaxCalculateRequest> request){

     // 過濾虛擬商品計稅請求
     filterVirtualItem(request);

     // 過濾免稅地址計稅請求(即外島)
     filterOuterIsland(request);

     // 過濾小B買家計稅請求
     filterPurchaseType(reqeust);

}

 

03 面向對象實現
面向過程是從過程視角或者是功能視角分析問題,而面向對象是從對象的視角分析問題,過濾計稅請求是計稅過濾器判斷計稅請求是否滿足計稅規則,這裡就包含了兩個對象:計稅過濾器和計稅規則,判斷是否滿足計稅要求這個職責應該是在具體的計稅規則處理器中,比如是否是小 B 買家等,因此我們可以畫出對象模型。

 

 關鍵代碼如下:

public abstract class AbstractRuleHandler {

    /**
     * 抽象的業務規則處理
     *
     * @param request
     */
    public abstract void handler(TaxCalculateRequest request);

    /**
     * 構造函數里完成註冊
     */
    public AbstractRuleHandler() {
        TaxCaluclateFilter.register(this);
    }
}

 

06 總結
在文章中提到,面向對象的底層邏輯是基於現實事物做的抽象映射,重要的不是要面向對象具體技術的使用上,而是分析問題的思維上,這是最難的,它最大的好處是問題空間到解空間是一一直接映射的,請註意是一一直接映射,它意味著我們在討論方案的時候,完全可以映射到問題空間,如果是間接映射,也就意味著設計的方案後面會面臨重新設計的可能性,因為它是基於場景或功能做出的歸納設計,而且是表層的設計。真正掌握了面向對象分析和設計的方法,也體會到其中的益處,對理解業務、方案設計、編碼開發都有好處。

 

作 者 | 不拔

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/The-underlying-logic-of-object-oriented-analysis-and-design.html


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

-Advertisement-
Play Games
更多相關文章
  • StoneDB與MySQL的相容性如何? StoneDB高度相容MySQL 5.6、5.7協議和MySQL生態等重要特性,支持MySQL常用的功能及語法。 由於StoneDB本身的一些特性,部分操作和功能尚未得到支持,如不支持創建索引、不支持刪除數據等。 StoneDB有自己的優化器嗎? Stone ...
  • 開心一刻 今天,朋友氣衝衝的走到我面前 朋友:我不是談了個女朋友,談了三個月嘛,昨天我偷看她手機,你猜她給我備註什麼 我:備註什麼? 朋友:舔狗 2 號! 我一聽,氣就上來了,說道:走,找她去,這婆娘確實該罵,臭不要臉的 朋友拉住我,勸到:哎哎,不是去罵她,是找她理論,叫她改成舔狗1號,是我先來的! ...
  • 請點贊關註,你的支持對我意義重大。 🔥 Hi,我是小彭。本文已收錄到 GitHub · AndroidFamily 中。這裡有 Android 進階成長知識體系,有志同道合的朋友,關註公眾號 [彭旭銳] 帶你建立核心競爭力。 前言 LeakCanary 是我們非常熟悉記憶體泄漏檢測工具,它能夠幫助開 ...
  • HMS Core機器學習服務文本翻譯能力提供多種語言和多種應用場景的翻譯服務,比如,在出國旅游的場景中,用戶可以藉助應用的語音翻譯播報功能在打車、酒店入住等場景中無障礙溝通,也可以通過拍照翻譯功能讀懂餐廳菜單、路牌信息等。 中文直譯模型讓文本翻譯能力升級 當前主流的翻譯模式大都以語料資源較為豐富的英 ...
  • 當const定義的常量是基本數據類型的時候不可以被更改 當const定義的常量是引用數據類型的時候,其值可以被更改。 文字有點描述不清楚,或者說用什麼存在記憶體什麼的解釋也有點不好理解。直接上圖吧。 重新定義const定義的數值的話,就會出現:Uncaught TypeError: Assignmen ...
  • 本文是深入淺出 ahooks 源碼系列文章的第十一篇,該系列已整理成文檔-地址。覺得還不錯,給個 star 支持一下哈,Thanks。 本文來講下 ahooks 中的 useUrlState。 通過 url query 來管理 state 的 Hook。 useUrlState 的特殊 在之前的架構 ...
  • 內聯模板 點擊打開視頻講解更加詳細 當 inline-template 這個特殊的 attribute 出現在一個子組件上時,這個組件將會使用其裡面的內容作為模板,而不是將其作為被分發的內容。這使得模板的撰寫工作更加靈活。 <my-component inline-template> <div> < ...
  • 組件之間的迴圈引用 點擊打開視頻講解更詳細 假設你需要構建一個文件目錄樹,像訪達或資源管理器那樣的。你可能有一個 <tree-folder> 組件,模板是這樣的: <p> <span>{{ folder.name }}</span> <tree-folder-contents :children=" ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...