一、系統設計 根據工程實踐經驗,系統設計總體來說可以精簡提煉分為兩個核心階段,即總體設計和詳細設計。 1、總體設計 總體設計的主要任務是把需求分析得到的結果轉換為軟體結構和數據結構,也就是確定軟體的主體系統結構。 設計軟體結構的具體任務是將一個複雜系統按功能進行模塊劃分、建立模塊的層次結構及調用關係 ...
一、系統設計
根據工程實踐經驗,系統設計總體來說可以精簡提煉分為兩個核心階段,即總體設計和詳細設計。
1、總體設計
總體設計的主要任務是把需求分析得到的結果轉換為軟體結構和數據結構,也就是確定軟體的主體系統結構。
設計軟體結構的具體任務是將一個複雜系統按功能進行模塊劃分、建立模塊的層次結構及調用關係、確定模塊間的介面和人機界面等。
概要設計方法的主要目標是根據特定維度確定各個子系統和模塊的劃分,將由一個或多個功能(或目標)密切相關或相似的應用程式所組成的程式集合抽象出來。根據經驗概要設計方法主要包括模塊化方法、功能分解方法、面向數據流和麵向數據結構的設計方法。按照面向服務架構(SOA)或者比較時髦的觀點,概要設計的主要工作就是提取和整合微服務及業務邏輯,按照領域抽取展示層,最終拆分出功能獨立的子系統。舉例來說,按照一般的模塊化或者功能拆分方法,我們可以將一個完善的電商系統分解為商品、庫管、訂單、支付、財務、結算、配送、搜索、CRM、虛擬貨幣、優惠票券、簡訊、郵件、活動等子系統。而子系統可以再次按照模塊或者功能細分,比如訂單系統可以按商品品類或者活動類型或者線上線下等維度拆分;支付系統可以按照內外部支付方式、支付和風控策略、支付模式(如跳轉或直連等)等不同維度進行劃分。從SOA的角度看,不論子系統劃分維度是什麼,SOA都會對各種服務進行佈局和整合,發佈服務和數據契約,其最主要的目的就是對子系統服務進行復用。當然,SOA如何和子系統設計佈局和整合聯繫起來這是另一個話題了,本文不展開討論。
2、詳細設計
細節決定成敗(Idea is cheap,detail is devil.),詳細設計是實現系統模塊的關鍵步驟。
程式=演算法+數據結構,雖然我認為這個公式不完全正確,但是突出了演算法和數據結構的重要性。
詳細設計的主要任務就是根據總體設計中確定的業務子系統,設計每個子系統功能或模塊的實現演算法和數據結構,但根據一般的業務系統開發經驗,詳細設計涉及的具體內容可能還包括資料庫設計、界面設計、子系統互聯設計等。
詳細設計非常考驗程式員的基本編程水平和經驗。我認為任何詳細設計的最終目標都是通過可編程的手段實現軟體系統,所以,對於開發人員,代碼是第一重要的作品,其次才是文檔,手冊,圖表,再其次是PPT等等這些副產品。
在實現業務子系統的過程中,必然會涉及到各種方法論,比如面向過程,面向對象等等。那麼通過哪種方法論如何實現一個可正常工作功能強大適應變化的子系統呢?
在系統具體實現這一塊,我個人接觸最多的是面向對象編程(OOP)。成功設計開發一個子系統,我的個人開發經驗可以總結為如下幾條:
a、分而治之,劃分模塊,子系統還可以拆分子系統,服務還可以拆分子服務,這裡涉及到一個粒度的問題,非常考驗開發者的水平和經驗,否則很容易過度設計
b、分層,這個不用說了,如果你真正理解分層的含義,那麼在很多情況下,N層不如經典三層,誰寫誰知道
c、保證隔離,劃清界限,不要過多假設,不要拖泥帶水,任何模塊或服務只做它該做的事情
d、實現隔離的最佳方法,就是針對介面,而不是對具體實現編程(Programming to an Interface, not an Implementation)
e、多態,多態,多態,如果一定要復用類,請優先使用對象的組合而非繼承
f、提取變化劇烈的變化點,定期重構,核心業務邏輯必須單元測試
g、UI變化最大,其次業務邏輯,而且很多時候UI變化會直接影響後端業務邏輯,所以,你的介面設計要向UI和業務邏輯傾斜,反而是基礎框架和基礎服務非常穩定,不需要過度設計
做到上面這幾點,絕大多數的開發問題都會迎刃而解,反正在我多年開發經歷中屢試不爽。
當然,歸根結底,成功的子系統的設計與開發還是看具體開發者的水平,如果邏輯和抽象能力差,或者不認真沒有追求看上去就不那麼讓人放心,說什麼都是白搭。
二、平臺化設計
我們可以把以提供統一的公共服務為主要職責的軟體或系統叫做平臺軟體。比如常見的框架基礎平臺、應用管理平臺、工作平臺(OA系統等)、MDM、運維平臺、財務平臺、結算平臺、支付平臺、配送平臺、決策平臺、客戶管理平臺、CTI平臺、開放平臺、雲平臺等等。
縱觀軟體發展歷程,圍繞著“復用”,各種方法論和工具層出不窮,比如:結構化開發中,函數和過程(表示一段代碼)的復用;面向對象設計(OOP)中的類和對象的復用 ,COM和COM+中的組件標志著模塊的復用;SOA架構中某個業務服務(子系統)的復用等等。
主流的軟體開發模式中,復用成了系統設計的一個重要目標,平臺化是復用軟體產品的一套成熟解決方案,開發和運營的性價比也較高,而且相對有利於擴展。
為什麼說平臺化設計有利於擴展呢?下麵的段落中我將講一個發生在自己身上的真實案例。
三、多商戶或多租戶系統
兩年前某司新擴張了業務,大致需求就是相當於註冊一個新公司同時該新公司可以使用已有的很多系統,但某些核心業務(如財務等)需要獨立運營,然後就涉及到我這裡說講的多商戶或多租戶的系統。
平臺化的軟體產品有多種多樣,其中,又以多商戶或多租戶的系統設計與實現最為複雜,而且隨著需求的變化,擴展性很容易成為瓶頸,多商戶或多租戶的系統數據存儲我曾經有過簡單總結。
具體到某司的系統擴展,我給出的是兩種方案,方案一是可以為新公司獨立部署一套應用實例然後修改配置搞定,方案二是可以通過增量增加代碼重新實現一遍已有的功能。
從維持系統穩定的角度,兩種方案在理論上而言都相對的不會改動原有系統的實現代碼,第一種直接拷貝原有的部署結構重新實施改改資料庫配置就行了,第二種則是不改動任何已有代碼而是通過增加新代碼實現功能(這種不改動任何已有代碼僅限理論上,考慮到業務複雜性,可能還是需要對已有邏輯做些微調)。對於這兩種實現方案,很顯然會有人有不同意見,好了,我知道你們要說重覆是魔鬼,不要重覆你自己等等等等。要是在2010年之前,我一定也有類似的看法,我甚至還可能寫篇博客之類的洋洋灑灑批駁一番,但是經過多年工作和編程實踐考驗,再碰到有人說重覆我就呵呵對待了。
無數事實證明理論和實踐不是一回事,歪果仁也流行說theory is ugly,idea is cheap,talk is very cheap...所以我們需要大膽實踐,驗證口頭上的理論在現實環境下到底行不行得通。
如果團隊人員充足,第一種簡直是為了擴展性而量身定做的,看上去只是增加了部署實施和後續維護的成本而已。但是如果人員不足,或者變化劇烈系統未來走向依然不確定,從維護角度,個人倒是傾向選擇第二種方案,因為通過數據共用和可擴展配置然後只維護一套系統,我實在想不到不使用這種方案更好的理由了。
最終我選擇了第一種方案,一份代碼配置成兩套系統。^_^ Yes,it works.兩個系統目前運行穩定。
這是我兩年多前近一個月的親身實踐,最大的收穫是,系統實現要高度可配置可運維,而且後臺管理工具要開發完備,一套系統按實例多次部署確實是很有效可行且實惠的解決方案。
四、通用架構基礎服務
在概要設計和詳細設計過程中,不論業務、方法論、工具或框架等外部條件怎麼變化,從各個(不同)系統中總是可以抽象出公共的相對穩定的框架工具或服務,比如分散式緩存服務、消息隊列服務、通用數據訪問代理DAL(提供訪問數據模型和後端數據服務API實現對資料庫的一致性訪問,如果分表分庫了,也包括DBRoute功能,不能簡單等同於ORM),企業服務匯流排(ESB)、分散式文件系統、通用日誌服務等等。這些基礎技術服務不同於業務系統,也不同於公共平臺服務(架構基礎服務可供公共服務調用),因為它們和多變的特定業務邏輯無關,相對偏重於底層技術,對技術要求較高,開發和運維這部分服務的都是水平較高的技術型選手為主。一般能獨立造輪子出來的公司還是比較有技術含金量的,雖然我也碰到過只發明卻不能用或者一用就有無數坑的團隊。我認為如果沒有這部分通用架構基礎積累,各個子系統各自為戰很可能會造成運營和管理上的難題。
總結
這是我個人從業10年的系統設計與開發經驗的粗淺總結,B/S和C/S結構的開發都通用。在很多人看來可能更多偏重於方法論,我所知道的絕大多數開發人員更喜歡討論技術細節的乾貨,比如幾年前的自己,更多的偏重於“小節”,比如記錄學習某某編程語言的語法糖,某某流行框架的實踐,某某資料庫操作的奇技淫巧,某某演算法和數據結構的妙用或誤用,某些新技術的使用經驗之類。
但是,我個人認為,當你真正從專註細節的小兵成長為可以獨當一面的大將後,你可能也會跳出這些“細枝末節”,從系統和架構的角度,把握全局,全面看問題。
難忘的2017即將過去,感謝志同道合的人,每一年,我們都要有收穫和進步,低頭沉默更堅定。Coding for fun.
祝大家新年快樂。