換個(gè)角度認(rèn)識軟件-2023.10_第1頁
換個(gè)角度認(rèn)識軟件-2023.10_第2頁
換個(gè)角度認(rèn)識軟件-2023.10_第3頁
換個(gè)角度認(rèn)識軟件-2023.10_第4頁
換個(gè)角度認(rèn)識軟件-2023.10_第5頁
已閱讀5頁,還剩125頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

換個(gè)角度認(rèn)識軟件林寧

著?2目錄為什么我們跟別人說不明白?用模型理解編程語言和面向?qū)ο罄斫廛浖澈蟮纳?1634透過領(lǐng)域建??窜浖墓窍?710553換個(gè)角度看架構(gòu)把團(tuán)隊(duì)看作分布式系統(tǒng)為什么我們跟別人說不明白?為什么我們跟別人說不明白?在軟件開發(fā)過程中,比較難的一件事就是如何表達(dá)需求、方案、問題,甚至有時(shí)候日常溝通也會出現(xiàn)“驢頭不對馬嘴”的溝通窘境。之所以會出現(xiàn)這類表達(dá)問題,一部分原因是我們對邏輯的理解不同。大多數(shù)有經(jīng)驗(yàn)的開發(fā)者、系統(tǒng)分析師都具備一定的辯證思維和方法,要說誰沒有邏輯,這件事情很難說得過去。如果每個(gè)人都是用自己的思維方式和“邏輯”,讓溝通過程變得非常困難。令我疑惑的是,每個(gè)人都相信邏輯是很重要的,但幾乎沒有文章討論過在軟件設(shè)計(jì)和開發(fā)過程中如何使用現(xiàn)代邏輯學(xué),以及解決詭辯的問題。1為什么我們跟別人說不明白?這里討論一些能在軟件工程中使用的邏輯學(xué)基礎(chǔ)知識,尤其是概念相關(guān)的內(nèi)容在業(yè)務(wù)分析、領(lǐng)域建模和架構(gòu)設(shè)計(jì)中都可能會被用到。1當(dāng)你提到用戶時(shí),你是指什么?我曾經(jīng)參與過一個(gè)物聯(lián)網(wǎng)系統(tǒng)的設(shè)計(jì),其中大家經(jīng)常會提到一個(gè)詞“設(shè)備”,但是“設(shè)備”這個(gè)詞在不同的開發(fā)者眼里有不同的概念,為此,討論“設(shè)備”這個(gè)詞花費(fèi)了不少的功夫,最終依然沒有定義清楚。有些開發(fā)者認(rèn)為“設(shè)備”是現(xiàn)實(shí)中看得見摸得著的物品,另外的開發(fā)者將服務(wù)器上用于映射物理設(shè)備的實(shí)例也叫做“設(shè)備”。于是,他們在溝通時(shí)經(jīng)常會出現(xiàn)對于“設(shè)備”的理解不一致導(dǎo)致的混亂。另外一個(gè)例子是“用戶”這個(gè)概念。在不同的場景(上下文)下,“用戶”這個(gè)概念可以是使用軟件的大活人,也可以是數(shù)據(jù)庫中的一條記錄,也可以是服務(wù)中的用戶對象,有時(shí)候也將用戶服務(wù)類叫做用戶。這樣就非?;靵y,不僅無法溝通,而且還導(dǎo)致開發(fā)者對系2為什么我們跟別人說不明白?統(tǒng)的認(rèn)知也變得困難,很多東西處于混沌狀態(tài)。在咨詢的工作中,我發(fā)現(xiàn)非常有意思的是,將軟件中的概念一一定義清楚,整個(gè)系統(tǒng)的設(shè)計(jì)工作差不多就完成了。所以設(shè)計(jì)軟件的過程和現(xiàn)實(shí)中人們相互交流非常類似。英國哲學(xué)家維特根斯坦把人們交流的過程叫做“語言的游戲”,當(dāng)我們描述事物的時(shí)候?qū)嶋H上就是將有清晰邊界的元素貼上標(biāo)簽,這個(gè)標(biāo)簽就是我們說的概念。樸素的概念是來源于個(gè)人背景和理解,因此概念難以統(tǒng)一。1正是因此不同語言之間準(zhǔn)確地翻譯也不太可能

,不同文化背景難以找到合適的概念互相映射。后來哲學(xué)家認(rèn)識到人們認(rèn)識概念是由一些更為基礎(chǔ)的屬性構(gòu)成的,那可以認(rèn)為概念就是由屬性組成的。比如“人”這個(gè)概念,有四肢、直立行走的行為、皮膚光滑等屬性。這些基本的屬性又是一些更基本的概念,如果我們對這些基本的概念達(dá)成共識,那么我們就有機(jī)會對概念進(jìn)行統(tǒng)一。類似于面向?qū)ο笳Z言

Java

中的類,類有各種屬性,這些1翻譯是否真的可以被實(shí)現(xiàn)是一個(gè)經(jīng)常被討論的觀點(diǎn),參考:嚴(yán)春友

.

翻.3為什么我們跟別人說不明白?屬性最終都可以通過

8種基本的數(shù)據(jù)結(jié)構(gòu)描述。因此屬性是認(rèn)識概念非常重要的一方面。屬性包含了事物自身的性質(zhì)、行為,比如黑白、高矮、是否能飛行、是否獨(dú)立行走。事物除了自身的性質(zhì)外,還與其他事物發(fā)生一定的關(guān)系,比如大于、相等、對稱、屬于等。事物的性質(zhì)、行為以及和其他事物的關(guān)系,統(tǒng)稱為事物的屬性。通過屬性就能找到概念的邊界。

具有相同屬性的概念是同一個(gè)概念,即使它們的名稱不同也不應(yīng)該分為不同的概念。例如,土豆和馬鈴薯都是同一個(gè)概念。如果意識不到屬性對概念的影響,則會出現(xiàn)生活中的命名錯(cuò)誤,例如小熊貓并不是小的熊貓,而是單獨(dú)的一種動物。2

嘗試精確定義概念一個(gè)概念可以具有多種表達(dá)方法,對于軟件設(shè)計(jì)來說,我們可以用自然語言描述概念。也可以通過定義一個(gè)類來描述,并在程序運(yùn)行時(shí)實(shí)例化這個(gè)概念。通過數(shù)學(xué)或者數(shù)理邏輯,我們可以使用集合來描述一個(gè)概念。比如“商品”這個(gè)概念,可以通過不同的方法表達(dá)。4為什么我們跟別人說不明白?自然語言中,商品是指可以通過貨幣或者其他物品交易的物品,可以是自然實(shí)體,也可以是虛擬物品。這是社會經(jīng)濟(jì)中對商品的描述,商品具有一個(gè)核心屬性就是價(jià)格,有價(jià)格意味著可以交易。自然語言(Natural

Language)就是人類講的語言,它是人類自然發(fā)展中自然形成的,比如漢語、英語。這類語言不是經(jīng)過特別設(shè)計(jì)的,而是通過自然進(jìn)化的。它的特點(diǎn)是語法規(guī)則只是一種規(guī)律,并非需要嚴(yán)格遵守的規(guī)則,這種語言含有大量的推測,以及對話者本身的認(rèn)知背景(比如東西方不同的文化背景形成了大量的哩語)。認(rèn)知背景賦予了詞匯、概念的不同含義,比如,豆腐腦這個(gè)詞,不說東西方差異,就是國內(nèi)南北都會有爭議。著名的白馬非馬爭論在于自然語言的不確定性:?

從概念上說,白馬這個(gè)概念不是馬這個(gè)概念,所以白馬非馬。?

從謂詞(“是”這個(gè)謂詞)邏輯來說,白馬這個(gè)概念代表的事物集合屬于馬這個(gè)概念代表的事物集合。5為什么我們跟別人說不明白?所以白馬是馬(白馬屬于馬,但是白馬這個(gè)概念不是馬這個(gè)概念)。正因?yàn)槿绱?,才會產(chǎn)生大量的詭辯,讓交流效率降低。在邏輯學(xué)中,形式語言開始發(fā)揮作用。形式語言(FormalLanguage)是指用精確的數(shù)學(xué)或機(jī)器可處理的公式定義的語言。例如數(shù)學(xué)家用的數(shù)字和運(yùn)算符號、化學(xué)家用的分子式等,以及編程語言中的一些符號(Token)。計(jì)算機(jī)編程也是一種形式語言,是專門用來表達(dá)計(jì)算過程的形式語言,以操作計(jì)算機(jī)。形式語言需要嚴(yán)格遵守語法規(guī)則,例如

1+1=2

是數(shù)學(xué)中一種形式語言??傊佬问秸Z言和自然語言之間的區(qū)別,可以避免無意義的爭論。軟件工程師就是一個(gè)對現(xiàn)實(shí)業(yè)務(wù)形式化的工作崗位,將需求這種自然語言轉(zhuǎn)變?yōu)榇a這種形式語言。正因?yàn)槿绱耍枨蠛蜏贤ǖ拿懿豢赡鼙苊?,除非提出需求的人也使用形式語言,那么軟件工程師的價(jià)值也就沒有了。6為什么我們跟別人說不明白?使用形式語言可以精確地定義一個(gè)概念,并使用精確的語義規(guī)則和計(jì)算機(jī)溝通,這就是軟件工程師編寫軟件的過程。如果通過計(jì)算機(jī)語言來描述一個(gè)概念,其實(shí)就是面向?qū)ο笾械囊粋€(gè)類,這里定義商品有兩個(gè)屬性名稱和價(jià)格:publicclassItem{privateStringname;privateBigDecimalprice;}如果用集合的枚舉法來表述商品就是:Item{name,price}計(jì)算機(jī)語言和數(shù)學(xué)語言是一種形式化的語言,可以精確地描述一個(gè)概念,但是自然語言只能通過模糊地給出概念的描述。自然語言翻譯成計(jì)算機(jī)語言的不確定性,帶來了無休無止的爭吵,但這也是軟件設(shè)計(jì)者的主要工作。7為什么我們跟別人說不明白?3

對象應(yīng)該定義多少屬性?正是因?yàn)樽匀徽Z言的這種模糊性,為了更加具體地描述一個(gè)概念。哲學(xué)上概念的共識是,概念有兩個(gè)基本的邏輯特征,即內(nèi)涵和外延。概念反映對象的特有屬性或者本質(zhì)屬性,同時(shí)也反映了具有這種特有屬性或者本質(zhì)屬性的對象,因而概念有表達(dá)屬性的范圍。例如商品這個(gè)概念的內(nèi)涵是“能進(jìn)行交換的產(chǎn)品”,本質(zhì)屬性是能進(jìn)行交換,從本質(zhì)上區(qū)別產(chǎn)品。它的外延就是投入市場能賣的所有事物。對概念外延的清晰描述對我們設(shè)計(jì)軟件產(chǎn)品的定位非常有幫助,我們購買軟件服務(wù)無非兩種情況,生活娛樂使用,或者工作使用。馬克思社會經(jīng)濟(jì)學(xué)精妙的描述為生產(chǎn)資料、生活資料。這其中的邏輯完全不同,按照生活資料的邏輯設(shè)計(jì)一款生產(chǎn)資料的產(chǎn)品注定要走彎路。概念的內(nèi)涵和外延在一定條件下或者上下文中被確定的,這取決于參與人的共識。嚴(yán)格鎖定概念的內(nèi)涵和外延,能幫助我們討論問題和改進(jìn)軟件模型。隨意修改內(nèi)涵和外延這是典型的偷換概念和詭辯。8為什么我們跟別人說不明白?概念的內(nèi)涵和外延是一個(gè)此消彼長的兄弟。當(dāng)內(nèi)涵擴(kuò)大時(shí),外延就會縮小,概念就會變得越具體。當(dāng)內(nèi)涵縮小時(shí),外延就會擴(kuò)大,反映的事物就會越多。這在面向?qū)ο筌浖V械挠绊懛浅C黠@。對象特有屬性或者本質(zhì)屬性越少,那么這個(gè)對象能被復(fù)用的場景越多,也就是內(nèi)涵越小。反之,特有屬性越多,能被復(fù)用的情況就越少了。軟件建模過程中隨意修改概念往往意識不到,但是每一次屬性的添加和移除都帶來概念的內(nèi)涵和外延發(fā)生變化。非常典型的一個(gè)例子發(fā)生在訂單模型中。一般來說,我們會把支付單和訂單分開設(shè)計(jì),訂單的概念中沒有支付這個(gè)行為,但有時(shí)候覺得支付單的存在過于復(fù)雜,會將支付單的屬性放到訂單中,這個(gè)時(shí)候訂單的內(nèi)涵和外延變了。內(nèi)涵和外延發(fā)生變化但是設(shè)計(jì)人員沒有意識到,會使用同一個(gè)詞語。一旦使用同一個(gè)詞語就會產(chǎn)生二義性,二義性的存在對軟件建模是致命性打擊。比如用戶維護(hù)的地址、地址庫中的地址、訂單中的地址,這三個(gè)“地址”雖然名字相同,但是內(nèi)涵和外延不同。9為什么我們跟別人說不明白?意識不到概念的內(nèi)涵和外延,是無法設(shè)計(jì)出邏輯良好的軟件模型的。4

