[架構師的修練] #1, 刻意練習 - 打好基礎

我在下半年的幾場公開演講,開始做了一點不同的嘗試。除了技術或是架構知識之外,我開始會強調為什麼會這樣思考的過程,也開始會帶到該怎麼培養這樣的經驗與能力的想法。在 2020 下半年,有幾場演講都往這個方向調整了。2020 下半年是個爆忙的半年,到現在終於有點力氣把這些內容整理一下了,於是就開了這系列文章 - 刻意練習。這篇是第一篇,主要就是對應到 2020/08 我在 Study4.Dev 八月份活動上分享的主題 - 後端工程師的修練之路

前言: 架構師的修練 系列文章導讀


我在過去一年多 (2020 ~ 2021) 的幾場公開演講,開始做了一點不同的嘗試。除了技術或是架構知識之外,我開始會強調為什麼會這樣思考的過程,也開始會帶到該怎麼培養這樣的經驗與能力的想法。在 2020 下半年,有幾場演講都往這個方向調整了。2020 下半年是個爆忙的半年,到現在終於有點力氣把這些內容整理一下了,於是就開了這系列文章 - 架構師的修練, 刻意練習。

這些場次都得到不錯的回響,我還是擅長用文字來表達這些想法,因此決定開這系列文,把我在當下礙於表達能力沒辦法說清楚的內容,寫成文章。以下是我預計寫的主題:

  1. 架構師的修練 #1, 刻意練習 - 打好基礎; 2021/03/01
  2. 架構師的修練 #2, SLO - 如何確保服務水準? 2021/06/04
  3. 架構師的修練 #3, 刻意練習 - 如何鍛鍊你的抽象化能力? 2021/09/16 (預計)
  4. 架構師的修練 #4, 刻意練習 - 練習題範例: 生命遊戲 2021/09/16 (預計)

寫這系列文章的動機

會開啟這系列文章,以及背後的動機,其實是來自這十幾年工作上面臨的挑戰,思考下來的結果。我踏入軟體開發這行,已經超過 20 年了 (Orz..), 經歷過幾年的工程師,技術經理,技術總監,一路到技術長,典型的工程師到管理職的過程。不過我希望台灣也能發展出真正的軟體業,能真正做點不一樣的服務出來,於是最近的幾年,我開始有計劃的轉職為架構師,重新回到專注技術的領域。

這轉換的過程中,越來越體認到,只有把 code 寫好是不夠的,在擴大架構團隊的過程中,我面試了很多人,也談過了很多人選,其實其中不乏實作能力比我強的高手啊! 但是談完後回到團隊的定位,總覺得缺少了些什麼,軟體開發不應該 “只有” 把需求做出來的過程,這過程只能算是軟體 “代工”,而不是軟體 “研發” 啊。在尋找這樣特質的人才過程中,我開始思考這樣的人除了 “招募” 之外,該怎麼 “培養” ? 所以才開始有了這念頭,想要好好地把我自己過去學習的經驗,用有系統的方式告訴大家,該如何培養自己在軟體產業長久發展下去的能力。

要在這行長久發展,你得要有能力跨過 40 歲這關卡。這門檻不會只有技術能力而已,一定還有其他更有價值的能力搭配才是。”高齡工程師” 這類話題最近幾年很熱門啊,只要有留意相關社群或是媒體,不難發現每隔一段時間都會有高齡工程師去留的問題被熱烈討論。我都當過 CTO 這樣的角色了 (雖然公司規模不算大),不過我想我開始能想像老闆的角度會考量什麼事情了。 40+ 的工程師,你除了把 code 寫得更快,工具更熟練,框架學得越多之外,你必須還要有一些年輕人取代不了的能力才行,否則老闆用 “scale out” (用在這裡好像怪怪的 XDD) 的策略,如果多找三個年輕人可能就能取代你了,那它還有可能用三倍以上的薪資聘用你嗎? 這些能力是需要漸漸培養累積的,等你 40+ 才開始做是來不及的,你必須在 30+ 摸清楚產業跟你自己職涯方向後,就要開始有計劃的學習累積才行。這正好呼應了時間管理的原則:

重要但不緊急的事情,你應該保留固定資源持續推動,並提早安排。

參考來源: Gipi的商業思維筆記 - 關於時間管理,我的五大訣竅

如果這是對你個人長期職涯很重要的事情,你就應該想辦法持續推動啊,累積這些有價值的能力,就是對你人生重要卻不緊急的事情 (明天不做也不會怎麼樣),但是因為他很重要,你應該要好好的計劃準備才是。寶貴的下班時間,就應該用在這些事情上面。如果你認同這觀點,那就繼續往下看吧 :)


以下正文開始。這次 Study4 辦的活動有線上直播,不想看一堆文字的可以看線上錄影。相關連結我放在這邊:

因為已經有現成的投影片了,我就趁機改改每次都是一堆字的寫作風格了,能用圖片就用圖片說明。我試著用文字的 方式重新說一次這個主題,這篇文章不是這場演講的逐字稿喔,而是同樣主題我另外用文章的方式來表達。我補了些適合用文字傳達的內容;也補了當時礙於時間因素沒有提到的內容;但是也刪掉了一些現場才有提到的案例… 內容多少會有些出入,有需要你可以兩邊都看一遍 XDD。

在進入正題之前…

有時候不得不說,一些前輩累積下來的觀點,自己經歷過真的覺得是有道理的。舉例來說很多人都講過類似的觀念,你學到的技能,都是點狀的學習,真正要發揮價值,是把他們串連起來靈活運用才是真正的知識:

同樣的觀念,不少人都講過。以前曹祖聖老師也在 教你成為 IT 界的德魯伊 講過:

讓 APPLE 起死回生的賈伯斯 Steve Jobs 也在 2005, Stanford 畢業演說 講過同樣的話:

引用了這麼多前輩大神的論點,想要在職涯內逐步建立這樣的連結,其實是個長期的考驗。我自己的解讀是這樣:

1, 打好基礎,做好能夠自我提升的準備

你很容易學到這些 “點狀” 的知識,現在 search engine 那麼發達,那麼多人在分享技能,線上課程也那麼多,只要你知道你想學的是什麼,其實根本不缺學習資源啊! 缺的是你有沒有時間把它學起來;缺的是你能不能靈活的運用他;缺的是你知不知道你缺什麼 (知道要去學什麼) …

這時,要走軟體工程師這條路,面對的方法不是去學更多的語言,更多的框架… (別擔心,你一定學不完的,所以請放棄要把他學完的念頭),而是先把基礎打好才是最重要的。面對追不上的對手,你的第一要務不是不顧一切拼命追 (你這等於是用你的弱項去追對手的強項,不是個聰明的對策);成功率更高的方式應該是: 好好準備,累積實力,讓自己有能力跟對方競爭之後再開始追趕。把基礎打好你才有能力靈活運用這些技能,把基礎打好你才有能力判斷你還缺什麼。基礎打好是 “內功“,不過你還是需要實際練習,因此,為了避免流於打高空 (只會講不會做),你至少要把前端到後端的各種語言、框架、開發工具等等,至少精通一套,讓你有開始自己 end to end 練習的入場券。這很重要,將來你也許會有各種想法突然從腦袋裡冒出來,你要能很快的驗證想法到底是空想還是可行,你會需要有一套熟悉的工具能夠把它做出來才能談得上改善等等正向的循環。

