[開發故事]架構師修練 I - 超級程式碼控

發表於2019-05-11
國內我們對架構師,專案經理,開發經理或者是技術總監這類職業定位普遍不都不清晰,很多的情況是“能者多勞”,一人身兼數職。達爾文的理論在我們的行業是絕對適用的,我從進入這個行業開始我就不甘於成為淘汰者,而我也由心地熱愛著這個行業很年前我就立志要成為架構師(當年流行叫:系統分析員 )這目標進發。回首這10幾年的磨練,我總結了一下一名合格的架構師應該具備哪一些方面的能力以及怎麼才能得到這些能力
編碼能力
    架構師是一個職業,是一種經歷了各種磨練與長年開發經驗積累出來的。另外我一直認為:不會編碼的架構師不是一個好的架構師。我見過很多所謂的架構師完全不懂編碼,但總喜歡拿著架構說事。但從嚴格來說他們並不屬於“軟體架構師”的範疇,充其量只能算是個“系統架構設計師”,遇到這樣的”架構師“我總喜歡說一句話:”Don't tell me the concepts show me the code!“。
    不參與編碼並不代表不會編碼,如果沒有過硬的開發基礎,巨量的編碼時間積累為基礎,在設計軟體時一定會忽略非常多的細節,而這將會直接影響到整個專案的成敗,試想想當專案經理按照架構師設計的軟體藍圖訂製開發計劃與安排專案資源時由於“藍圖”記憶體有大量未確定的風險因素,以及由風險觸發後所帶來的不可預知的結果,最後專案是否能成功 ?
 
  • 多看 - 多看別人的程式碼,從別人的程式碼中讀出軟體的架構與設計的設計思路
  • 多學 - 掌握各種語言,不要偏執於某一技術陣形,不管java, .net , phyon 還是javascript每種語言都有其優缺點,成為一名語言控,從語言本身學習與理解語言設計者的思想。
  • 多做 -  瘋狂編碼,從時間與實踐中去體驗與領悟,工多藝熟。
  • 勇敢 - 嚴格要求自己不要寫出”發臭“的東西,勇敢地重構!讓程式碼變得優雅,易讀充滿你的設計思想。
可實現的是架構,空談是概念 So don't tell me the concepts show me the code!  “不懂編碼的架構師不是好架構師” 好架構師都是超級程式碼控。
程式碼是最好的老師
 
從程式碼中學習設計的思想、方法是提升類庫設計能力、印證你所瞭解的概念與理論這就是架構師看程式碼的觀點。
 
基本準備
一個類庫可能有數千個類上萬個方法,應該如何去看呢? 在看程式碼前我們需要進行一些什麼樣的準備呢 ?
 
  • 設計模式 - 最標準的23種設計模式基本上要有一個瞭解,可能一下子不能理解他們的用法,但一定要記下他們的英文名字和基本的用途,如:Factory, Wrapper (Decorator), Command,  Builder等 。
  • 語言規範 - 熟讀語言本身的官方編碼規範與命名規則,這是共同的標準,也是從官方得到寫程式碼的第一指導。
  • 要看懂UML中對類的圖形表示方法(類、介面、抽象類、繼承關係、使用關係)
 
看程式碼的方法
這裡所提供的方法就先以C#作為語言基礎,因為C#有極為規範的的語法規則。.net 的文件在類庫方面的文件是最完整也是最易讀的。以.net framework作為起點會是一個很好的練習入口。在開始前我還推薦一下大家需要有一個反編譯工具我用的是.NET Reflector, 用反編譯工具不是讓你去抄程式碼(程式碼本身是沒有多大價值的,價值的核心在於設計)而是可以更深入地瞭解到程式碼是怎樣實現的。用反編譯工具看微軟的程式碼會看到很多的不同的,你會發現大最設計得非常有意思的內部類 (Internal) 。從中大至可以推斷出微軟的開發方法,“在外部介面完全一至的情況下,讓程式設計師編寫的自由度最大邊界就是內部類與內部方法” 你可以馬上動手先看看 System.Web.Mvc.dll 的實現
 