如何為變量命名?變量命名和緩存失效是編程中最讓人頭疼的兩件事。變量命名實(shí)際上就是為一個(gè)概念進(jìn)行定義。定義是揭示概念內(nèi)涵和外延的邏輯方法,而一個(gè)準(zhǔn)確的定義需要反映出對象的本質(zhì)屬性或特有屬性。在下定義時(shí),存在兩個(gè)常見的困難:1.

不知道如何使用良好的邏輯方法進(jìn)行定義。2.

對業(yè)務(wù)概念或者領(lǐng)域不熟悉。對于第一個(gè)困難,邏輯學(xué)有一些很好的下定義方法,可以根據(jù)概念的屬性、內(nèi)涵和外延來進(jìn)行。屬加種差定義法。

這種下定義的方法通俗來說就是先把某一個(gè)概念放到另一個(gè)更廣泛的概念中,邏輯學(xué)中將這個(gè)大的概念叫做“屬概念”,小的概念叫做“種概念”。從這個(gè)屬概念中找到一個(gè)相鄰的種概念,進(jìn)行比較,找出差異10為什么我們跟別人說不明白?化本質(zhì)屬性,就是“種差”。比如,對數(shù)學(xué)的定義,數(shù)學(xué)首先是一門學(xué)科,和物理學(xué)處于同類,它的本質(zhì)屬性是研究空間形式和數(shù)量關(guān)系。于是可以得到數(shù)學(xué)這個(gè)概念定義:數(shù)學(xué)是一種研究現(xiàn)實(shí)世界的空間形式和數(shù)量關(guān)系的學(xué)科。用這種方法給訂單、支付單、物流單下一個(gè)定義:訂單是一種反映用戶對商品購買行為的憑據(jù)。屬概念是“憑據(jù)”,種差是“反映用戶對商品購買行為”。支付單是一種反映用戶完成某一次支付行為的憑據(jù)。屬概念是“憑據(jù)”,種差是“用戶完成某一次支付行為”。物流單是一種反映管理員完成某一次發(fā)貨行為的憑據(jù)。屬概念是“憑據(jù)”,種差是“管理員完成某一次發(fā)貨行為”。在邏輯中可以參考下面的公式:被定義的概念

=種差

+屬概念對于第二個(gè)痛點(diǎn),這不是軟件建模能解決的問題,需要充11為什么我們跟別人說不明白?分和領(lǐng)域?qū)<矣懻?,獲取足夠的業(yè)務(wù)知識。人們對概念的定義或者認(rèn)識是隨著對事物的認(rèn)識不斷加深而變化的。一個(gè)完全對某個(gè)領(lǐng)域沒有基本認(rèn)識的軟件工程師很難做出合理的軟件建模,例如銀行、交易所、財(cái)會等領(lǐng)域的軟件需要大量的行業(yè)知識。我們做消費(fèi)者業(yè)務(wù)的互聯(lián)網(wǎng)開發(fā)時(shí),往往因?yàn)楹臀覀兊纳钕嚓P(guān),所以這種感受并不明顯。當(dāng)做行業(yè)軟件時(shí),領(lǐng)域知識對軟件模型的影響甚至是決定性的。5

避免無意義的爭論如果需要建立邏輯思維,還需要一些邏輯規(guī)律。邏輯學(xué)的三個(gè)基本規(guī)律可以讓溝通更加準(zhǔn)確,避免無意義的爭論,減少邏輯矛盾,讓討論有所產(chǎn)出。這三個(gè)重要的規(guī)律是:同一律、矛盾律、排中律。同一律在同一段論述(命題和推理)中使用的概念含義不變,這個(gè)規(guī)律就是同一律。形式化的表述是

A

A。同一律描述的是在一段論述中,需要保持概念的穩(wěn)定,否則會帶來謬誤。12為什么我們跟別人說不明白?在辯論賽中可以利用這個(gè)規(guī)律,贏取辯論。比如論題是“網(wǎng)絡(luò)會讓人的生活更美好嗎?”,兩個(gè)主要的論點(diǎn)是:?

網(wǎng)絡(luò)讓人們的生活更方便。?

網(wǎng)絡(luò)讓人們沉溺于虛擬世界。假如我們選擇的論點(diǎn)是“網(wǎng)絡(luò)讓人們的生活更方便”。在辯論賽中,我們陳述了“沒有網(wǎng)絡(luò)非常不方便”,反方被誘導(dǎo)描述了“打電話、寫信也可以讓人生活很美好,不一定需要網(wǎng)絡(luò),且不會像網(wǎng)絡(luò)一樣容易沉溺在虛擬世界中”。這剛好落入我們的邏輯陷阱。我們指出,郵政、電話網(wǎng)絡(luò)也是網(wǎng)絡(luò)的一種,對方的邏輯不攻自破。這屬于典型的“偷換概念”,我們偷換了“計(jì)算機(jī)網(wǎng)絡(luò)”和“網(wǎng)絡(luò)”這兩個(gè)概念。矛盾律矛盾律應(yīng)用得更為普遍,幾乎所有人都能認(rèn)識到矛盾律。它的含義是,在一段論述中,互相否定的思想不能同時(shí)為真。形式化的描述是:“A不能是非

A”。13為什么我們跟別人說不明白?矛盾律這個(gè)詞的來源就是很有名的“矛和盾”的典故,出自《韓非子

?

難勢》中。說有一個(gè)楚人賣矛和盾,牛吹得過大,說自己的盾在天底下沒有矛能刺破,然后又說自己的矛,天底下的盾沒有不能穿透的。前后矛盾是一個(gè)眾所周知的邏輯規(guī)律,但是并不是一開始馬上就能看出來,需要多推理幾步才能看出來。即使如此,在同一個(gè)上下文中,出現(xiàn)了矛盾的邏輯論述也被認(rèn)為是不可信的。具有矛盾的論述有時(shí)候又被稱為悖論。尤其是宗教領(lǐng)域充滿了大量的悖論,例如,是否存在一個(gè)萬能的神,做一件自己不能完成的事情。矛盾律的用處可以駁斥不合理的論斷,也可以用于反證法。在軟件開發(fā)過程中,我們時(shí)常遇到這種情況,需要在開發(fā)過程中才能發(fā)現(xiàn)矛盾。我們常常會接到一些充滿矛盾的需求,下面舉一個(gè)例子?!霸诙嘤脩艨臻g系統(tǒng)中,用戶可以被禁用并且可以加入多個(gè)空間。用戶所屬空間的管理員有權(quán)禁用用戶。即使用戶被某個(gè)空間管理員禁用,仍然可以使用其他空間的功能。”14為什么我們跟別人說不明白?上面提出了一個(gè)矛盾的業(yè)務(wù)需求:空間管理員可以修改用戶自身的禁用狀態(tài),但是又要求空間之間保持隔離。實(shí)際上,需求提出者并沒有理清用戶本身和空間成員之間的關(guān)系。在需求評審過程中,我們經(jīng)常會發(fā)現(xiàn)這種矛盾,并通過解決矛盾來改進(jìn)業(yè)務(wù)需求。排中律排中律是邏輯規(guī)律中最難理解的一個(gè)規(guī)律。它的表述是:同一個(gè)思維過程中,兩個(gè)互相否定的思想必然有一個(gè)是真的。用形式化的表述就是:“A或者非

A”。排中律的意義在于,明確分析問題的時(shí)候不能含糊其辭,從中騎墻。比如有人討論:人是不是動物。不能最終得到一個(gè)人既是動物又不是動物,這種討論是沒有意義的。比如在一次技術(shù)會議中,需要選擇使用的數(shù)據(jù)庫,只能使用一種數(shù)據(jù)庫。如果采用了

MySQL

就不能說沒有采用MySQL。排中律看起來好像沒有意義,卻是一項(xiàng)重要的邏輯原則,讓討論最終有結(jié)論,而不是處于似是而非的中間狀態(tài)。15用模型理解編程語言和面向?qū)ο笥媚P屠斫饩幊陶Z言和面向?qū)ο?模型是錯(cuò)誤的模型這個(gè)詞常常會聽到,通常出現(xiàn)在某個(gè)

PPT

或者一篇商業(yè)評論中。社會和經(jīng)濟(jì)學(xué)中的模型往往比較樸素,金字塔、V

型圖、四象限會以各種形式出現(xiàn)在不同場合中;軟件工程師的模型會更加形式化,UML、E-R

圖等,能用較為精確的形式語言描述;數(shù)學(xué)模型就更加精確,馬爾可夫、蒙特卡洛等模型可以用數(shù)學(xué)語言描述。廣義來說這些都叫模型,甚至是你隨手在白板上畫的一個(gè)用來解釋當(dāng)前程序結(jié)構(gòu)的圖形,通過這種方式表達(dá)思維框16用模型理解編程語言和面向?qū)ο蠹?。哲學(xué)家?guī)於鲗⑦@種思維框架叫做范式,也就是模型。維基百科將廣義的模型定義為:“用一個(gè)較為簡單的東西來代表另一個(gè)東西,這個(gè)簡單的東西被叫做模型?!蔽覀兲焐陀杏煤唵蔚臇|西代表另外一個(gè)東西的能力,比如幼兒園數(shù)數(shù)用的竹簽,學(xué)習(xí)物理時(shí)的剛體、真空中的球形雞,都是模型。通俗來說模型就是經(jīng)驗(yàn)的抽象集合,平時(shí)聽到的諺語、公式、定理本質(zhì)上都是一種模型。為了理解模型,斯科特

?

佩奇在

《模型思維》一書中給出了模型的幾個(gè)特征:1.

模型是簡化的。正是因?yàn)槲覀円J(rèn)識的事物非常復(fù)雜,因此需要通過簡化找出最一般的規(guī)律,才能一語中的?!疤靾A地方”學(xué)說就是最簡單的古人認(rèn)識世界的模型之一;毛主席的“階級劃分論”

簡單、直接地指出舊中國的社會狀態(tài)。2.

模型是邏輯的。例如用金字塔原理描述社會階層,每層的定義是明確的而非模糊的,數(shù)學(xué)模型能用數(shù)學(xué)符號系統(tǒng)和公式描述,模型中的元素能用一種邏17用模型理解編程語言和面向?qū)ο筝嬯P(guān)系做到自洽。3.