你不一定要挑最熱門的語言,但是你至少要有一套,而且是要能精通,到時驗證想法時,工具才不會成為你的阻礙。有了這兩個敲門磚,你才開始具備往更高階的能力前進。

2, 刻意練習, 累積特定領域足夠的經驗與能力

接下來就是你該如何做好實戰的練習了。我引用 Ruddy Lee 老師跟我們講過的一個觀念:

軟體專案開發很吃經驗的,在專案開始之初,團隊對於這個專案的知識掌握程度是低的,在了解規格與需求的過程中,知識會緩慢的逐漸累積 (紅色曲線左半部),在交付給使用者測試的階段 (紅色曲線右半部) 是知識經驗累積最快的時候,因為這時使用者會不斷地給予回饋,在修正與回饋的過程中就快速累積經驗與知識。不過矛盾的是,專案很多重要的決策,都是在初期就決定的啊,但是往往很多關鍵知識你是在末期才弄懂。

變化越快速的產業,進入門檻越低的產業,這種情況越明顯。敏捷對應這種狀況的解決方式是: 想辦法在前期就有後期的累積知識的速度啊! 只要提高交付的頻率,利用頻繁的迭代,盡可能的提早交付的時間,就可以提早取得重要的回饋,習得關鍵的知識。不過這樣還不夠,另一個角度來看,團隊需要用更積極的方式,透過 “刻意” 的發現問題過程,讓自己能提早得到這些知識。

這個 “刻意” 的過程,要認真說起來就是個大學問了,我沒辦法涵蓋所有的面向,我只能就我的經驗,跟大家分享我的應對方式而已。如果這是軟體產業注定要面對的問題,那我會往前一步,在每次都要學習一堆知識之前,我先讓自己準備好能快速學習的技能。Build School 的理念 “ Learn how to learn “ 剛好跟我的想法不謀而合,因此借他們的海報來用一用 (正好當天演講的場地也在 Build School, 轉頭一看背後就貼著這張海報)

接下來,學習的能力到位了之後,必須面對的是 “你要知道你該學什麼”。這是另一個難題啊! Ruddy 老師常跟我們講 “無知” 分成四種,一種是 “無知的無知”,意思是你連你不知道什麼都不知道…。現在資訊那麼發達,你只要下對關鍵字, Google Search 或是 Stackoverflow 都會有一堆方式解決你的問題。但是,如果你對問題還不夠了解,連關鍵字都不知道該怎麼下,或是找到的資訊沒有能力判斷能不能用,那怎麼辦?

這時才是每個人能力見真章的時刻。我的面對方式是: 培養這種能力沒有捷徑,你只能不斷的累積各種基礎知識,累積到某個程度,涵蓋的範圍夠廣的時候,大部分的問題若都能落在你的基礎知識掌握範圍內的話,雖然你也不會做,但是你的基礎知識可以引導你找到對的關鍵字,進而判斷參考資料的價值,找到正確的資訊。這時若能再配合自己學習能力,以及自己創造練習的環境的話,你就能夠有系統的把學到知識的時間往前提了。

回想前面講到的,點狀的知識你學習時並不曉得何時才會用的到啊! 但是當你需要他的時候,在那瞬間你會發現一切都可以串連起來了。單點的知識很容易被取代,世界這麼大,每個點永遠都找的到比你擅長的人;但是你累積的組合就不見得是人人能取代的了。這些基礎知識的布局,以及靈活的連結用來解決問題的關聯能力,才是讓你變成無可替代的關鍵。

想通了這個情境之後,後面要做的事情就容易了。我自己常常跟 team member 講,平常要累積基本功夫 (這樣你基礎知識的布局才會廣),而且要有夠好的抽象化能力 (這樣才能盡可能的排除不必要的細節,精確找出要解決的關鍵點),同時配合你至少要熟悉的一套語言與框架,用最少的功夫做出 MVP (Minimum Viable Product), 你就能更快地知道你的想法是否可行。這時不論成功與否,你都知道接下來你缺什麼能力了 (這時恭喜你已經擺脫 “無知的無知” 裡面講的其中的一個 “無知” 了)。剩下的,就是持續的修正你的想法,以及有系統的學習你定位出來缺乏的能力。

這個過程,就是我自己理解的 “刻意” 發現與練習的過程。後面的內容,我都是用我自身的經驗,用實際的案例告訴大家我怎麼累積跟布局。在過去其實我也不知道這樣布局對我有什麼用,我是在這行打滾了 20 年後,回頭看才發現這些過程,就是我現在面對問題能快速找到核心的關鍵。

我自己的案例

當你掌握基礎知識,也做好能夠自我改善提升能力的準備時,你就開始有能力挑選領域不斷加強自己能力的本錢了。接下來我就用我比較熟悉的 “後端工程師 / 架構師” 的領域為主,用我自己過去的經驗說明一下我的作法。過去很少公開我自己的背景,不過要講到這些職涯的規劃,透漏一些我的背景好了。在 Study4.Dev 這場次,我用了這張投影片來說明:

接下來,我就分幾個階段,從基礎知識、實作經驗、以及真正發揮影響力的過程,交代一下我自己的職涯發展路線。最後後面的段落再告訴大家我的建議跟想法。

1, 掌握資訊科學的基礎知識

我的工作經歷,並不是單純一路從工程師做上來而已。剛出社會的前三年,在當時台灣頗具規模的兩家軟體公司任職。第一家是影像處理軟體公司,學到大規模開發團隊的協作,包含當時還不算普及的版控技巧,以及沾到現在 CI/CD 雛形的 Daily Build.. (當時在 約耳談軟體 那系列文章,以及 Ken Beck 的 eXtreme Programming Explained 都提到這些觀念);第二家則是當時頗具盛名的網路服務業、以及自行開發的 search engine…) 總共待了近三年。

包含學生時代,及開始工作的前三年,大概就對應到我前面講的累積基礎能力的階段。我大學念的是電機系,當年電機系也有教計算機概論 & 程式設計,不過當年電機系重點都在背後的自動控制跟電路與 IC 設計啊,語言以組合語言 (Assembly) 與 C 為主,大三也修了微處理器的設計,這些課程累積了我如何從硬體的邏輯閘,一路往上堆砌到處理器 (CPU),再到組合語言如何在硬體上被執行的整串過程。大四我則用多餘的學分選修資工系的必修課 (資料結構,系統程式,作業系統,物件導向等等),這些課程讓我串起我寫的每一行程式,如何在電腦上被執行起來。當時修這些課程,以學分來說很不划算,CP值超低 (以畢業來說)。不但把自己搞的很累,還要小心不夠學分畢業… 不過多虧有這些基礎,讓我後面工作受用 20 年。

