軟件開發隨筆系列二——關於架構和模型

軟件開發隨筆系列二——關於架構和模型


我感覺,關於軟件的架構(architecture、framework、skeleton等詞,畢竟這詞是從國外來的,國外這個詞是參考建築行業的概念)其實很難有一個明確、清晰的定義。每個架構師都有自己的定義和看法。甚至同一個需求,不同架構師畫出來的架構圖(其實什麼纔是架構圖,每人的定義也不一樣)也不一樣。

從我自己的角度,非要給“架構”一個定義的話,我認爲就是在軟件真正動手做之前能說清楚這軟件要做成什麼樣和怎麼做。這樣一個產出物,就是架構。一般情況下,會把設計過程分爲架構設計、概要設計和詳細設計。詳細設計和其他有明顯區別——當然,現在僞代碼一級的詳細設計基本也很少人做了。而架構設計和概要設計,一般就是籠統的說架構是系統級,概要設計是模塊級別。但什麼是系統級別?尤其現在複雜的分佈式設計中,到什麼程度,才能算是充分設計明白這個系統呢?以前我們一般對比建築行業,蓋樓之前先弄出一個微縮版本的房子——這才叫模型——然後各種圖紙,對着圖紙就可以施工了。

而實際上,我們既沒辦法在開始編碼之前給軟件先做一個微縮版本的“模型”,也沒辦法輸出一堆讓工程師看着就能直接開發的圖紙。其實,就算軟件真的做出來之後,項目組成員都未必都理解這個軟件怎麼做的,何況沒做之前——軟件本就是一個抽象的東西,爲抽象的軟件建立更加抽象的軟件模型,確實很難。

回想每次作爲架構師拿到一份項目需求,一般都做下面幾個事情:

  1. 分析、甚至是學習其中的業務要求,歸納、分類所需要的功能
  2. 對最主要、最核心的幾個業務功能分析、整理其業務流程,可能包括操作流程、數據遷移等。
  3. 這個業務需要留下什麼數據記錄,以及需要什麼數據支撐業務運行。
  4. 思考用什麼樣的技術來實現,包括開發語言、運行環境、可用的基礎組件/工具等,以及重點、難點技術如何解決。

軟件架構概要

也就是,包括:功能流程數據技術的“3+1”組合。這意味着,架構師需要什麼都懂,從業務到技術都要懂——要能看得懂業務需求,能轉換成開發團隊看得懂的功能說明或者功能需求;深入理解,研究業務流程;最後還得掌握很多的技術,知道怎麼實現這個需求。基本屬於出去能對付客戶,在家能撐得住團隊的核心人物了。

當然,如果有幸在一個有好的產品經理或者業務分析師的公司,最爲繁雜的業務功能和流程分析,應該不需要架構師去做。但架構師也必須看得懂,並且能理解所有的功能和流程的需求,纔能有針對性的設計對應的數據和技術方案。不要相信放之四海而皆準的技術框架,這種框架能給架構師一個指導,但並不能解決一個軟件該如何做好。

很不幸的是,我所設計過的軟件基本都需要我自己從業務開始理解、學習到技術實現的設計。這裏插一句,很多時候很多技術人員說業務很難學,怎麼辦?我跟他們說不是業務難學的問題,你學計算機花了四年時間,貌似也沒太學明白,你指望你幾天時間把另外一個專業就學明白了?

然而從純技術轉型架構,這個確實是一個必經的關隘。這就涉及到如何建立自己的知識體系,快速學習的問題了。我稱爲“思維鍛鍊”。這很重要,但是另外一個話題了。

軟件模型

架構和模型往往分不開。“模型”是一個很高大上的名詞。什麼叫模型,我常用的定義是:客觀事物的抽象表述。軟件設計進入到面向對象階段之後,幾乎所有的教材都讓程序員扔掉代碼邏輯(循環、分支、遞歸、函數等),而把你的代碼看着一個一個鮮活的“對象”。比如我常用的茶壺作爲例子。

茶壺

  • 能裝水,能倒水;
  • 一般的規格是長寬高和容積、顏色等;
  • 由一個容器主體,外加把手,壺嘴和蓋子組成。

這樣,就形成了抽象的“水壺”,雖然我們還不知道這個水壺是方的還是圓的,但無所謂,慢慢細化規格描述,總會清楚的。然後,我們用同樣的方式,在程序裏建立了一個叫“水壺”的對象——有一些屬性,聚合了一些子對象(容器,蓋子,把手,壺嘴),實現了一些方法(倒水,裝水)。

很清晰,很簡單。可是,我們要做的軟件往往不是像水壺一樣看得見摸得着能輕易地能形容出來的。一個軟件,本身就不是一個“現實”的物體,而是在計算機中,由一些界面(功能)組成,實現了一些業務流程,存儲了一些數據。本來就很抽象。前面說過,就算做出來了,一樣摸不到。所以在面向對象誕生之後,出現過很多方法、工具來設計軟件模型。比如,最出名的UML,最近挺火的領域驅動設計(DDD)。一些大公司也有一些自己的實現框架,比如我老東家IBM的The Information FrameWork (IFW)。當然了,我覺得,如果把這些東西當做是可以拿來直接用的工具,然後就能形成想要的軟件的想法,是不可取的。我不認爲軟件行業存在這種神器,以前沒有,以後也不會有。把其當做一個方法論,幫助自己最終形成自己的分析方法纔是最重要的。

這些方法論,首要的都是教我們如何把“業務”說清楚,但業務越來越複雜,設計的標的,就從對象,到組件,到領域,不斷的擴大。

我自己這麼些年的總結,對軟件模型的理解也由簡到繁,又由繁到簡幾次變更。形成了自己的一些模式,我稱爲一種三維表示法。

模型三維表示法

也算是溯本追源,體現了一個軟件應該具有的基本點:

  • 展現一些界面,提供一些功能;
  • 實現一些業務流程、交易流程;
  • 使用以及存儲了一些數據。

把這三個維度表示清楚,應該也可以把一個軟件說明白了。所以,在我這裏定義:

軟件模型=功能模型+流程模型+數據模型

這三個維度有各自的表達方法,其中數據部分比較傳統,也比較規範,E-R圖(實體關係圖)還是非常實用,到現在依舊是最廣泛被接受的模型表示方式。先借用數據庫理論中對模型的分級定義:

  • 概念模型(Conceptual Data Model),是一種面向用戶、面向客觀世界的模型,主要用來描述世界的概念化結構,基本上跟計算機、數據庫無關。
  • 邏輯模型(Logical Data Model),是一種面向數據庫系統的模型,是具體的DBMS所支持的數據模型。此模型既要面向用戶,又要面向系統。
  • 物理模型(Physical Data Model),是一種面向計算機物理表示的模型,描述了數據在儲存介質上的組織結構,它不但與具體的DBMS有關,而且還與操作系統和硬件有關。