模型是錯(cuò)誤的。因?yàn)槟P褪且环N抽象,所有的模型都是錯(cuò)誤的,只能在一個(gè)方面反映事物的特征。場景變了,模型就需要修正,連牛頓、愛因斯坦的定1律都沒能逃脫這個(gè)規(guī)律

。好的模型能在盡可能簡單的情況下較好地?cái)M合事物,完全匹配現(xiàn)實(shí)的模型就不再滿足簡化特征了。為了建立和利用模型,模型思考有幾個(gè)層次:1.

數(shù)據(jù)。我們能直接觀察到的現(xiàn)實(shí)情況,比如下雨了,并從觀察到的情況中采樣,轉(zhuǎn)換成具體的數(shù)字,得到某個(gè)地區(qū)某年的降雨量。2.

信息。信息是數(shù)據(jù)中反映出能被人類理解的內(nèi)容,比如通過降雨量判斷一個(gè)地區(qū)是否屬于干旱地區(qū)。3.

知識。知識是對信息的處理方式,比如我們利用信息,將信息中的一般規(guī)律找出來,建立模型。比如某地區(qū)降雨量和年度呈現(xiàn)一定相關(guān)性,建立一個(gè)周期性降雨模型。1經(jīng)典力學(xué)在高速、微觀場景不適用;相對論在粒子物理學(xué)不適用。18用模型理解編程語言和面向?qū)ο?.

智慧。面對不同情況需要使用不同的模型和修正模型的能力,并能用它指導(dǎo)實(shí)踐,比如根據(jù)周期性降雨模型修建水利設(shè)施。我們可以嘗試用這種方式來看待原本很困難的知識,比如去簡化復(fù)雜問題,并理解它。通過模型思維來看待軟件開發(fā),我們會發(fā)現(xiàn),軟件從設(shè)計(jì)到開發(fā)的過程就是各種模型的轉(zhuǎn)換。2

軟件工程中的模型我整理了一個(gè)圖表,說明了一款軟件從商業(yè)探索開始,到編譯成可交付的軟件整個(gè)過程中可能會用到的模型。PPTERUML圖?1??軟件工程中的模型19用模型理解編程語言和面向?qū)ο笪覍⒛P头譃樾问交头切问交瘍煞N。形式化的模型是精確描述的模型,例如表達(dá)領(lǐng)域模型的

UML、ER

圖,而非形式化的模型是一些非精確描述的模型,主要用來做商業(yè)、業(yè)務(wù)探索。對于應(yīng)用開發(fā)的軟件工程師來說,核心的問題并非如何編寫代碼,而是如何將非形式化的業(yè)務(wù)輸入(模型)進(jìn)行合理抽象、設(shè)計(jì),并轉(zhuǎn)換為形式化的過程。某種程度上來說,通過高級語言編寫的代碼也是一種模型。在多年以前,計(jì)算機(jī)科學(xué)家們認(rèn)為編寫

Java

代碼的人不算程序員,可以由業(yè)務(wù)人員直接編寫業(yè)務(wù)軟件。由于軟件工程中非形式化和形式化之間存在一個(gè)巨大的鴻溝,編程就是模型的形式化過程,從這個(gè)角度看能深刻分析業(yè)務(wù)并獲得良好抽象結(jié)果的程序員具有競爭力,即便我們有了ChatGPT,分析業(yè)務(wù)和建模的工作也不會被它替代。在非形式化模型這一步,實(shí)際上又存在兩種模型。一種是描述軟件背后的生意,即使不使用計(jì)算機(jī)系統(tǒng)參與到業(yè)務(wù)中,該如何完成交易,并讓企業(yè)獲得利潤,我把它叫做商業(yè)模型。另一種是描述軟件的操作和交互的模型,關(guān)注參20用模型理解編程語言和面向?qū)ο笈c的用戶、流程和業(yè)務(wù)規(guī)則,我把它叫做軟件業(yè)務(wù)模型。除此之外,還有一些模型和計(jì)算機(jī)工作原理相關(guān)的模型,這是計(jì)算機(jī)科學(xué)家的工作,對于普通開發(fā)者來說可以加深對計(jì)算機(jī)的理解。例如,符合人類的認(rèn)知的編程語言(面向?qū)ο蟆⒑瘮?shù)式)背后的模型,面向?qū)ο罂梢钥醋饕环N模型,還有一些計(jì)算機(jī)科學(xué)基礎(chǔ)的模型:馮諾依曼結(jié)構(gòu)、圖靈模型、布爾邏輯(數(shù)理模型)。將這些模型串起來,能夠提高對軟件工程的理解,以及每個(gè)部分背后的邏輯,明白這些模型背后的目標(biāo)后可以更加從容地應(yīng)對各種問題。限于篇幅本章討論計(jì)算機(jī)科學(xué)中的模型,關(guān)于商業(yè)、業(yè)務(wù)分析、架構(gòu)的模型將在后續(xù)討論。3計(jì)算機(jī)科學(xué)中的模型如今,計(jì)算機(jī)已經(jīng)發(fā)展到一種近乎魔法般的存在。對于非計(jì)算機(jī)專業(yè)畢業(yè)的從業(yè)者而言,理解計(jì)算機(jī)和編程語言的原理以及面向?qū)ο笏枷胱兊美щy。然而,我們可以尋找一些模型或比喻來幫助我們理解與計(jì)算機(jī)相關(guān)的內(nèi)容。21用模型理解編程語言和面向?qū)ο髲乃惚P、計(jì)算機(jī)到電腦從算盤到計(jì)算機(jī),人類走過了漫長的歷史。計(jì)算機(jī)發(fā)展的轉(zhuǎn)折點(diǎn)往往都是一些大師提出關(guān)鍵模型的時(shí)期,了解這些模型可以幫我們更好理解計(jì)算機(jī)世界。新一代的軟件工程師已經(jīng)不再關(guān)注計(jì)算機(jī)是如何工作的了,他們把計(jì)算機(jī)當(dāng)作一種可以通過編程語言對話的“生物”來看待了。我曾被問到過,我們?nèi)粘J褂玫摹半娔X”為何被稱作計(jì)算機(jī),它和計(jì)算看似毫無關(guān)系。要回答這個(gè)問題需要將圖靈和馮諾依曼模型兩個(gè)計(jì)算機(jī)科學(xué)基礎(chǔ)模型清晰地分開。算盤會被經(jīng)常和計(jì)算機(jī)一起提到,算盤是人力驅(qū)動的一種計(jì)算機(jī),算珠的狀態(tài)可以看作寄存器。對中國人來說理解圖靈機(jī)非常簡單,我們可以使用算盤來類比。當(dāng)算盤歸零后,算盤的狀態(tài)為初始狀態(tài),每一次撥動算珠就是一個(gè)指令,當(dāng)所有的指令下發(fā)完成,算盤上最終狀態(tài)就是計(jì)算結(jié)果。指令序列就是算法,算盤就是一個(gè)狀態(tài)機(jī)。在算盤之后的時(shí)代,還有計(jì)算尺,甚至手搖計(jì)算機(jī)。手搖22用模型理解編程語言和面向?qū)ο笫接?jì)算機(jī)算是一種半自動的計(jì)算機(jī),我國科研人員曾使用它進(jìn)行原子彈的計(jì)算工作。把“計(jì)算”這兩個(gè)字與計(jì)算機(jī)聯(lián)系在一起的功勞應(yīng)歸于圖靈。1937

年,圖靈發(fā)表了一篇論文,闡述了可計(jì)算性的概念,并提出了計(jì)算機(jī)的抽象模型。在論文《論可計(jì)算數(shù)及其在判定問題中的應(yīng)用》中,圖靈提出了著名的理論計(jì)算機(jī)抽它描述了這樣一種機(jī)器:一個(gè)虛擬的機(jī)器,由一條無限長的紙帶和讀寫頭組成。紙帶上分布有連續(xù)的格子,并能被移動、讀寫。機(jī)器能讀取一個(gè)指令序列,指令能對格子紙帶進(jìn)行移動和讀寫。和算盤的邏輯一樣,機(jī)器每執(zhí)行一個(gè)指令,紙帶的狀態(tài)就發(fā)生了變化,最終完成計(jì)算。圖靈模型只是描述了一步一步地完成計(jì)算任務(wù),這種機(jī)器稱不上“電腦”。讓一堆“沙子”具備通靈般能力的人是馮

?諾依曼。現(xiàn)代的計(jì)算機(jī)實(shí)際上是一個(gè)死循環(huán),可以類比為沖程發(fā)動機(jī),才讓計(jì)算機(jī)看起來有了生命。這才有了我們說熟悉的“電腦”。ENIAC

是公認(rèn)第一個(gè)滿足圖靈模型的計(jì)算電子計(jì)算機(jī),23用模型理解編程語言和面向?qū)ο驟NIAC

通過紙帶編寫程序,并撥動開關(guān)執(zhí)行和獲得結(jié)果。馮

?

諾依曼在比

ENIAC

更先進(jìn)的計(jì)算機(jī)項(xiàng)目

EDVAC

中描述了另外一種模型,他認(rèn)為程序本質(zhì)上也是一種數(shù)據(jù),將指令和數(shù)據(jù)共同存放到內(nèi)存中,這些指令中存在特殊的跳轉(zhuǎn)指令,讓程序周而復(fù)始地運(yùn)行。存儲程序模型構(gòu)建了一個(gè)能自我運(yùn)行計(jì)算模型,構(gòu)成了一個(gè)系統(tǒng)。處理器和內(nèi)存之間使用總線連接,用來給這個(gè)系統(tǒng)提供輸入的設(shè)備叫做外設(shè),每一次指令循環(huán)可以訪問一次外設(shè)傳入的信號,這就是中斷。想象一臺由繼電器組成的計(jì)算機(jī),如果每一次執(zhí)行指令計(jì)算機(jī)會發(fā)出“嘚”

的聲音,圖靈模型就是程序開始運(yùn)行后線性地嘚嘚嘚……嘚嘚?!?。馮

?

諾依曼的模型就是上電后

嘚嘚嘚嘚嘚……中斷……嘚嘚嘚嘚嘚”,并反復(fù)循環(huán)。馮

?

諾依曼讓計(jì)算機(jī)永不停息,并產(chǎn)生交互效果。24用模型理解編程語言和面向?qū)ο驝PU圖?2??馮

?

諾依曼簡化模型總的來說,圖靈模型將解決問題的過程抽象為算法和數(shù)據(jù),馮

?

諾依曼進(jìn)一步抽象了算法也是數(shù)據(jù),進(jìn)而讓計(jì)算機(jī)無限循環(huán)下去。至于怎么通過門電路實(shí)現(xiàn)基本運(yùn)算(全加器)可以參考《編碼:隱匿在計(jì)算機(jī)軟硬件背后的語言》一書。通過自動推理模型理解編程語言各種各樣的編程語言層出不窮,由于工作的需要,我們會接觸不同的編程語言。如何能理解編程語言的本質(zhì)是什么呢?我嘗試找一些模型簡化對編程語言的理解。先用矛盾論分析一下編程語言解決的什么矛盾:計(jì)算機(jī)只能識別機(jī)器指令和人類難以使用機(jī)器指令解決具體問題之間的矛盾。所以人類設(shè)計(jì)出來各種各樣符合人類習(xí)慣(各不相同)的25用模型理解編程語言和面向?qū)ο蠓绞骄帉懗绦?,這些編寫程序的模型就是高級語言。要使用自己定義的語法規(guī)則來寫程序,就需要一個(gè)轉(zhuǎn)換器,能將符合人類習(xí)慣的語法進(jìn)行轉(zhuǎn)換,這就是編譯器。一門新的語言需要滿足幾個(gè)條件:1.

