架構師修煉 II - 表達思維與駕馭方法論
開篇之前我想先說說當年開發的那點事兒:大約10年前吧,我還是一個程序員的時候經常都是遇到這樣的項目開發流程:
- 解決方案 :滿足客戶目的和投標用的一堆文檔(不少還是互聯網上抄的) ,是以Word為主的純文字。
- 投標完成和客戶付訂金后項目組成立,通常為(0至1)個項目經理或者叫項目負責人+(1至N)個程序員 的項目組模式
- 設計:由項目的頭或者經驗最足的成員參與編寫設計。倒霉的時候我們會得到一份按照軟件工程學的純中文形式的設計想法(抱歉我只能這樣來形容),而更糟的情況是得到一份完全看不懂的Rose文檔(那個年代可是UML大放異彩的時代,而當時我對UML完全就是個***)
- 開發:到這里才有我參與的份,前面的內容通常作為項目組中低層的人員是不透明的。得到“設計”后,我們只能靠自己的“猜想”來實現,***拿著界面給經理看是否符合他的“設計要求”。
- 測試? 這項目是沒有的,只要程序能跑通直接就交付了。
項目的結果不言而喻,最多的溝通就是吵架與被訓斥還有就是被客戶抱怨。在這種例子很可笑,但更可笑的是至今我還聽到不少的朋友跟我說起這種類似的苦B經歷。他們不是沒有設計,不是沒有溝通也不是沒有管理,只是每個人都在用自己方式在表達,沒有共同的語言和溝通方式。那么換個溝通能力很強大的項目經理會改變這種境況嗎? 可能可以,但遇到最多的只能是改善,只是苦B這個角色換成項目經理而已,因為本質上沒有多大的變化。
我很感恩能有這么讓人難受的開發經歷,因為太難過了所以才促成當時的我去想辦法,去學習***努力去改變。接下來的部分會是我將這10多年來的經歷進行的一些總結,因為我學的東東很雜當時在大學里根本沒有這些知識只能靠在項目實踐中摸索前行,我受MSF與敏捷開發的影響很大,并且我是一個反UML人士,但我并沒有完全去采用某一種標準化的開發方法與開發流程,長年來只是以我對這些方法論的理解應用到我的項目里,而在這里我不想過多地討論關于開發方法論與項目管理的內容,而只是將其中與架構和設計相關的內容抽取出來論述。
表達思維
架構師的職責
世界上最難的兩件事是:將別人口袋的錢放到自己的口袋里面;將自己腦子的想法完整放到別人的腦子里面。在大家的印象中,項目經理是項目中溝通得最多的角色,其實架構師的溝通量也不遜于項目經理。在國內更多的情況是架構師與項目經理就是同一個人。作為系統/項目的總設計師,并不是單純只為客戶想出技術解決方案然后做出一份設計扔給項目組就完事了,而需要向每個位參與項目的成員或角色從不同的層面介紹或解釋設計原意與理念。
有效溝通
本文的主要內容說得簡單一點就是架構師銷售自己的設計的一些方式與方法。除了開發能力與設計能力以外“有效溝通”也是架構師的很重要一項技能。架構師與項目經理不同主要工作時間與精力不是全放在溝通上,但如果溝通不當就會出現因為反復溝通而大量消耗架構師的設計時間,甚至設計出讓人難以理解的架構,就算設計本身的含金量再高,在沒有找到伯樂之前也只能處于“曲高和寡”的尷尬局面。我之所以將溝通看作一項修煉的另一個原因是這些內容都是從書看不到的,只能從實戰中摸趴滾打慢慢積累而成,不同的經歷可能也會有不一樣的看法與心得,而接下來就是我積累多年的一點經驗的總結:
如果說開發流程是大的迭代那么設計就是經歷一次次的小迭代以至于完善,項目的每個參與者的想法與建議都是架構師修正設計,積累迭代的參考來源,。所以,架構師的溝通是需要雙向激蕩的。
我按照項目中與架構師溝通頻率***的角色、掌握的技能、信息的需求進行了歸類,這樣將更便于了解怎么樣的溝通方式最為有效:
銷售
- 溝通的需求:從設計中尋找賣點與特色,豐富銷售方案和定制預售計劃。
- 知識技能:對開發或深入的技術內容可能只存在于概念性的理解、掌握市場的***手信息并且對客戶的需求最為了解。
- 推薦工具:特色列表 (Full Feature List),字段:特色功能(Feature)+說明(Summary)
以產品開發(做項目會省事,沒有這一步)為例,我與銷售討論整個產品的***有特色的10項目功能(實際上3項就夠了,實踐告訴我只有前3項是別人記得最深刻的),這10項特色我們又稱之為“購買理由”,然后是整個系統全部特色功能(Full Features)。我經常會與銷售因為某個特色功能而經常激烈地碰撞,但***銷售所提出的意見與建議往往發揮著最重要的作用,有時甚至直接影響到項目的可行性。
修練的法門:
- 拋棄一切技術實現細節,寫/說出產品最重要的三個特色
- 拋棄一切技術實現細節,用心聆聽“非專業”的意見
項目經理
- 溝通需求:根據設計進行時間估算、準備項目資源與工作分解。
- 知識技能:大多是熟悉體系架構類的知識(需要了解他/她是偏向于技術還是管理),熱衷于溝通與跟蹤
- 溝通工具:Excel
- 圖形工具:架構圖、原理圖
項目經理是架構師在項目中最重要的伙伴,因為他在負責跟蹤與保證你的設計被實現的全過程,是項目資源的提供者與進度的控制者,他需要了解每一個檢查點(CheckPoint)與里程碑(Milestone),這也是項目經理與架構師最重要的連接點(Connection Point)。我與項目經理討論得最多的是系統實現的原理和實現各部分可能存在的難度和可能發生的風險。
修煉法門:用最簡單的圖形視覺化設計
以下這兩個圖是我為數不多的公開項目中可以拿出來作為示例的,我用的設計工具是Excel:
圖例1:技術架構
圖例2:應用程序架構
注:這兩個圖例是我的一個多年的開源項目DotNetAge CMS的架構圖,有興趣的朋友可以訪問GitHub或者 DotNetAge (英文)官網了解其它的相關內容
開發
- 溝通需求:根據設計要求進行技術準備、部署開發環境、編寫DEMO以及最終編碼,關心自己所負責的技術細節與實現方法。
- 知識技能:掌握或精通特定的開發工具及開發技巧
- 溝通工具:范例代碼
- 圖形工具:序列圖,狀態圖,類圖
與開發人員溝通是最困難也是最有思想激蕩的環節,開發人員就像是小朋友一般富有嘗試新事物的膽氣與想法,在沒有制度與行政壓力的作用下要讓他們完完全全“遵守紀律”可不是一件容易的事。我并不認為架構師或者項目經理在地位與行政上要領導其它的成員,這種“自然層級”并不利于溝通,反而容易讓項目組變成“一言堂”。我認為與開發人員有效溝通的***方法就是“用代碼說話”,這也是為什么我在***篇文章就提出架構師也需要是一個代碼控的另一原因。
我們交付到開發人員手上的都是空的公共接口或是公共類,開發人員是不能隨意改動任何接口、類、方法的命名的,這是一種最基本的約定,否則就亂套了。另外就是針對核心、多人使用、原理復雜的代碼必須帶有代碼范例。代碼范例就是與開發人員產生討論與激蕩的專用區域,也是為以后加入項目的人員提供的快速入門的***途徑,可以在很大的程度上降低不可見的、難實現、高風險代碼出現的機率。
修煉的法門:一邊設計一邊寫范例代碼,讓范例代碼成為設計的一部分
測試
- 溝通需求:根據設計劃分測試粒度、測試的覆蓋范圍、準備測試環境、定制測試計劃
- 知識技能:掌握各種測試方法、對Bug的所在有著天然的直覺。
- 溝通工具:類使用參考
- 圖形工具:架構圖,序列圖,狀態圖,類圖
我認為測試人員的架構能力往往并不亞于任何的架構師。能從常規化測試(單元測試、界面測試)發現問題是最為初等的測試人員;能從系統性能、流程或架構中發現問題的測試靠的是經驗,閱歷甚至是一種直覺或者說是能“嗅”出問題的所在(在下一篇文章中我將會詳細解釋這種能力的源泉),這才是高級的測試人員。與測試人員的溝通與開發有點類似,只是當沒有高級的測試人員配置時,架構師也只能充當這個角色,作為軟件的設計師是最能了解自己的系統可能存在的問題,在溝通時這些“問題”就是溝通的重點,必要時需要反復地觀察測試報告的結果,以找出“隱患”所在。在這里,所謂的修煉法門與上一點基本相同。
在此只對常見角色進行大至的分類,按我們采用的開發方法不同可能還會存在更多的其它角色如:RM(發布經理),TM(技術經理)等等就不作一一細分了。
#p#
駕馭方法論
前文更多在探討如何向不同角色的人去表達自己的設計與思想的一些方法與見解,而作為架構師自身的能力也由為重要。對方法論的掌握、理解與實踐就成為架構師真正的“本錢”,用流行一點的語言就是所謂的“核心價值(Core Value)”。
我是一個很愚鈍的人,10多年來讀了很多的這方面的知識但真正能理解并用起來的也就兩三個,實在是由于環境、閱歷所限,很多理論沒有特定的環境也只能當小說看。通過對各種方法論的學習, 我悟到了一個心得:
“ 方法論的學習曲線是迭代的,也就是說同樣的理論在經過不同的經歷后再次重新學習就會有更深入的理解和新的領悟。”
單單是《設計模式》一書我就從來沒有停止過迭代式的學習與實踐,而每一次實踐我都能得到一次新的領悟與體會。
我會在下一篇文章中講述我認為最有迭代學習價值的方法論。
接下來就說說我認為在設計中很用的一些方法論,以及我對這些方法論的一些總結。
框架理論
“框架”一詞近年來隨著 .net framework 的成功推廣感覺上都被用爛了,什么東東都會加上個XXX框架,可能是源于市場需求吧。我接觸“框架”這個詞或者說這個理論是在.net 誕生以前,在開始探討框架之前,我在 WhatIs 上找到了一段在軟件框架方面比較貼切定義:
原文:
In general, a framework is a real or conceptual structure intended to serve as a support or guide for the building of something that expands the structure into something useful.
In computer systems, a framework is often a layered structure indicating what kind of programs can or should be built and how they would interrelate. Some computer system frameworks also include actual programs, specify programming interfaces, or offer programming tools for using the frameworks. A framework may be for a set of functions within a system and how they interrelate; the layers of an operating system; the layers of an application subsystem; how communication should be standardized at some level of a network; and so forth. A framework is generally more comprehensive than a protocol and more prescriptive than a structure .
譯文 【Ray】通常地一個框架是為了解釋如何構建某項有用的事物及其結構的實現或概念的一份支持或指南。在計算機系統內,框架通常被用于描述一個程序應該構建的層次結構。某些系統架構甚至會包含實際的程序,接口或開發工具集。一個框架指的可能是一套相關的函數集合、操作系統內的某些層次、或者某個子系統內的層次又或者是網絡中某個層次結構下的標準化通信方式等等。一個框架通常比一個協議的定義更為全面,比結構的定義更為規范。
在設計上,我對框架的理解是:框架是用于定義并鎖定對某個概念的理解范圍與實現的邊界,在既定的邊界下可具體化至其實現、并能迭代進化的一份設計指引,是架構師手上總的設計藍圖。這是我喜歡使用的一種方法論,微軟在MSF中的Function Spec (功能說明書)與之有點類似。它是一份對用戶需求以技術架構形式***次細化的一種輸出。我喜歡這種方法論的原因是“簡單”,“靈活度高”,不需要標準化(標準化的東西是不需要設計的只需要套用,那是模式),只需要掌握兩種原則就行了。
建立藍圖(Build A Whole Picture)
在閱讀框架文檔時只即使所有內容都忘記了,只要整個設計圖景能印在讀者的腦海就達到目的了。這是一份指引,是思維的起點,有共同的圖景自然就會產生共同的討論點,鎖定設計與話題的邊界。同時也是系統進化的重要依據。
定義邊界 (Compressive Definitions)
所謂的邊界其實是對要畫出來的模塊的作用有一個明確并且清晰的文字表述,讓讀者能在建立全景藍圖后可以深入地了解每一個部分的具體含義,從而加深入系統的認識。
怎樣學習
最簡單的入手辦法就是從你所熟習或者了解的系統入手,將其框架重新描繪出來。然后將你所了解的每個部分的定義套入其中,你將會發現你對現有的系統建立起一個全新的認知。而關于工具的話可以用最原始的紙和筆,熟練后用Excel的夠了(想更為美觀可以用PhotoShop), 最重要的一點是不要讓工具分散你思考的集中度,所以簡單就好。
至此,如果你開始嘗試這個方法可能你就會明白,為何我這個系列的開篇需要花那么長的篇幅去說明成為架構師先得成為代碼控的必要性,因為從藍圖開始既需要超越語言限制又需要對語言有深刻的了解。
UML
要成為架構師的話,UML則是一門必修課。相關的資料與學習資源極其豐富,至于相關的學習方法也非常個性化,能掌握就好在此不作過多的贅述。在此,只是想分享一些我在學習和使用UML的一些心得。首先,在入手UML前必須非常熟悉對面向對象的所有基本概念否則基本上是浪費時間的。然后是有選擇性的學習,UML畢竟是一個非常陳舊的方法論即使到2.0版本如果真的全部安照UML的理論作為核心開發指導會非常坑爹,它是個重武器!看看當年最牛X設計工具: Rational rose 雖然強大,但我覺得它更像個玩具。他的所謂文檔也只能是設計師級的人看的,由其是Use Case基本上是個集丑陋與非人類思想為一體的圖形,我基本上不用,因為他在與人溝通和整理自己思路上顯得極為不便,還不如用文字直接寫兩句話能說明問題(純屬個人的吐槽)。
UML是設計的常識或者說用于建立共同的設計語言,但不要以其為藍本,它在發現類,抽象出接口、梳理類或類與類之的關系和交互性時有重要的作用。我的方法是只學圖形不學過程,能讓人看得懂的才是設計,也不需要特意安裝什么UML的專用工具,優秀的IDE一般都會帶有一些基本的UML圖形工具,比如:VisualStudio 。簡言之:UML只是共同語言,“活用就好”。
設計模式
設計模式是架構師解決復雜問題的一把雙刃劍,用好了問題可能會被大大簡化甚至是巧妙地解決,但用得不好可能也會讓體系架構出現不可控制的膨脹而變成一個糟糕的設計。面對設計模式理念我們需要以清晰的態度面對,當我們理解或掌握某種模式時肯定也會有一種嘗試的沖動,但請不要將這種頭腦發熱式的行為應用到設計中來,有沖動就去做一個實際的范例。在理論上掌握與實際理解畢竟會有一段距離,將這種淺層次的理解直接放到設計中,一旦運用不當就會控制不住類的規模而造成設計錯誤。前面這些話不是讓大家不去用設計模式而是需要慎用、活用,吃透了再用,為了能掌握它們我也吃不了少的苦頭,在此總結出一些運用的經驗,以供參考:
明確動機
不要為模式而模式。模式本身是針對解決某一問題域所提出的一個高度抽象的對象模型,每種模式都會有明確的使用動機的說明,這個動機與我們的實際的需求是否匹配是衡量其適用性的標準。
建立局部架構
在使用模式前,建議獨立的創建一個工程。把模式以TDD的方式邊實現,邊測試。網上雖然存在很多的模式實現的“例式”,但很多都寫得糊里糊涂的,真正能用的并不多,值得推薦的只能數Enterprise Library 了,它以模式為其礎也加入了MS的實踐算是一個設計者入門的寶庫。雖然EL的代碼很多,不過運用我在***篇所提到的看代碼的方法來學習也不會很吃力。在開發人員使用工程的公共接口和類以前,架師最應該做的就是模型測試, 采用了設計模式的架構最為有效的文檔是范例代碼,這樣可以避免去解釋內部原理的時間,開發者就是使用者會用就好。另外,作為設計者本身,寫范例代碼可以驗證設計的準確性與正確性,而對于測試用例的編寫也一份重要參考指南。有了范例代碼我們就可以同時向兩種角色(開發、測試)交付實際的設計結果。
理解組合的效果
標準的23種模式并不單單是獨立的,模式與模式之間的互用往往會產生1+1>2的效果。但同時需要注意的一點是,增大使用效果的同時也會同樣的增加系統復雜度。
設計模式是架構師伴侶,她是為解決問題簡化問題而生的。綜觀23種模式都是在不同的場景圍繞 耦合度、封裝性、易用性為核心論述,因此我檢驗運用模式效果的簡單標準是:
- 耦合度是否被降低了?
- 實現細節是否已被接口隱藏了(封裝性)?
- 外部接口實現是否簡單?
測試驅動(TDD)
大家都知道測試的重要性,但運用于實際的并且貫徹整個開發過程的并不多見。可能是“測試”的可選擇性與“Quickly and Dirty” 的思想讓測試始終沒有被放到一個絕對重要的位置上去。說實在話我也是最近兩三年才完全地體驗到TDD給我帶來的方便性與認識到其中的重要性。由其是設計規模龐大的項目時,架構師再強也不可能考慮到全面的細節問題,由其是代碼實現。而MOQ這一類的工具類庫的出現也非常好的幫助我去模擬出類被實現后的效果,能直接測試出模型中可能存在的隱性或顯性而被忽視的問題。在團隊配合開發的流程中測試的作用更是貫穿全局。好的測試流程可以在無溝通的情況下讓項目經理了解每個CheckPoint的完成情;讓架構師能模擬實現,測試類模型和編寫使用范式;讓開發人員可擁有最小化的代碼運行入口;正如前文所提到的,一名高級的測試其設計能力可與架構師并肩,他們能從表象中發現架構中可能隱含的問題所在。那能不能反過來說一名架構師也應該具有高級測試的相應能力?很明顯答案是肯定的。架構師最起碼的需要掌握的是測試驅動的相關知識,最起碼了解如何寫單元測試、順序測試并能使用MOQ來模擬接口實現等的基本測試方法。
小結
這一篇文章我并沒有與上篇一樣給出一些具體的方法,因為本文討論的更多的是我僅有的一點點經驗的總結,而更多的是來源于思維上的。我極力地想用有限的文字能力去表達這種意識和思維,最終卻仍然覺得有很多的內容未必能盡說,或者你也可以嘗試通過實踐來去檢驗我以上的理論。而在下篇中我將會更為深入地討論在設計中我認為高層次的內容:“變化”,我一直想多舉出一些實例而并不想寫得與到處可見的“干貨”般無味,***還是那句:敬請期待吧。