工程師的江湖:技術為外功,思維乃內力

身為一種以數學、邏輯觀看世界並創造事物的職業,軟體工程師到底該具有什麼樣的條件?若以金庸先生筆下的武林來形容,若技術為外功,那麼思維就是推動一切的內力。
評論
評論

本文原刊於 合作媒體 36 Kr,身為一種以數學、邏輯觀看世界並創造事物的職業,軟體工程師到底該具有什麼樣的條件?若以金庸先生筆下的武林來形容,若技術為外功,那麼思維就是推動一切的內力。

一個足球評論家可能並不會踢足球,卻並不妨礙在解說比賽時對某某球星的技藝評頭論足。同樣也絕不敢以高明的工程師自居,而只是以類似金庸先生筆下的武林高手來闡述筆者對工程師的理解。這樣,大家也許就不以筆者為鄙薄狂妄了,這是筆者必須首先聲明的。

一、重新給工程師下個定義

640

按照 Wikipedia 的定義,工程師又稱為電腦程式設計人員(Computer Programmer)、開發者(Developer)、編碼者(Coder)或電腦工程師(Computer Engineer),和網絡上廣泛流傳的碼農同義。筆者無意於也不能夠為工程師給出一個精確的定義,這裡,只是利用工程師的語言做一個簡單描述。不是故弄玄虛,不過博取讀者諸君一笑。

class Programmer : public Thinker {

public:

void design (System &);

void model (Problem &);

void code (ProgrammingLanguage &);

void debug (Defect &);

void refactor (Code &);

void learn ();

void communicate ();

virtua voidl think (Logic &);

private:

vector _pls;

}

工程師是徹頭徹尾的腦力工作者(Mind Worker),怠于思考者絕對不能成為好的工程師。有鑒於此,類 Programmer 天生的就應該是 Thinker 的子類。就工程師所使用的思考技巧而言,Thinker 的具體內涵包括邏輯 (Logic) 和數學(Mathematics)。作為工程師,不一定非要達到邏輯或數學領域的專業水準,而是必須具有邏輯和數學的基本素養。邏輯用來推理,數學用來培養邏輯。另外,數學還有助於工程師訓練另外兩項必不可少的思考的技能,分析和抽象。下文還要展開討論。

工程師的工具是寫程式語言,日常活動和主要工作包括設計(design)、建模(model)、編碼(code)、除錯(debug)、重構(refactor)、溝通(communicate)、學習(learn)和思考(think)。

有關工程師有一個流傳甚廣的誤解,認為做工程師門檻低,沒什麼技術含量。即使沒有學過電腦的課程如離散數學、數據結構、算法等,也可以寫程式。寫幾行程式當然算不得什麼,但要修煉成有一定思想境界的一流工程師,卻殊非易事。這就如同會做飯的人很多,但真正的烹飪大師卻並不常見。所謂碼農者,乃是工程師的自我吐槽,豈足深信耶?所以,作為工程師要有持續進階的強烈的進取心,斷不可妄自菲薄,自怨自艾。

2、工程師的思維「內力」

640-2

漫長的學生生涯中,筆者遇到的最好的數學老師是高中時老師。他上課時講過這樣一段話,當面對一個數學問題,一要想的明白,二要算的準確,三要寫的清楚。直到今天,這句話對於筆者的工程師生涯也具有很強的現實意義,能不能想的明白其實是考量一個工程師成敗的至關重要的因素。

金庸的武俠小說中有一個普遍的規律,那就是武功必定以內力為根基。比如張君寶與崑崙三絕何足道在少林寺的那場經典之戰中,張君寶能夠「以少林拳中最平淡無奇的拳招,化解了最繁復的敵招」,始終不落下風,所恃者不過內力之渾厚爾。另外的著名戰例還包括少林寺小和尚虛竹 VS 吐蕃國師鳩摩智以及聚賢莊蕭峰 VS 玄難。內力達到登峰造極空前絕後的第一高手莫過於少林寺的掃地僧。也許風清揚是一個例外,好在我們討論的是一般規律,所以就顧不得他了。

電腦程式所特有的思維(Thinking)就是工程師的「內力」,思維能力不濟,功能再強大的程式語言也無用武之地。所以,筆者在這裡特別強調工程師的思維藝術。

工程師的思維有一個專業術語,叫做計算思維(Computational Thinking)。計算思維是按照電腦科學的基本概念和方法,用來理解需求、設計系統、實現編程、解決問題的思維方法。