新定義的語法必須是形式化的。2.

新定義的語法能方便地轉(zhuǎn)換。3.

人們能接受這種語法編寫程序。所以編譯器是一個(gè)自動推理機(jī),只要能被推理的形式化語言都可以作為輸入。除了自然語言無法實(shí)現(xiàn)之外,無論用中文、表情包、符號、圖形都能作為一種編程語言的形式。編譯的過程有:語法分析、詞法分析、語義分析、中間代碼和優(yōu)化、目標(biāo)代碼。大師通過編譯過程學(xué)習(xí)如何實(shí)現(xiàn)編譯器,普通工程師可以反過來用這個(gè)過程理解一門新的語言。我嘗試將編譯過程中的環(huán)節(jié)找到一個(gè)現(xiàn)實(shí)中的類比來理解編譯器,將其類比為人類閱讀法律文書(法律文件是最貼26用模型理解編程語言和面向?qū)ο蠼问交淖匀晃谋荆?。階段編譯器類比掃描,識別代碼處理調(diào)查材料,案詞法分析Token,將關(guān)鍵字、變量、

件人員、行為等要操作符提取出來素將

Token

組織為一棵樹

(AST)用于推理將人員和行為映射成圖譜,用于形式邏輯推理語法解析識別行為發(fā)生的語義分析

處理上下文相關(guān)的信息

動機(jī)、背景,提取上下文信息上面三步是前端,中中間代碼間代碼是為了多平臺

整理為卷宗代碼生成用根據(jù)不同的平臺進(jìn)行

輸出到報(bào)紙、網(wǎng)目標(biāo)代碼代碼生成站等媒體27用模型理解編程語言和面向?qū)ο笪?/p>

程,

https:///a-map-of-the-territory.html這個(gè)網(wǎng)站介紹了一個(gè)清晰的編譯過程。理

學(xué)

多,

法(Grammar)有三個(gè)層次:1.

詞法(Lexical):決定哪些表達(dá)式、關(guān)鍵字是否合法。2.

句法(Syntax):決定一個(gè)句子是否合法,比如流程語句。3.

語義(Grammar):決定一段代碼的組織結(jié)構(gòu)是否合法,函數(shù)、類、閉包等規(guī)則。Lexical

Syntax

往往可以看成一體,Grammar

不太一樣,在一些編譯器中

Syntax

Grammar

的錯(cuò)誤提示都不太一樣。所以可以這樣看一門語言:Syntax

是類

C

的還是非類

C

的,Grammar

上是面向?qū)ο蟮倪€是面向過程的,是否支持閉包這類上下文追溯的能力。理

學(xué)

習(xí)

言,

如TypeScript

可以編譯成

JavaScript,很多時(shí)候我們不需28用模型理解編程語言和面向?qū)ο笠貏e學(xué)習(xí)

TypeScript,將小段

TypeScript

代碼編譯一下,看看生成的

JavaScript是什么就行了。面向?qū)ο竽P陀辛俗詣油评頇C(jī),可以將人們定義的語法轉(zhuǎn)換成機(jī)器代碼的語法規(guī)則。讓我們有了方法、變量、條件、循環(huán)等這些概念,可以大大簡化編程的心智負(fù)擔(dān)。面向過程的語言依然還是圖靈模型解決問題的思路:有限的有序指令序列。只不過這里的指令從機(jī)器語言、匯編代碼換成了容易理解的表達(dá)式而已,面向過程的編程語言和機(jī)器代碼在認(rèn)知上沒有本質(zhì)區(qū)別。組織面向過程的程序,這部分工作的心智負(fù)擔(dān)需要高水平的程序員來完成,將現(xiàn)實(shí)中的業(yè)務(wù)分解成有限的有序指令序列。分解任務(wù)成為指令序列的過程就是編程,它要求程序員既要像人一樣思考現(xiàn)實(shí)又要像機(jī)器一樣思考。像機(jī)器一樣思考需要最聰明的人來完成才行,好的程序員可不好找。能不能想辦法利用推理機(jī),再進(jìn)一步,讓程序員按照人類29用模型理解編程語言和面向?qū)ο笠粯铀伎际挛?,寫出符合人類語義的代碼,然后再翻譯成目標(biāo)代碼呢?回答這個(gè)問題就需要先回答另外一個(gè)問題,符合人類認(rèn)知的思考方式的語言是怎么回事。人類需要通過概念來進(jìn)行交流,給一撮物質(zhì)一個(gè)標(biāo)簽,這個(gè)標(biāo)簽就是概念。將一堆便簽夾起來再打上標(biāo)簽,就是抽象概念。不同的語言、不同文化背景的人無法交流就是因?yàn)槭褂昧瞬煌臉?biāo)簽系統(tǒng),甚至也有可能標(biāo)簽貼錯(cuò)了的情況,導(dǎo)致認(rèn)知無法對齊。要理解面向?qū)ο缶幊?,需要到生活中去觀察小孩玩泥巴的情景。他們用泥巴創(chuàng)造出一個(gè)城堡,而泥土就好像計(jì)算機(jī)世界中的數(shù)據(jù)。將泥土組織成有清晰邊界的物品就是對象。我們?yōu)榱嗣枋鲞@類對象,就給它們起個(gè)名字以便交流。類可以對應(yīng)現(xiàn)實(shí)中的一個(gè)概念,但很多面向?qū)ο缶幊痰臅]有明確說明這一點(diǎn)??梢园熏F(xiàn)實(shí)和面向?qū)ο笾械脑貙Ρ纫幌?,建立一個(gè)理解面向?qū)ο蟮哪P汀?0用模型理解編程語言和面向?qū)ο蟋F(xiàn)實(shí)人類語言比喻面向?qū)ο笠活愇镔|(zhì)概念標(biāo)簽類給一組標(biāo)簽打包再打個(gè)標(biāo)簽不存在實(shí)物抽象概念抽象類一個(gè)有清晰邊界的物體用陶土制作了一個(gè)杯子對象的實(shí)例化實(shí)體拿起了這個(gè)杯子一個(gè)有行動的人人調(diào)用者有手就能拿起杯子符合條件的人契約接口所以面向?qū)ο缶幊淌墙⒃诜浅:玫男闹悄P蜕系模徊贿^這個(gè)模型對于不熟悉西方哲學(xué)的人來說過于抽象。對象、實(shí)體、類、行為,這些面向?qū)ο笾械膬?nèi)容和概念早已經(jīng)被哲學(xué)家討論過數(shù)千年,但是在中文的語境中并不常見。人是通過語言思考的,我們不遺余力地使用自然語言描述事物,面向?qū)ο笫怯?jì)算機(jī)語言和自然語言的一座橋梁,這座橋梁由哲學(xué)連接。對象這個(gè)詞在不同的領(lǐng)域都被用到,31用模型理解編程語言和面向?qū)ο蠖也皇乔珊希?.

哲學(xué)中的對象概念。2.

數(shù)學(xué)(范疇學(xué))中的對象概念。3.

語言中的賓語。維特根斯坦的《邏輯哲學(xué)論》中對對象、類的闡述和面向?qū)ο髽O為相似,不過這本書非?;逎?。通俗來說:對象是人認(rèn)識世界的基本單位,對象由實(shí)體和正在發(fā)生的事構(gòu)成。也就是說對象不是一成不變的,可以由“造物主”自由地設(shè)計(jì)和組合。當(dāng)我們在開發(fā)一款

XXX

管理系統(tǒng)時(shí),被管理的“物品”被模擬為一個(gè)靜態(tài)的物品,就能看作一個(gè)對象。假設(shè)我們正在開發(fā)倉儲管理系統(tǒng),極端的面向?qū)ο笳邥嬖V你將行為放到“貨物”這類實(shí)體中,這樣看起來更加像面向?qū)ο蟮娘L(fēng)格,但是他們背離了面向?qū)ο蟮某踔浴L摂M的世界里,靜態(tài)的對象需要由動態(tài)的對象處理構(gòu)成了一組主客體關(guān)系。而對于“上帝”來說,它們都是對象。32用模型理解編程語言和面向?qū)ο笫煜?/p>

Java

的程序員可以這樣理解,Spring

中的

Bean

是一種對象,在應(yīng)用啟動時(shí)就被初始化了,就像上帝造出亞當(dāng)開始干活兒。而從數(shù)據(jù)庫中提取出來的實(shí)體,就像是從倉庫中提取出來的“物品”。如果開發(fā)一款游戲,對象貌似都是有生命的。但是對于普通的管理系統(tǒng)來說,真正需要設(shè)計(jì)的是“貨物管理者”、“收銀員”這類對象,而“貨物”這類實(shí)體就應(yīng)該讓它們安安靜靜地躺在那里。使用面向?qū)ο笤骄?,越會下意識地使用面向?qū)ο笏伎棘F(xiàn)實(shí),面向?qū)ο笫浅绦騿T進(jìn)入哲學(xué)世界的啟蒙課。33理解軟件背后的生意理解軟件背后的生意1

需求變化的原因:軟件價(jià)值金字塔需求變化是軟件工程師最難以容忍的一件事,為了做好軟件設(shè)計(jì),不得不猜測未來需求的變化方向。猜中了就是“正交分解”,猜不中就是冗余設(shè)計(jì)。那么需求變化背后的邏輯是什么呢?首先我們不得不承認(rèn),從客觀上講軟件它是有區(qū)別于硬件的,為什么叫軟件,因?yàn)樗旧砭褪悄芨牡?,并且修改的成本低于硬件。硬件涉及電路設(shè)計(jì)、制版、開模等流程,在開發(fā)的過程當(dāng)中,需求變化會帶來巨大的成本。這是為34理解軟件背后的生意什么軟件能夠提高效率的原因,因?yàn)橥ㄟ^軟件搭建在通用計(jì)算機(jī)平臺上,能夠很快做出業(yè)務(wù)應(yīng)用和實(shí)現(xiàn)。通用軟件的出現(xiàn),軟件開發(fā)和硬件開發(fā)分離是信息社會的一個(gè)關(guān)鍵節(jié)點(diǎn),所以軟件被發(fā)明出來就是為了容易改。但是事物總是矛盾的,容易改的軟件相比硬件降低了成本,但軟件容易修改的能力被濫用后,給軟件工程也帶來負(fù)擔(dān)。對于軟件來說,修改并不是沒有成本的,只是相對硬件而言小了許多。對軟件工程師來說,業(yè)務(wù)的變化往往會帶來困擾,因?yàn)樗鼤屲浖募軜?gòu)設(shè)計(jì)和模型的建立變得非常復(fù)雜。但并不是所有的軟件需求變化,我們都不能接受。對于一些軟件的交互和界面

UI

樣式等這些細(xì)節(jié)上面的修改不影響主體的業(yè)務(wù)變化,這種修改是沒有任何問題的。我們說的軟件需求變化帶來的困擾指的是在軟件開發(fā)過程中隨意變更軟件的邏輯,讓軟件的整體性和邏輯性受到了破壞,這是我們不喜歡,不能接受的軟件修改的方式之一。對于專業(yè)的產(chǎn)品經(jīng)理來說,軟件的修改是非常謹(jǐn)慎的,因?yàn)樾薷囊粋€(gè)地方,可能會影響其他地方。35理解軟件背后的生意那么在軟件開發(fā)和迭代的過程當(dāng)中,我們可能難以意識到一個(gè)小小的修改會影響整個(gè)開發(fā)、測試、上線等不同的環(huán)節(jié),造成項(xiàng)目的延期,這是開發(fā)團(tuán)隊(duì)人員不喜歡軟件被修改的根本原因。那么怎么應(yīng)對軟件需求的變化呢?軟件價(jià)值金字塔模型如果我們對軟件的需求進(jìn)行分層,我們可以把軟件所存在的價(jià)值分為