參照上述分級,對照功能和流程兩個模型,也可以有一個大概的,並不嚴謹的分層定義:

  • 概念層:對需求直觀的概念化表述,與實現技術和方式無關。
  • 邏輯層:面向實現但不依賴具體技術(開發語言等),精確體現需求的表述;
  • 物理層:可以轉換爲系統實現的表述,依賴於具體的平臺和技術。

總結起來就是從簡單的示意圖一直到可以生成代碼(部分是可行的)的設計過程。據此,有一個不太嚴謹的表格,大家可以參考:

三維度分

功能和流程最終的實現就是可部署的代碼包了,在物理層面,實際上就合二爲一了。而數據部分,最終可以生成單獨的數據庫可接受的SQL文件。

我們分別討論模型的三個維度,基本遵循這三個層次進行。

功能模型

接觸到一個新的需求,設計一個新的領域的軟件,最開始研究和分析的,就應該是功能。如:

  • 研究同類業務參與人員都要做什麼。
  • 參考類似軟件有什麼功能等。

功能設計很重要,基本就是確定軟件的目標了。架構師不一定需要做這個工作,這往往是產品經理的職責。但我們站在一個軟件的設計者角度,也值得研究。

在這裏的定義,功能模型大概可以類比UML中的類圖,表示功能的分佈的靜態關係。

概念層

功能的概念層表述,在UML中可以用用例圖,比如針對電商系統,可以有一個簡單的例子:

電商用例圖

用例圖其實沒啥不好——除了不好看之外——最大的問題就是“用例”(Use Case)的定義不但拗口還不好理解。記得以前經常爭論:這算不算一個用例?不能讓大家無異議地直接理解的概念都是挺難用起來的。

所以,後期我自己也放棄用這種我需要先做科普什麼是用例,然後再表達軟件需要什麼功能的方式了。回到最簡單的概念——功能點。表述方式也不拘一格,好看、清晰就行——腦圖,示意圖,表格都可以。

功能概念模型

至少看上去好看多了吧,而且,不具備任何技術概念的人都能看懂(UML直到不被流行了對於大多數人來說都是晦澀難懂的)。直觀、清晰,是最重要的。功能模型的概念層有幾個要點:

  1. 邊界:系統都需要提供什麼功能,有需要跟什麼外部資源(人、系統)打交道。相當於畫了一個圈圈,分清楚那些是圈圈裏面要做的,那些是關聯方做的。
  2. 參與方:誰用這個系統做什麼。現代系統不會只服務一個人,也不會只服務一類(一種角色)人,列清楚都什麼人需要用這個系統,分別用這個系統的那些功能。
  3. 功能分組分類:功能分組分類很重要,甚至我認爲是最重要也最消耗時間精力做的事情。可以類比功能菜單一樣,清晰合理的分組分類,對之後的設計很有指導作用。

邊界

參考剛剛的例子,一個簡單的電商系統的邊界是比較明顯和清晰的,用戶會直接操作系統,而系統有需要使用第三方支付公司提供的系統實現支付結算退款等資金操作。而另外的很多系統,需要對接的第三方就很多,甚至沒有操作界面,都是後臺服務。比如銀行的中間業務系統:

中間業務系統

這個系統的邊界就比較複雜了。它並不提供直接的界面給任何用戶,而是通過“大前置”系統轉發櫃面系統或手機銀行系統、網銀系統以及各類自助終端系統等的請求,同時需要使用各種第三方系統的功能。這樣我們確定功能的時候,就不能單純的叫“繳費”了,而是需要明確“交水費”,“話費充值”等。一般情況,可以只把和需要開發的系統直接關聯的資源(人或系統)畫出來就行,但是爲了清晰展現業務的全貌,多畫一些也不是壞事。畢竟,有些功能實現的時候,也得考慮隔了兩層系統的人如何操作更加便捷。

當然了,上述的兩個例子並不是說電商系統一定比銀行系統要簡單多少。而是關注的粒度不同。劃分邊界,對於更明細的粒度,可能關聯的系統越多。比如在一個比較有規模的電商平臺,已經微服務化分成了多個子系統,我們需要新增一個“分銷”系統,可能會有如下的邊界:

分銷

把邊界劃清楚,並不是爲了不管外面的事情,而是爲了更好的響應外部的需求,以及適應外部的變化。這是很重要的一點。

參與方

都有哪些類型的用戶使用這個系統。一般來說,如果是帶界面的系統,會比較容易理解一點,比如一個辦公系統,可以像下面那樣分析:

  • 員工上去辦理各種申請,查詢各種文件;
  • 領導對各種申請進行審批;
  • 人力資源開通員工賬號,設置員工狀態;
  • 財務部門專門對報銷等財務信息審覈、處理;
  • 管理員設置系統參數等。

可能還有很多其他的“角色”。這裏我們用“角色”來表示參與方會更加精確,因爲一個用戶可能同時具備多種角色,類似於身份,比如在辦公系統,某個財務部門員工需要審覈報銷,但他也是需要爲自己的報銷發起申請。

而對於面向公衆的服務系統,一般分外部和內部用戶兩種。外部用戶一般就是客戶了,不同類型、不同級別的用戶能使用的功能不盡相同。

內外部用戶

內部用戶一般和組織架構有關係,畢竟一般公司都是按照不同的部門劃分權責,不同部門的員工參與系統的操作就各不一樣了。

劃分參與方的角色能更好地分析系統的功能需求,而且,對後面設計流程模型和數據模型都有幫助。有很多業務流程是需要多角色配合的,而且涉及到各種狀態變遷。

分組分類

對功能分析最重要的一項就是分組分類了,我認爲。現在系統都相當複雜,最明細功能點(比如菜單的最明細層)都會幾十個、甚至幾百個,這些功能點必須有組織的碼放整齊。我們一般都會採用一種層次結構(hierarchy)形態組織衆多的功能。具體的方法,其實沒很多可說,其實原則就是一個,著名的

自頂向下,逐層細化。

我自己再加一句:

自外而內,逐步深入。

自頂向下不用多說,這句話太出名了,通用的分析方法。類似腦圖這樣的工具,很好的支持了功能分析,一層一層的羅列出來,然後歸納,再羅列,再歸納。所有的功能組織成一棵樹狀結構。一般原則,一個節點的子節點不要太多,七八個就好。

功能分解

上圖是一個功能分解的組織的例子,不完整,只是簡單舉例示意而已。

