坑:重構過程中的過度設計

吳YH堅發表於2017-01-18

這個系列是系列,會說一些在系統設計,系統架構上的,這些都是我想到哪說到哪,有像這篇一樣比較巨集觀的,後面的文章也會有到具體技術細節的(比如某個函式,某個系統呼叫),總之,到處都是坑,這些坑有些是我經歷過的,有些是聽說的,你也可以留言說說你遇到的

這一篇,我們從重構這個場景來看看系統架構的設計中過度設計這個坑。

首先,我們這裡說的「重構」,和《重構:改善既有程式碼的設計》這本書中的重構不太一樣,這是本好書,它主要說的是程式碼級別的重構,這種重構是需要在編碼的時候時時刻刻進行的,更多的是一種程式設計思想的訓練,而我們這篇的重構主要是說系統設計的重構

0. 關於架構師

在說之前先聊聊架構師這個職位吧,這個職位最近兩年特別特別火,哪個公司沒個架構師好像都不好意思跟人打招呼,各位架構師打上這個標籤後頭上就頂了一個光環了,本人也認識各個公司的一些架構師,我認識的架構師分成幾種:

  • 系統架構師,這種技術能力是最強的,這也是一般人眼中的架構師了,這種架構師一般屬於領域架構師,對某個領域的技術有比較深入的瞭解
  • 業務架構師,我只是用了這個名字而已啊,有些地方的業務架構師其實和上面的系統架構師沒什麼兩樣,但有些業務架構師有些脫離了技術了,基本上變成了一個專案經理的角色,各種溝通,我覺得不應該算架構師了。
  • PPT架構師,這個顧名思義,這是”最高階”的架構師了,只要PPT做得酷炫就OK了,這是我等達不到的程度,呵呵呵呵。 最近還有一種說法就是架構師到底要不要會寫程式碼?我的理解是沒什麼可說的,必須要會寫啊,你一個架構師,程式碼都不會寫還架構個屁啊,就算你是PPT架構師,沒時間寫程式碼,但出問題了掄起袖子來解BUG的能力得有吧,而且很關鍵的一點,架構師面對的都是一群技術宅,你連個程式碼都不會寫,你覺得下面的技術宅會看得起你麼?至少你得顯得很會寫吧。 為什麼說架構師呢?因為大部分架構上的坑都是從一個不好的設計開始的,而現在的各個系統的設計都是由架構師來操刀的。

1. 重構中的過度設計

技術人員最喜歡做的一件事就是重構,因為技術宅們都看不上別人的程式碼,特別是需要在別人程式碼上加新功能的工作更是看不上,架構師們是技術宅的升級版,所以更加看不上別人的架構設計,所以重構是經常做的事情,小的是功能模組的重構,大的是整個系統的重構,總之,都是不重構不舒服斯基

重構本身並沒有問題,但是需要看的是重構的時機,是不是應該重構了?

我們以一個例子來詳細說說重構中的過度設計吧,你也可以想想要是遇到這樣的系統,你是架構師,你怎麼做?歡迎留言討論。

假如有個初創公司,是幫企業做OA系統的,最開始的時候是由三個程式設計師小哥開發出來的,系統架構很簡單,是個AllInOne的設計,開發語言PHP,就像下圖一樣。

每當客戶有新需求,基本的操作就是加個表 --- 加個邏輯模組 --- 修改一下介面 --- 上線,而且一般OA系統是部署在客戶內部的,所以每次修改都是針對單獨客戶進行開發。

公司發展的越來越好,有了一些大公司買了他們的OA,有錢了,請了個架構師過來優化優化技術架構,架構師叫小明(每次都黑小明),小明來了一看現有設計,我去,這怎麼行?三天後,給出了他的建議

  • 首先,資料層都在一個庫裡面,以後資料量大的話資料庫效率太低了,首先要分庫分表,把使用者資料表和事件表橫向和縱向的拆分一下,雜湊到不同的機器上去,減輕單臺機器的壓力。
  • 其次,AllInOne的設計太臃腫了,要把各個模組微服務化,把許可權模組,附件管理模組拆分出去成為一個微服務,提供API給其他模組使用,方便維護,後續新增新功能做一個微服務就行了,和其他模組的耦合性急劇降低。
  • 在資料層和業務層之間加一個代理層,用個開源的中介軟體,以後資料端再有分庫分表操作,對上層遮蔽細節,業務人員不用關心底層資料庫細節,專心寫業務邏輯就行了。
  • PHP效能不太行,並且介面做出來不好看,前端分離還不徹底,改成Nodejs+Angularjs來進行前後端分離,前端人員專注頁面,做出更絢麗的頁面來,後端人員專注業務邏輯,使用RESTAPI進行資料互動。
  • docker部署,每個服務啟一個docker,對運維人員友好,而且有很多工具可以看各個docker的健康狀況。 於是,整個系統變成下面這個樣子了。

臥槽,好高大上,乍一看,這就是一個目前比較流行的架構圖了,有資料層,有中介軟體層,有業務層,有前端展示層,資料層支援分庫分表,可以無限擴充套件,業務層微服務化,也可以無限擴充套件,docker部署,一個image搞定部署,簡直了!除了訊息佇列沒有用上以外,其他的流行東西用了個遍啊。

那麼,開始幹吧,把人員分成兩撥,一撥繼續維護現有系統,接客戶新需求,一撥開始重構,一個月時間,把資料和功能模組梳理了一遍,然後開始定各個服務中的介面,又用了小一個月,然後全部人員投入進去開始編碼,又忙活了三個月,終於重構完成了,再花一個月時間追上這4個月新來的需求,牛逼的架構上線了!