4層。最底層是軟件所存在的業(yè)務(wù)價(jià)值,或者是通俗來說它是前面提到的“軟件的生意”。我們在構(gòu)建一個(gè)點(diǎn)餐軟件、構(gòu)建一個(gè)電商軟件、構(gòu)建一個(gè)物流軟件,那么軟件幫我們做的事情就是取代原來傳統(tǒng)商業(yè)活動中人需要做的事情。提高這些行為的效率,為社會創(chuàng)造更多的價(jià)值,這些軟件背后的需求就是我們的生意。業(yè)務(wù)價(jià)值,可以看做軟件的靈魂。那么在這層軟件需求之上的,是我們軟件的架構(gòu)。軟件的架構(gòu)承載了生意或者商業(yè)模式,可以看做軟件的骨骼。比如說電商里面就有訂單等這些關(guān)鍵的模型,或者一些慣用模式。類比起來就相當(dāng)于我們?nèi)梭w的一個(gè)骨架或者建筑物36理解軟件背后的生意的一些承重結(jié)構(gòu)。還有一些是軟件的一些具體的邏輯細(xì)節(jié),比如說約束電商系統(tǒng)確認(rèn)收貨時(shí)間是多少天。軟件這些業(yè)務(wù)規(guī)則,就像人體的血肉一樣,豐富了軟件。業(yè)務(wù)規(guī)則填充了軟件的一些交互邏輯細(xì)節(jié),讓軟件工程師在不修改主體結(jié)構(gòu)的情況下去,改這些邏輯細(xì)節(jié),有時(shí)候并不是非常困難的,軟件工程師對于這類需求的變化也是樂于接受的。還有一種軟件的需求,就是軟件的交互方式和

UI

樣式,這些就好像動物的皮膚。不具備特別的功能性,而是負(fù)責(zé)軟件的美觀性。這些需求的變化,修改成本也是非常低的。所以我們總結(jié)一下軟件的價(jià)值可以分為

4層:圖

1??軟件價(jià)值金字塔模型37理解軟件背后的生意當(dāng)我們軟件的業(yè)務(wù)架構(gòu)和業(yè)務(wù)價(jià)值發(fā)生翻天覆地的變化時(shí),修改這個(gè)軟件的難度,會呈指數(shù)上升,不亞于重新設(shè)計(jì)一個(gè)軟件。對于創(chuàng)業(yè)公司來說,他們的業(yè)務(wù)架構(gòu)和生意,或者說它的商業(yè)模式還不確定,還在探索當(dāng)中。對于這樣的業(yè)務(wù)來說,他們的需求幾乎每天都會發(fā)生變化,因?yàn)樗麄兊纳鈺?,一旦生意會變,“上層建筑就會變化”。對于成熟的公司來說,軟件是這個(gè)公司業(yè)務(wù)流程的沉淀,業(yè)務(wù)流程可能不會發(fā)生特別大的變化,比如說銀行、保險(xiǎn)或者財(cái)會,這些特定的業(yè)務(wù)流程基本上已經(jīng)形成了行業(yè)的規(guī)范或者標(biāo)準(zhǔn)。他們的變化情況不會特別大,那么軟件的架構(gòu)也就不容易受到破壞,重大的業(yè)務(wù)需求變化就會非常少。理解軟件背后的生意軟件價(jià)值模型給了軟件工程師兩點(diǎn)啟示。一個(gè)能夠在市場上存活的軟件,一定有它背后的業(yè)務(wù)邏輯和業(yè)務(wù)價(jià)值。那么我們從底層出發(fā),找到了一個(gè)軟件的業(yè)38理解軟件背后的生意務(wù)價(jià)值,也就是它的生意,我們就可以快速地理解軟件的架構(gòu)。其次,我們可以真正地挖掘出業(yè)務(wù)分析師或產(chǎn)品經(jīng)理希望的業(yè)務(wù)?;谲浖r(jià)值模型,軟件背后的邏輯和生意總是存在的,但是產(chǎn)品經(jīng)理不一定能夠用自己的語言或合適的方式講給軟件工程師。對于軟件工程師來說,只有兩個(gè)選擇。要么給自己的軟件的架構(gòu)設(shè)計(jì)提供足夠的靈活性,這也是很多軟件設(shè)計(jì)思想提倡的。但它背后的代價(jià)很明顯,我們需要留出

“冗余設(shè)計(jì)”,在特定的環(huán)境下,軟件的競爭力被削弱。一個(gè)有靈活或者彈性的軟件架構(gòu),背后是付出一定的代價(jià),但往往我們沒有意識到這一點(diǎn)。另外一個(gè)選擇就是真正地理解軟件背后的生意,通過軟件價(jià)值模型的啟示從變化中找到不變。因此我們不得不將視野從軟件本身返回到軟件承載的業(yè)務(wù)上,為了理解這些業(yè)務(wù)我們又需要追溯回到這些業(yè)務(wù)服務(wù)的商業(yè)目標(biāo)中。那么軟件工程師理解軟件的路徑為:理解商業(yè)→理解業(yè)務(wù)→理解軟件產(chǎn)品和信息系統(tǒng)。39理解軟件背后的生意2

理解商業(yè)模式如果我們理解了軟件背后的生意,可以更加從容地設(shè)計(jì)軟件。更為重要的是,和需求提出者的交流更加容易,除非需求提出者也并不熟悉正在設(shè)計(jì)的軟件背后承載的商業(yè)目標(biāo)。分析一個(gè)企業(yè)的商業(yè)模型方法非常多,下面介紹比較常見顧名思義,商業(yè)模式畫布是一種描述企業(yè)商業(yè)模式的模型,最早來源于亞歷山大

?

奧斯特瓦德的《商業(yè)模式新生代》一書。其主要的思想是,商業(yè)模式不應(yīng)該由幾百頁的商業(yè)策劃書來描述,而是應(yīng)該由一頁紙就能清晰地呈現(xiàn)。根據(jù)思維經(jīng)濟(jì)性原則,無法清晰表述的商業(yè)模式其價(jià)值也值得懷疑。商業(yè)模式畫布,包含

9

個(gè)模塊,可以呈現(xiàn)在一張畫布上。如下圖所示:40理解軟件背后的生意87241Key

PartnersKey

ActivitiesValueCustomerCustomerPropositionRelationshipSegmenets63KeyResourcesChannels95CostStructureRevenueStream圖?2?商業(yè)模式畫布編寫商業(yè)模式畫布實(shí)際上是需要回答

9

個(gè)問題,弄明白至少這

9個(gè)問題,才能知道對未來相關(guān)的商業(yè)設(shè)想是否靠譜。如果投資人看這份商業(yè)模式畫布,才能快速知道這筆生意是否能賺錢。使用商業(yè)模式畫布來研究商業(yè)模式的案例非常多,這些案例的研究材料容易找,我以拼多多為例并結(jié)合

IT

視角來看商業(yè)模式對信息系統(tǒng)的影響。很多人可能和我一樣對拼多多有一些疑惑,為什么在電商41理解軟件背后的生意格局已經(jīng)充分競爭后,依然還有崛起的機(jī)會?我們不妨用商業(yè)畫布來分析一下。1.

客戶細(xì)分(CS,Customer

Segments)拼多多的客戶是什么?如果不加以區(qū)分客戶和用戶,我們很容易得到拼多多的客戶是普通的消費(fèi)者。實(shí)際上從財(cái)務(wù)的角度,如果消費(fèi)者的每一筆消費(fèi)都算在拼多多的收入中,那么拼多多需要支付巨額的增值稅,消費(fèi)者不是拼多多的客戶。拼多多的業(yè)務(wù)旨在幫助小微企業(yè)、農(nóng)戶和個(gè)人快速開設(shè)店鋪,并從中獲得傭金。因此,在客戶這一側(cè)和淘寶網(wǎng)的初期發(fā)展階段相比,拼多多并沒有太大的差別。在某種程度上,由于天貓的存在和戰(zhàn)略因素,阿里電商在這個(gè)領(lǐng)域相當(dāng)薄弱。2.

價(jià)值主張(VP,ValuePropositions)關(guān)于價(jià)值主張這部分我一直比較疑惑,拼多多到底能提供什么新的價(jià)值?42理解軟件背后的生意1在一份名為《“電商黑馬”拼多多的商業(yè)模式探析》的報(bào)告中,提到了拼多多價(jià)值主張為“免去諸多中間環(huán)節(jié),實(shí)現(xiàn)

C2M

模式,提供物有所值的商品和互動式購物體驗(yàn)的

“新電子商務(wù)”平臺。C2M

為(Customer-to-Manufacturer,用戶直連制造)但是這個(gè)模式并不新鮮,戴爾、玫琳凱等直銷公司都是這種模式。一些分析者將拼多多的模式總結(jié)為物找人。通過拼單的方式,先定義物品,再通過社交媒體找到需要的目標(biāo)群體。讓“社會化消費(fèi)”發(fā)揮作用。從價(jià)值主張上說,拼多多的價(jià)值和其他主流、非主流電商的差異并不大。3.

渠道通路(CH,Channels)在價(jià)值主張上,各種電商平臺差距非常小,無非都是“消除中間商,降低流通成本”。但是在細(xì)分領(lǐng)域,渠道通路的競爭非常明顯,甚至有些電商平臺將自己的電商屬性隱藏了起來。1

.“

馬”

業(yè)

[J].

務(wù)

財(cái)會

,2021(11):34-37+41.43理解軟件背后的生意例如,以社交抹茶美妝、小紅書、Keep

這些產(chǎn)品的電商屬性非常弱,實(shí)際上是通過社交渠道強(qiáng)化了電商的渠道能力。拼多多的渠道是建立在一種病毒營銷的模式上的,俗稱“人傳人”。4.

客戶關(guān)系(CR,Customer

Relationships)2拼多多的店鋪分為了幾類

,不過最終還是可以分為專業(yè)類(企業(yè)或個(gè)體工商戶店)和普通類。專業(yè)類的客戶為具有一定資本的經(jīng)銷商,需要繳納保證金以及工商登記材料,普通類的無需保證金和工商材料即可開店,而正是普通類占據(jù)了主要的店鋪類型。5.

收入來源(RS,Revenue

Streams)根據(jù)財(cái)報(bào)顯示(2021

年數(shù)據(jù)),拼多多的收入來源為在線市場服務(wù)和少量的自營商品銷售,財(cái)務(wù)來源并沒有特殊的地方,主要還是來源于店鋪傭金。6.

核心資源(KR,KeyResources)在商業(yè)模式和收入來源都沒有特殊的情況下,拼多多的核心資源是什么呢?在一些商業(yè)分析中,將拼多多的核心資2參考拼多多商家入駐說明

/qualifications44理解軟件背后的生意源歸結(jié)為用戶流量。截至

2021

年第一個(gè)季度結(jié)束,拼多多年活躍買家數(shù)達(dá)

8.238

,那么這些買家是從哪里來的呢?3除了前面說的“人傳人”的基礎(chǔ)上,拼多多借助了微信渠道,可以說這是拼多多的核心資源。7.

關(guān)鍵業(yè)務(wù)(KA,KeyActivities)拼多多的關(guān)鍵業(yè)務(wù)是市場活動和供應(yīng)鏈管理。8.