自外而內,意味着我們應該從可見的功能出發,比如用戶的操作菜單,以及系統提供的對外接口。前面提到的,先確定邊界,一按來說,對外功能整理清楚,就完成了絕大部分的工作了。

菜單

對外提供的功能一般都有一個入口,對現代系統來說,基本上都可以用URL來表示了。入口的組織或表現方式,有三種:

  • 功能菜單:一般內部系統(MIS),或者後臺運營管理系統都有一個明顯的分級菜單。不管是放在左邊豎向,還是上面橫向。菜單功能的組織就是一個典型的分層組織。
  • 導航:面向客戶的界面可能沒有集中的功能菜單,一般通過頁面導航、鏈接、按鈕體現,會分佈在不同的頁面中。所以在表述功能模型的時候,合理的分組分類就很重要,可以清晰的知道想要的功能應該放在哪裏。
  • 接口API:系統可能提供不帶界面的API,調用之後執行某些動作然後返回某些數據或者提示。

除了可見的功能之外,還有一類型的功能對用戶不可見,比如:

  • 支付狀態自動查詢:第三方支付系統回調超時需要自動查詢支付狀態。
  • 自動對賬:根據設定好的時間自動下載對賬文件進行對賬。
  • 結算佣金:自動提取訂單完成狀態,爲分銷商結算佣金。

等等,還有一些非業務需求,比如需要記錄訪問日誌等。

分組的作用:

  • 是便於分析、歸納,不容易遺漏功能。
  • 相當於建立了目錄,便於檢索,方便和業務人員溝通。
  • 有助於模塊劃分,同一類功能一般在一個模塊實現。

物以類聚,人以羣分,分組沒什麼標準,但是會讓人看起來舒服。而且在這個分組框架下,可不斷細化、完善。

邏輯層

功能模型的邏輯層,其實就是用更加規範嚴謹的表達方式,把功能描述清楚。由於功能描述確實沒有太好的規範遵循,同樣叫功能規格說明書的,不同公司不同模板,就算同樣模板,不同人寫出來的也千差萬別。所以,遵循一定的規則,確定一個自己的規範就好。

一般來說,功能描述應該包括如下幾方面的內容:

  • 功能組織圖:完整的功能組織圖,包含合理的分類以及所有的功能點。
  • 分層、分模塊:所有的功能在系統中應如何有機的組織起來,落在不同的層和模塊中。
  • 接口:規定好每一個功能的接口契約。

功能組織圖

前面說過形成一個分層的組織架構形式的功能圖,多級展現功能分組和所有的功能點。最後,輸出一個表格。如下:

功能表格

其實,怎麼做都可以,主要清晰,直觀,最重要的,是把功能都分析完整了。主要包含如下要素:

  • 分組編碼:一般情況我喜歡爲每一個功能和功能分組都做一個編碼,在交流的時候可以精確的表示是哪個功能或分組。
  • 分組名稱:每個分組取一個有意義而且唯一的名稱,讓大家一看就知道什麼意思。一般分組層粗不要太深,一般經驗不要超過4層。
  • 功能編碼:每個功能唯一的編碼,分層中最終端的是一個具體的功能。
  • 功能名稱:每個功能起一個唯一的名稱。
  • 功能說明(備註):對功能進行簡單的說明。

表格的好處,除了清晰之外,還方便於升級成爲開發功能的跟蹤(checklist),測試的跟蹤等。雖然到了那個時候,會有一些專門的工具輔助了,但一個好的表格,永遠是好用的。

層次、模塊化

和分組同樣,把功能分在不同的層次、模塊,其實也是一種功能的佈局。分組是從業務的角度,形成菜單讓用戶很容易找到需要的功能入口。而分層、分模塊,則是針對軟件設計的角度,如何佈局才最合適開發。

分層概念在軟件設計中非常常用。最常見的,會把一個系統分成界面交互層、服務接入整合層,應用層,數據層等各種劃分方式。分層是對功能的橫向切分,而模塊則是縱向切分了。在同一個層次中,分成多個部分。

如下圖是以前爲某銀行設計的掌上廳堂系統的功能分層:

功能分層

功能的分層、模塊化可以看做是一種功能的佈局,對一個架構強迫症的人來說,這個功能佈局一定要好看,整齊,清晰。一般來說這種功能佈局圖,是一份架構或者業務說明幻燈片中最重要的一張圖。爲了把系統介紹的更加完整——有些技術性功能也是系統的優勢——會把一些技術組件/功能也呈現出來。佈局,其實也隱含着模塊之間的關係:通過位置或者更加直接的線條連接,體現一種靜態的依賴和聚合關係。

如一個電商系統的功能佈局圖:

電商功能架構

其實在我看來,具有功能佈局圖和分組功能清單,就已經很足以說明系統的功能了。至少是功能架構中最重要的部分了。所以,畫的好看,很重要。

如果是對於模塊之間依賴有明確要求,或者比較複雜,需要專門表示模塊之間的依賴關係的話,也可以用關係連線明確的表示模塊之間的關係。比如電商終中的分銷模塊:

分銷模塊關係依賴

從圖的表述來看,複雜的東西一定要簡化,如果把整個電商系統所有模塊的關係依賴都畫出來,這個基本上也沒法看了。

接口

從面向對象開發開始,到網絡化服務(dot net, SOA,微服務),前後分離等等軟件設計模式的發展,接口也來越重要。從功能層面談接口,我們一般特指WEB API接口,也就是URL形式的接口。近年來我很崇尚RESTful設計風格——RESTful+json實在太賞心悅目了。所謂RESTFul是一種基於HTTP的接口定義風格,幾個特點:

  • 每種資源有一個URI來表示;
  • 對資源的操作包括:
    • GET用來獲取資源
    • POST用來新建資源
    • PUT用來更新資源
    • DELETE用來刪除資源。
  • 服務無狀態,數據傳遞用JSON。

JSON這個是我自己加的。

操作從語義上非常好理解,獲取(GET)某個資源,新增(POST)某個資源等。因此,這部分輸出是一組表格,包含了系統提供的所有服務接口,如:

API接口

接口定義要素包括:

  • 接口編號:還是我的習慣,喜歡任何一個東西都有一個唯一編號。
  • 接口名稱:說明接口的名稱和作用。
  • URL:接口的入口地址。
  • 方法:操作URI資源的方法,如POST、GET等。
  • 請求參數:請求接口的參數,展現方式其實無所謂,爲了讓業務人員能看懂,我一般用表格,包括參數名稱(代碼)、名稱和說明。
  • 響應數據:返回的數據。

其實具體形式沒關係,簡單清晰就行,對業務和對開發都能溝通清楚。

流程模型

