[譯文]Domain Driven Design Reference(四)—— 柔性設(shè)計(jì)

如果這是第二次看到我的文章,歡迎訂閱z哥的公眾號(hào)(跨界架構(gòu)師)哦~

每周五11:45 按時(shí)送達(dá)。當(dāng)然了,也會(huì)時(shí)不時(shí)加個(gè)餐~

本書(shū)是Eric Evans對(duì)他自己寫(xiě)的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)-軟件核心復(fù)雜性應(yīng)對(duì)之道》的一本字典式的參考書(shū),可用于快速查找《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中的諸多概念及其簡(jiǎn)明解釋。


其它本系列其它文章地址:

[譯文]Domain Driven Design Reference(一)—— 前言

[譯文]Domain Driven Design Reference(二)—— 讓模型起作用

[譯文]Domain Driven Design Reference(三)—— 模型驅(qū)動(dòng)設(shè)計(jì)的構(gòu)建模塊

[譯文]Domain Driven Design Reference(四)——?柔性設(shè)計(jì)


Ⅲ.柔性設(shè)計(jì)

  要讓一個(gè)項(xiàng)目加速發(fā)展,而不是被其自身的歷史包袱所拖累,需要一個(gè)能與之良好協(xié)作的設(shè)計(jì),它會(huì)帶來(lái)改變。一個(gè)柔性設(shè)計(jì)。

  柔性設(shè)計(jì)是對(duì)深度建模的補(bǔ)充。

  開(kāi)發(fā)人員扮演兩種角色,每種角色都必須通過(guò)設(shè)計(jì)來(lái)完成。同一個(gè)人可能扮演這兩個(gè)角色,甚至可以在幾分鐘內(nèi)來(lái)回切換,但與代碼的關(guān)系卻不是這樣。一個(gè)角色是客戶(hù)端的開(kāi)發(fā)人員,他們利用設(shè)計(jì)的方式將領(lǐng)域?qū)ο缶幙椀綉?yīng)用程序代碼或其他域?qū)哟a中。柔性設(shè)計(jì)揭示了一個(gè)深層次的潛在模型,使其潛在性變得清晰??蛻?hù)端開(kāi)發(fā)人員可以靈活地使用一組最小松散耦合的概念來(lái)表示域中的一系列場(chǎng)景。設(shè)計(jì)元素以自然的方式融合在一起,其結(jié)果是可預(yù)測(cè)的,清晰的特征并且是健壯的。

  同樣重要的是,設(shè)計(jì)必須服從于開(kāi)發(fā)人員來(lái)改變它。要做出改變,設(shè)計(jì)必須易于理解,并能表達(dá)出客戶(hù)端開(kāi)發(fā)人員正在使用的相同底層模型。它必須遵循該領(lǐng)域深層模型的概念,所以大多數(shù)變化都會(huì)在靈活點(diǎn)上柔性設(shè)計(jì)。其代碼的影響必須透明明顯,因此更改的后果將很容易預(yù)測(cè)。

    ?? ?使行為特征明顯

    ?? ?降低變更成本

    ?? ?創(chuàng)建與之合作的軟件開(kāi)發(fā)人員


釋意接口

  如果開(kāi)發(fā)人員必須考慮組件的實(shí)現(xiàn)才能使用它,則封裝的價(jià)值就沒(méi)有了。如果原始開(kāi)發(fā)人員以外的人必須根據(jù)其實(shí)現(xiàn)來(lái)推斷對(duì)象或操作的目的,新的開(kāi)發(fā)者可能會(huì)推斷出一個(gè)意圖——操作或類(lèi)只是偶然地執(zhí)行。如果這不是意圖的話(huà),那么代碼可能暫時(shí)有效,但設(shè)計(jì)的概念基礎(chǔ)已經(jīng)被破壞了,兩個(gè)開(kāi)發(fā)人員將在交叉目的下工作。

  因此:

命名類(lèi)名和操作名來(lái)描述它們的效果和目的,而不用參考它們做出履約的方法。這減輕了客戶(hù)開(kāi)發(fā)者理解內(nèi)部的必要性。這些名字應(yīng)符合通用語(yǔ)言,以便團(tuán)隊(duì)成員可以快速推斷其含義。在創(chuàng)建它之前為行為編寫(xiě)一個(gè)測(cè)試,以強(qiáng)制您的思維進(jìn)入客戶(hù)端開(kāi)發(fā)人員模式。