當年電機系的關係,從微處理器 (CPU) 的設計開始學,修資工系的過程中,也寫過很簡單的 CPU 模擬器 (就是你要有能力寫出模擬器,把輸入的 ASM 程式碼的結果跑出來)。這個過程讓我從 CPU 怎麼執行指令;到程式語言編譯後的指令怎麼被執行起來,都在那時搞清楚了。因為有這些基礎,我開始有能力看懂雜誌上介紹 intel 最新 CPU (當年還在 386 / 486 / Pentium 年代) 的 super scale 的設計上 (就是一個 clock 能夠執行完成一個以上的指令) 是怎麼回事。 之後碰到各種語言或是開發工具的最佳化,或是後來在學 Java / .NET 的 RunTime 各種設計時,所謂的 Java VM 就只是在軟體層上面,做好這些事情而已啊! 越挖越發現原來當年學的技術都用在這上面了。這時我得到的優勢,就是我不需要再去了解當年的 .NET CLR (Common Language Runtime) 為什麼要有那些設計? 比起其他人還要 K 文件搞清楚背後的原理,學生時代累積的基礎我只需要看一看 overview, 抓到一些關鍵字,就能了解背後的設計邏輯。剩下的就是熟悉工具的操作而已。

這其中,最困難的不是學習這些知識 (當年考試分數比我高的人很多啊,我也不是拿書卷獎的那些族群 XDD),重要的是在後面的應用時,我能聯想到課本上的知識才有用啊。過去有花時間好好的把 lab / homework 都做完幫助很大啊! 舉例來說,資工系我選修了 system software 這門課 (當年我其實也搞不懂這堂課要幹嘛),但是這堂課最後期末的作業,就是要我們自行開發一個規格很簡單的 CPU 的 assembler, 你要按照規格寫出這個 CPU 的模擬器,並且載入他的執行檔 (助教有定義好 spec 了) 並且順利執行。這個作業花了我幾個禮拜的時間,還好當年我認真地完成他了,印象深刻到現在我還記得這件事。

拍賣網站上挖出當年的課本: System Software, 2nd edition

這些基礎對於後來的工作有什麼幫助? 幫助可大了。要掌握一個新的技術,通常有兩大障礙,一個是了解它的設計概念,另一個是了解它要怎麼使用。通常要看懂設計原理是比較困難的,基礎不夠可能看不懂, (尤其是很多前一代的設計你也不瞭解的時候)。有些人就選擇跳過這部分,直接去看操作的說明,反正把語法看一看,熟練之後就用那幾種 template, 就能解決 80% 的問題了。這樣速成的學習方式是走不遠的,因為你很難累積啊! 只要工具換了一個世代,你熟練的語法與工具可能一夕之間就換了一套了,但是基礎知識不會。

累積基礎知識其實並不容易,因為它不容易有立即的好處,但是能讓你越學越快,同時你能建立的門檻也越來越高,其他人很難在短時間內追上你的基礎。相對於操作技能,就容易 (速成) 的多。我並不是說學習語法很簡單,而是語法或是工具的操作,通常學習成效是線性的,你只要照著練習自然會越來越熟練,你可以預期花 1 ~ 3 個月就能掌握一套工具或是語法的用法。但是要運用的到位,或是面對問題你能精準地解決它,通常就要有背後的知識支撐才能做正確的判斷。我在我的部落格上寫了很多架構面試題的文章,其實講的都是這些,端看你是否了解怎麼解決問題,而不是看你熟不熟 C# 的語法或是熟 ASP.NET 的框架…。當你跨過這道障礙時,你的學習速度就不是其他人能追得上的了。

時間跳到研究所的那兩年,我從電機的領域換到資工的領域了。考研究所前,我伴隨著電機系的訓練,加上在大四花不少時間去修資工系的必修課,順利的考上資工所。在研究所那兩年我挑了我有興趣的主題 (OOP + DBMS),跟了這兩個領域專長的指導教授。一樣很感謝當年指導教授的栽培,當年誤打誤撞,挑的這些領域,都是現在 Cloud Native 的基礎啊! OOP 很強調抽象化,我前面寫了那麼多篇 抽象化設計 的基礎都是靠 OOP 打起來的,這邊我就不多提了。另外一個 OO + DBMS = OODB (物件導向資料庫),當年很多論文都在探討怎麼把 “物件” 儲存在 “資料庫” 內的學術研究。聽起來好像跟工作扯不上關係? 那你就錯了。隨便舉兩個例子就知道它的應用。一個是現代的 ORM,講求的就是程式語言中的物件 (Object) 如何 對應(Mapping) 到資料庫中的表格 (Relation database)。過去研究 Entity Framework 如何面對程式碼的繼承,就用到這些觀念。另外一個例子: 現在除了 RDBMS 之外,另一個主流 NoSQL, 就是從 OODB 發展出來的啊! 你只要把物件序列化之後轉成 XML or JSON, 把這些 data 存到資料庫內,不就是學術圈裏討論的 OODB 的實作了嗎? 現在的 NoSQL 就是在做這些事情而已!

當年的基礎,當然對我現在怎麼 “操作” NoSQL 沒有太多幫助,現在主流的 NoSQL 使用的技術 (例如 Json / XML 等等),在當年根本連個影子都沒看到。不過當年 K 了很多論文,我掌握了 code 裡面的 object 該怎麼樣才適合存到 database 內的知識,這類資料庫如何面對索引,查詢,甚至是 schema 異動的課題,我當年都 K 過了啊 XDDD, 跟前面一樣,我只需要看一看現在各大廠 NoSQL 提供的 SDK, 還有 API documentation, 掌握好這些工具或是元件的使用方式;因為真正要注意的 know how, 那堆論文都念過了啊! 至於最關鍵的,我的系統該如何善用這些資料庫來解決問題,這層的基礎知識,早就在學生時代就準備好了。有這些基礎知識,其實對我的幫助,遠比我拿到各種服務或是 DB 的證照還有用。

基礎知識的重要,我就寫到這邊點到為止。花了這些篇幅,就是想讓各位了解基礎的重要性。也許你會覺得,學校教的業界都用不到啊! 這句話從表面上來看是沒錯的,我現在在用的服務沒有一個 20 年前就存在,當年的教授再厲害也沒辦法直接告訴你未來的發展跟應用啊! 但是現在的服務,都是靠這些基礎知識逐漸發展出來的,你掌握這些基礎知識你才有抄捷徑的本錢。我還在當學生的時候我也不曉得學這個要幹嘛 (單純有興趣就研究下去了 XDD),直到現在回頭看才知道這些知識對我的幫助。這呼應了 Steve Jobs 在 2005, 在 Stanford 演講 提到的那段話。我再次引用這段話:

(原文)

Of course it was impossible to connect the dots looking forward when I was in college, but it was very, very clear looking backwards 10 years later. Again, you can’t connect the dots looking forward. You can only connect them looking backwards, so you have to trust that the dots will somehow connect in your future. You have to trust in something–your gut, destiny, life, karma, whatever–because believing that the dots will connect down the road will give you the confidence to follow your heart, even when it leads you off the well-worn path, and that will make all the difference.

(中譯)