要點:多問為什麼,帶著問題看程式碼——為什麼這樣寫(存在理由)?為什麼這樣設計(出發點)? 由你來寫又將如何實現?
 
看命名 
    以物件導向的語言為例,大多會在名字內帶有具體的用法資訊,從名稱推算可能使用的模式及實現
 
帶有模式印記的類:
  • TagBuilder - 以Builder模式實現的Html標記的構建器
  • StringBuilder - 以Builder模式實現的字串構造建器
  • XXXXWriter - 以構建器模式實現的各種寫入器
  • ConnectionFactory - 資料庫連線物件構造工廠

 
XXX+模式名 是慣用的對模式類的一種命名規則
 
找到了模式實現如果你看不懂,那恭喜你這就是學習的機會到了,馬上翻開設計模式與實現類進行對照印證,這個過程可以加速模式在你大腦中的印象與加深理解。(模式是架構師的大殺招,能不能上檔次就看對模式的理解與認識了,一有機會就應該學)

帶有家族印記的類:
 
XXX+Base - 抽象類
基類名+XXX - 某抽象類的子類 
 
是繼承關係一種常見的命名規則。
 
注:每一種基礎語言會有自身的命名規則,所以必須對官方提供的命名規則爛熟於胸,既可以學習別人怎麼寫程式碼也可以規範自己的程式碼寫法。
 
 做完這兩個練習基本上你可以在不看 Classes References(類手冊)的情況下一下子瞭解一大堆類的存在與用法。
 
看介面

   介面在設計中有著極為重要的地位,結構再複雜的系統到了介面級別基本上都會很簡單。而且也是判定這個類庫設計是否成熟的一種標準。介面與介面間的定義就定義整個系統的基本框架。看介面的最基本意義就是深入理解類庫設計者的設計思路與瞭解類庫最核心的能力。
 
這裡我們以 IRepository 為例來講講怎麼去看介面 (如果想深入瞭解IRepostiory的朋友可以閱讀我之前的文章:“Repository模式與UnitOfWorks模式的運用” )
我以 IRepository 為例是因為它的共識度很大,而實現起來可以很龐大也可以很小,眾所周知IRepository提供的就是對某個實體的CURD(增加、更新、讀取、刪除)的一個介面。那麼當我們看到它的存在時,應該可以推斷出另一個介面:IUnitOfWork 因為它們往往會是孿生兄弟般的存在,再進一步推斷是否會存在IRepositoryFactory 和 IUnitOfWorkBuilder 呢? 那麼就可以帶著這些問題在類庫中找答案。    
 
通過IRepository我會可能會發現一大堆的Repository類,
如抽象類:EntityRepositoryBase, FiledRepositoryBase ,JSONRepositoryBase 等
具體類:BlogRepository, PostRepository, UserRepository 等

注:作為練習大家可以去下載我在NuGet上釋出的一個名為 DotNetAge Document Storage 類庫,裡面就有Repository的實現
 
一但掌握了從介面看結構的方法,就可以快速地在無文件的情況下理解類庫的核心與設計理念。
 
參考“最佳實踐”
      一般上來說,流行的語言都會提供官方的“最佳實踐”提供下載學習。這是一個必修專案,同一個需求,我們可以採用各種的設計方法來實現,但哪一種最好的? “最佳實踐”就提供了方法選擇的指導。“最佳實踐”會有大量文件輔助講解,在此時使用上述兩個方法去學習那將會更大地提高你在設計上的提升。
 
隨著不斷的積累與大量的程式碼閱歷,你可能就會得到這樣一種能力:隨便拿個Dll,在一個短時間內你可以如數家珍般說出整個Dll中的特點與功能。
 
這,就是“看”的練習方法,與練習後的效果
 

 要成為架構師就需要突破語言的障壁,不同的語言有不同的優勢,設計應該是因勢利導,好的架構可用任何語言實現,反過來優秀的架構則應儘可能地發揮語言的特性。應用此方法前首先你至少已掌握或精通一門語言。
  
