都說軟體架構要分層、分模組,具體應該怎麼做(一)

2021-03-10 12:01:17

道哥的第 027 篇原創

一、軟體架構設計的生命週期

什麼是架構?如果你問十個人,有可能得到十一種不同的答案;如果去翻一下相關的書籍,每一本都可能給出不同的定義。

因此,我們沒必要糾結於那些概念,只要方法對、能完成專案任務就行,不管黑貓白貓,能抓到耗子的就是好貓!

1. 軟體開發流程

一個軟體專案,從立項開始到最終的交付,中間經歷了諸多環節。具體到軟體設計的生命週期來說,可包括這些階段:需求調研-需求分析-概要設計-詳細設計-架構驗證-開發-單元測試-整合測試

上面這幾個步驟,仍然是非常粗略的概念。在實際操作中,其中的每一個步驟又可以細分為很多具體的執行環節。

例如:

  1. 需求調研:應該怎麼做?用什麼方法?有什麼指導思想?有什麼好的工具?
  2. 需求分析:應該怎麼分析?所有的需求都應該被分析嗎?如何找出關鍵需求?
  3. 詳細設計:在軟體工程中有什麼實踐性比較好的方法?如何分層?如何分模組?

以上這些都是軟體設計的過程中,需要涉及到的問題。那麼軟體設計的最終目標是什麼呢?就是下面幾個檔案:

  1. 邏輯架構;
  2. 物理架構;
  3. 執行架構;
  4. 開發架構;

2. 關於套路

我認為,在這個世界上,一切皆有套路,包括任何事情、任何領域、任何行業。

當我們進入一個新的領域時,比如:讓你設計一個車輛排程系統、機器人控制系統,或者設計一個對講機、一個物聯網閘道器,如果你是這個領域的新人,那麼肯定是兩眼一抹黑:我對這個領域完全不懂,怎麼設計啊?

這讓我想起一個小故事:

有一次我剛入職一家新公司,接手一位離職同事手裡的工作。當時執行 KPI 考核,bug 直通率(就是一次性把 bug 解決掉的比例,QA 人員不會再把 bug 踢給你),是一個重要的指標。面對系統裡那麼多的bug,領導問我:這些問題你大概需要多久能解決掉?我說:以前沒接觸過這方面的工作,沒法給出準確的時間。領導說:沒關係,你先給我一個具體的時間就行了。當時我就懵逼了。

在這個時候,最重要的事情就是,快速把這個領域裡的基本的、重要的背景知識瞭解、掌握。那麼應該如何做呢?找套路

不要貪大求全,不要奢望把所有相關的內容都掌握,這是不可能的,尤其是在短時間內。我們的目標是把活做好,把專案完成

這個時候,我一般的做法是:找套路!

這麼說可能有點虛幻,那麼就以軟體開發中的架構設計來舉例。在軟體工程或者專案管理的書籍、資料中查詢下面這些相關內容:

  1. 別人是怎麼來設計架構的?
  2. 設計過程中需要哪些步驟?
  3. 每一個步驟中,輸入是什麼?輸出是什麼?
  4. 每一個步驟中,需要考慮的點是什麼?
  5. 有哪些好的軟體工具?
  6. 如何與專案的相關人進行溝通(專案經理、開發人員、測試人員、甲方客戶)?

把以上的這些別人的經驗進行梳理,總結出一套適合自己的「方法論」,然後在具體執行的時候按照這個套路一步一步的走,根據實際情況適時的動態調整,一般來說都能夠順利的推進一個專案。

3. 先僵化,後優化,再固化

這九個字是華為的掌舵人任正非在引進管理體系時提出的,這是一種非常實用的方法。

  1. 僵化:站在巨人的肩膀上:處於學習初期階段的「削足適履」;
  2. 優化:掌握自我批判武器:在實踐中不斷吸收、改良、創新,優化自己;
  3. 固化:創新是有階段性的、受約束的,如果沒有約束,創新就是雜亂無章、無序的創新,需要像夯土一樣,一層層夯上去,一步步固化階段性的優化成果;

對於軟體架構設計,我們也可以按照這樣的步驟走。

第一步就是僵化,也就是按照按照固定的套路走,雖然可能會「落入俗套」,但是至少能保證在正確的道路上,不會走歪,這是最重要事情!