當然,當我在大學往前看時,把點連接起來是不可能的,但十年後往後看它是非常,非常清楚的。再提一次,往前看時你無法把點連起來。只有往後看時你才能連接它們,所以你必需相信點將在你的未來以某種方式連接。你必需相信某些事情 – 你的直覺、命運、人生、因緣、不管是什麼 – 因為相信點將在未來的路上連接起來將帶給你追隨內心聲音的信心,即便它引領你離開已被踏平的步道,而那將造就所有的不同。

來源: 賈伯斯對史丹佛大學畢業生演說 Steve Jobs’ Stanford Commencement Address 2005

2, 掌握基礎的開發能力

(以下會出現很多陳年的技術,我盡可能附上 wikipedia 的說明…)

之後出了社會,前三年都在做基層的工程師的工作。雖然如此,我也是開了眼界。我最主要的收穫,是學到了如何從 “一個人” 寫 code, 進化到 “一個團隊” 該怎麼寫 code…。學生時代,或是研究計畫,大概只要跑得出來就可以了 (我那個年代)。所謂的程式碼可讀性,所謂的模組化,這類軟體工程在意的議題,通常不會是學生時代在意的重點。但是到了業界,程式碼是要拿來賺錢的啊! 當生產力變成指標的時候,這些技巧就開始被重視了。對我來說,工作前幾年最大的收穫,就是在 coding 時學到這些有效率的做法。

其他還包含怎麼切割函示庫,怎麼透過 interface 來溝通,那些都是在這階段累積起來的。細節其實我過去的文章都有提到,我就不在這邊多做介紹。實作技巧很重要的地方,就是你有沒有能力把你想像的東西做出來? 到了業界,很多人都只講求 “眼見為憑”。你能把你想的做出來,活生生的擺在眼前展示給大家看,跟只存在投影片說明的解決方案,有很大的差別。換句話說,你無法端出實體的展示的話,某種角度,你等於把事情的成敗,寄託在別人 (老闆、同事) 的理解能力了,因為他可能只看到投影片啊! 這時如果他還能慧眼識英雄,嚴格的來說厲害的也不見得是你,而是你老闆啊 XDD

工作的前三年,讓我累積了足以跨過這門檻的實作能力,當年在 IE3 的年代,我就能用 DHTML + JavaScript 做出現代 ajax 的原型, 也開始能用 HTML 刻出一些 UI 元件。舉個例子來說,當年我負責的一個專案,就是 “線上影像處理”。我透過 DHTML 在畫面上讓 user 在圖片上選擇要在哪個位子加字,傳回 server side, 用 CGI / COM 元件,在 server side 做好影像處理,再傳回前端,讓 user 可以寄出個人化的電子賀卡… 回想一下,這些事情在 2000 年代要做出來,在實作上是有點難度的。不過在這個階段,我開始被迫研究 COM 的技術是怎麼堆積起來的。

Microsoft 的 COM (Component Object Model) 是 windows 的核心技術之一, 它的前身是 OLE (Object Linkage & Embedded)… 講白一點, 就是在 windows 3.1 那個年代,怎麼做到一份 word 文件,裡面可以崁入一個由 excel 控制的表格, 能在同一份文件內顯示與編輯。別小看這技術,如果你自己不靠任何 OS 或是 framework 的協助,要從無到有弄出來,可不是那麼容易的一件事啊! 那時花了時間,研究 IUnknown 這個 interface 到底是什麼鬼,花掉了我幾個月的時間。不過我也開始體會到,存在語言內的 object, 跟存在於 binary code 的 object 在設計上到底有什麼差別了。COM 的其中一個目標就是建立 binary 世界的 “物件” 規範,讓你用 C 寫一個物件,可以被 VB 使用,這種跨語言的溝通就堆砌起 Microsoft Windows 的整個應用程式的開發框架。

我只能說當年念書學的 OOP, 研究所時代學的 OODB, 還有這些 OLE / COM 的基礎,大概就足以搞定現今一堆 Microservices 分散式溝通的設計問題了 (這有點扯遠了,以後有機會另闢專欄再來聊聊)。

3, 有計畫的累積設計與開發能力

離開了純工程師的角色後,我來到一家新創的小公司。當年 2000 年成立,我 2001 就加入了 (然後一待就待了 15 年 XDD)。在這間公司,我們有自己的產品線,開始有 “架構設計” 的期待。產品跟專案的區別,就是你必須要顧好 “設計” 的品質。因為不顧好品質,賣得越多套,維護與服務的成本就會越多… 包含服務的設計,跟系統的設計都是。簡單的說就是要控制技術債的累積就對了。

雖然公司不大,但是身為 tech leader, 我開始要面臨各種技術的抉擇。比如當年處理 e-learning 需要運用大量的 XML data, 那我到底該選用成熟的 RDBMS? 還是選用當時很新潮的 XML database? 當時正是 ASP (沒錯,就是 ASP, 不是 ASP.NET), 還是選擇才在 1.1 的 .NET Framework + ASP Web Form ? 我該選擇大家都在用的 vbscript, 還是選擇 jscript 來寫 ASP ? 我該…… ?

不館我做了任何決定,接下來所有的 RD 團隊就都必須按照我選擇的技術把所有功能開發出來,如果你怕事後被抱怨決策不佳,唯一的做法就是把這些技術弄得更清楚 (不是更熟練),你才能做出相對正確的決策。包含趨勢有沒有壓對邊? 技術選擇有沒有延續性? 團隊容不容易上手? 招募是否容易等等議題上。除了選擇新潮的技術之外,也開始知道規劃的重要性了。我就列幾個當時我做的重大決策:

  1. (第一版) 採用 IIS + ASP, 搭配 Tamino ( pure xml database ) 為基礎的設計
  2. (第二版) 決定採用市場接受度高的主流技術: IIS + ASP + MS-SQL
    • 自行實作 XML-RDB 的 ORM, 降低轉移 DB 的結構衝突 (有太多 XML 的資料必須轉移到 SQL, 當年還沒有 XML for SQL 的支援…)
    • 核心元件用 COM 包裝共用, 頁面的 JScript 只處理商業邏輯, 系統的核心用 COM 來封裝
    • COM 元件的開發捨棄成熟通用的 VB6, 也捨棄複雜門檻高的 C++, 改用 C# 搭配 CCW (COM Callable Wrapper), 簡單的說就是用 C# 開發 COM 元件讓 ASP 呼叫就對了

事隔多年,因為當年做了這些準備,ASP 已經不再是主流,因為核心邏輯早就是 .NET based, 因此要從 ASP 轉移到 ASP.NET, 就沒有那麼痛苦了。因為有這層互通性,當年也有辦法做到將 ASP / ASP.NET 並存在同一個 site 上, 並且也能互通 session. 這也許不是個漂亮的架構,但是達成了平順的轉移技術的目標。

這段的經歷,其實還有很多大大小小的技術決策 (我就不一個一個說明了),很多擔任架構師必要的基礎能力 (就是技術決策啦) 就是這個階段訓練出來的。說是訓練,其實實際上都只是撞牆的經驗而已。因為也沒有教練或是前輩在教我啊,都是自學,跟參加各種社群活動找人討論累積起來的。但是也因為經歷過這些技術決策的過程,同時也親自替這些決策做出實作,以及轉移的規劃,對大型系統背後運作的原理都有一定的掌握了。