重要合作(KP,KeyPartnership)拼多多的合作伙伴有:騰訊微信、物流企業(yè)、電視媒體。將商家排除在外的原因是,商家已經(jīng)作為了客戶存在。換句話說,商家是賺消費(fèi)者的錢,拼多多是賺商家的錢。由騰訊微信提供渠道,通過特有的病毒營銷獲得用戶流量,并將流量轉(zhuǎn)化為商家的客源,可以看做是微信的用戶群體資源在電商領(lǐng)域的變現(xiàn)。9.

成本結(jié)構(gòu)(CR,Cost

Structure)拼多多的成本結(jié)構(gòu)主要是市場推廣費(fèi)用,其次是管理費(fèi)用3數(shù)據(jù)來源

/k/20220527A0AG730045理解軟件背后的生意和研發(fā)費(fèi)用。根據(jù)商業(yè)模式畫布分析,拼多多的商業(yè)模式主要是以獨(dú)特的營銷推廣為基礎(chǔ),為小微企業(yè)和個(gè)體農(nóng)商戶促成交易。在交易渠道上借助了微信騰出的渠道真空(微信渠道對淘寶不開放,拼多多和京東無太多競爭關(guān)系,騰訊為拼多多的第二大股東)。從其營收結(jié)構(gòu)主要為在線市場傭金收入反映了這一點(diǎn),成本結(jié)構(gòu)上以營銷費(fèi)用為主也進(jìn)一步佐證。3

理解業(yè)務(wù)通過商業(yè)模式畫布可以理解企業(yè)的商業(yè)模式,弄明白在企業(yè)的業(yè)務(wù)中誰是客戶,收入從哪里來,合作伙伴是誰等。不過,商業(yè)模式畫布沒有將企業(yè)的內(nèi)部運(yùn)轉(zhuǎn)結(jié)構(gòu)打開,一個(gè)企業(yè)需要運(yùn)轉(zhuǎn)起來,需要各個(gè)部分之間的通力合作,并和用戶產(chǎn)生交互。要明白地表達(dá)企業(yè)內(nèi)部各方的合作情況,業(yè)務(wù)服務(wù)藍(lán)圖可以幫上忙。不過請注意在使用服務(wù)藍(lán)圖時(shí),存在一些爭議。例如,是否應(yīng)該將

IT

系統(tǒng)參與到服務(wù)藍(lán)圖中表達(dá)?這里存在兩種流派和方法:一種是使用兩張圖來表達(dá),這樣能看清楚企業(yè)引入

IT

系統(tǒng)前后的變化,區(qū)分為業(yè)務(wù)服務(wù)藍(lán)圖和46理解軟件背后的生意應(yīng)用服務(wù)藍(lán)圖;另外一種流派是將其繪制到一張圖上,統(tǒng)稱為服務(wù)藍(lán)圖。由于在這里區(qū)分了商業(yè)模型和業(yè)務(wù)模型以及加入

IT

系統(tǒng)之后的形態(tài),應(yīng)用服務(wù)藍(lán)圖更多地是關(guān)注待分析的

IT信息系統(tǒng)。業(yè)務(wù)服務(wù)藍(lán)圖本質(zhì)上是一種流程圖,表達(dá)商業(yè)中各個(gè)參與的主體(參與業(yè)務(wù)的各個(gè)部門可以看做業(yè)務(wù)主體)之間的往來,通過多個(gè)泳道來表達(dá)參與的業(yè)務(wù)主體。服務(wù)藍(lán)圖在“服務(wù)設(shè)計(jì)”這個(gè)概念下可以看做是用戶旅程的延伸。在服務(wù)藍(lán)圖中,不僅包含水平方向的客戶服務(wù)過程,還包括垂直方向各個(gè)業(yè)務(wù)主體之間的合作關(guān)系,描述服務(wù)前、中、后臺構(gòu)成的全景圖。以蔬菜配送為案例,我們來看下服務(wù)藍(lán)圖的應(yīng)用。我還原業(yè)務(wù)形態(tài)。餐廳老板往往(或者他的員工)需要自己整理一些食材清單,然后通過電話下訂單給某家配送公司的客戶經(jīng)理,客戶經(jīng)理生成食材訂單后,構(gòu)成簡易合同,隨即讓倉配部進(jìn)行配送。好在我虛擬的這家配送公司自建了物流,出庫和配送是一47理解軟件背后的生意個(gè)部門,否則還需要新的契約來滿足配貨出庫和物流之間的關(guān)系。當(dāng)餐廳收到貨物后,食材配送公司一般會出具一張清單,餐廳清點(diǎn)完成后需要簽字蓋章。這張單據(jù)往往會被用來作為處理糾紛的關(guān)鍵單據(jù),而糾紛的發(fā)生會比想象中多非常多,可以說商業(yè)就是處理糾紛的藝術(shù)。在具有固定合作關(guān)系的商業(yè)主體之間,往往都不會結(jié)算現(xiàn)款,都有一定的結(jié)算周期,通過結(jié)算單來完成結(jié)算,隨之進(jìn)行支付,某些情況下還會出現(xiàn)抵扣。4理解軟件產(chǎn)品和信息系統(tǒng)圖?3??業(yè)務(wù)服務(wù)藍(lán)圖模板48理解軟件背后的生意如果理解了一個(gè)企業(yè)的商業(yè)模式,以及支持了支持商業(yè)模式的業(yè)務(wù),再來看構(gòu)建在兩者之上的信息系統(tǒng)或者軟件就容易很多。我們可以做一個(gè)思維實(shí)驗(yàn),一家主營食材配送的企業(yè),它的客戶是餐廳老板,公司的主要業(yè)務(wù)為每日清晨為各個(gè)餐廳配送食材。毫無疑問在現(xiàn)代化的社會,信息系統(tǒng)必然是存在的。這家公司使用了微信作為渠道,建立了小程序、H5

應(yīng)用建立了食材訂購的應(yīng)用,同時(shí)又為承擔(dān)配送工作的員工開發(fā)了具有送貨、打單功能的安卓原生

APP,以及財(cái)務(wù)核算的

Web

應(yīng)用。假定在某天系統(tǒng)故障了,但是配送的工作不能停下來,這是事關(guān)商譽(yù)的事情。如果因?yàn)橐淮螣o理由的斷供,會導(dǎo)致相關(guān)的餐廳無法營業(yè),營業(yè)中斷帶來的損失遠(yuǎn)遠(yuǎn)超過當(dāng)天貨物的價(jià)值。于是,公司領(lǐng)導(dǎo)無論如何都需要想辦法將食材送到客戶手中。在信息系統(tǒng)無法使用時(shí),它們可能的做法是,從數(shù)據(jù)庫導(dǎo)出備份的數(shù)據(jù),打印出來,人工通知到客戶。我們會發(fā)現(xiàn),對于這類軟件,完全可以使用紙和筆進(jìn)行延續(xù)之前的業(yè)務(wù)。這種思維實(shí)驗(yàn),也是也是在軟件設(shè)計(jì)時(shí)常用的方法。當(dāng)業(yè)49理解軟件背后的生意務(wù)復(fù)雜,產(chǎn)品經(jīng)理或者業(yè)務(wù)人員無法描述清楚,我們可以將“電”斷掉,思考如何通過紙和筆來完成軟件設(shè)計(jì)。斷電法,可以將系統(tǒng)中晦澀難懂的概念在現(xiàn)實(shí)中找到可以被理解的物品。比如,用戶這個(gè)概念比較抽象。餐廳老板或者經(jīng)理可以作為用戶在配送平臺上下單,如果斷電了,那么用戶在現(xiàn)實(shí)中是什么呢?可能是食材配送老板大腦中的一段記憶,也可能是寫在筆記本上的一段記錄??赡軙l(fā)生這樣的場景:烤鴨店張老板老板需要預(yù)定

100

斤大蔥,打電話給食材配送的王老板。張老板:老王?。娫捊油ê螅?。王老板:原來是老張啊,今天需要什么貨呢。(根據(jù)電話號碼、聲音定位到這個(gè)用戶)張老板:我需要

100斤大蔥,上午幫我送過來。(下單、填寫配送時(shí)間)王老板:收到等下我就去裝(確認(rèn)訂單,備貨)……如果用現(xiàn)實(shí)中的行為來扮演

IT

系統(tǒng)的邏輯,可以降低認(rèn)知50理解軟件背后的生意難度,更容易理解業(yè)務(wù)。前面的業(yè)務(wù)服務(wù)藍(lán)圖可以看做是斷電后的紙筆推演,接下來我們需要將

IT

系統(tǒng)引入整個(gè)商業(yè)體系。對于行業(yè)軟件來說,軟件技術(shù)本身并不復(fù)雜,它更像是一個(gè)“機(jī)器人”(軟件),難在如何教會這個(gè)機(jī)器人像專業(yè)人士一樣工作(領(lǐng)域知識)。有軟件參與的服務(wù)藍(lán)圖,我們可以叫做應(yīng)用服務(wù)藍(lán)圖。意味著,我們找到了“電子幫手”,電子幫手會參與到業(yè)務(wù)體系中。在應(yīng)用服務(wù)藍(lán)圖中,我們可以將

IT

系統(tǒng)看做新的主體,這個(gè)主體可以幫助業(yè)務(wù)完成更高效的工作。在前面食材配送的例子中,微食材(這里設(shè)定出來的產(chǎn)品名稱)會參與到業(yè)務(wù)中,作為虛擬的主體存在。51理解軟件背后的生意圖

4??應(yīng)用服務(wù)藍(lán)圖52透過領(lǐng)域建??窜浖墓窍嗤高^領(lǐng)域建??窜浖墓窍嗤ㄟ^對軟件業(yè)務(wù)模型的分析,對業(yè)務(wù)領(lǐng)域進(jìn)行建模就能獲得軟件的邏輯結(jié)構(gòu)。獲得了軟件的邏輯結(jié)構(gòu)就能進(jìn)一步指導(dǎo)服務(wù)劃分、數(shù)據(jù)庫設(shè)計(jì)、API

設(shè)計(jì)等技術(shù)實(shí)踐。沒有領(lǐng)域模型設(shè)計(jì)的軟件,工程師往往會過多地關(guān)注到技術(shù)問題上,而忽視了產(chǎn)品設(shè)計(jì)和業(yè)務(wù)的目標(biāo)。領(lǐng)域建模對于商業(yè)軟件來說是非常重要的一環(huán),也是工程師消化行業(yè)領(lǐng)域知識的重要方法。53透過領(lǐng)域建??窜浖墓窍?認(rèn)識領(lǐng)域驅(qū)動設(shè)計(jì)1Eric

Evans提出的一種軟件設(shè)計(jì)領(lǐng)域驅(qū)動設(shè)計(jì)

(DDD)

是方法和思想,主要解決業(yè)務(wù)系統(tǒng)的設(shè)計(jì)和建模。DDD

有大量難以理解的概念,尤其是翻譯的原因,某些詞匯非?;逎?,例如:模型、限界上下文、聚合、實(shí)體、值對象等。實(shí)際上

DDD

的概念和邏輯本身并不復(fù)雜,很多概念和名詞是為了解決一些特定的問題才引入的,并和面向?qū)ο笏枷爰嫒荩梢哉f

DDD

也是面向?qū)ο笏枷胫械囊粋€(gè)子集。如果遵從奧卡姆剃刀的原則,“如無必要,勿增實(shí)體”,我們先把

DDD

這些概念丟開,從一個(gè)案例出發(fā),在必要的時(shí)候?qū)⑦@些概念引入。從紙和筆思考

IT