簡而言之,計算思維就是工程師或電腦科學家是如何思考的。當然,電腦科學的理論知識如數理邏輯、離散數學、數據結構、算法以及面向對象是計算思維的必要條件。計算思維有一系列的智力工具,不能一一盡述,僅列舉關鍵的幾項如下:

抽象思維(abstract thought)。給定一個問題,抽象就是去掉紛繁蕪雜的與計算無關的部分,用規約(Reduction)的方法還原到問題的本質。所謂本質即把原來的問題轉換為一個或幾個可以使用電腦描述並解決的問題,進一步講也就是轉換為在算法上可計算的(algorithmically computable)一個或幾個問題,更準確更理論化更上檔次的描述是轉換為邱奇-圖靈論題(TChurch-Turing thesis)可計算的可數個問題。圖靈機(Turing Machine)和 λ 演算(Lambda calculus)本身就是對可計算性(Computability)的漂亮的抽象,可以作為抽象思維的經典案例來揣摩學習。

一般在實際工作中,常常需要把問題的實體對象根據需求表示為各種數據結構如樹、堆、棧等,而業務邏輯(Business Logic)過程表示為各種算法如排序和查找等。表示(Presentation)是解決問題的第一步,也是關鍵的一步。在工程師的實踐中,我們有很深的體會,一旦問題被準確的無歧義表示出來了,解決方案就烘雲托月般地呈現出來了。這就是「數據即代碼,代碼即數據」的道理。

抽象思維也廣泛用於數學家的工作。面對一個困難的問題,數學家們常從兩個方向開展研究。一方面,從特殊情況入手,推廣到更一般的情況;另一方面,將一個一般問題具體化成幾種特殊情況。兩個方向的結果最終匯聚在一起,就找到了問題的答案。筆者想這可能是論語中「我叩其兩端而竭焉」的一個最好註解。而從特殊到一般就是不斷抽象的過程。

筆者用一個具體的例子加以說明,有一個著名的 六度分隔理論(Six Degrees of Separation)講的是世界上任意兩個人都可以通過最多另外 6 個人相互認識,如果要驗證這一理論,怎麼做呢?我們可以借助一個圖(graph)來表示人與人之間的關係,每個人用圖中的一個節點表示,如果 A 和 B 認識,那麼在代表他們的節點之間有一條連接。

那麼現在的問題就轉換為檢查這個圖的直徑是否大於 6。考慮到世界人口眾多,且有生老病死,圖的規模必然超大,並且是動態的不斷變化的,算出它的直徑仍需要更多的簡化。這裡就到此為止了。

邏輯推理(Reasoning)。邏輯推理對於工程師的重要性不言而喻。與其說邏輯推理用於程式新功能的開發,毋寧說更多的應用在程式修改 BUG 的過程中。程式除錯有點類似於 Sherlock Holmes 偵破案件的過程。

和 Dr. Wason 比較起來,Holmes 的推理優於常人的地方有兩點:第一,在觀察現場或聽取來訪者敘述時,他能夠得到更多的的數據,尤其是一些別人容易忽略的關鍵的細節,這得益於他對犯罪領域知識的豐富積累,知道什麼才是更重要的數據;第二,根據得到的數據,他能夠聯想到更多的可能的結論,這得益於他大量的案例儲存。有了這兩點,就能夠通過一環套一環的推理鏈逐漸縮小偵察範圍,最終認清犯罪事實。

程式除錯也是如此,首先必須掌握程式實際的執行過程的細節。然後從問題出發,分別朝著產生的原因和導致的後果前後兩個方向推理。逐漸定位問題的範圍,最終找到問題的根源和解決的方案。我們比 Sherlock Holmes 幸運的是可以借助於除錯工具來瞭解程式運行的過程,所以一個不能使用除錯工具的程式真是令工程師感到無比沮喪,只能通過 trace 資訊來跟蹤程式運行的過程。

如果不知道程式運行的過程,推理就只能靠猜,那麼修改 BUG 是非常危險的,很容易導致回退(Regression)的錯誤,因為這種情況下如同瞎子摸象,根本不知道自己在做什麼。另外,Sherlock Holmes 還多次表達過這樣的觀點,案子越是離奇,越容易解決,因為 Singularity is almost invariable a clue。

對工程師來講,也不必擔心奇怪的問題,奇怪本身就是線索 。關鍵看對程式運行細節的瞭解程度和邏輯推理的技術水平。