前面提到,功能模型可以類比UML中的類圖,是一種靜態模型。而流程模型則是一種動態模型,表現上是不同的操作步驟組成一個業務流程,導致記錄數據的變更或狀態改變。功能模型體現了要做什麼,流程模型則體現瞭如何做到。

流程有很多比較成熟的工具來表現,比如流程圖,泳道圖,活動圖,狀態圖等。甚至如適用於工作流的系統還可以用BPMN的實現來表示,畫完流程圖對應的流程實現就出來了。但工作流引擎不適合用在對併發和響應時間都有要求的交易系統中,所以大部分情況,我們都要老老實實分析業務流程,落實到每個交易的實現流程,畫出流程圖,寫出說明,然後交給開發。

概念層

在流程模型中,我定義概念層是純業務流程的表述。

業務流程

一個系統本質上是爲了實現若干的業務流程的。比如還是電商系統,最核心的流程可能是:

電商主流程

一個簡單的流程圖,可以從很高的層面表現用戶在電商系統的最主要的操作,或者是設計者希望用戶的遵循的操作流程。在如此高層次的流程圖中,每一個步驟其實是一組操作的組合。同樣遵循自頂向下,逐層細化的原則,把大流程的每一個步驟細分爲具體的操作流程,然後小流程中的每一個步驟展開爲交易流程。

流程分層

一個操作流程中的每一個步驟一般情況可以認爲是用戶的一下操作(點擊),比如瀏覽商品的操作流程可能爲:

  1. 查看商品列表;
  2. 查看商品詳情,包含查看商品評價等。

可選操作如:

  • 收藏商品;
  • 給好友推薦商品等。

這裏的每一個操作,基本上會對應一個後臺的操作(WEB API接口),而這個WEB API接口的實現會包含多個相對獨立的操作步驟,即經歷多個模塊,子系統或者微服務。某電商系統的一個流程例子:

電商流程

這裏爲了更明顯的看出逐層展開的過程才這樣畫。實際的交付,會單獨畫出"提交訂單"的交易流程,會更好看。這裏的交易流程採用的是類似活動圖一樣的方式,可以更好的體現出多個子服務之間的依賴和時序關係。

參與用戶

這裏表述的參與用戶,和功能模型中的參與用戶定義一致,都是具有該系統某些角色的用戶。功能模型中定義不同的角色可以操作不同的功能;而在這裏,則是從一個流程的角度出發,不同的角色在不同的階段介入流程。當然,實際上最終也會體現到具有不同的功能。其實就是更換一個視角來分析。

可以用泳道圖(跨職能流程圖),把角色加入到流程中。比如用戶申請退換,除了用戶進行申請之外,還需要運營崗進行審覈,收到退貨之後,經確認,轉單給財務退款,最後更新訂單狀態。如下圖:

退貨流程

當然泳道圖還有很多作用,除了表示不同的用戶,還可以表示不同的組織部門、不同的系統等。反過來,也有很多流程只有一個用戶執行,那就不需要劃分參與角色的區別了。

邏輯層

對於流程模型的邏輯層來說,就是面向設計的流程設計了。這裏應該有三個重點需要關注:

  1. 狀態遷移:重要的狀態的變遷,比如訂單狀態。
  2. 流程圖:對於重要的交易流程的設計。
  3. 一致性:由於現在的系統往往是分佈式的,在一個業務流程的實現中需要考慮一致性。

狀態遷移

狀態圖其實是很古老的東西。從計算機專業的本科課程開始,我們就知道軟件處理的都是有窮狀態。還有一門專業課程叫“有窮狀態機”,來表示各種狀態以及狀態的遷移。典型的案例就是電梯在各樓層停靠。比如停靠在1層,是一個狀態,有人在5層要下去,按了按鈕,就是一個狀態遷移條件,觸發了電梯的狀態往5層轉移。而大部分的商業軟件的各種業務流程都會涉及到一些重要實體的狀態變遷。比如,用戶的狀態,訂單的狀態,資金的狀態等。

如電商系統中的訂單,是最核心的實體之一。訂單狀態比較複雜:

訂單狀態

嚴格來說,一個狀態圖應該包含如下要素:

  • 源狀態:存在特殊狀態表示開始,每個狀態都應該有唯一的命名,比如訂單處在“待支付”狀態。
  • 觸發器:發生某個事件的時候,導致狀態發生遷移,比如用戶“發起支付”或者用戶“取消訂單”,分別導致狀態向各自的目標狀態遷移。
  • 條件:附在在觸發器,符合條件轉移,或者形成分支。
  • 目標狀態:原狀態由某個觸發器觸發,進入目標狀態。
  • 操作:進入目標狀態的同時,附帶的操作。

對於狀態多的實體,狀態圖會比較複雜。但要知道,越複雜的狀態才更需要一個完整、準確的狀態圖,否則很容易有遺落,甚至狀態有矛盾。

狀態圖設計並不難,充分理解業務就好。只有一點,別把操作當做狀態,這兩個詞看着沒啥相似的地方,但在實際設計的時候,卻是很容易搞亂的。比如,“退貨處理中”這個狀態,接下來會遷移到什麼狀態呢?很多時候會直接下意識的給出“拒絕退貨”和“同意退貨”這兩個詞。但這兩個詞其實是動作,是觸發器,而非狀態。拒絕之後,進入什麼狀態?這是需要好好思考的。

流程圖

此處流程圖應面向設計,充分表述清楚核心功能的實現流程,尤其設計到跨層次,跨子系統,跨模塊的調用關係和次序。流程圖的設計依然是用標準的流程圖,泳道圖,時序圖,活動圖等,甚至直接用原型描述操作流程。按照前面對流程分三層的劃分,這裏應該重點提現:

  • 操作流程:一個用例(這裏用例比較準確)實現過程的每一個獨立的操作,包括用戶點擊、頁面跳轉等。在實際設計操作流程的時候,往往會從流程圖開始畫,然後變成頁面跳轉的示意圖,然後,結合功能點的具體要求,變成原型了。
  • 交易流程:對於用戶提交的每一個後臺請求,在後臺系統實現的流程。如果要精細地設計,可以使用時序圖,泳道圖。而對於架構師來說,不會對所有的流程都進行設計,而是會對核心的流程進行跨系統流程的設計(結合狀態圖)。

原型設計工具真是一個很好的東西,不管Axure還是墨刀。一般來說,原型設計是產品經理的工作,但作爲萬能的架構師,最好也會。這裏不深入展開,只需要知道成敗在細節——產品經理可能更關係頁面佈局、操作;架構師可能更關係流程和數據。