如果小明夠厲害並且開發人員也給力的話,最好的情況就是上線後一切正常,你不是重構麼?客戶完全感覺不到有變化,繼續使用得很high。但這種概率幾乎為零,最有可能的情況是什麼呢?

  • 客戶說,臥槽,少了個功能了,臥槽,數不對了,這都是小事,新系統嘛,總歸有一些問題,解決這些bug就好了。
  • 某天發現登入不上了,如果在之前,跟蹤一下程式碼就知道哪裡有問題了,立刻解決了,現在已經微服務了,你說是網路問題還是許可權服務問題還是邏輯問題呢?要跟蹤可沒那麼容易。
  • 某天發現資料寫入和讀取都有問題,最後查問題發現是開源的中介軟體偶爾抽風了,要修改的話,得看中介軟體的原始碼了,跪了吧。。。。
  • 最關鍵的是,你會發現,上了這個新的架構以後,是耦合性降低了,但開發一個新功能的工作量比以前多了,效率反而降低了。

這就是一個典型的過度設計過度設計特點:

完全脫離了業務場景來進行技術架構的設計就是過度設計

這個例子中的業務場景是一個OA系統,OA系統的主要資料是企業的人和人的資料,一個企業能有多少人?一個初創公司,能接入10萬人的大公司做OA已經非常不錯了吧?即便是10萬人的大公司,人的資料也就10萬條,我們在成100,算單個表1000萬條資料吧,單臺MySql完全可以hold得住,所以第一條分庫分表的設計在這個場景下就完全沒有必要,企業主最關心的是什麼?是資料的安全可靠,所以你在這裡把MySql換成Orecle,企業主覺得安全也會買單,並且你收入還能更多,而且換成Orecle的話,單個表上億問題也不大,何必分庫分表?

好,就算你資料量巨大,需要分庫分表,那你整個中介軟體幹嘛?中介軟體的作用是遮蔽底層資料沒錯,但還有個場景是資料讀寫分離,一般是在大資料量並且有高併發需求的系統使用,你一OA系統,能有多高的併發?需要用中介軟體這麼高階的東西麼?

再看看微服務,為了降低系統的耦合度使用了微服務,同樣場景也不對,什麼時候需要把服務拆分出來呢?只有在當前服務已經耗費了單臺機器太多的資源了,單機扛不住了,才會把功能比較獨立的模組拆分成微服務出去,因為微服務雖然降低了系統的耦合度,但是需要更多的考慮到系統的可用性和網路因素造成的問題,對開發人員的要求更高,一個OA系統,能有多大的計算量?

後面的前後端分離啊,docker部署啊,你想想各自的必要程度如何?一個OA是否需要絢麗的介面?一個OA系統的更新頻率有多高?是否需要docker這樣的東西來幫助部署?成本如何?再看看是否是過度設計

最後,我覺得上面這個系統,比較合理的修改設計是:

  • 把資料庫加上一個主從同步,保證資料的可靠性,別資料庫掛了,那客戶可會跟你拼命,這是最重要的。
  • 把系統的SQL語句梳理一遍,看看有沒有什麼慢SQL,然後做針對性的優化,比如加索引,改SQL之類的。
  • 把後端的服務加上詳細的Log資訊,這樣出了問題也好查問題,並且可以把Log收集起來做分析,看看系統的瓶頸在什麼地方,然後再在區域性做優化也好重構也好,這樣對系統的侵入性最小。

這樣下來,系統的效能應該有提升,資料可靠性也增強了,並且也耗費不了多少資源,通過Log分析,一個區域性一個區域性的優化,直到發現了一個大坑需要拆分服務了,再進行服務的拆分,如果你有更好的建議,歡迎留言討論啊。

2. 重構的理由

我覺得重構得滿足以下幾個條件的大部分,才有重構的必要,第一個條件是必須滿足的。

  • 現有系統的所有功能模組和對外介面都瞭解得非常清楚了。如果你沒把對外介面瞭解得非常清楚,重構完了以後外部的依賴系統必然要跟著改,那就是個無底洞了。
  • 現有系統有明顯的重大BUG,並且在現有條件下無法解決或者很難解決。如果僅僅是系統有BUG,那麼解決BUG就好了,完全沒有必要為了BUG來重構,只有當確實BUG已經無法解決或者解決的成本實在太高了,才有重構的必要。
  • 文件缺失或者維護人員大量離職導致目前系統的可維護性降低,很難新增新功能。如果大家都很熟悉現有系統,可以很快的在上面迭代新功能,你重新來一個系統幹什麼呢?
  • 現有系統在可預見的未來無法支撐業務的發展了。只有當業務部門已經跑到了技術部門前面了,可以預見得到業務發展的方向了,再來審視目前的系統,發現已經無法繼續支撐了,這時候才需要重構現有系統。

而重構最忌諱的用以下理由來重構系統

  • 現有程式碼太臃腫,實現不完美。難道你重新實現一個就完美了?
  • 這個系統的技術棧太陳舊,沒有使用最新的技術流,以後肯定會落伍。難道用了新技術就不會落伍?
  • 現有系統沒有考慮高可用的情況,要是出問題了就是大問題。
  • 這個語言就不適合做這個系統,得用XXX語言來實現。雖然說每個語言都有他擅長的場景,但是一個既有系統更換實現語言,是一件成本非常高的事情。

總而言之,重構一個系統最需要考慮的就一個詞:成本,需要衡量各方面的成本後,再考慮是否需要重構,這樣的重構才是有意義的重構。

OK,這一篇簡單的說了一下重構場景下的過度設計的問題,後面還會有和過度設計相關的,你也可以說說你遇到的過度設計,歡迎留言給我哈。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

坑:重構過程中的過度設計

相關文章