分析(Analysis)。分析是上文提到的數學家所用思維方式中從一般到若干特殊情況的過程。面對一個問題,如果一下子描述不清楚或者表示不出來,可以先找出滿足問題條件的幾種特殊情況。通過仔細檢查這幾種特殊情況,求同存異,找出他們共同的規律或模式,並對這些模式或規律加以驗證,就可以找出描述或表示問題的方法。這就是猜測加驗證(guess-and-verify)的過程。項目需求分析時常見的應用案例分析(Use Case Analysis)方法,就是用一個個具體的使用案例將模糊的項目需求生動的表達出來。

分解(Decomposing)。把一個大問題分解為幾個小問題,或者把一個複雜的過程分解為幾個子過程,當然有助於問題的解決。這也是工程師常用的手段,如算法策咯中的分而治之(Divide-and-Conquer)和合併排序就是這方面的例子。

遞歸(Recursion)。對於初學編程的人,遞歸可能是一個比較詭異的較難掌握的概念。但是一個工程師如果不懂遞歸,很難再稱之為工程師。因為很多稍微複雜的算法他都不可能理解,如回溯和動態規劃,甚至於樹的遍歷。遞歸常常可以用簡單的方法非常優雅的表達複雜的算法。

另外,有關計算思維的特有方法還有並行、異步 / 同步、模擬 / 近似、優化、分層、封裝、解耦等等。工程師的思維藝術即計算思維不是一天兩天短時間可以形成的,需要在實踐中慢慢琢磨,不斷提升,且永無止境。

3、工程師的「戰鬥力」技藝

工程師的思維藝術融化到對程式語言的使用上,最終形成工程師的技藝。因此,程式語言之於工程師,就如同青龍偃月刀之於關羽,如意金箍棒之於孫悟空。離開了青龍偃月刀和如意金箍棒,關羽和孫悟空的戰鬥力就無從談起。所以,脫離程式語言來討論工程師的技藝也無異於緣木求魚,自欺欺人。結合程式語言, 工程師的技藝有四個境界 ,從低到高分別是

初窺門徑 。程式語言的初學者,如同小兒咿呀學語,也許可以寫一個類似於「Hello World」這樣的程式,但對語言的所有東西都是一知半解,不可能應用於實際的項目中。這是我們很容易就可以達到的級別。有些人初窺門徑之後,往裡面看看,感覺不容易,就放棄了。

登堂入室 。對程式語言所共有的基本表達方式有了一定的瞭解,如變量、賦值、循環、選擇等。可以用在一般的目標中,但是寫出來的程式碼看起來滯澀笨拙,很難做出高品質的程式。這個時候,工程師很容易產生自滿的情緒,以為完全掌握了這種程式語言,寫程式也不過如此。如果陷入這種自滿情緒中不能自拔,就失去了進一步進階的機會。

熟能生巧 。掌握了程式語言特有的功能,並能駕輕就熟,靈活使用。因此,寫出的代碼更加的精煉易懂,常常使用簡單的方法表達較為複雜的算法。這是一個成熟的工程師的水平,也是我們大多數工程師所能追求的目標。

妙不可言 。 這是傳說中神龍見首不見尾大師級的境界。柏楊在《中國人史綱》描述李白的才華稱,李白寫詩時,對漢語的使用就像魔術師手中翻轉的手帕一樣,神鬼莫測。如同李白作詩一樣,筆者想這個境界的工程師對寫程式的各種精微之處了如指掌,能夠將程式語言的各種功能特性發揮到極致,且恰到好處。運用之妙,存乎一心。並且往往能夠別出機杼,奇思妙想,層出不窮。寫出的程式優雅、高效、別緻。這是我們一般工程師可望不可即的。

4、工程師的精神「修煉」

640-4

開放。在以往的工作中,曾經遇到過這樣的工程師,自以為掌握了某些核心的、關鍵的技術或技能,卻不願意和別人共享,處心積慮的保護著他的「地盤」,擔心別人染指他的工作。也遇到過這樣的組織,幾個被信任的工程師把持著產品的所謂關鍵模塊,其他人莫想參與,即便再有才華,也只能扮演跑龍套的角色。

這讓筆者想起《三國演義》中諸葛亮舌戰群儒的情節,在回答江東首席謀士張昭的詰難時,諸葛亮將儒生分為君子之儒和小人之儒。這裡不妨將這樣的工程師稱為「小」工程師吧。工程師的技藝根植於計算思維中,沒有所謂的不傳的絕招或秘笈。交流和實踐是工程師持續進階的必要且有效途徑。固步自封和抱殘守缺是工程師的大忌,完全是作繭自縛,毫無出息。

嚴謹縝密。在軟體開發中,任何事情在邏輯上原因和結果都是清晰明瞭的,不存在任何意義上的說不清道不明的神秘主義。工程師討論問題時,當然應該使用工程師的語言,即用數據而不是猜測,用邏輯而不是臆斷,來表達自己觀點。