學習多種語言的動機
  • 開拓視野,從不同語言中學習特有的設計理念
  • 尋找與更新自己的 “最佳實踐”
  • 規避語言被淘汰的風險

 
開拓視野
    我最近在不少網站上看到這樣的一種論調:“學語言只學一門就好,不需要多隻需要精”。咋一看,似乎是對的,而我認為僅限於初學者或不求進取者。這是一種語言同質論,是一種誤導與限制!如果學習語言能“窺一斑而見全豹”那就不需要有那麼多的其它語言存在了,對嗎? 
    當對某一門語言精通(我指的是精通類庫而不是語法)後,這個時間大概也得幾年,很容易進入到一種“思維定式”,以某種固定語言為基點想問題,或是設計。一旦進入這種狀態也就意味著侷限性的出現,程式設計師或是架構師就被限制在了一個區域性的小範圍,而且還是風險極高的範圍內。
    IT的發展是飛速的,今天的寵兒明天的乞丐這種劇目屢屢上演著,你願意被大浪淘沙嗎?吊在一顆樹上真是一條死路,這是技術發展的風險層面。又,你的設計工作對你還有挑戰性嗎?你是否仍然對設計和開發充滿激情?你的設計是否在當下可以有什麼讓你自豪的特色或建立呢? 被同質化後這些答案都會被否定掉。 
   
   我的論點是:不斷學習各種語言,體驗各種語言所帶來的開發與設計的激情,開拓自我的視野才是一個架構師應走的路。架構師不單單是技術的選擇者,而更應該是技術的整合者。


選擇“最佳實踐”
 
   我們長期會在某一領域內工作,自然而然會誕生出對此領域內的軟體的設計理念與實現方法。但這僅是一種,舉一個最簡單的例子,同一個網站我們可以用ASP.NET MVC , Java, PHP 或是NodeJS來實現,固然實現方法與程式碼量就截然不同了。隨便寫個部落格網站就能體驗他們的區別所在:
 
  • ASP.NET 和 Java的思維方式與程式碼量差異不大,學習曲線最長、 Hosting 資源成本中等,但資料庫Hosting成本高
  • Php 相對前兩者簡單而且資源眾多,Hosting 資源最多,成本最低
  • NodeJS效能最高、學習曲線最短、程式碼量最少、資源也最多但Hosting 成本最高
 

從這個比較中可見,作為架構師不單要考慮設計方法與實現,還得考慮部署環境。如果只是某一方面的“能手”那隻能幹瞪眼,無可選擇。
 
我不是要選擇“最好”的而是要選擇“最合適”的,因時制宜,因地制宜才是我們所需要的“最佳實踐”

成為 “O” 型架構師
 開發是一個團隊共同完成的,與真實社會一樣,活在哪裡就說哪裡的話才會深入瞭解對方的文化。 架構師不是一個獨立的個體,而是團隊中不可或缺的成員,在行政與地位上與其它成員是對等的。開發隊團就像是一個人,流著共同的血液。一個架構師,一份設計就應該是一種“O”型血,無論在哪個隊團內都能融合,使用哪種語言都能實現與優化這才是一個好架構師的目標。

學習多種語言的方法
 學習語言的方法大家都會有各自的路徑與方法,在這裡我只是介紹一下我自己的學習方法僅供大家參考與給我建議。我從業也10多年了,經歷了不少語言以下這些是一些記憶與狀態:
 
  • Delphi (1-5) (Object pascal) - 這是初戀 , 擁有最多的介面元件和最簡單的視覺化開發環境,VCL算是當時最好的選擇。
  • VB (2-6) - 最容易呼叫COM的語言也是做物件導向很苦B的一個了。
  • C++ - 學得最差的
  • java - 用來學物件導向的
  • C# - 算是我最擅長的,也是做專案最多的
  • Php - 只能算是懂一點
  • javascript - 我最喜歡的動態弱型別語言。
  • css/less - 最讓我頭疼 (有了Less會好一點) 
  • html/xml/xslt - 最容易建立方法論的標記性語言是最容易建立發散性思維與抽象思維的工具
  • Objective-C 和 Swift - 現在在學的