無(wú)副作用方法

  多個(gè)規(guī)則或計(jì)算的組合的相互作用變得非常難以預(yù)測(cè)。開(kāi)發(fā)人員調(diào)用一個(gè)操作必須理解它的實(shí)現(xiàn)以及所有委托的實(shí)現(xiàn),以便預(yù)測(cè)結(jié)果。如果開(kāi)發(fā)人員被迫刺破遮罩層,任何抽象接口的用處都是有限的。如果沒(méi)有安全可預(yù)測(cè)的抽象,開(kāi)發(fā)人員必須限制組合爆炸,對(duì)可行的豐富行為設(shè)置較低的上限。

  因此:

將盡可能多的程序邏輯放入函數(shù)中,返回沒(méi)有明顯副作用的結(jié)果。嚴(yán)格地將命令(引起明顯的狀態(tài)改變的方法)分隔成不返回領(lǐng)域信息的非常簡(jiǎn)單的操作。當(dāng)發(fā)現(xiàn)了一個(gè)符合職責(zé)的概念時(shí),通過(guò)將復(fù)雜的邏輯轉(zhuǎn)化為值對(duì)象來(lái)進(jìn)一步控制副作用。

  值對(duì)象的所有操作都應(yīng)該是無(wú)副作用的函數(shù)。


斷言

  當(dāng)操作的副作用只是通過(guò)實(shí)現(xiàn)而隱含地定義時(shí),大量委托的設(shè)計(jì)就會(huì)成為一種混亂的因果關(guān)系。理解程序的唯一方法是通過(guò)分支路徑來(lái)跟蹤執(zhí)行。封裝的價(jià)值失去了。跟蹤具體執(zhí)行的必要性使抽象也失敗了。

  因此:

狀態(tài)操作的后置條件以及類(lèi)和聚合的不變性。如果斷言不能直接用你的編程語(yǔ)言編寫(xiě),請(qǐng)為它們編寫(xiě)自動(dòng)單元測(cè)試。將它們寫(xiě)入符合項(xiàng)目開(kāi)發(fā)過(guò)程風(fēng)格的文檔或圖表中。

  尋找具有相關(guān)概念集的模型,這些概念引導(dǎo)開(kāi)發(fā)人員推斷預(yù)期的斷言,加速學(xué)習(xí)曲線(xiàn)并降低矛盾代碼的風(fēng)險(xiǎn)。

  斷言定義了服務(wù)和實(shí)體修飾符的契約。

  斷言在聚合上定義了不變性。


孤立類(lèi)

  即使在同一個(gè)模塊中,隨著依賴(lài)性的增加,解釋設(shè)計(jì)的難度也會(huì)大幅增加。這增加了理解的負(fù)擔(dān),限制了開(kāi)發(fā)人員可以處理的設(shè)計(jì)復(fù)雜性。隱式概念對(duì)此負(fù)擔(dān)的促進(jìn)作用甚至超過(guò)了顯示的引用。

低耦合是面向?qū)ο笤O(shè)計(jì)的基礎(chǔ)。如果可以,一直這樣做。消除圖中的所有其他概念。然后類(lèi)將完全獨(dú)立,可以單獨(dú)研究和理解。每個(gè)這樣的自包含類(lèi)都顯著減輕了理解一個(gè)模塊的負(fù)擔(dān)。


閉合操作

  大多數(shù)有趣的對(duì)象最終都只能做一些無(wú)法用基本元素來(lái)表示的東西。

  因此:

在適當(dāng)?shù)那闆r下,在定義操作時(shí)讓它返回類(lèi)型與其參數(shù)的類(lèi)型相同。如果實(shí)現(xiàn)者的狀態(tài)在計(jì)算中會(huì)被用到,那么實(shí)現(xiàn)者實(shí)際上就是操作的一個(gè)參數(shù),因此參數(shù)和返回值應(yīng)該與實(shí)現(xiàn)者有相同的類(lèi)型。這種操作就是在該類(lèi)型的實(shí)例集合中的閉合操作。閉合操作提供了一個(gè)高層接口,而不會(huì)引入對(duì)其他概念的依賴(lài)。

  這種模式通常應(yīng)用于值對(duì)象的操作。因?yàn)橐粋€(gè)實(shí)體的生命周期在領(lǐng)域中具有重要意義,所以你不能創(chuàng)造一個(gè)新的實(shí)體來(lái)回答一個(gè)問(wèn)題。也有一些操作在實(shí)體類(lèi)型下閉合??梢韵蚱渲黝}對(duì)象請(qǐng)求一個(gè)屬性對(duì)象并取回另一個(gè)屬性。但總的來(lái)說(shuō),實(shí)體并不是那種適合成為計(jì)算結(jié)果的概念。所以,大多數(shù)情況下,這是一個(gè)尋找值對(duì)象的機(jī)會(huì)。

  你有時(shí)會(huì)陷入這種模式的一半。參數(shù)與實(shí)現(xiàn)者匹配,但返回類(lèi)型不同,或者返回類(lèi)型與接收者匹配,參數(shù)不同。這些操作并不是閉合的,但是他們給與了思考閉合的一些優(yōu)勢(shì)的想象空間。