有兩種情況可能造成自己表述時似是而非,模稜兩可:第一,數據掌握的不夠;第二,沒有「想的很明白」。例如,當我們討論性能(Performance)時,一定要用回應時間(Response Time)或吞吐量(Throughput)這樣有意義的參數,而不只是泛泛的講「這系統怎麼這麼慢啊」,「電腦在幹什麼呢,等的時間太長了」,「簡直受不了這樣的程式了」。用戶可以這樣抱怨,而工程師則不可。

同樣當我們講到系統耗能時,要用 CPU 佔用率、記憶體這樣定量的參數。因此,一個腦筋清楚的工程師不會把這樣的話掛在嘴邊,「太神奇了,不知道為什麼」,「弄不清楚是否可以解決這個問題」,「先這樣吧,以後再說」。一般地講,智慧和非智慧並沒有清晰的界限,因為我們並不知道如何嚴格地定義智慧。

然而,有了圖靈—邱奇論題,可計算的和不可計算的確實有明確定義的界限,也就是說,電腦可以解決的問題和不可以解決的問題是涇渭分明的,且是可以區分的。對於一個問題,能夠解決就是能夠解決,不能解決就是不能解決,不至於難以確定是否可以解決。所以,所有以上這些說法都不應該是工程師使用的語言,工程師就是要把一切都弄得清清楚楚,不放過任何潛在的問題。

完美主義。筆者不瞭解完美主義的真實意義,也不大拿得准完美主義是褒義詞和貶義詞。筆者用這個詞是為了強調工程師要堅持追求工作的完美。寫代碼時是要有潔癖,不允許有任何瑕疵,這樣的代碼才可能正確、易讀、高效、簡單、優雅。對一項任務,不僅僅是做完就算了,還應該仔細想想是否是否可以做的再好一點。對遇到的問題,即使看似解決了,也要從頭至尾完全弄明白,不能似是而非,不求甚解。

面對變化。變化意味著在新的徵程上,要面對許多未知的東西,加之對安定狀態下的安樂窩(Comfortable Zone)的眷戀,讓我們有著或多或少的畏懼和抗拒。筆者認為這些都是人之常情, 無可厚非。

不幸的是,對工程師來說,變化就是家常便飯,如新的目標、新的應用領域、新的程式語言、新的技術架構、開發過程中新的問題、新的功能等,可以說不變的只有變化。其實,好逸惡勞是畏懼變化的根源。只有克服「懶」的思想,強迫走出自己的安樂窩,對新的事物充滿好奇心和求知慾,才能適應永遠的變化。

5、工程師的價值提升

640-5

有的公司把工程師看作和水電、機器一樣的冷冰冰資源,做專案計劃時,一些專案經理以為只要給專案分配足夠的資源(包括工程師、水電、機器)並加以正確的管控,項目就可以預期的順利完成。就好像做大鍋炒,只要把各種食材往鍋裡一丟,開火等著就萬事大吉了。

但是,工程師首先是有血有肉的人,絕不等同於毫無感情的機器。一個有雄心的公司要不斷提升產品的競爭力,什麼是競爭力?就是把產品做的好到不能再好,天下第一,誰與爭鋒?產品向好的每一步都需要借助於工程師創造力和想象力,這才是工程師的價值之所在。沒有工程師願意把最寶貴的創造力和想像力奉獻給只把自己看作資源的公司。所以,聰明的管理者會想方設法把工程師這種創造力和想像力激發出來。

《延伸閱讀》

想提升工作效率嗎?聽聽 Facebook 高效能工程師怎麼說!

我是怎麼靠自學成為工程師的:懂原理比應用更重要

我要成為前端工程師!給 JavaScript 新手的建議與學習資源整理

兩性大不同:男女工程師在學習中的 9 個差異

從 C++ 創造者到 Facebook 共同創辦人,你該認識的 12 位工程師

寫碼容易,讀碼難:工程師 千萬別重寫程式碼

向矽谷的 90 後取經 如何成為受歡迎的工程師?

歡迎加入「Inside」Line 官方帳號,關注最新創業、科技、網路、工作訊息

好友人數

精選熱門好工作

客戶管理企劃 Key Account Management Planner

樂購蝦皮股份有限公司
臺北市.台灣

獎勵 NT$20,000

產品經理 / Product Manager

奔騰網路科技有限公司
臺北市.台灣

獎勵 NT$20,000

社群經營專員

關鍵評論網股份有限公司
臺北市.台灣

獎勵 NT$4,000

評論