重構,讓人快樂讓人苦

2022-04-09 04:10:56 字數 3052 閱讀 8986

重構,是編寫**必須要面對的一項操作,同時也應該是程式設計師樂於實踐的一項內容。不論是邏輯實現還是設計過程,乃至整個分層結構,我們都可能面臨並且實施重構。這篇文章不會告訴您什麼是重構,如何去優美的重構等等的理論,只想和大家分享一些感受,並且**一些問題。最近的兩周,我一直對我們團隊的乙個子業務框架做重構的工作,很多地方讓我感到很痛苦,於是便有了這篇文章。

牽一髮而動全身的根源在**

當我開啟解決方案,檢視**的時候,我們會發現很多問題,比如冗餘的**,效能低下的邏輯實現等等,但是當我著手去改造的時候,潛意識告訴我整個似乎不能動,牽扯的面太廣了。更改乙個小地方,上下一串都要做相應的調整,這當然不是我想要看到的。大範圍的調整會直接影響系統的穩定性,帶來潛在的危險,同時會增加測試團隊的負擔;在版本控制方面會造成線上和線下版本在同一內容的巨大差異,版本更新的時候拿什麼來保證一套幾乎全新的**替換線上系統是正確的選擇呢?因為很多問題只有在最真實的環境才能被暴露出來。

這樣的修改,修改成本無疑是巨大的,因為我們期望修改的只是那一小塊**而已。大範圍的**調整,同時也伴隨著單元測試**的調整。測試團隊如果因此來重新走測試用例,那麼付出的辛苦可想而知。

我要做的是重構而不是重寫,造成這種現象的原因在**呢?

整個解決方案具有相對完整的分層結構,dao層、實體層、業務邏輯層。實體層也對資料實體和業務實體做了分別定義。但是進行業務實現的時候我們並沒有進行有效的隔離和**的職責劃分。

很多**在處理業務邏輯的時候直接呼叫dao,然後使用返回的資料組織業務實體。當我們的業務實體需要按照領域劃分為兩個或者更多的層次的時候,結果會變得更為糟糕,因為我們需要以底層的業務實體為輸入從而輸出上層的實體。當你以乙個順序工作流的方式完成一整套操作的時候,也許感覺很有成就感,整個過程天衣無縫,完美無缺。但是當我們嘗試改變其中的某些內容的話,噩夢就開始了,實體的改變勢必會引起邏輯的改變,但是這種改變是有連鎖反應的。

業務實現的過程很多時候就是不同層次間的實體的轉化過程,那麼實現過程中單單考慮解除依賴不能收到很好的效果,從業務邏輯的職責出發,劃分出清晰的業務層次,再以實體轉變的結合點來考慮分解才能達到良好的效果。

獨立的領域層尤為重要

各種經典的mvc架構的實現,常常讓人產生誤解,認為那樣做就已經完美了。事實上,乙個業務的框架的重點不是增、刪、改、查,我更傾向於將dao從業務框架中分離出去(最後我也是這樣做的),整個系統應該提供統一的dao服務,子業務框架要專注於業務的實現。

當我們嘗試將一整套業務實體獨立出來的時候,我們認為已經做了很好的業務理解,但是這是只見樹木不見森林的想法。在某些系統中,領域的實現只佔**總量的很少乙個比例,但是其重要性往往卻是相反的乙個比例。當我們選擇將領域**和其他**混合在一起的時候,意味著我們的分層結構也隨之混亂。

"用標準的架構模式來完成與上層的鬆散關聯。將所有與領域相關的**都集中在一層,並且將它與使用者介面層、應用層和基礎結構層的**分離。領域物件可以將重點放在表達領域模型上,不需要關係它們自己的顯示、儲存和管理應用任務等。這樣使模型發展得足夠豐富和清晰"。在清楚了整個領域模型之後,再考慮選擇合適的模式來解決分層問題,我覺得是合理的做法。

在對業務和領域沒有充分理解的時候不要下手

在重構過程中,發現很多業務實體的定義不著邊際,很多概念只是對資料實體的拓展,結果出來的東西和資料實體的邏輯關係截然不同。對資料調取的邏輯沒有充分理解,那麼組織業務實體的時候很容易出現不恰當的資料訪問方式,比如迴圈訪問資料庫。

如果整個領域模型的建立和劃分都是錯誤的話,我們仍然能實現所需要的功能,但是如果對這樣的**進行重構無疑等於推倒重來。

