問題: 重構(gòu)項(xiàng)目如何借助領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)做指導(dǎo)蚓挤?
簡(jiǎn)單地說:就是通過“領(lǐng)域建乃祭纾”驅(qū)動(dòng)對(duì)業(yè)務(wù)高效的學(xué)習(xí)和分析萨驶,并以“領(lǐng)域建谋啬幔”驅(qū)動(dòng)對(duì)軟件更好的再設(shè)計(jì)和重構(gòu)。
首先,圍繞著領(lǐng)域建模來學(xué)習(xí)業(yè)務(wù)知識(shí)和既有代碼判莉,會(huì)更加系統(tǒng)和高效豆挽。
我們說軟件開發(fā)是一個(gè)學(xué)習(xí)的過程。咨詢師在面對(duì)陌生的業(yè)務(wù)和復(fù)雜的遺留代碼時(shí)券盅,通過建模相當(dāng)于是對(duì)業(yè)務(wù)和既有代碼的一個(gè)系統(tǒng)化的學(xué)習(xí)過程帮哈。領(lǐng)域模型是記錄所學(xué)結(jié)果的最好方式,除此之外它還能在學(xué)習(xí)過程中時(shí)刻提醒優(yōu)先去關(guān)注核心概念锰镀,以及指導(dǎo)應(yīng)該在哪些還不一致的地方繼續(xù)投入精力梳理娘侍,挖掘更本質(zhì)的問題。
在過程中我會(huì)要求客戶中對(duì)系統(tǒng)最了解的專家和我結(jié)對(duì)泳炉,也會(huì)抽時(shí)間自己一個(gè)人安靜的看代碼憾筏。我會(huì)畫各種草圖,然后再整理成UML花鹅,講給客戶專家獲得他們的反饋氧腰,直到大家一致認(rèn)可當(dāng)前的模型設(shè)計(jì)基本可以解決對(duì)應(yīng)的業(yè)務(wù)問題并滿足代碼改進(jìn)目標(biāo)。
具體到建模方法上刨肃,如前文所說古拴,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)并沒有約束采用哪種方式。一般我用的最多的還是面向?qū)ο蠓治鲈O(shè)計(jì)以及正交設(shè)計(jì)的各種原則和技術(shù)真友。
需要注意的是黄痪,很難一開始就能有完美的設(shè)計(jì),就算有也應(yīng)該需要花很長的時(shí)間盔然,可能超出所有人的耐心桅打。而且越是完美的設(shè)計(jì)落地難度越大,而沒有落地的設(shè)計(jì)是沒有產(chǎn)生實(shí)際價(jià)值的愈案。
合理的做法是油额,先有一個(gè)大家認(rèn)可的更好的設(shè)計(jì),然后在重構(gòu)過程中不斷獲得反饋刻帚,再去迭代的演進(jìn)這個(gè)設(shè)計(jì)潦嘶,讓它逐步在落地的過程中趨于完美。
有了初始的領(lǐng)域模型后崇众,接下來我們需要考慮新的設(shè)計(jì)如何落在當(dāng)前系統(tǒng)里面掂僵,即如何將代碼重構(gòu)過去。這也不是能一蹴而就的顷歌,需要設(shè)計(jì)如何和既有系統(tǒng)兼容的演進(jìn)式方案锰蓬。我們不能只有high level的設(shè)計(jì),還要和大家協(xié)商出一個(gè)可落地眯漩、可執(zhí)行的演進(jìn)策略芹扭。
再然后就是和大家pair programming麻顶,在重構(gòu)的過程中逢山開路遇水搭橋,解決一個(gè)一個(gè)的問題舱卡,通過反饋再繼續(xù)演進(jìn)領(lǐng)域模型和代碼辅肾。
這里要回答另一個(gè)問題:為什么沒有用社區(qū)里很流行的事件風(fēng)暴(Event Storming)建模方法?
“事件風(fēng)暴”和“四色建穆肿叮”都屬于可視化的分析建模方法矫钓。尤其是“事件風(fēng)暴”,適合團(tuán)隊(duì)一起參與舍杜,幫助所有成員快速達(dá)成共識(shí)新娜。在建模過程中需要用到各種顏色的便利貼,按照一定的建模規(guī)則進(jìn)行既绩,所有參與者一起分析業(yè)務(wù)并得到初始的模型設(shè)計(jì)概龄。
我在重構(gòu)咨詢工作中沒有使用“事件風(fēng)暴”,最主要的原因是 “我不會(huì)” :)
在客戶現(xiàn)場(chǎng)饲握,大多時(shí)候只有一個(gè)業(yè)務(wù)專家能陪著我私杜。大部分時(shí)間我只需要畫畫草圖,和他安靜的討論就夠了互拾。我見過的顧問帶著團(tuán)隊(duì)做事件風(fēng)暴建模,最后取得的最大成果是團(tuán)隊(duì)所有人幫著顧問梳理和熟悉了業(yè)務(wù)嚎幸。
最后颜矿,也是最重要的一點(diǎn)是,每種建模方式有自己的側(cè)重點(diǎn)嫉晶。事件風(fēng)暴擅長于可視化引導(dǎo)取得共識(shí)骑疆,而不善于對(duì)復(fù)雜業(yè)務(wù)進(jìn)行分析并對(duì)設(shè)計(jì)進(jìn)行抽象。
對(duì)于新開發(fā)的項(xiàng)目替废,在尚不清楚未來的業(yè)務(wù)變化方向的時(shí)候箍铭,本著不過度設(shè)計(jì)的原則,可以基于初始的共識(shí)模型先進(jìn)行編碼以快速獲得反饋椎镣,然后根據(jù)隨后業(yè)務(wù)的變化逐步演進(jìn)模型以及調(diào)整代碼诈火。
但是對(duì)于一個(gè)既有系統(tǒng)的重構(gòu)項(xiàng)目,任何初始的分析模型状答,只是做到把業(yè)務(wù)映射到初始設(shè)計(jì)冷守,幫助參與者達(dá)成共識(shí),還是遠(yuǎn)遠(yuǎn)不夠的惊科。這樣的模型可以作為起點(diǎn)拍摇,但還遠(yuǎn)不是終點(diǎn)。
好的模型設(shè)計(jì)是需要抽象的馆截,是在抽象之后依然易于理解的充活,甚至更易于理解的蜂莉。
既有系統(tǒng)的代碼里沉淀了曾經(jīng)業(yè)務(wù)面臨過的各種變化,它們體現(xiàn)在代碼中到處散布的條件分支判斷中混卵,體現(xiàn)在代碼中到處的重復(fù)邏輯上映穗,體現(xiàn)在每次新需求到來時(shí)的散彈式修改中。
代碼里所有的這些點(diǎn)都是抽象的源泉淮菠!模型設(shè)計(jì)需要基于代碼男公,識(shí)別業(yè)務(wù)的主要變化方向,分離不同的變化方向合陵,建立抽象枢赔,從抽象的維度重新解構(gòu)模型元素并尋求更本質(zhì)的組合關(guān)系,從更深的業(yè)務(wù)洞察里為抽象的概念和關(guān)系找到更符合業(yè)務(wù)本質(zhì)的設(shè)計(jì)拥知。
而上述這些踏拜,大多數(shù)時(shí)候需要的是學(xué)習(xí)更多的業(yè)務(wù)文檔,安靜的閱讀和分析代碼低剔,以及在需要的時(shí)候能找到相關(guān)的人進(jìn)行深入的交流速梗。
當(dāng)我們能進(jìn)一步得到一個(gè)兼顧易理解性和低成本響應(yīng)變化的,更體現(xiàn)業(yè)務(wù)本質(zhì)的領(lǐng)域模型襟齿,這才是指導(dǎo)既有系統(tǒng)重構(gòu)的良好起點(diǎn)姻锁。