每一種語言就像自己的女朋友一般天天在身邊陪伴著我們,所以想學得快首先是愛上她。即使她不再受寵她也會給我們留下很多美好的記憶。
 
感性認知

   我學語言的第一步是不看語法的,因為物件導向的語言語法上基本是相似的,而且語法參考會很長讀起來慢(這跟找老婆不要光看外貌是一個理)。我是從類庫入手的,從主打的類庫中可基本上快速瞭解整個語言的重要特色和常用的內容。就如iOS吧,一入手我會先看Cococa Layer中的UIKit,花兩小時看完就知道XCode怎麼用瞭然後就可以做個簡單的移動應用跑一下,從感性上互相認識一下。
 
相互印證
   沒有哪個語言是沒有參照物憑空發明出來的,就像學java時如果學過c++會很快因為java就是在極大層面上改進C++而來的,學C#的時候學過java就一下能上手,因為C#是微軟沒買到java自己搞出來的同時也去改進了java。所以語言之間會有互通性存在,在學習的路徑上可以先了前他們的前輩是誰,有什麼特色通過雙向的印證瞭解可以很快速地去掌握與深入理解一門語言。
 
長年的積累
    掌握一門語法很快,精通一門語言就是硬功了。這和我們學自然語言一樣,詞彙量是日積月累的成果。開發語言的詞彙量就在於類庫了,每一門語言的標準類庫也是夠我們喝一壺的,需要實踐、學習與理解結合經驗沉澱成我們的成果。在這方面我給出的建議就是要培養自己的耐心與毅力,羅馬不是一天建成的,高手也不是一天就能修煉出來的。除了掌握官方類庫還得將業界流行的類庫和框架都能瞭解與熟悉這才算是“精通”。

寫 - 瘋狂的編碼
 
“實踐是檢驗真理的唯一標準” 能說不如能寫。學到的知識是別人看不到的內容,作為程式設計師或是架構師將腦中的精華程式化呈現,然後成為產品這才是我們的終極目標。
 
學會一門語言並不代表寫得好,作為一名架構師寫的程式碼要求更是不同:
  • 易讀 - 命名是否符合程式碼規範,所有介面是否全部程式碼都有註釋
  • 易用 - 每一個類,每一個方法都是架構師與程式設計師的UI,少引數,容易理解的設計可以大大減少溝通成本。
  • 框架化 - 一個一個類寫是很慢的事,要活用模式於程式碼中能同時構建出10幾個或幾十個類。
  • 參考性 - 架構師不是程式設計師,寫程式碼為的是固定核心功能與公共用法,便於成員開發。面對複雜的場景需要多寫示例同時也是測試設計的易用性的方法。

 
怎麼才能達到這樣的標準呢?
  • 為自己立項從現在起為自己而編碼
  • 多寫程式碼片 - 對區域性的理論進行實踐,多寫一些小的程式碼片段或實驗程式,而按正式專案一樣來對待。完整的記錄,共享原始碼獲得Feedback,有良好的註釋。
  • 模仿是學習與理解新事物的最佳捷徑 — 可以去仿造某些專案,當深入其中可以更直接地理解設計者的最初設計想法,同時也可以得到一個仿造品(不是抄,仿造的目的是獲得編碼經驗)
  • 嘗試使用模式並控制類的規模
 

最後也就是時間的積累,瘋狂地編碼。同樣的時間一個架構師的編碼能力至少需要同等於五個以上程式設計師同時編碼。

架構師之路是一條很漫長而且需要不斷學習、思考與實踐積累的道路。我只是走了這條路的一小段,以此總結與更多的朋友分享共勉。在下一篇文章中我將會從另一個角度來談架構師的修改專案:表達力。希望有興趣的朋友能給予更多的關注與反饋。