聲明式設(shè)計(jì)

  在程序軟件中不可能有真正的保證。僅以一種逃避斷言的方式命名,代碼可能會(huì)產(chǎn)生額外的副作用而這些副作用并沒(méi)有被排除在外。無(wú)論我們的設(shè)計(jì)如何以模型為導(dǎo)向,我們?nèi)匀蛔罱K編寫(xiě)程序來(lái)產(chǎn)生概念上的交互效果。并且我們花費(fèi)大部分時(shí)間在編寫(xiě)樣板代碼上,而這些代碼并沒(méi)有實(shí)際增加任何意義或者行為。本章中的釋意接口和其它模式有所幫助,但是它們不可能給傳統(tǒng)的面向?qū)ο筇峁┬问缴系膰?yán)謹(jǐn)。

  這些是聲明式設(shè)計(jì)背后的動(dòng)機(jī)。這個(gè)術(shù)語(yǔ)對(duì)很多人來(lái)說(shuō)意味著許多東西,但通常它指示一種編寫(xiě)一個(gè)程序或者程序的某個(gè)部分的方式,作為一種可執(zhí)行的規(guī)范。對(duì)屬性的非常精確的描述實(shí)際控制著軟件。在它的各種形式中,可以通過(guò)反射機(jī)制或編譯時(shí)通過(guò)代碼生成來(lái)完成(基于聲明自動(dòng)生成傳統(tǒng)代碼)。這種方法允許其他開(kāi)發(fā)人員以表面價(jià)值接受聲明。這是一個(gè)絕對(duì)的保證。

  如果開(kāi)發(fā)人員有意或無(wú)意地繞過(guò)它們,很多聲明式方法可能會(huì)被破壞。當(dāng)系統(tǒng)難以使用或限制過(guò)多時(shí),這很可能發(fā)生。每個(gè)人都必須遵守框架的規(guī)則才能獲得聲明式編程的好處。


一種聲明式的設(shè)計(jì)風(fēng)格

  一旦你的設(shè)計(jì)有釋意接口,無(wú)副作用函數(shù)和斷言,你就會(huì)進(jìn)入聲明式領(lǐng)域。聲明式設(shè)計(jì)的許多好處都是在您具有可交流其含義的可組合元素,并且具有特征或明顯效果,或根本沒(méi)有可觀察效果時(shí)獲得的。

  柔性設(shè)計(jì)可以使客戶(hù)端代碼使用聲明式的設(shè)計(jì)風(fēng)格成為可能。為了說(shuō)明這一點(diǎn),下一節(jié)將介紹本章中的一些模式,以使規(guī)范更加靈活和聲明性。


圖上的形式主義(形式化的繪畫(huà))

  從零開(kāi)始創(chuàng)建一個(gè)嚴(yán)格的概念框架是你每天都不能做的事情。有時(shí)在項(xiàng)目的生命周期中,您會(huì)發(fā)現(xiàn)并改進(jìn)其中的一個(gè)。但是你可以經(jīng)常使用和調(diào)整那些長(zhǎng)期在你的領(lǐng)域或其他領(lǐng)域建立起來(lái)的概念系統(tǒng),其中一些已經(jīng)經(jīng)過(guò)了幾個(gè)世紀(jì)的精煉和提煉。例如,許多商業(yè)應(yīng)用程序都涉及會(huì)計(jì)。會(huì)計(jì)定義了一套完善的實(shí)體和規(guī)則,可以輕松適應(yīng)深層模型和柔性設(shè)計(jì)。

  有許多這樣的形式化的概念框架,但我個(gè)人最喜歡的是數(shù)學(xué)。讓人驚訝的是,在基本算法上做一些改變是多么有用。很多領(lǐng)域包括數(shù)學(xué)。尋找它。挖出來(lái)。專(zhuān)業(yè)的數(shù)學(xué)是干凈的,可以通過(guò)清晰的規(guī)則組合起來(lái),并且人們發(fā)現(xiàn)它很容易理解。

  在本書(shū)的第8章討論一個(gè)真實(shí)世界的例子“Shares Math”,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)。