如果被別人認為是「落入俗套」了,說明什麼?說明別人已經認為你的做法符合這個領域中最「一般的」的做事流程,也就是相當於認可你已經真正進入這個領域了,這是好事情!

作為初學者,被別人這樣評價,不應該覺得自豪嗎?畢竟我們自己心裡知道:我就是剛剛進入這個領域的小白而已。

4. 佛說:「知我說法,如筏喻者」

我寫這篇文章的目的,主要就是想聊一聊我是如何「僵化」的來進行軟體架構設計的。

我們在剛進入軟體開發行業的時候,每天的工作主要是擼程式碼,也許還不夠資格來進行整個系統的架構設計。但是這並不妨礙我們自己來主動學習,機會都是留給有準備的人的,如果有一天,專案組裡出現了架構設計的這個坑,那麼領導會找哪個蘿蔔來填坑呢?

因此,這篇文章主要介紹的就是最初級、最基本的軟體設計步驟,以及在每一個步驟中使用的指導思想、順手的工具等等。

如果您已經是資深軟體設計工程師,那麼可以去喝咖啡、享受人生了,當然也可以分享您的方法論,我們相互學習!

這些內容也不是我自己摸索出來的,而是在專案開發過程中翻閱書籍、搜尋資料、總結而來的,比較適合我所面對的專案,我也僅僅是知識的搬運工

之前,我主要參考了幾本關於軟體架構設計的書籍,相互借鑑,總結出適合我的一套方法。上次搬家,好多書籍丟掉了,只剩下電腦裡的零碎筆記了。這篇文章的素材來源,就是這些筆記,當然,大部分內容都是來源於書本,我只是進行了一些取捨、裁剪而已。

《金剛經》第六品,如來常說:「汝等比丘,知我說法,如筏喻者;法尚應舍,何況 非法。」

佛法就像渡人過河的木筏,過了河上了岸,就應該把木筏丟掉,心中不要再想著木筏。木筏就像佛法,佛法尚且應該丟棄,何況不是佛法的東西,你還糾結他幹嘛。

所以,我這裡所講的設計套路,也類似於木筏,用來幫助你在剛開始進入軟體架構設計時的一個腳手架。當你進入到第二個段位「優化」時,就可以把這個腳手架扔掉了。

到那個時候,你就可以自信的說一句:「道哥寫的都是寫什麼東西啊,小兒科的東西,我需要向更高階的段位去探索」。到了這個時候,我就要衷心的恭喜你了!

二、需求調研和需求分析

大多數人都認同「需求決定架構」,但是需求究竟是「如何決定」架構的?這部分就來聊一下我的認識。

在立項階段,如果運氣比較好,可能會拿到一份檔案《軟體功能需求規格書》(話說一些日本公司的需求說明書,寫的真的是變態的詳細)。如果運氣不好,什麼檔案都沒有,所有的需求全部需要自己來收集、整理。

從狹義上來說,需求就是功能;從廣義上來說,還包括品質屬性、條件約束這些非功能需求。

1. 功能需求

功能需求部分是最直觀的,就是我們設計的軟體需要完成哪些事情。在一個系統中,各個功能之間不可能有清晰的邊界的,每一個小模組之間通過一定的互動,形成一條一條的「共同作業鏈條」來完成指定的功能。

例如下面這張圖,是我之前寫的一篇文章:物聯網閘道器開發:基於MQTT訊息匯流排的設計過程(上) 中,不同模組之間的互動模型,紅色和藍色部分就是 2 條不同的共同作業鏈條。

當然了,這幅圖是最終設計出來的系統架構(分層、分模組),在得到這幅圖之前,我們首先要把所有的功能需求進行收集、整理

在這個階段,最重要的事情是做什麼,而不是怎麼做。另外,作為設計人員,需要經常問自己一個問題:掌握的需求全不全?有沒有遺漏?

2. 品質屬性

我們可以把品質要求,按照不同的階段來進行歸類:

開發階段

  1. 可重用性,不要做重複的工作;
  2. 靈活、容易擴充套件(想一想發生的需求變更時開發人員的心理活動);
  3. 容易理解(想想你接手別人的專案時);
  4. 方便測試(單元測試、整合測試);
  5. 可移植(尤其是嵌入式專案,需要執行在不同過的平臺);