系統(tǒng)的工作邏輯讓我真正對計(jì)算機(jī)軟件和建模有了更深入的認(rèn)識是在一家餐廳吃飯的時(shí)候。數(shù)年以前,我還在一家創(chuàng)業(yè)公司負(fù)責(zé)餐飲軟件的服務(wù)器端的開發(fā)工作,因?yàn)楣ぷ鞯脑?,外出就餐時(shí)常都會對餐廳的點(diǎn)餐系統(tǒng)仔細(xì)觀察,以便于改進(jìn)我們自己產(chǎn)品的設(shè)計(jì)。1/subject/2681966654透過領(lǐng)域建模看軟件的骨相一次偶然的情況,我們就餐的餐廳停電了,所幸是在白天,對我們的就餐并沒有什么影響。我突然很好奇這家店,在收銀系統(tǒng)無法工作的情況下怎么讓業(yè)務(wù)繼續(xù)運(yùn)轉(zhuǎn),因此我饒有趣味地等待服務(wù)員來接受我們的點(diǎn)單。故事的發(fā)展并沒有超出預(yù)期,服務(wù)員拿了紙和筆,順利地完成了點(diǎn)餐,并將復(fù)寫紙復(fù)寫的底單麻溜地撕下來交給了后廚。我這時(shí)候才回過神來,軟件工程師并沒有創(chuàng)造新的東西,只不過是數(shù)字世界的磚瓦工,計(jì)算機(jī)系統(tǒng)中合乎邏輯的過程,停電后人肉使用紙和筆一樣合乎邏輯。合乎現(xiàn)實(shí)世界的邏輯和規(guī)則,使用鼠標(biāo)和鍵盤代替紙和筆,就是軟件設(shè)計(jì)的基本邏輯。如果我們只是關(guān)注于對數(shù)據(jù)庫的增、刪、改、查(CRUD),實(shí)際上沒有對業(yè)務(wù)進(jìn)行正確地識別,這是導(dǎo)致代碼組織混亂的根本原因。會計(jì)、餐飲、購物、人員管理、倉儲,這些都是各個(gè)領(lǐng)域?qū)崒?shí)在在發(fā)生的事情,分析業(yè)務(wù)邏輯,從中找出固定的模式,抽象成計(jì)算機(jī)系統(tǒng)中對象并存儲。這就是

DDD

和面向?qū)?5透過領(lǐng)域建??窜浖墓窍嘞笏枷胫熊浖_發(fā)的一般過程。你可能會想,我們平時(shí)不就是這樣做的嗎

?現(xiàn)實(shí)是,我們往往馬上關(guān)注到數(shù)據(jù)庫的設(shè)計(jì)上,想當(dāng)然地設(shè)計(jì)出一些數(shù)據(jù)庫表,然后著手于界面、網(wǎng)絡(luò)請求、如何操作數(shù)據(jù)庫上,業(yè)務(wù)邏輯被封裝到一個(gè)叫做

Service

對象上或散落在其他地方,然后基于對數(shù)據(jù)的操作。圖?1?面向數(shù)據(jù)庫的編程方法一般來說這種方法也沒有大的問題,甚至工作得很好,Martin

Fowler

將這種方法稱作為事務(wù)腳本(TransactionScript)。還有其他的設(shè)計(jì)模式,將用戶界面、業(yè)務(wù)邏輯、數(shù)據(jù)存儲作為一個(gè)“模塊”,可以實(shí)現(xiàn)用戶拖拽就可以實(shí)現(xiàn)簡單的編程,.net、VF

曾經(jīng)提供過這種設(shè)計(jì)模式,這種設(shè)計(jì)模式叫做

SMARTUI。56透過領(lǐng)域建??窜浖墓窍噙@種模式有一些好處。?

非常直觀,開發(fā)人員學(xué)習(xí)完編程基礎(chǔ)知識和數(shù)據(jù)庫CRUD操作之后就可以開發(fā)。?

效率高,能短時(shí)間完成應(yīng)用開發(fā)。?

模塊之間非常獨(dú)立。麻煩在于,當(dāng)業(yè)務(wù)復(fù)雜后,這種模式會帶來一些問題。雖然最終都是對數(shù)據(jù)庫的修改,但是中間存在大量的業(yè)務(wù)邏輯,并沒有得到良好的封裝??腿送瞬?,并不是將訂單中的菜品移除這么簡單。需要將訂單的總額重新計(jì)算,以及需要通知后廚嘗試撤回在做的菜。由于沒有真正的“訂單”對象負(fù)責(zé)執(zhí)行相關(guān)的業(yè)務(wù)邏輯,初學(xué)者程序員擅自修改數(shù)據(jù)片段,破壞了整體業(yè)務(wù)邏輯。Service

上的一個(gè)方法直接修改了數(shù)據(jù)庫,業(yè)務(wù)邏輯的完整性完全取決于程序員對系統(tǒng)的了解。我們在各個(gè)餐廳交流的時(shí)候發(fā)現(xiàn),這不是一個(gè)

IT

系統(tǒng)的問題。在某些餐廳,所有的服務(wù)員都可以收銀,即使用紙和筆,57透過領(lǐng)域建??窜浖墓窍嗟浙y員劃掉菜品后沒有更新小計(jì),另外的服務(wù)員結(jié)賬時(shí)會出現(xiàn)錯(cuò)誤。因此,餐廳約定修改菜品后必須更新訂單總價(jià)。圖?2?一致性問題我們吸收這個(gè)業(yè)務(wù)邏輯到

IT

系統(tǒng)中來,并意識到系統(tǒng)中這里有一些隱藏的模型:?訂單。?菜品。我們決定,抽象出訂單、菜品的對象,菜品不應(yīng)該被直接修改,而是通過訂單才能修改,無論任何情況,菜品的狀態(tài)變化都通過訂單來完成。復(fù)雜系統(tǒng)的狀態(tài)被清晰地定義出來了,

Service

承擔(dān)處理各個(gè)應(yīng)用場景的差異,模型對象處理一致的業(yè)務(wù)邏輯。58透過領(lǐng)域建模看軟件的骨相在接觸

Eric

Evans

DDD

概念之前,我們沒有找到這種開發(fā)模式的名字,暫時(shí)稱作為樸素模型驅(qū)動開發(fā)。圖?3??樸素模型驅(qū)動開發(fā)模型和領(lǐng)域模型從上面的例子中,模型是能夠表達(dá)系統(tǒng)業(yè)務(wù)邏輯和狀態(tài)的對象。我們知道要想做好一個(gè)可持續(xù)維護(hù)的

IT

系統(tǒng),實(shí)際上需要對業(yè)務(wù)進(jìn)行充分的抽象,找出這些隱藏的模型,并搬到系統(tǒng)中來。如果發(fā)生在餐廳的所有事物,都要能在系統(tǒng)中找到對應(yīng)的對象,那么這個(gè)系統(tǒng)的業(yè)務(wù)邏輯就非常完備?,F(xiàn)實(shí)世界中的業(yè)務(wù)邏輯,在

IT

系統(tǒng)業(yè)務(wù)分析時(shí),適合某個(gè)行業(yè)和領(lǐng)域相關(guān)的,所以又叫做領(lǐng)域。59透過領(lǐng)域建??窜浖墓窍囝I(lǐng)域,指特定行業(yè)或者場景下的業(yè)務(wù)邏輯。DDD

中的模型是指反映

IT

系統(tǒng)的業(yè)務(wù)邏輯和狀態(tài)的對象,是從具體業(yè)務(wù)(領(lǐng)域)中提取出來的,因此又叫做領(lǐng)域模型。通過對實(shí)際業(yè)務(wù)出發(fā),而非馬上關(guān)注數(shù)據(jù)庫、程序設(shè)計(jì)。通過識別出固定的模式,并將這些業(yè)務(wù)邏輯的承載者抽象到一個(gè)模型上。這個(gè)模型負(fù)責(zé)處理業(yè)務(wù)邏輯,并表達(dá)當(dāng)前的系統(tǒng)狀態(tài)。這個(gè)過程就是領(lǐng)域驅(qū)動設(shè)計(jì)。我從這里面學(xué)到了什么呢?我們做的計(jì)算機(jī)系統(tǒng),實(shí)際上是替代了現(xiàn)實(shí)世界中的一些操作。按照面向?qū)ο笤O(shè)計(jì)的話,我們的系統(tǒng)是一個(gè)電子餐廳?,F(xiàn)實(shí)餐廳中的實(shí)體,應(yīng)該對應(yīng)到我們的系統(tǒng)中去,用于承載業(yè)務(wù),例如收銀員、顧客、廚師、餐桌、菜品,這些虛擬的實(shí)體表達(dá)了系統(tǒng)的狀態(tài),在某種程度上就能指代系統(tǒng),這就是模型,如果找到了這些元素,就很容易設(shè)計(jì)出軟件。后來,如果我什么業(yè)務(wù)邏輯想不清楚,我就會把電斷掉,假裝自己是服務(wù)員,用紙和筆走一遍業(yè)務(wù)流程。60透過領(lǐng)域建模看軟件的骨相分析業(yè)務(wù),設(shè)計(jì)領(lǐng)域模型,編寫代碼。這就是領(lǐng)域驅(qū)動設(shè)計(jì)的基本過程。領(lǐng)域模型設(shè)計(jì)好后(通俗來說,領(lǐng)域模型就是一些

UML類圖),可以指導(dǎo)后續(xù)的工作:?指導(dǎo)數(shù)據(jù)庫設(shè)計(jì)。?指導(dǎo)模塊分包和代碼設(shè)計(jì)。?指導(dǎo)

RESTfulAPI設(shè)計(jì)。?指導(dǎo)事務(wù)策略?指導(dǎo)權(quán)限設(shè)計(jì)。?指導(dǎo)微服務(wù)劃分(有必要的情況)。圖

4軟件設(shè)計(jì)過程在我們之前的例子中,收銀員需要負(fù)責(zé)處理收銀的操作,同時(shí)表達(dá)這個(gè)餐廳有收銀員這樣的一個(gè)狀態(tài)。收銀員收到61透過領(lǐng)域建??窜浖墓窍噱X并記錄到賬本中,賬本負(fù)責(zé)處理記錄錢的業(yè)務(wù)邏輯,同時(shí)表達(dá)系統(tǒng)中有多少錢的狀態(tài)。技術(shù)和業(yè)務(wù)復(fù)雜度我們進(jìn)行業(yè)務(wù)系統(tǒng)開發(fā)時(shí),大多數(shù)人都會認(rèn)同一個(gè)觀點(diǎn):將業(yè)務(wù)和模型設(shè)計(jì)清楚之后,開發(fā)起來會容易很多。但是實(shí)際開發(fā)過程中,我們既要分析業(yè)務(wù),也要處理一些技術(shù)細(xì)節(jié),例如:如何響應(yīng)表單提交、如何存儲到數(shù)據(jù)庫、事務(wù)該怎么處理等。使用領(lǐng)域驅(qū)動設(shè)計(jì)還有一個(gè)好處,我們可以通過隔離這些技術(shù)細(xì)節(jié),先進(jìn)行業(yè)務(wù)邏輯建模,然后再完成技術(shù)實(shí)現(xiàn),因?yàn)闃I(yè)務(wù)模型已經(jīng)建立,技術(shù)細(xì)節(jié)無非就是響應(yīng)用戶操作和持久化模型。我們可以把系統(tǒng)復(fù)雜的問題分為兩類:?

技術(shù)復(fù)雜度。軟件設(shè)計(jì)中和技術(shù)實(shí)現(xiàn)相關(guān)的問題,例如處理用戶輸入,持久化模型,處理網(wǎng)絡(luò)通信等。?

業(yè)務(wù)復(fù)雜度。軟件設(shè)計(jì)中和業(yè)務(wù)邏輯相關(guān)的問題,62透過領(lǐng)域建模看軟件的骨相例如為訂單添加商品,需要計(jì)算訂單總價(jià),應(yīng)用折扣規(guī)則等。圖