在這個過程中,學什麼其實都看當下的情境而定,真正重要的是你要有能力靠自己學習 & 改善。現在回過頭來看,最重要的是這件事啊! 學習成長的過程如果無法跟外在因素脫鉤 (例如你一定需要有人指導你,一定須要老闆送你去受訓,或是需要回學校念書等等),限制住你能力發展的就是外在因素了。如果你能在年輕時先讓自己有能力自學,往後限制祝你能力發展的才會是你自己的想法。

我自己抓了幾個關鍵:

  1. 基礎知識 (前面講過了)
  2. 實作的技能 (至少能自己啟動練習的最低要求),你至少該有全端的能力 (60分就夠,不用精通),你練習時才有辦法前後兼顧
  3. 抓出關鍵問題(或是知識),自己建立練習的環境,專注解決問題

這循環一旦能夠建立起來,並且變成你自己的習慣的話,那恭喜你了,你開始有資格選擇你想要成為哪種人了 :)

4, 培養其他的經驗與能力

隨著年紀虛長,某次公司改組,突然之間名片的 title 就從 tech director 變成 CTO 了… Orz, 從此也開始碰到更多公司層及決策,以及管理與營運的議題了。我們當時的系統,應用的領域跟 HR 人資的領域有沾到邊,加上角色的轉變,硬是被迫跟一些顧問學了不少人資及管理相關的內容。說實在話這些都是技術人員沒興趣的議題啊… 但是還好有當年刻意惡補這些 know how, 即使擔任管理職不是我的專長,但是至少這不會是我的阻礙了。我也可以開始從管理的角度,回過頭來思考大型系統該怎麼設計,才能符合組織的管理要求等等角度,來檢視設計的合理性。這些關聯,都是在當年完全沒有想到的…。

我就跳過這段枯燥的管理專業到底都學了什麼好了 (我也只是入門而已) XDD,我直接舉幾個對我開始擔任架構師之後的影響。因為開始有點概念該怎麼管理好團隊的績效,因此用在技術的推廣也有些幫助。大家談的很起勁的 DevOps, CI/CD 等等, 其實背後都是管理議題。 例如:

  1. 我在 2019 DevOpsDays Taipei 提到軟體部署要從三個層面 ( code + infra + config ) 的觀念, 其實就是看了國外大師的設計, 從組織管理的角度也能對上不同團隊的職責怎麼透過系統整合起來而得出的結論。開發團隊負責的就應該是 code, 而執行的環境就應該是 infra 團隊的職責, 至於 release 則是最複雜的部份,每家公司都不同。但是不管組織怎麼切,總是有一組人要負責 release, 因此這角色就應該把正確的 code 放在正確的環境上。讓 code 能在正確環境下正確的執行 (好繞舌), 關鍵就是 configuration 的管理。想通這些關聯,自然知道你的系統邊界該切在哪裡了 (這是所有導入微服務的人都很頭痛的議題)。但是當你了解組織管理的議題時,這些議題突然間該怎麼做就變得理所當然了…。

  2. 前陣子 (公司自己在 2020/11 辦的 TechDay, 以及 Study4 主辦的 .NET Conf 2020) 我講了一個主題: SLO (service level objective) 的議題, 其實也有異曲同工之妙。整個背後的觀念就是 HR 怎麼看待績效考核跟目標管理的那一套啊! 只是 KPI 從你的業績,變成你系統的服務水準而已… 演講的內容也提到高德拉克的限制理論,其實都是從管理上面學來的應用方式。我要做的只是把管理的概念,用來管理系統跟運算資源的分配而已。因為大部分的工程師缺乏這部分的 know how, 往往系統層面的問題,也都會去找更強大的工具或是更新的框架來解決。不過主要問題都在管理層面啊,用技術來解管理問題,通常會解不乾淨的。

  3. 我自己在部落格上,發表了一系列平行處理調教的問題 (包含 pipeline 等等), 其實換成主管怎麼有效運用人力, 你要怎麼調度人力…, 都是一樣的問題啊! 管人還比較困難 (每個人的脾氣都不一樣,工作效率也不同,連薪資都不同 XDD),相較於系統,只要規格一樣的 VM 價格就一樣了,部署的系統版本一樣,能做的事情就一樣了,相較人的管理時在簡單太多了 XDDD, 剩下的就是把資源管理的技巧,抽象化成系統可運作的流程,把它寫成 code 就完成了。

其實其他還有很多例子,我就不一一的列舉了。能把管理觀念,融合到系統設計,除了這兩個領域的基礎知識之外,串連的最重要關鍵就是抽象化的能力了。沒有足夠的抽象化思考能力,你永遠不會覺得管理學跟工程有什麼交集。常看我文章的人,或是待過我的 team 的人,大概都知道我很要求抽象化思考,就是這個原因。很多人跟我閒聊的時候,都會問我碰到問題怎麼能想出這些解法? 其實就是這樣想出來的啊 XDDD, 剩下的就是你的 coding 技巧是否足以掌控它而已…。當你很清楚知道你要的 solution, 你自然會知道在技術上你還缺什麼;這時有計畫的去補強你缺的 skill, 會比亂槍打鳥看到新的就學, 來的有效率, 也更為精準。

架構師 該累積什麼經驗與能力?

我不斷的強調 Steve Jobs 這段話,意思是就連我自己,在當年也真的不曉得學這些有什麼用,我只是單純相信,只要花時間學就要學到位,以後總有一天會派上用場的。事實上,確實做到這一點,遠比依賴其他人告訴你該學什麼還來的重要啊! 我過去學了 OOP, OODB, OLE/COM, 所以現在有這些能力,不代表現在你也得去學這些知識才能有一樣的能力啊! 現在跟 30 年前不同, 你該學的 “基礎知識” 是要為了未來而用的,不是現在。即使你跟我同年紀,你當年也不見得要跟我走一樣的路線,因為每個人的天賦都是不同的。

不過,即使如此,如果鎖定在 “後端工程師” 這領域;甚至未來你也打算跟我一樣,朝向架構師的路線發展,終究還是有些脈絡可循的。我給大家一些原則跟方向,但是具體的內容,則各位應該試著自己去尋找:

  1. 請盡量累積資訊科學相關的基礎知識 (例如資料結構、演算法、作業系統等等)
  2. 請盡量累積軟體開發相關必要的知識與技巧 (例如 TDD, DevOps, 抽象化, OOP, Cloud Native, Security 等等)
  3. 請具備基本的管理能力,不管你是否要走管理職
  4. 請盡量累積特定領域 (domain) 的知識與技能
  5. 學習的過程中,持續將學到的知識嘗試與其他知識連結起來

這些能力,請切記,不是越多越好,而是越專精越好。知識的 “點”,你功夫下的不夠深,你是沒有能力把他跟其他 “點” 串連起來的。我在 Study4 這場演講裡面,我分享了我自己的歷程。各位可以盡可能用客觀的方式,觀察一下職場的需求是那些? 尤其你可以特別關注一下你心中認為理想的職缺,人家要求的條件是什麼 (沒有叫你真的投履歷,你不用擔心你到底符不符合)。這些資訊,在人力銀行上面其實都是公開的,你只要註冊個 104 帳號就看的到。