執行階段

  1. 系統必須可靠;
  2. 效能必須達到一定要求(吞吐量、響應時間等等);
  3. 沒有漏洞,系統安全;
  4. 伸縮性要好,方便擴充套件部署;

3. 條件約束

約束主要是指一些限制條件,比如:

  1. 團隊人員的技術棧情況(如果大家都用C,你就不要選擇C++);
  2. 領導給的資源有哪些;
  3. 如果利用一些開源軟體,是否存在bug?是否方便二次開發?
  4. 專案開發週期是多久?
  5. 軟體的執行平臺有哪些?有什麼限制?

4. 畫用例圖

關於用例圖的概念,我也總結不好,這裡就直接參照百度知道里的定義了:

用例圖是指由參與者(Actor)、用例(Use Case),邊界以及它們之間的關係構成的用於描述系統功能的檢視

用例圖(User Case)是外部使用者(被稱為參與者)所能觀察到的系統功能的模型圖。用例圖是系統的藍圖。用例圖呈現了一些參與者,一些用例,以及它們之間的關係,主要用於對系統、子系統或類的功能行為進行建模。

其中有幾個概念

  1. 參與者: 不是特指人,是指系統以外的,在使用系統或與系統互動中所扮演的角色。
  2. 用例:是對包括變數在內的一組動作序列的描述,系統執行這些動作,併產生傳遞特定參與者的價值的可觀察結果。
  3. 系統邊界: 是用來表示正在建模系統的邊界。邊界內表示系統的組成部分,邊界外表示系統外部。
  4. 箭頭: 用來表示參與者和系統通過相互傳送訊號或訊息進行互動的關聯關係。
  5. 作用:(1)獲取需求;(2)指導測試;(3)還可在整個過程中的其它工作流起到指導作用。

我從網上找了幾個用例圖,其中的每一個圓圈,都代表一個功能。

通過用例圖,可以一目瞭然的看到系統提供的所有功能。

5. 寫用例描述

但是用例圖沒有詳細的描述每一個用例的執行過程,也就是說:用例圖從總體上描述了系統的需求,但是沒有描述行為過程

因此,我們可以對每一個用例,附上一個簡單或詳細的用例描述,這樣就更加具體的確認了這個用例的行為過程

下面也是從網路上找的 2 個用例描述範例,可以看到並沒有統一的格式,需要根據專案的性質進行增減。

6. 確定關鍵需求

假設我們在不斷的蒐集和分析中,儘可能地列出了所有的需求(功能需求、品質屬性、條件約束),下一步需要做什麼呢?需求這麼多,該從哪一個需求入手呢?

關鍵需求 = 關鍵功能 + 關鍵品質。它確定了架構的大方向。

首先要明確一點:不可能所有需求都是一律平等。我們要從眾多的用例出找出下面這 3 類需求:

  1. 關鍵功能需求:那些涉及到的模組最多、模組之間共同作業方式最有代表性的功能,篩選出關鍵功能子集;
  2. 關鍵品質屬性:在開發和執行階段,哪些品質屬性對軟體架構的影響比較大,如果品質屬性之間存在相互矛盾的地方,應該優先考慮哪個?
  3. 高風險部分:從技術難度上考慮,哪些功能在技術實現上存在風險,需要體驗提前進行技術驗證?

這 3 類需求就是需要我們重點照顧的需求,也是進行下一個步驟(領域建模)的輸入材料。

由於篇幅太長了,關於設計部分的內容(領域建模、概要設計和詳細設計),下一篇文章我們再繼續,希望能對你有所幫助!


好文章,要轉發;越分享,越幸運!


推薦閱讀

【C 語言】

C語言指標-從底層原理到花式技巧,用圖文和程式碼幫你講解透徹
原來gdb的底層偵錯原理這麼簡單
一步步分析-如何用C實現物件導向程式設計
提高程式碼逼格的利器:宏定義-從入門到放棄
利用C語言中的setjmp和longjmp,來實現異常捕獲和協程

【應用程式設計】

物聯網閘道器開發:基於MQTT訊息匯流排的設計過程(上)
物聯網閘道器開發:基於MQTT訊息匯流排的設計過程(下)
我最喜歡的程序之間通訊方式-訊息匯流排

【物聯網】

關於加密、證書的那些事
深入LUA指令碼語言,讓你徹底明白偵錯原理

【胡說八道】
以我失敗的職業經歷:給初入職場的技術人員幾個小建議