交易流程的設計是爲了更加清晰的看出時序(流程中時序是非常重要的),可以採用時序圖的方式,但可以把設計層面放的高一點,比如是子系統之間的時序交互。比如,關於訂單觸發分銷的時序:

分銷時序

當然,我個人來說,更喜歡用泳道圖來畫。最後,就是用流程圖描述在一個子服務中的處理步驟了。這裏不展開說了。

一致性

對於一個分佈式系統來說,一致性是很重要的,而且還是很麻煩、很複雜的事情。關於一致性的問題,我在另外一個文章中軟件開發隨筆——分佈式架構中有專門的討論。有興趣的可以看看,請不吝賜教。

模型層面爲什麼要關注一致性呢?在這裏的主要是考慮業務上的,並不是單純數據庫的事務提交或者回滾。因爲從業務上,每個操作都是獨立發起後臺請求的,而兩個或者多個操作之間,存在因果依賴關係。比如,預覽訂單的時候,用戶選定使用積分或者優惠券,此時需要凍結這部分積分。如果不凍結會如何呢?用戶這筆訂單暫時沒有支付,而去支付另外一筆訂單了,同樣使用了積分或者優惠券,然後支付成功了。這時候回去再支付上一筆訂單的時候,發現積分不足,或者優惠券已經無效了。這筆訂單的支付就會無效了。給用戶的體驗就不好了。

反過來這樣的順序,借用上面的時序圖來表示一下。如:

訂單支付

從上圖中看到,紅色加粗的四個操作,可以認爲是一個邏輯上的“事務”。時序圖不好表現分支,但可以增加描述,表現其特點:

  • 凍結積分:凍結之後,積分賬戶的可用餘額減少,如果用戶再次下單,選擇積分的時候,就只能看到被凍結之後的可用積分,而不會選擇超出可用範圍,用戶體驗會比較好。不至於像上面說的,用戶選擇了,但實際支付的時候發現積分不足。
  • 積分支付、現金支付、更新訂單狀態,三個操作是有時序依賴的,後面的任何一步發生錯誤,都需要依次撤銷之前的操作。比如,現金支付失敗了,需要把積分支付給撤銷掉。就是所謂的“衝正”。需要注意的是,衝正之後,積分依然是凍結狀態的。
  • 如果訂單超時,或者用戶取消訂單,需要對積分進行解凍操作。

這裏需要關心在什麼地方需要考慮一致性,而不是採用什麼機制保障一致性。在分析流程確定了那些操作具有“事務”要求之後,需要做的是:

  • 提供對應的反交易。
  • 對異常的處理需要調用對應的反交易。

功能模型和流程模型的物理層

物理層就是面向實現的,對於功能模型和流程模型來說,最終的實現基本上都可以認爲是代碼。有一些特殊運行平臺,比如工作流引擎,可以直接運行BPMN的腳本。當然,我們也可以認爲這個配置腳本也是一種代碼也是可以的。代碼實現基本上功能和流程是分不開了,畢竟功能的實現就是通過代碼組織的流程,當然,最後會記錄一些數據在數據庫。

所以,我這裏定義功能模型和流程模型的物理層包括幾個內容:

  • 可以直接運行的配置、腳本,比如Activiti使用的BPEL。
  • 可以直接生成代碼的腳本、配置。比如類圖,UML流行的時候,通過Rational Rose或者Together都可以直接生成JAVA源代碼,尤其對接口類(Interface)適用。另外,某些MIS工具,也提供自己的定義格式,可以直接生成針對表格的怎刪改查的代碼。
  • 針對實際基礎設施的部署,包括網絡、服務器、存儲、安全等。實際上就是一個網絡拓撲圖以及衆多的部署腳本了。現代容器技術給了我們更加靈活、簡便的實現,比如通過Docker來部署,一個Docker-compose.yml就可以把所有的節點配置好。

物理層直接面向實現,其實更多是技術層面的設計。需要針對特定的開發語言,運行環境(操作系統、虛擬化、容器等),甚至網絡環境去設計。另外,有一些公共的功能,比如用戶認證授權等,其實在開源世界,比如Spring Cloud都有支持,我們只需要部署、並且用起來。

意味着我們需要很懂技術了,當然這也是架構是的任務。不過我們這裏主要分析如何建立軟件的模型,並不展開具體的技術實現。再次給自己再做一個廣告:軟件開發隨筆——分佈式架構,有興趣的可以看看,請不吝賜教。

數據模型

數據模型應該是最有規範的的一套體系。早些年就有“面向數據設計”,針對數據模型來設計界面和功能——當然現在又有新的“面向數據設計”了,基於大數據發現用戶的偏好等進行系統優化,這是另外一個事情了。

我自己的體會,在十幾年前開始比較大量的接觸國外的系統,比如銀行的Core Banking System,財富管理系統,資金系統等。發現幾個特點:

  • 這些系統都很貴,國內的軟件是青銅,他們的就是鑽石。
  • 這些系統採用的技術都很保守,很傳統,甚至可以說是很落後。就算到現在也一樣。比如當年我們說的經久不衰400系統。
  • 這些系統的數據庫表設計,也就是數據模型都很好,很清晰。

也就是,數據模型纔是最值錢的。一個很複雜的系統,幾十張,上百張,甚至幾百張表的實體和關係,設計的很和諧。

ER模型

數據模型本身是一個很古老的東西,尤其在關係數據庫出現之後,利用實體關係(E-R)圖來設計數據模型的技術就出現了。但是很多人在設計數據庫的時候,往往很茫然,不知道如何入手。確實,E-R模型的設計直接可以用的指導太少了,我總結一下,大概也就這些:

  • 從業務出發,識別實體,啥叫實體?太難明確定義了,你看花是一個實體,他看花瓣和花蕊分別是實體,另外的人會認爲花粉也是。這完全是看你對業務的理解,關注點在哪裏。
  • 識別關係,這個簡單,一對一,一對多,多對多,強依賴(主鍵),弱依賴(非主鍵)。某些ER工具在做邏輯模型的時候,吸收了面向對象的特點,提供泛化(繼承)關係,更方便設計實體。
  • 範式:基本需要掌握的是從第一範式到第三範式。學術的這裏不討論,大概知道就是不斷地拆表,消除冗餘,消滅異常(修改異常、刪除異常、插入異常)。

E-R圖本身的理論和範式,這裏不做討論,太成熟了,很容易找到資料。

從這裏看出,可以用的指導太少了。所以,要設計好數據模型,需要幾個東西:

  • 好的E-R模型設計工具,最好能支持邏輯模型設計,並轉換爲物理模型,以及生成對應數據庫的SQL文件。
  • 好的模型參考,因爲E-R模型本身的指導太少,所以一個好的模板作爲參考是非常重要的。