以職缺的說明為出發點,多少能夠勾勒出你理想工作必要的技能有哪些。接下來我試問幾個問題:

  • 我需要現在就會每一項技術嗎? (反思: 我有可能每一項都學嗎? )
  • 如果不會的話… (反思: 我多快能學起來? )
  • 比起學會這些技術,更重要的是什麼? (反思: 我應該怎麼運用這些技術 )
  • 怎樣才能算是 “熟悉”這項技術? (反思: 怎樣才能算是 “精通”? )

前面是表面的問題,後面的括號,才是你該思考的。與其你把每一項技能都很快地學起來,那可能是囫圇吞棗而已。如果你不可能每項都學精,那下個問題就是當你需要的時候,你多快才能學得起來? 這就呼應到前面我說的,基礎打好遠比學的多還來的重要。尤其時間拉越遠越看得出差距。比起學的多,學的精還更重要,因為了解夠透徹你才能靈活運用。

套句在 HR 領域學來的技巧,客觀的評估你是否夠 “精通”,其實有些指標可以參考的。 以職能評量的角度來看:

Lv 0. 代表 不具備該項能力
Lv 1. 代表 我知道該領域的知識
Lv 2. 代表 我知道該領域的知識並可以獨立操作
Lv 3. 代表 我可以擔任講師並教授他人
LV 4. 代表 我可以獨立解決和改善問題

這是從某分評量表上面抄來的。你可以用這方式來評斷你所謂的 “精通”,是不是別人眼裡的 “精通” ? 就我認為,任何一項技能或是知識,至少都要到 (3) 以上才能算是精通。因為你至少能開始教受這項技能,你才有可能藉由準備、教導、接受問題或回饋、自行找出答案,才達成自我改善的循環,你才算真正跳出需要依賴別人帶領才能進步的限制。

舉個例子來說明好了。公司內部我們負責的一套系統,需要深入的了解 Rabbit MQ 設定跟管理的細節,我就以 Rabbit MQ 來當作例子,說明每個 Level 應該有的行為表現:

LV2:
我會 Rabbit MQ, 代表我知道如何安裝、設定、管理 Rabbit MQ 服務;我也知道如何透過 C# 將 Message 送入 MQ, 也知道如何將 Message 取出處理。 基本上就是知道 Rabbit MQ 是拿來幹嘛用的,同時有能力正確使用他的 SDK,基本上就具備 LV2 的要求了。

LV3:
我了解什麼情況下需要用 Message Queue 來解決非同步任務執行的問題;我知道 Rabbit MQ 的特色: Exchange / Queue 的組合與應用,何時該用 Fanout, 何時該用 Topic。基本上你對 Rabbit MQ 已經有一定的了解,如果你的團隊來了個新人,你除了自己會用之外,也有能力開始跟新人說明介紹 Rabbit MQ 的概念與操作。

LV4:
Rabbit MQ 適合用來處理 “生產者與消費者”問題,非同步任務產生後可以交給 MQ 處理,不需等待回應可以繼續後面的動作,而另一端可由 Worker 負責消化任務。MQ 後端可以善用平行處理的技巧,提高整體的處理能力,也能同時用多個 Worker 分攤處理的任務。每個 Worker 都能夠以最佳效能運作,處理完畢後才領取下一個任務,輸出穩定,不會受到瞬間大量所影響,這種情況下能達到最佳的處理效能。


回到知識平等,你需要將自己提升到 (3) 以上的另一個原因,就是連結。LV(3) 以上的知識,你才開始有連結的本錢。低於 LV(3) 的技能,大概只能應付需求,還不到能靈活運用的階段。當你對某個問題越理解,一定伴隨著你對這問題的原理越清楚。我反問一個問題,你如何知道你已經對某個領域了解到不能再了解了? 人外有人,天外有天;問題在於在當下,你是否知道在這領域你還有不知道的地方? 這就是 Ruddy 老師常在講的 “無知的無知” - 你不知道你不知道些什麼。既然你不知道,你該怎麼判定你現在的狀況是不知道?

又再繞口令了… Orz, 我自己的作法是這樣: 我認為所有的知識,背後關聯的知識一路往外推展出去,最終一定會落在某個基礎科學為止。當你想在一團迷霧之中,搞清楚自己是不是還在無知的階段 (好像火影忍者裡面的忍者,怎麼判斷自己是不是中幻術… 或是電影裡面的李奧納多會拿出陀螺來判斷一樣),就試著在腦袋裡想像,你有沒有辦法自己從無到有打造出某項技術出來? 當你想通怎麼做,就繼續往下推衍,直到推演到該領域的基礎知識為止。這方法有助於你了解自己還缺了什麼技能。你不用每項都把它補齊 (你時間一定不夠用的),但是你至少把地圖打開了啊! 你至少知道某個地方有你還無法突破的關卡,你就知道該準備什麼,或是到哪個等級才能再去攻克它。你也開始有機會掌握全貌,知道攻克它之後就能解鎖那些其他更高階的技能。

開地圖 (星海爭霸的用語 XDD) 對於架構師這個角色是很重要的。架構師不是把所有東西實作出來的角色啊,其實不需要精通所有技巧的。但是架構師必須做好技術決策,即使是你不擅長的領域也是。你必須做好決策,讓系統的每個環節都能扣起來順利運作,才是個稱職的架構師。該怎麼做到這點? 在你腦袋裡的知識地圖開的多廣就是關鍵了。知識地圖開的越廣,你在做決策時就會越到位;如果碰到關鍵知識你無法判斷時,你也知道你缺什麼,該找那些技能的專家來協助,或是用周圍的知識來推測包圍。打開了這項能力,你才開始有辦法評估一項你不懂的東西該不該做。知識的連結威力就在這裡,你的角色越接近決策方,你越需要累積這樣的能力。

我該如何培養這樣的能力?

說的簡單,做起來難。你學到的知識或技巧,真正能得到 feedback 一定都是在真正使用它來解決問題後,你才會知道他是否真的有用。不論是你自己用在案子上,或是你教導別人,別人問你問題得到的 feedback 其實都算。如果你有興趣的課題,還沒熟練到可以開班授課,工作上也沒合適的案子可以應用,那怎麼辦?

沒機會練習,就自己創造機會練習啊! 這就是我一直強調的 “刻意練習”。軟體開發的進入門檻,已經是所有行業裏面最低的一個了 (基本上只要你有台電腦就搞定了),但是也是最難精進的一個 (因為複雜度太高了)。跨過進入門檻後,你應該要養成自己創造一個適合練習的環境,你才有機會自己實際練習,取得 feedback. 我舉一些我在這個場子沒提到的案例: Blogging As Code !!

工作上沒機會用的技術,我就用在自己的部落格身上啊! 自己當自己的老闆給自己提需求很簡單的,找個題目給自己做就可以了。這篇文章就提到我自己部落格的每一次改版,驅動力其實有一大半都只是我想玩看看而已。我改版的經歷大致是這樣:

  • 2002 - 土炮 blog (asp.net 1.1 + sql server)
  • 2004 - .Text
  • 2005 - Community Server
  • 2008 - Blog Engine
  • 2015 - Word Press
  • 2016 - GitHub Pages