表達力
世界上最難的兩件事是:將別人口袋的錢放到自己的口袋裡面;將自己腦子的想法完整放到別人的腦子裡面。
我認為一份成功的設計是 ”能讓不同層面的人都能看得懂“。為什麼這樣說?那麼得了解誰需要看設計,又是出於何目的來看設計。
  • 銷       售 - 從設計中尋找賣點與特色,豐富銷售方案和定製預售計劃。
  • 專案經理 - 根據設計進行時間估算、專案資源準備與工作分解。
  • 開       發 - 根據設計要求進行技術準備、開發環境、編寫DEMO以及最終編碼 。 
  • 測       試 - 根據設計劃分測試粒度、準備測試環境、定製測試計劃 
 
不同的開發方法與開發流程都會有不同的設計文件要求,而受眾無非也是上述幾種。作為專案/軟體的設計者,能清晰地向受眾準確地傳達自己的設計思路就顯得極其重要。這裡指表達不是指嘴上的功底,更多的是在工具的掌握能力與文字的表達能力。使用不同的工具表達向不同的受從表達相同的理念,這基實是對架構設計的一種驗證,這種溝通與表達能有效地融合不同角度的觀點,也能讓架構師能更深入地理解自己的設計方向。
 
要面對如此多的複雜性應該如何來鍛鍊自己的表達性呢?
  • 多與人溝通,多參與頭腦風暴
  • 練習用人類語言表達“非人類”的專業知識。一張用鉛筆畫的框圖往往比一個使用專業UML設計工具做出來的設計更容易讓人理解。 UML為作架構師基本上是必修課,也是輔助架構師思維的工具,但對於不懂UML的那就是“非人類”的文件,設計是給人看的,別人看不懂再專業再標準化的設計也只能淪為廢紙。
  • 培養測試先行的習慣 - 在設計時多寫範例與測試,在很大程度上可以減少設計誤區和驗證被實現的可行性。這樣可以在將設計交付給開發、測試後節約大量的溝通時間。
 
擁抱變化
正如XP(極端程式設計)中所說:“世界上唯一不變的就是變化”。擁抱變化、預測變化、控制變化不單純是優秀開發人員的和專案經理的要求同樣也是架構師一種重要的能力。
“變” 
     我的理解 設計中的“變” 就是 “可定製化” 的要求,可定製化程度越高系統/專案的可擴充套件性就越強。架構師就是需要鍛鍊的是控制這種變化的範圍與程度,“變”是雙刃劍,允許過多的變化就會造成“過度設計”,出現一大堆“未來可能使用的功能”;過於封閉則會變得僵化難以適應新的要求。 
“不變”
這裡所說的“不變”也只是相對而然,在系統/專案中相對不變的就應該是“核心”或者是“基礎框架”,舉最簡單的例子就是 .net framework 就是其中一者,雖然它會不斷髮展,增強功能。但其基礎核心設計理念與架構也從來沒有發生過質的改變。更具體的一點來說“不變”的是規則、用法和基礎設計理念。
 
我認為學習控制變化的最佳方法是多看出色的類庫或系統,多問為什麼這樣做,理解原設計師的想法。經過一定時間的積累,隨著對“變化”觀察的增多,自然而然會在自已的設計中按設計要求將”變“與”不變“應用得當。
 
方法論 
針對架構設計的方法論眾多,應該如何選擇?我也讀過很多的相關書籍,我只選最實用的,這裡我推薦幾本書。
  • 《設計模式》- 要讀懂、活用,我讀了10幾年每次都可以從中學到不一樣的想法,將其應用於架構內可以極大地簡化很多複雜的問題。
  • 《Java 程式設計思想》 - 談物件導向方面最好的其中一本書,提高物件導向的設計能力會有很大幫助
  • 《Refactoring》- 重構不單單是一種做法和程式設計師才關心的事。重構重於意識與思維完全可以用於架構設計 。
  • 《eXtreme Programming》- 雖然討論的是開發方法,但它最能詮釋什麼是”變化“。
方法論的實踐與應用也需要時間磨合並融會貫通,它們給予我們更多的是理念與意識,一定要避免走進為實踐方法論而設計的誤區。
 
成為架構師的路子我相信還有許許多多,我相信相同的是每位架構師都需要通過長時間的學習、實踐、思考而也且也擁有一顆熱愛軟體心。
回覆

相關文章