工具層面就不多說了,主要是可用的太少了,還貴。這是一個很難過的事情。

這裏主要說模型參考。

數據模型參考

業內最成熟的數據模型,是早年我們叫NCR模型,現在叫Teradata FS-LDM模型(針對金融行業)。當時我比較熟悉的是7.0版本,有將近1200個實體、5000個屬性,200多個邏輯視圖來闡述金融的數據模型。而之後一直在持續升級,不斷地增加實體和關係。

爲了更好的闡述數據模型,Teradata的數據模型分成三層:

  • 第一級:主題域,一般在10個左右;
  • 第二級:概念層,50多個關鍵實體;
  • 第三級:細節和邏輯視圖,將近1200個實體、5000個屬性和超過200個邏輯視圖。

下圖就是一個典型的主題域模型。一般耳熟能詳的Party域(參與方,而非客戶),以及協議、資產、產品、財務、營銷、渠道、地理位置、事件和內部組織架構等。基本上,要設計一個業務系統所涉及的數據(表),都可以套到這些主題裏面去。

NCR模型主題域

這裏可以簡單的說明一下各個主題域的意思(這模型主要針對金融機構,後面我們用“機構”一詞來指代平臺運營方):

  • Party團體,描述客戶的基本信息,如不同的客戶類型或角色等。
  • Party Asset資產,描述客戶的資產,有些模型可能增加專門域描述金融資產。
  • Finance財務,客戶的金融資產,比如各類賬戶情況。
  • Campaign營銷活動,針對客戶展開的各種試圖達到某種目的活動;
  • Agreement協議,客戶與機構之間的各種協議。
  • Channel渠道,客戶與機構發生交互關係的渠道。
  • Event事件,客戶發生的各種事件,與系統發生的交互也可以看做一種事件,但有些模型提示我們,可以把針對系統的交易當做一個獨立的主題域。
  • Internal Organization內部組織架構。
  • Location位置:描述物理座標或者定位(互聯網位置、電話、移動終端標識等),以及這些位置標識和用戶的關係等。
  • Product產品,我們能爲客戶提供的產品和服務信息。

主題域和軟件的模塊其實沒有必然的聯繫。主題域單純對客觀事物進行分類。大概意思就是這個世界應該有些什麼東西,但你要用這些東西來幹嘛,就不管了。比如我們的傳統玄學,世界由金木水火土五種基本物質組成。主題域的作用,就是給表分類。如果我們並不能直接應用NCR的模型進行改造,我們也可以根據主題域給我們的提示,在我們設計一個系統的表的時候知道應該有幾類表需要設計。比如一個電商系統,可能出了Party Asset域之外,其他的域我們都會用到。

下圖是Party的其中一個片段:

party

在這裏,引入了泛化的關係,類似面向對象的繼承一樣,一方面爲了充分表達“分類”的情況,另一方面,轉換爲物理模型的時候,父類的屬性,會自動放到子類中,節省勞動力。

另外流傳比較廣泛的還有IBM的數據模型,花旗的數據模型等。其實大體方式差不多,但主題域的分類方式不太相同。有興趣的可以看看我寫的另外兩個文章:

參考模型來進行ER模型設計

之前說過,設計表的時候,我們首先要識別實體。而有主題域的分類指導下,我們直接針對Party進行分類。根據Party的定義,是與系統發生關係的一切參與方。我們就可以之類對Party進行分類。當然,分類有很多種方式:

  • 參與方的組織形態:
    • 個人
    • 機構
      • 公司
      • 政府部門
      • 社會團體
      • ……
  • 參與方和系統/平臺所有機構的關係:
    • 潛在客戶
    • 客戶
    • 商戶
      • 零售店
      • 餐廳
      • ……
    • 供應商
    • 經銷商

如此,我們找出所關心的所有分類,就可以識別所有的實體。其他的域,比如產品、協議等,也進行分類。這樣,基本上就能把關心的實體識別出來了。雖然也不是那麼容易,但畢竟有一個指導,把無目的的思考變成了特定分類的羅列,還是簡單多了。

確定了實體之後,確定屬性。比如,對於Party中的個人,正常思考,屬性會包括如下:

  • 姓名;
  • 生日;
  • 身份證號;
  • 電話;
  • 地址;
  • 職業類型等等。

而與機構簽訂的協議,用戶在機構擁有的賬戶,發生的交互事件等,我們可以看到都有專門的主題域,也就是有專門的一套表。所以我們知道在對應的主題域中專門針對這類實體進行分類,並建立和Party的關係就好。

回來在看這幾個“基本屬性”,貌似很簡單,但深入一下,會發現,如果你關注的更多,比如,姓名是否變化過,住址是否變化過,或者多個不同的地址(辦公地址,家庭住址,甚至多個家庭住址)都要關注?

如果關注這些的話,這些屬性就會形成“表中表”,違背了範式要求。這樣,我們就需要單獨拆出來一個表,比如Party的名稱,我們需要跟蹤名稱的改變情況,那我們就需要記錄每一個名稱以及名稱的有效期,當前生效的名稱。與Party形成一對多的關係。

又比如住址,由於有專門的Location域,我們會在其中專門設計地址的要素,比如從國家->省->市->區->街道分成多個層次,然後再輸入具體地址,可以更好地利用地址數據來分析客戶。這時候,就會現成一個Party和地址的關聯表(多對多),同時在這個關聯表中還得加上關係類型,比如居住地址,辦公地址等。

關係示意

原諒我沒有很好看的邏輯模型設計工具。有點醜陋,但意思出來了。

總而言之,一個既有的,成熟的模型,就是一個好的指導。熟悉他的表,熟悉他的設計方法,分析自己的業務的時候,也就順理成章的把數據模型給設計出來了。

在具體設計表的時候,我覺得還有幾點實踐建議:

  1. 個人喜歡每張表用一個3位的編碼表示,比如:T101_PERSON,第一位數字表示所處主題域。後面兩位是域內的唯一編號。其實任何編碼方式都行,只要能清晰的表示唯一。
  2. 按業務模塊分別畫E-R圖,比如在電商裏面,商品可以畫一個圖,訂單可以畫一個圖。基本原則就是一張圖不要超過一個A4頁面範圍。
  3. 外鍵關係一定要有,尤其邏輯模型層面,組合主鍵一定要保留,不要過早改成無意義的唯一序號做主鍵。丟失了關係,設計就會變得很難維護。