當年會土炮,我只是想自己試試 RBAC (Role Based Access Control) 啊,當時參加了一些比賽,就拿這套 code 的應用去騙騙獎品,既然都寫了就拿來經營自己的 blog, 接著觀摩別人的 code, 就看到 .Text / Community Server 這套 code; 接著不想花資源養 SQL server, 就發現另一套更漂亮的 Blog Engine; 接著為了看看業界都怎麼架站的,我決定拋開 .NET 的系統,擴大到 word press… 於是又搬了一次家。最後為了把專注力擺在寫作身上,開始研究 Markdown, 還有靜態網站 + 高度整合版控的各種優點,開始轉移到 GitHub Pages, 就一直維持到現在…

中間的過程,可以去看看我 2016 寫的那篇 Blogging as code 的文章。我要在這邊講的是,有想學的技術,就替自己找個能夠練習的場合吧! 只要你能自主創造題目跟環境,你就達成能讓自己 “刻意練習” 的條件了。這些其實跟能力沒有太大關連,跟你的意志力與企圖心有多強有關。就如同前面講的,你自己能形成學習與改善的循環,才是你能真正進步的開始。你能自己學習成長,你的進步幅度就不會受制於環境或是導師。否則你總是要靠著前輩帶領,那你不就注定任何事情最多只能做到第二名嗎?

常看我部落格文章的朋友們,應該不陌生,我不定時都會丟出一些架構練習題。其實這就是我自己練習的方式,我除了自己練習,這幾年也開始公開,讓大家發 PR 一起練習同一個題目。我也可以藉此得到別人的靈感,一舉數得。這是我的方式,提供給大家參考。我在這場演講的 slides 也舉了幾篇文章當例子,我另外拿一個案例來說明。我拿我兩年前寫的這篇文章來說明:

後端工程師必備: 平行任務處理的思考練習

在這篇文章內,我帶著團隊的成員,跑完整個過程了。也因為跑過這整個過程,團隊成員開始有能力設計及開發處理全公司大大小小 (約有 200+ 種) 不同的批次/非同步任務的管理系統。我引導成員練習的順序是:

1, 用 code 定義問題 (POC)

既然是軟體開發領域的練習,學習用 code 來溝通是我一直認為很有用的作法。透過 code 來說明自己的想法,遠比用語言來的精準多了。TDD 就是個很好的示範,寫的好的 test case (搭配註解), 其他人一看就知道你的 code 該怎麼使用,會有什麼預期的執行結果或是錯誤代碼。短短的 test case code 不但能驗證你程式碼的正確性,同時還兼顧了良好的說明文件用途,就是個代表性的例子。 我這邊更進一步,先用 code 來呈現你想解決的問題本身 (在這篇文章的例子裏就是要依序執行三個步驟的 Job)。有了 code, 一切溝通就會變得精確了。問題有沒有正確解決掉? 看測試或是結果就知道。解的好不好? 看指標就知道。

2, 定義評估指標

當問題已經用 code 定義好之後,剩下的一切就都變得清晰了。你可以透過單元測試或是其他測試的技巧,來驗證你的 solution 結果是否正確。不過指標的用意則是更進一步,判定你的程式碼執行的好不好。最簡單的指標就是執行時間,他直接代表了執行效率。在這篇文章內,我對於 “好” 的定義是丟了 1000 個 task 給你,你能多快處理完畢? 我定義了第一筆處理完成的時間 (TTFT, Time To First Task), 最後一筆處理完成的時間 (TTLT, Time To Last Task), 平均處理時間。至於我為何挑選這些指標? 可以參考這篇文章的段落: 品質指標的挑選

3, 將解決方案抽象化

下一步,先別急著一次到位,把理想的 code 寫出來。切忌這是練習,不是工作。通常會需要練習,代表你的能力還無法完全駕馭這個題目,這代表你有越多機會了解細節越好。我自己的習慣是,面對問題,我願意先多花一點時間,先寫一個簡單,評估指標可能不是那麼理想,但是結果一定正確的版本。其實 TDD 也有類似的觀念,你先寫一版能通過測試,然後再不斷的重構,藉由 test case 保護你的每次重構的執行結果都跟先前一樣,讓你能穩定可靠的改善程式碼的品質。

我把同樣的觀念用在練習。先寫出一版能通過測試的版本,紀錄評估的指標。先做到這一步之後,再開始不斷地修正改善你的程式碼,在維持結果都是正確的前題,你每次的調整都可以透過指標來告訴你,你的修正有沒有比前一版還要更好? 這些練習的回饋其實很重要的,你先把這練習的環境搭建起來,你就等於有個盡責的教練在旁邊指導你一樣。你不論想到任何天馬行空的解決方法,你只要試著把你的想法寫成 code, 剩下測試會告訴你結果對不對,指標會告訴你評估的結果夠不夠理想。每改一行 code 你都可以得到精確的回饋,你就會知道每一個改變,到底對結果的影響是好是壞。

這回饋的資訊量是很豐富的,你確確實實作完一次練習,你對這個題目的掌握,勝過聽講師講十次還來的有用。透過肌肉學習是最好的練習方式。也唯有你有能力自己建立練習的環境,你才開始有真正有效率的靠自己就能進步的循環。當你能做到這個地步,你就不需要再依賴老師了,靠有系統的自學的效果更好!

4, 思考理論極限

前面的步驟一開始會很有成就感,因為你會不斷的進步,看到指標不斷地被改善…。但是,你要改善到哪裡才該停下來? 改善 2x ? 5x ? 10x? 這沒有絕對的答案的,這時,理論的基礎開始變的重要了。我自己的作法是,當你對問題理解到某個程度時,你就該開始靜下心來,好好整理思考背後的邏輯了。並且想一想,這個問題最理想的指標會落在什麼地方?

知道理論極限,是很重要的。理論極限代表這個問題指標的極限,是改善幅度的天花板。你再怎麼改善,都不會超越這個天花板的 (除非你想錯了)。有了天花板的指標,你才知道你現在有多接近理想值了。你如果不知道滿分是多少,那你會知道考了 99 分是好是壞嗎? 滿分 100 分,跟滿分 1000 分的結果完全不同啊! 如果我知道滿分是 100, 可能考 99 分我就滿意了;但是如果滿分是 1000, 那就代表我還有很多努力空間。

試著透過前面累積的經驗,理出脈絡,把指標的理論極限想清楚,這時你才知道不斷的循環改善到哪邊可以停下來。做好這練習,不但有助於你想清楚問題背後的脈絡 (想清楚才能推論出極限),你也能決定停在哪邊是最有效益的。不斷的練習可以讓你的 skill 技巧提升,但是思考天花板則可以幫你補足理論的基礎。這兩者不平衡就很可惜,你會很容易碰到障礙;一種是理論派的,想得出來但是做不出來;另一種是實做派的,寫很快但是理論基礎不夠到位。不論哪一種都有發展的極限,最好的方式是每當你學習一個新的領域的時候,同時兼顧這兩者。練習的過程就不斷的配合思考,找出理論極限,同時不斷改善你的實作,逼近理論極限。兩者並進你就能兼顧。

