年底了, 趁著閑暇,想寫點什么。
2019年,很開心這一年又堅持看了很多書。如果讓我找到一本收獲最大的,無疑是《演示式架構(gòu)》。薄薄的138頁,我反復(fù)了看了很久,也在工作中體會到了作者提出這個美妙的詞匯——“演進”。我之前看了很多相關(guān)的書籍,我看到過“架構(gòu)是經(jīng)驗主義”(《架構(gòu)之美》),“整潔架構(gòu)”,我能從里面體會到項目分層和權(quán)職劃分的妙處,但直到看過這本書,才體會到,是有一些技巧去權(quán)衡和選擇項目架構(gòu)設(shè)計的方法論的(其實,直到1年多以前,我都還體會不到很多概念該怎么應(yīng)用到實踐中),當(dāng)然這真的是需要體會和打磨的。
我想整理下這本書中學(xué)到的和在項目中體會到的一點點方法和經(jīng)驗,當(dāng)然,這只是我閱讀了2遍左右的收獲,也可能僅僅適用于移動端的敏捷開發(fā),僅供參考,別被誤導(dǎo)了哈,不到之處歡迎批評。對了,這里沒有到具體細節(jié),因為很多公司分享過的演進過程更有參考價值(印象比較深的:微信、美團、安居客)。
《演進式架構(gòu)》:
1. 架構(gòu)師應(yīng)不斷的對項目進行平衡,以適應(yīng)環(huán)境的變化。
2. 架構(gòu)師應(yīng)不斷的關(guān)注團隊的關(guān)系,讓架構(gòu)適應(yīng)團隊的合作方式,符合“康威定律”。
3. 架構(gòu)是不斷努力的結(jié)果,是一個與開發(fā)工作緊密結(jié)合的過程,這樣它才能同時響應(yīng)不斷變化的需求和開發(fā)人員的反饋。我們稱之為“演進式架構(gòu)”,正是要強調(diào)當(dāng)無法預(yù)測變化時,該架構(gòu)仍然可以朝著正確的方向發(fā)展。
4. 演進式架構(gòu)的核心是采取小步驟變更,然后通過反饋環(huán),讓團隊的每個成員從系統(tǒng)地發(fā)展過程中學(xué)習(xí)。持續(xù)交付的興起使得演進式架構(gòu)變得切實可行。
5. 大泥團架構(gòu)、單體架構(gòu)、事件驅(qū)動架構(gòu)、服務(wù)導(dǎo)向架構(gòu)、“無服務(wù)”架構(gòu)。
注:如果開發(fā)人員難以構(gòu)建最簡單的架構(gòu),那么轉(zhuǎn)向更復(fù)雜的架構(gòu)并不能解決問題。
6. 適應(yīng)度函數(shù):現(xiàn)實架構(gòu)由很多不同的維度構(gòu)成,包括性能、可靠性、安全性、可操作性、代碼規(guī)范和繼承等方面的需求。我們需要適應(yīng)度函數(shù)能代表每一項架構(gòu)需求(開發(fā)人員由多種描述是硬度函數(shù)的機制,比如測試和衡量指標(biāo))。
敏捷開發(fā)的思路讓一個項目可以快速迭代,演進式架構(gòu),無疑是為適配敏捷開發(fā)的絕好工具,一直在往前走,所以一直在調(diào)整,永不過時。之前接觸過“微服務(wù)”、無服務(wù)的設(shè)計,一直在嘗試是否能在項目里實踐,可是上面“注”的那句話太好了,這些結(jié)構(gòu)可以是演進過去的,永遠不要覺得換結(jié)構(gòu)就能解決目前的問題。
在迭代中我是怎么實踐演進的實踐的?
? 1. 在需求演講階段(產(chǎn)品時主角),發(fā)現(xiàn)代碼中的痛點,并制定重構(gòu)計劃,將重構(gòu)任務(wù)盡量適配到迭代版本中(分步驟切分到多個版本中),達到持續(xù)交付、隨時線上驗證設(shè)計(當(dāng)然,這個很考察開發(fā)人員對項目和編碼的熟練度,別挖坑,別挖坑,慎之又慎是關(guān)鍵?。?!但是,要大膽,這樣才能做出事情);
? 2. 在review和日常工作中,收集開發(fā)人員對業(yè)務(wù)層、業(yè)務(wù)管理層、數(shù)據(jù)層接口的痛點,并搜集大家期待的舒服訪問方式,考慮進行重構(gòu);主動接收項目中維護困難的部分,重寫或重構(gòu)其實現(xiàn),減少閱讀和維護成本;
? 3. 在開發(fā)過程中,發(fā)現(xiàn)業(yè)務(wù)層可下沉到數(shù)據(jù)管理層的部分,在繁重的迭代任務(wù)后盡快適配到目前的設(shè)計結(jié)構(gòu)中,減少業(yè)務(wù)層的代碼難度;
(處于原型期的項目)
對于一個新項目,早期的迭代,實現(xiàn)的優(yōu)先級是大于編寫整潔代碼的(以前我也覺得我的精力絕對可以一直把做對和做好兼顧到。但是實踐證明,時間不等人,人的精力真的是有限的,做好真的是需要不斷積累的,畢竟還是能抽出時間做好的),繁重的開發(fā)任務(wù)甚至讓大家無暇去考慮重構(gòu)。但是,相信一點”早期項目架構(gòu)的整潔更是能為后面的迭代節(jié)省大量的時間”。我們可以在迭代初期以一種先實現(xiàn)的思路去做好功能(這個時候,分層的考慮、自上而下的訪問等規(guī)則甚至都難以保證),這就好比先忍受讓一棵樹木,四處亂長,但是我們需要及時(這個詞匯太重要了!別等,等就會越來越多?。?/b>、不斷的進行修剪,讓其盡量美觀;早期的項目嘛,不得不面對較多的設(shè)計錯誤。在一個版本提測后犯錯誤的成本是比較低的,這時候為重構(gòu)和設(shè)計提供了較充分的時間;一定要利用好這段空閑時間,果斷的進行重構(gòu)和打磨,讓代碼保持到盡量整潔,這樣的工作絕對不是一直持續(xù)的,因為幾次的重構(gòu)我們會積累下經(jīng)驗,慢慢的在迭代中去考慮設(shè)計,可能需要重構(gòu)的代碼會越來越少;這樣下一版、下下一版的擴展和修改成本才會越來越低。在測試后改結(jié)構(gòu),測試很多時候是無感知的哦,要小心!
(處于增量期間的項目)
我覺得《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》最后一章對于怎么維護這樣的項目講的挺好的。
做演進式設(shè)計,就是個“積跬步成千里”的過程,而重構(gòu)是一直在用的鋒刃利器,能較敏銳的發(fā)現(xiàn)重構(gòu)和實踐重構(gòu)是我一直在追求和實踐著的。實踐證明,追求好的過程中一定會受到吐槽和阻攔,但是先對事,解決問題后重新審視問題并豐富設(shè)計的方式可以更從容的應(yīng)對這些矛盾。我將重構(gòu)劃分為三個層次:函數(shù)級別的重構(gòu),類級別的重構(gòu)和體系結(jié)構(gòu)重構(gòu)。
函數(shù)級別的重構(gòu),旨在提高減少閱讀成本(讓注釋顯得多余),讓修改變得簡單(應(yīng)對散彈式修改),事不過三(重復(fù)的代碼不寫三遍,當(dāng)然,重復(fù)有時候會優(yōu)于整合,這是個權(quán)衡問題)。比如:為減少注釋而新建的函數(shù)、為減少代碼行數(shù)而劃分的小函數(shù)等(減少維護者在代碼處的停留時間);
類級別的重構(gòu),以前很多人都提到了設(shè)計模式等概念糾結(jié)太多會提高復(fù)雜度,甚至提出了反模式。我記得一本書上說過:所有的反模式都是可以使用設(shè)計模式更好的實現(xiàn)的。我記得有這樣的一個理論,當(dāng)你覺得有一個反人類的設(shè)計時,也許是你走入死胡同了。我個人一直在向身邊的朋友建議,也許這并不是解決問題最好的思路,你可以嘗試接受一下XX設(shè)計的思路也會可以更好的解決問題呢。對了,分享一個設(shè)計模式絕好的項目:https://github.com/iluwatar/java-design-patterns?,參與這個項目很久了,這里有上百個大家多年工作和總結(jié)后的模式,并解決了很多經(jīng)典23設(shè)計模式的缺陷,我個人覺得這是做類級別重構(gòu)的絕好學(xué)習(xí)資料,盡量閱讀完,收獲絕對是非常非常大的。
體系結(jié)構(gòu)的重構(gòu)。這塊我還是在摸索,以我的水平,暫時只是參考google等提供的分層設(shè)計并找出部分問題嘗試修改的階段,這其實還是第二級吧。從一個分層設(shè)計切換到模塊化設(shè)計,甚至到現(xiàn)在主流的微服務(wù)設(shè)計,沒經(jīng)歷過(也是因為項目的痛點沒體現(xiàn)到導(dǎo)致的吧),我能體會到這一定是大量功能的重寫支撐起來的,我從網(wǎng)上的文章中看到過美團外賣android和微信android曾經(jīng)分享的體系結(jié)構(gòu)的重構(gòu),還是挺成功的,過程耗時0.5-1年左右,我吸收了他們的經(jīng)驗,但不太適合我所經(jīng)歷的小、中型項目,其實主要也違背了“架構(gòu)要適應(yīng)組織結(jié)構(gòu)的變化”。