聯合主鍵這個事情,一直都有很多爭議。畢竟,如果一張表主鍵有好幾個字段,在程序裏面修改刪除等,確實比較麻煩,另外有一些CRUD工具不支持聯合主鍵。以至於很多人設計表結構的時候,凡是聯合主鍵的都用一個無意義的自增字段或者序號來代表;而原來的主鍵字段則變成了非主鍵的弱依賴外鍵了。唯一性保證就需要專門創建聯合唯一索引來實現,或者通過程序來保證。在物理實現的時候,這兩種方法談不上好壞,但邏輯設計的時候,還是儘量按照客觀事物本身的內涵和關係去設計,不要過早加入物理實現的約束。

關於邏輯模型的設計最後補充一句就是儘量每次都按照正確的方式去努力設計,可能一開始慢,但多做幾次之後,就掌握技能了,熟能生巧。

物理模型

邏輯模型轉換爲物理模型一般的ER工具都支持,比如把泛化關係轉化爲具體的表,多對多關係也落實爲實際的關係表等。除此之外,我們一直說,物理模型是針對實現的,一方面是針對具體數據庫的設置,另一方面更重要的是要針對程序實現做優化。比如:

  • 視圖及物化視圖:爲了便於查詢,有時候會把多個表的字段放到一起,形成一個視圖,在程序端可以當一個表用。但動態視圖效率很低,數據庫一般支持物化視圖,事先把數據保存下來,在查詢的時候快速返回。而實際的表數據改變,物化視圖中的數據也會對應的改變。
  • 索引:在業務上,大部分的查詢都不能僅僅通過主鍵實現,索引的作用就很重要了,根據業務的需求,把常用的條件字段作爲索引,提高檢索效率。
  • 分區:對於數據量會持續快速增長的表,可以設置分區,不同的分區實際保存的文件不同,提高在一個分區中的檢索效率。增長和時間相關的,一般可以通過日期做分區。
  • 分庫:實際上就是數據集羣了,採用何種方式集羣需要考慮數據一致性的需求,是讀寫分離,還是橫向分割(不同表在不同數據庫),還是縱向分割(分庫實現分區)等。

當然,最重要的一點,是選擇好用什麼數據庫。開源的Mysql還是商業的Oracle,當然這兩現在是一家。或者用Mariadb,PostgreSql等。其實都很不錯。甚至有人會選擇無強制模式要求的MongoDB。MongoDB確實是很優秀的數據庫產品,沒有強制模式要求,也就意味如果需求發生變動修改表結構不用做太多處理——存數據的時候直接加上就好了。但我個人認爲,在部分特殊場合,比如需要快速記錄交易流水/日誌,而交易流水/日誌的格式多種多樣(不同的交易需要不同的數據),可以使用MongoDB。但作爲一個系統的整體設計而言,決策一個表是否修改的思考和決策過程,應該會遠超過實際改變了表結構之後對程序的修改時間。

如果嚴肅的對待“數據是資產”這句話,就需要慎重的建立一個清晰的數據模型,否則,混亂的數據結構會變成災難。這也是各個企業後期大量精力去做所謂“數據治理”,投入大,成效小的原因。只有要可能,從一開始就重視數據模型是不會有錯的。

面向分析的數據模型

達到或接近第三範式的數據模型我們認爲有兩個作用:

  • 滿足聯機交易系統(OLTP)需求,避免數據冗餘,消除各種數據異常。
  • 構建數據倉庫的時候作爲企業數據模型反映業務全貌。其實前面提到的Teradata等模型,都是在數據倉庫項目中推廣開的。

而在爲客戶提供的分析界面的時候,基本上不會直接針對此模型去提取數據。這種爲客戶提供數據檢索、分析的系統,稱爲聯機分析系統(OLAP)。我們會定義這一類系統所處理的數據有如下幾個特點:

  • 批量更新,至少也是非實時更新,不需要考慮交易事務的一致性。往往可通過ETL工具或者消息隊列傳遞過來。
  • 不可更新,進入的數據不可變動,因此也不考慮跟新異常、刪除異常等。
  • 有時效性,爲了反應企業業務發展的全貌和過程,所有數據都會有時間表示,代表其生效的時間。

由此也產生了一系列專門面向分析的數據庫產品,如Hadoop生態的HIVE、HBase等。具體產品、工具這裏不展開了。主要考慮針對分析查詢需求的數據模型構建。一個最基礎的手段就是:

逆泛式

或者叫降低範式。簡單的來說,就是允許數據冗餘出現,表現有兩種:

  • 根據客戶查詢的需求,直接把多個表的數據合併在一個表,類似於物化視圖一樣,但這裏的數據往往需要經過複雜的處理計算,形我們一般稱爲“寬表”的結構,就是字段很多的表。這樣客戶在這個需求範圍的查詢,都可以在一張表內完成,不需要做表連接。
  • 多維模型,又稱爲立方體的一種特殊ER模型結構。通過維表和事實表的關聯形成一個像星星的形狀。

維模型如下圖:

維模型

其中,時間維、地區維等維表,是降低了範式要求。比如按照第三範式的要求,地區維應該國家、省和市各一張表,才能避免數據冗餘。但在這裏,爲了快速查詢,把多個層次的數據合併在一個表裏面。算是一種空間換時間的策略。

  • 維表:所謂維就是分析的角度,統計的方向。比如,我們希望看到某年某月所有的訂單數量,或者某年某月某個產品的訂單數量,甚至某年某月某個產品在某個地區的訂單數量。一般的分析角度都會有很多,所以,維模型也稱爲多維模型。
  • 事實表:事實表是反映業務發生事實的表,由其所關聯的維表的外鍵和需要統計的指標組成。因此,統計算法可以看做是在事實表不同條件分組彙總(SUM & GROUP BY)。從概念上,指標也可以看做一個維度,但爲了減少事實表的記錄數量,便於操作,把指標維拉平了放到事實表的字段裏面了。

用戶的界面則是選擇出需要看的維度,其他維度蜷縮(彙總或者過濾),形成一個二維平面的表格:

報表

如上圖,展現了機構和各種指標的關係。而這些指標的計算,則是彙總了所有時間範圍、地區範圍和幣種範圍。而我們可以附加過濾,只看今年和人民幣的。表格形式不變,但裏面的數據會發生變化。

維模型對於分析來說,是非常重要的,如銀行需要的維表大概有:機構、科目、產品、幣種、時間、地區、客戶等公共維度。

技術實現

模型最終需要通過技術手段來實現,也就是變成可以部署運行的代碼。軟件技術發展到今天,出現了無數很好用的框架、組件、工具,這些都對我們的軟件開發的方式造成了影響。分佈式從分層、集羣到現在的微服務,各種開源組件可以幫助我們迅速構建技術原型。當然了,各類型開源組件層出不窮,也給架構師帶來了昂貴的學習成本。這裏不打算討論具體的工具和技術,這方面可以參考的資料很多,只要你知道你需要什麼,肯定就能找到。“面向百度編程”是很重要的。在互聯網信息時代,只要你知道有一個東西可以用,基本不是傻子都能在網上找到這個東西,以及這一類東西都是什麼,怎麼用。從入門到精通都不在話下。