5, 找同伴一起練習

最後一步,就是別閉門造車。軟體開發很吃想像能力的,有時候就是有人會用你意想不到的方法來解決問題。即使你的思考程序都正確,有時缺了那靈光一閃,就是沒想到的作法,你再怎麼重構都重構不到那條路上的。這是外來的刺激就變重要了,找人一起參與練習的過程是個好方法。就像生物演化也需要一些突變一樣,有基因突變才有演化的機會,即使突變大部分都是缺陷,但是一但有好的突變,就能透過遺傳延續下去。找人一起練習,互相觀摩也有同樣的好處,整個群體只要有人想到一個好的做法,其他人都能受益。

這時最重要的就是怎麼讓互相觀摩這件事越容易發生越好了。當練習的程序被系統化之後 (有 code, 有指標, 有測試),你就很容易能找別人一起練習,互相觀摩解決方式。如果都是公司同事,可以用讀書會的方式互相切磋,如果互不認識,可以透過 github 發 PR 交出自己的 solution, 大家可以互相觀摩對方的 PR。如果 (1) 已經能用簡化的 code 表達要解決的問題,那麼對應的 solution 也能很精準的瞄準問題,不會有太多外在環境因素的干擾,要互相觀摩也相對的容易。如何創造一個更容易切磋的環境與方式也是很重要的。


上面幾個步驟,就是我常常在內部團隊推動練習的方法。其實我的重點都在於怎麼啟動練習到改善的循環。一個是前面提到,你至少必須先具備基本的全端開發能力,你練習的方式才不會受限。在來就是你要有一套方法,能把面臨的問題,轉化成可以練習的形式。兩者具備後你就開始有自學的能力,能自己解決問題。你的成長不受外面限制時,限制你的就只剩下你有多努力了。

自己驅動自己練習,很多時候就像寫測試一樣,你也許會覺得要另外寫 code 來練習是很浪費時間的事,直接用工作上的 code 來分享跟練習不是更快嗎? 不過,試過你就知道,好的練習方式跟環境,會讓你的練習更有效率。效率來自排除不相干的雜訊 (你要寫出 solution 的門檻就降低了),也讓瞭解程式碼的阻礙降低了 (你不用花時間找出關鍵的 code 在哪裡,整個 project 就是關鍵的 code)。因為夠簡單,你要嘗試不同的解決方案也變得容易了,你要評估成效也變得容易了。多寫一點 code, 換來這麼多長期的好處,值不值得? 你試過就知道。

我該如何用在工作上?

我忘了在哪邊看到這段話了 (有人知道出處麻煩告知我),大意是這樣:

老闆請你來工作,是要你解決問題的。在生產環境上面用你掌握度不夠的新技術是不負責任的,因為你可能無法掌控風險跟額外衍生的支援成本。負責任的做法是: 用 side project 的方式熟悉新的技術,然後再把它用在生產環境上。

其實這跟我用的練習手法有同樣的意涵啊,多練習多嘗試是好事,你的能力才會成長;但是在不能冒險的環境上嘗試你沒把握的技巧,你就不夠專業了。兩者兼顧的方式就是自己創造友善的學習環境,得到經驗能力後再套用在正式的專案身上。

基本上,依循這樣的模式,反覆幾次你應該就有能力應付工作上的需要了。如果你是團隊的 team leader, 我會建議適時的推動這樣的循環:

  1. 用成熟可靠的技術,推行正式的專案。
  2. 專案執行過程中碰到的困難,挑出有解決價值的部分,用獨立的 code 來表達 (或是重現問題),並定義好評估的指標
  3. 用練習的方式,找出 (2) 的 solution, 只要夠簡單夠快速驗證,可以多試幾種方法;讓你的 team member 能在這環境內充分練習與理解,找出理想的 solution
  4. 在下次的改版或是迭代,將系統重構成新的架構
  5. 如果還有需要改善的地方,重複 (1) 的步驟。

其實說穿了不值錢,就是不斷的做同樣的事情而已。練習不就是這麼一回事嗎? 你只要熟練把問題變成練習,練習後的成效拿來改善問題,並且不斷的驅動這樣的循環,如此而已。

給各位的建議

零零總總寫了一堆 (其實這場演講也只有 50 min 而已,我卻打了這麼多),我想不缺例子了,我整個部落格的內容大概就是我過去 20 年親身經歷…。我把前面講的那些原則,收在最後這頁 slide:

能力的培養,真的沒有速成的。如果你想問我怎麼一步登天,那我也給不出答案 (我自己都辦不到啊 XDD)。如果我現在具備的能力,是你想學到的,那可以參考看看我過去的路線。關鍵還是一個,也是這系列的主題,請朝自己的目標,找題目讓自己能夠 “刻意的練習” 吧! 學習沒有什麼捷徑的,如果真的有,那你身邊早就一堆高手了。如果真的有捷徑,那你也要想辦法讓你自己成為 “找到捷徑的人”,而不是被告知捷徑在哪,真正去抄捷徑的人。唯有這樣你才有可能在某個領域是第一把交椅,而不是永遠的第二名。

每一次的練習,除了挖深之外,也請同時把連結弄清楚,知道他跟其他知識的關聯為何。前面說過,這是你自己判斷練習是否夠深入的方法。如果你想要有計劃地培養自己成為一位架構師,那麼技術的深度跟廣度,以及彼此之間的關聯是最重要的。你要多練習,廣度才會夠。每個練習的深度要夠 (要能理解背後的原理並且有能力改善),你才有連結 (應用、改善) 的能力。方法上面都說過了,我就從我部落格的文章挑一些清單出來,以下的這幾篇,都是把幾個技術高度的整合與應用得到的成果。仔細看看這幾篇文章,你會發現看下去都是很基本的知識,但是當你能組合,並且很準確的應用他的時候,就能發揮出不可思議的力量。這幾篇都是我自己實際的案例,如果這些文章你過去都看過了,你可以重新換個角度重讀一次,體驗一下串聯不同領域的知識能發揮的效益有多大:

最後,如果你缺題目練習,那刷刷 LeetCode 是不錯的選擇。如果你覺得 LeetCode 太學術了,我的部落格有很多篇都是務實的練習題。不嫌棄就盡量取用,文章內容跟 source code 都可以在 GitHub 上找的到。

架構面試題:

後端工程師必備:

以上就是這系列的第一篇,拖了將近半年 ( 2020/08/24 演講,到 2021/02/28 才寫完這篇 XDD ) 才把文章補完。比起演講,我還是習慣用文章表達我的想法,我也趁著文字化,把當時沒講的內容補上了。不論你當天有沒有現場聽我演講,都歡迎重讀一次文字版的內容。有任何 feedback 也歡迎跟我聯絡~

類似主題 “刻意練習”,我在 2020/12 的 .NET Conf 也還有另一場,講的是抽象化的練習過程。按照我寫文章的速度,應該再等…..一陣子就會看到文章了吧 XDD, 敬請期待~






Facebook Pages

Edit Post (Pull Request)

Post Directory