5

技術(shù)復(fù)雜度和業(yè)務(wù)復(fù)雜度當(dāng)我們分析業(yè)務(wù)并建模時(shí),不要關(guān)注技術(shù)實(shí)現(xiàn),因?yàn)闀順O大的干擾。和上一章聊到的斷電法理解業(yè)務(wù)一樣,就是在這個(gè)過程把“電”斷掉,技術(shù)復(fù)雜度中的用戶交互想象成人工交談,持久化想象成用紙和筆記錄。DDD

還強(qiáng)調(diào),業(yè)務(wù)建模應(yīng)該充分和業(yè)務(wù)專家在一起,不應(yīng)該只是實(shí)現(xiàn)軟件的工程師自嗨。業(yè)務(wù)專家是一個(gè)虛擬的角色,有可能是一線業(yè)務(wù)人員、項(xiàng)目經(jīng)理或者軟件工程師。由于和業(yè)務(wù)專家一起完成建模,因此盡量不要選用非常專業(yè)的繪圖工具和使用技術(shù)語言。可以看出

DDD

只是一種63透過領(lǐng)域建??窜浖墓窍嘟K枷耄]有規(guī)定使用的具體工具。我這里使用

PPT的線條和形狀,用

E-R

的方式表達(dá)領(lǐng)域模型,如果大家都很熟悉

UML

也是可以的。甚至實(shí)際工作中,我們大量使用便利貼和白板完成建模工作,好處是一屋子的人方便參與到共創(chuàng)的工作坊中來。這個(gè)建模過程可以是技術(shù)人員和業(yè)務(wù)專家一起討論出來,也可以使用“事件風(fēng)暴”這類工作坊的方式完成。這個(gè)過程非常重要,DDD

把這個(gè)過程稱作協(xié)作設(shè)計(jì)。通過協(xié)作設(shè)計(jì),我們得到了領(lǐng)域模型(這里以簡單的圖表表示,也可以用

UML)。1N1NNN圖

6

領(lǐng)域模型

v1上圖是我們通過業(yè)務(wù)分析得到的一個(gè)非?;镜念I(lǐng)域模型,我們的點(diǎn)餐系統(tǒng)中,會有座位、訂單、菜品、評價(jià)幾個(gè)模型。一個(gè)座位可以關(guān)聯(lián)多個(gè)訂單,每個(gè)訂單可以有多個(gè)菜品和64透過領(lǐng)域建??窜浖墓窍嘣u價(jià)。同時(shí),菜品也會被不同的訂單使用。上下文、二義性、統(tǒng)一語言我們用領(lǐng)域模型驅(qū)動的方式開發(fā)軟件系統(tǒng),相對于事務(wù)腳本的方式,已經(jīng)容易和清晰很多了,但還是有一些問題。有一天,市場告訴我們,這個(gè)系統(tǒng)會有一個(gè)邏輯問題。就是系統(tǒng)中菜品被刪除,訂單也不能查看。在我們之前的認(rèn)知里面,訂單和菜品是一個(gè)多對多的關(guān)系,菜品都不存在了,這個(gè)訂單還有什么用。這里的菜品存在了致命的二義性?。?!這里的菜品實(shí)際上有兩個(gè)含義:?在訂單中,表達(dá)這個(gè)消費(fèi)項(xiàng)的記錄,也就是訂單項(xiàng)。例如,5號桌消費(fèi)了魚香肉絲一份。?

在菜品管理中,價(jià)格為

30

元的魚香肉絲,包含菜單圖片、文字描述,以及折扣信息。菜品管理中的菜品下架后,不應(yīng)該產(chǎn)生新的訂單,同時(shí)也不應(yīng)該對訂單中的菜品造成任何影響。這些問題是因?yàn)?,技術(shù)專家和業(yè)務(wù)專家的語言沒有統(tǒng)一,

DDD

一書提到了這個(gè)問題,統(tǒng)一語言是實(shí)現(xiàn)良好領(lǐng)域模型的前提,因此應(yīng)65透過領(lǐng)域建模看軟件的骨相該“大聲地建?!?。我在參與這個(gè)過程目睹過大量有意義的爭吵,正是這些爭吵讓領(lǐng)域模型變得越來越清晰。這個(gè)過程叫做統(tǒng)一語言。1N1N1N圖

7

領(lǐng)域模型

v2和現(xiàn)實(shí)生活中一樣,產(chǎn)生二義性的原因是我們的對話發(fā)生在不同的上下文中,我們在談一個(gè)概念必須在確定的上下文中才有意義。在不同的場景下,即使使用的詞匯相同,但是業(yè)務(wù)邏輯本質(zhì)都是不同的。想象一下,發(fā)生在《武林外傳》中同??蜅5膸锥螌υ?。66透過領(lǐng)域建模看軟件的骨相圖

8關(guān)于上下文的對話這段對話中實(shí)際上有三個(gè)上下文,這里的“菜”這個(gè)詞出現(xiàn)了三次,但是實(shí)際上業(yè)務(wù)含義完全不同。?

大嘴說去買菜,這里的菜應(yīng)該被理解為食材,如果67透過領(lǐng)域建模看軟件的骨相掌柜對這個(gè)菜進(jìn)行管理,應(yīng)該具有采購者、名稱、采購商家、采購價(jià)等屬性。?

秀才說實(shí)習(xí)生把賬單中的菜算錯(cuò)了價(jià)格,秀才需要對賬單進(jìn)行管理,這里的菜應(yīng)該指的賬單科目,現(xiàn)實(shí)中一般是會計(jì)科目。?

老白的客人點(diǎn)了一只醬鴨,但老白關(guān)注的是訂單下的訂單項(xiàng)。訂單項(xiàng)包含價(jià)格、數(shù)量、小計(jì)、折扣等屬性信息。實(shí)際上添加菜品到菜單中,客人才能點(diǎn),這個(gè)商品就是我們平時(shí)一般概念上的商品。我們把語言再次統(tǒng)一,得到新的模型。68透過領(lǐng)域建模看軟件的骨相1N1N1N圖

9

領(lǐng)域模型

v3在被虛線框起來的四個(gè)區(qū)域中,我們都可以使用“菜品”這個(gè)詞匯(盡量不要這么做),但是大家都知道“菜品”具有不同的含義。這些區(qū)域被稱為上下文。當(dāng)然,上下文不僅僅是由二義性決定的,也可能是由完全不相關(guān)的概念產(chǎn)生的。例如,在訂單和座位之間實(shí)際上并沒有強(qiáng)烈的關(guān)聯(lián),當(dāng)我們討論座位時(shí),我們完全在談?wù)撈渌虑?,因此座位?yīng)該被視為單獨(dú)的上下文。識別上下文的邊界是

DDD

中最難的一部分,同時(shí)上下文69透過領(lǐng)域建??窜浖墓窍噙吔缡怯蓸I(yè)務(wù)變化動態(tài)變化的,我們把識別出邊界的上下文叫做限界上下文(Bounded

Context)。限界上下文是一個(gè)非常有用的工具,限界上下文可以幫助我們識別出模型的邊界,并做適當(dāng)?shù)牟鸱?。限界上下文的識別難以有一個(gè)明確的準(zhǔn)則。上下文的邊界非常模糊,需要有經(jīng)驗(yàn)的工程師并充分討論才能得到一個(gè)好的設(shè)計(jì)。同時(shí)需要注意,限界上下文的劃分沒有對錯(cuò),只有是否合適??缦藿缟舷挛闹g模型的關(guān)聯(lián)有本質(zhì)的不同,我們用虛線標(biāo)出,后面會詳細(xì)討論這種區(qū)別。1N1N1N1NN11NN1圖

10

領(lǐng)域模型

v470透過領(lǐng)域建??窜浖墓窍嗍褂蒙舷挛闹?,帶來另外一個(gè)收獲。模型之間本質(zhì)上沒有多對多關(guān)系,如果有,說明存在一個(gè)隱含的成員關(guān)系,這個(gè)關(guān)系沒有被充分分析出來,對后期的開發(fā)會造成非常大的困擾。聚合根、實(shí)體、值對象上面的模型,尤其是解決二義性這個(gè)問題之后,已經(jīng)能在實(shí)際開發(fā)中很好地使用了。不過還是會有一些問題沒有解決,實(shí)際開發(fā)中,每種模型的身份可能不太一樣,訂單項(xiàng)必須依賴訂單的存在而存在,如果能在領(lǐng)域模型圖中體現(xiàn)出來就更好了。舉個(gè)例子來說,當(dāng)我們刪除訂單時(shí),訂單項(xiàng)應(yīng)該一起刪除,訂單項(xiàng)的存在必須依賴于訂單的存在。這樣業(yè)務(wù)邏輯是一致的和完整的,游離的訂單項(xiàng)對我們來說沒有意義,除非有特殊的業(yè)務(wù)需求存在。為了解決這個(gè)問題,對待模型就不再一視同仁了。我們將相關(guān)性極強(qiáng)的領(lǐng)域模型放到一起考慮,數(shù)據(jù)的一致性必須解決,同時(shí)生命周期也需要保持同步,我們把這個(gè)集合叫做聚合。71透過領(lǐng)域建模看軟件的骨相聚合中需要選擇一個(gè)代表負(fù)責(zé)和全局通信,類似于一個(gè)部門的接口人,這樣就能確保數(shù)據(jù)保持一致。我們把這個(gè)模型叫做聚合根,聚合根充當(dāng)一組領(lǐng)域模型領(lǐng)航員的角色。當(dāng)一個(gè)聚合業(yè)務(wù)足夠簡單時(shí),聚合有可能只由一個(gè)模型組成,這個(gè)模型就是聚合根,常見的就是配置、日志相關(guān)的。在聚合中,無論是否是聚合根,對于有自己的身份(ID)的模型,我們都可以叫做實(shí)體。1N1N1N1N11NN1N圖

11領(lǐng)域模型

v5我們把這個(gè)圖完善一下,聚合之間也是用虛線連接,為聚合根標(biāo)上更深一點(diǎn)的顏色。識別聚合根需要一些技巧。72透過領(lǐng)域建模看軟件的骨相?

聚合根本質(zhì)上也是實(shí)體,同屬于領(lǐng)域模型,用于承載業(yè)務(wù)邏輯和系統(tǒng)狀態(tài)。?實(shí)體的生命周期依附于聚合根,聚合根刪除實(shí)體應(yīng)該也需要被刪除,保持系統(tǒng)一致性,避免游離的臟數(shù)據(jù)。?

聚合根負(fù)責(zé)和其他聚合通信,因此聚合根往往具有一個(gè)全局唯一標(biāo)識。例如,訂單有訂單

ID和訂單號,訂單號為全局業(yè)務(wù)標(biāo)識,訂單

ID為聚合內(nèi)關(guān)聯(lián)使用。聚合外使用訂單號進(jìn)行關(guān)聯(lián)應(yīng)用。還有一類特殊的模型,這類模型只負(fù)責(zé)承載一組字段值的表達(dá),沒有自己的身份。在我們飯店的例子中,如果需要對賬單支持多國貨幣,我們將純數(shù)字的

price

字段修為Price類型。publicclassPrice{privateStringcurrency;privateBigDecimalvalue;publicPrice(Stringcurrency,BigDecimalvalue){this.currency=currency;this.value=value;73透過領(lǐng)域建??窜浖墓窍鄛}價(jià)格這個(gè)模型,沒有自己的生命周期,一旦被創(chuàng)建出來就無須修改,因?yàn)樾薷木透淖兞诉@個(gè)值本身。所以我們會給這類的對象一個(gè)構(gòu)造方法,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論