這裏我試圖把我自己常用的一種技術框架以及設計的思路方法展現出來,爲大家提供點思路。

技術分層

實話實說,現在一個好的架構師真不容易。除了上面說的業務分析之外,在實現的時候,也必須懂的很多技術。不過確實,一個現代軟件從設計、開發、運行到維護,確實需要大量的技術。而且技術還不斷地在發展,架構是需要不斷的往自己的“技術棧”添加新的東西。

當然,我個人並不喜歡“技術棧”這個詞。把技術先進後出的堆砌,總覺得不是那麼個味道。個人更新喜歡傳統一點的“知識體系”這個詞。作爲一個架構師,學了無數東西,每個人都會在自己腦中建立自己的知識體系。把各種知識點歸納出來,形成一個合理的“架構”,或者建立一個形象的佈局,知道那個地方需要什麼東西。比掌握具體的技術點更重要。

知道要用什麼技術,是架構師最重要的能力。

“形象”這個詞,我一直認爲很重要。軟件開發本來是一個很抽象的事情。而我這麼些年做的很重要的一個事情就是,把抽象的軟件開發過程變成形象的、直觀的展現。在前面討論功能分組、數據中實體分類,我都有強調,歸納分類是非常重要的。

一個可以參考的技術層次和分組如下:

技術分層

從基礎設施到運行環境、開發支持、互聯網服務。逐層向客戶貼近。

其中數據庫,我放到了運行環境中。以前單純的使用關係數據庫保存數據的時候,是放到基礎設施一級的。但各種NoSQL數據庫作爲高速緩存,內存數據庫輔助計算等,也成爲一種設計主流。也就是“數據庫”更往應用層貼近了。

Devops是一個近年比較新的詞。一個軟件開發設計的週期包括:

開發過程

簡單的說就是包含了:

  • 軟件開發技術。
  • 質量保障技術。
  • 運行管理技術。

這是典型的瀑布流程。而現代軟件開發採用迭代模式,每一個迭代週期都經理完整的上述過程。迭代能更好的保障軟件交付的效率,但帶來的問題是對於一個線上系統來說,會面臨多次的升級,容易造成停機事故,影響業務。

所以出現了把上述三類技術融合在一起的Devops。融合性的技術都比較複雜,我認爲比較重要的點在於:

  • 版本分支管理。
  • 構建、測試、部署自動化。
  • 容器技術及容器管理自動化。
  • 監控技術。

開發語言方面,我個人相對傳統,強烈建議對於一個複雜的系統,應該採用強類型、面嚮對象語言,比如JAVA來進行主體的設計和開發。對於特定模塊、服務,採用其他快速便捷語言補充,比如PHP,Python等。程序開發不僅僅考慮開發效率,還得考慮維護成本。

技術架構

上面按照一種“層次”來劃分技術形成知識體系。還可以按照一個軟件應該的“樣子”,形成一個架構,或者腳手架,結合分層和分模塊,更細緻和形象的從技術角度描述一個軟件的樣子。如下圖:

技術架構

相當於把從底層到用戶層的分層設計,每個層次所需要的模塊,以及公共的支持工具,都做了一個佈局,有點像玩樂高。但所謂好壞,就是看起來優雅、勻稱。

把具體的功能或者技術要求的實現替換上去,差不多可以得到一個大概的技術架構。不見得適合所有的項目,但對於我做過的項目,基本上可以覆蓋。這了不打算展開,反正每個詞百度或者狗狗一下,就都出來了。

總結

這篇文章基本上不涉及具體的技能、工具,更多是我對“如何設計好一個軟件”這個問題多年來的思考和總結。要回答這個問題,我覺得第一是要說清楚這個軟件究竟是什麼樣的。我自己的答案就是上面描述的“3+1”模型:

3:(功能模型+流程模型+數據模型)
1:技術實現

一般人都說做軟件是一個邏輯性特別強的工作,確實也如此,尤其是在設計業務邏輯,算法上,人類需要用到的所有邏輯方法,都需要用上——演繹和歸納。但就是因爲太過抽象,所以我們需要各種工具(流程圖、腦圖,甚至用圖畫工具畫畫,用筆畫畫)來努力讓軟件變得具現化,更直觀,更形象。所以我認爲其實至少在架構層面,形象思維和邏輯思維是同樣重要的。

雖然前面寫了那麼多工具,畫了這麼多例子,其實,對於我來說,在設計一個軟件的開始,最重要的在自己腦海裏面把軟件運作的整個過程推演之後,形成一個具象化的實物投影一樣的概念。就跟我看到一個水壺之後,這個水壺會在我腦海中形成的立體影像。只不過形成這個投影的過程很艱難,尤其隨着要設計的系統越來越龐大,一次性把所有東西都裝到腦子裏面推演放不下了。必須藉助各種工具存下來。基本的流程,就是前面介紹的這麼一大堆。

具體的工具和技術很重要。但是知道該怎麼做更加重要。我特別欣賞據說是愛因斯坦說的一句話(雖然我也沒考究過是不是他真的說過):

字典裏有的東西我從來不記!

我的話則是:

網上能隨便查到的東西我記來幹嘛?

互聯網信息爆炸時代,任何東西,你知道他的名字,甚至知道這東西的關鍵詞,你都能找到所有的資料,然後快速掌握他。就怕你不知道有這種東西。幾乎任何技術,都可以速成。我經常和開發人員說,你還沒本事碰到別人都沒碰到過的問題。所以你碰到問題,先上網找。找不到最大可能就是:

  1. 換搜索引擎(不可說)。
  2. 沒看英文的網頁。

英文好不好都必須能看懂英文網頁。這是一個很基本的要求。

建立自己的知識體系,是最重要的——對於一個架構師來說。形成了對自己行之有效的思維模式,甚至一些設計模板,在拿到需求之後快速形成方案,並評估項目的難度、開發週期、迭代次數,甚至於投入資源等等重要問題的答案。

其實,做軟件本身需要建模,而對自己的知識體系,也需要建模。這纔是軟件的“裏”或者“道”,具體技術是“表”或者“術”。——一家之言,可以無視。

關於一些具體的開發技術、開源組件如何快速構建一個分佈式系統,可以參考軟件開發隨筆——分佈式架構(再次宣,最後宣)。有興趣的可以看看,請不吝賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章