現在看來,當我們為了實現功能而急匆匆的不擇手段的時候,為將來的維護和公升級埋下了隱患。當我們想要將公用的資料調取和業務邏輯實現從各個子專案中抽象出來變成基類、介面、helper或者service的時候,我發現不同子專案的開發者對業務和領域的理解有著很大的差異,因而在實現方式和實體定義上都有很大的不同。這個時候我們又注意到組織實體的邏輯並沒有單獨的分離出來,抽取的工作遇到了難題。也許我們可以分離出**,然後使用adapter來適應原有的實體組織邏輯,又或許我們應該廢除不合理的實體定義,也意味著廢除了相應的實現邏輯。

如果我選擇將不合理的實體替換為正確的實體定義將面臨巨大的挑戰,也許從資料調取到最終的邏輯都要調整。當然全面調整的原因是我們沒有實現很好的隔離。

迷茫,面對乙個幾千行的method

這是我無法容忍的情況,整個子業務的實現幾個大方法全搞定了,每個方法裡無數個"region"和"end region"。這樣的情況就別談什麼分離和設計了。最起碼的,當你在用"region"和"end region"的時候,就應該意識到這裡可以分離出乙個方法來。

大方法帶來很多弊端。它的可維護性差,可閱讀性差,和系統的分層結構不融合,不能進行有效的單元測試。當然對大方法的重構並不像**本身那麼發雜,如果它的邏輯足夠清晰的話。但是如果乙個思維足夠清晰的程式設計師又怎麼會寫出這樣的**,所以對這樣的**進行重構,面臨乙個很大的問題就是那些在不同邏輯裡重用的區域性變數。當然更重要的問題是理不清頭緒。

光去抱怨是沒什麼意義的,這樣的方法出現的原因是什麼呢?乙個是開發者沒有很好的理解業務框架的結構和目的,二是對程式設計的基本思想理解的不夠好,三是對業務邏輯本身理解的不夠清晰。對於這樣的實現去重構,除了從業務角度出發,抽絲剝繭,慢慢的剝離,還有什麼好辦法呢?推倒重來嗎?

重構,要隨時進行

當有乙份**覺得不合適,而沒有及時重構的話,那麼整個解決方案就可能變成垃圾場。後續的開發人員會以存在即合理的想法來看待這些垃圾**。尤其是新加入的成員,只能模仿別人在怎麼做。從測試驅動的開發理念看,程式開發是乙個不斷重構的迭代過程。很多人將重構看成是一件大事,一聽到重構就害怕起來,尤其是測試團隊。當然這裡不能否認,不恰當的重構會給測試團隊造成很大的麻煩。

集中重構是極其錯誤的思想。不要想著等某些開發任務結束了,有時間了再集中精力來重構**。當系統相對穩定之後,重構要付出的代價可能是整個團隊無法接受的。對分層架構的重構應該是建立架構的最初一段時間,不斷的調整達到最優。當專案進行一段之後,再來調整整體結構無疑是讓人無法接受的。

重構要避免過度設計

最後要說的是,重構要圍繞乙個適度的目標來進行,要考慮代價,同時不代表模式應用的越多越好。相反的,在重構過程中,要時時考慮是否把簡答的事情想複雜了。

目前我重構的**中,還沒有這樣的問題,這裡也就不囉嗦了。

說了這麼多,我還是想聽聽各位的看法和感受,如何進行有效的重構,如何在程式設計的最開始的階段就避免很多重構障礙的產生?

讓人抓狂HTML DTD

在做網頁時,經常會遇到一些瀏覽器差異的問題,即使你對常見瀏覽器差異有些知識儲備,但你死活也修改不好。我就遇到幾個這樣的問題。兩個div之間在ie下有幾個畫素的空白,乙個div莫名其妙的高度變高兩個畫素。雖然都是小問題,但是不解決心理總覺得彆扭。這些bug改起來很讓人抓狂。最後把替換為,問題就消失了,...

夜 讓人回想

久日子重複了,人便無靈魂,心不再有竅,便不再思索,不再有感覺,就只能繼續重複,像鐘擺一樣,迷失在時間的海洋。夜是心靈的燈塔,對,只有寧靜的夜晚才能撥開那禁錮的靈魂的迷霧,露出那塵封已久的心性,夜像新雨 像朝露,像甘泉滋潤著她。我們在茫茫人海中穿梭,滄海一粟,星星點點,幾經碰撞,只為擦出那炫麗的火花,...

MongoDB讓人失望

最近由於專案需要,使用了mongodb儲存資料。坦率的說,挺讓人失望的,當然,不排除對mongodb不太熟悉的原因。但總的說來,感覺名不副實,想讓大家喜歡並接受,mongodb還有很長的路要走。簡單說一下碰到的問題 1.非常耗記憶體。貌似這點很多人都抱怨過。因為mongodb採用的是記憶體對映檔案的...