概念輪廓

  有時(shí)人們會(huì)為了靈活的組合而砍掉一些功能。有時(shí)候他們會(huì)把它封裝得很復(fù)雜。有時(shí)他們會(huì)尋求一致的粒度,使所有類(lèi)別和操作達(dá)到相似的程度。這些都是過(guò)于簡(jiǎn)單化的,不像一般規(guī)則那樣有效。但是他們通過(guò)基本問(wèn)題來(lái)激發(fā)。

  當(dāng)模型或設(shè)計(jì)的元素被嵌入到一個(gè)整體結(jié)構(gòu)中時(shí),它們的功能會(huì)被復(fù)制。外部接口并不表示客戶(hù)端可能關(guān)心的所有內(nèi)容。他們的意思很難理解,因?yàn)椴煌母拍钍腔旌显谝黄鸬摹?/p>

  相反,分解類(lèi)和方法可能會(huì)使客戶(hù)端無(wú)意識(shí)去復(fù)雜化,迫使客戶(hù)端對(duì)象了解如何將小塊組合在一起。更糟糕的是,一個(gè)概念可能完全喪失。鈾原子的一半不是鈾。當(dāng)然,重要的不是顆粒度的小大,但這只是顆粒度的來(lái)源。

  因此:

將設(shè)計(jì)元素(操作、接口、類(lèi)和聚合)分解為內(nèi)聚單元,同時(shí)考慮到您對(duì)領(lǐng)域重要分支的直覺(jué)。通過(guò)連續(xù)的重構(gòu)觀察核心的變化和穩(wěn)定性,并尋找解釋這些切分方式的基本概念輪廓。對(duì)比模型與領(lǐng)域一致的方面,首先讓它成為一個(gè)可行的知識(shí)領(lǐng)域。

  基于深度模型的柔性設(shè)計(jì)產(chǎn)生了一組簡(jiǎn)單的接口,這些接口邏輯上可以在通用語(yǔ)言中作出合理的聲明,并且沒(méi)有無(wú)關(guān)選項(xiàng)的干擾和維護(hù)負(fù)擔(dān)。


?作者:Zachary(個(gè)人微信號(hào):Zachary-ZF)

微信公眾號(hào)(首發(fā)):跨界架構(gòu)師<-- 點(diǎn)擊查閱近期熱門(mén)文章

如果你是初級(jí)程序員,想提升但不知道如何下手。又或者做程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關(guān)注我的公眾號(hào)「跨界架構(gòu)師」,回復(fù)「技術(shù)」,送你一份我長(zhǎng)期收集和整理的思維導(dǎo)圖。

如果你是運(yùn)營(yíng),面對(duì)不斷變化的市場(chǎng)束手無(wú)策。又或者想了解主流的運(yùn)營(yíng)策略,以豐富自己的“倉(cāng)庫(kù)”。歡迎關(guān)注我的公眾號(hào)「跨界架構(gòu)師」,回復(fù)「運(yùn)營(yíng)」,送你一份我長(zhǎng)期收集和整理的思維導(dǎo)圖。

定期發(fā)表原創(chuàng)內(nèi)容:架構(gòu)設(shè)計(jì)丨分布式系統(tǒng)丨產(chǎn)品丨運(yùn)營(yíng)丨一些深度思考

掃碼加入小圈子??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,045評(píng)論 25 709
  • 今天是我的生日,農(nóng)歷臘月二十八,陽(yáng)光格外溫暖,氣溫最高15℃,這在臘月是少有的好天氣。 農(nóng)村出生的我,習(xí)慣記得是農(nóng)...
    如瓷_372c閱讀 557評(píng)論 8 6
  • 往事被光陰帶走了.有些人,有些愛(ài),就住在時(shí)光里,安靜的,與滄桑對(duì)望,與心緒相依,如此,總會(huì)留有一處花香縈繞,...
    DD李東東閱讀 957評(píng)論 0 1
  • 今天聽(tīng)了一本書(shū)—《關(guān)鍵期的關(guān)鍵幫助》,由于正好學(xué)習(xí)了幼兒天賦開(kāi)發(fā)指導(dǎo)師認(rèn)證班的課程,走在成為指導(dǎo)師的路上,...
    胡永群閱讀 765評(píng)論 0 51

友情鏈接更多精彩內(nèi)容