My life as a CTO — Technology (Daily Work)

Jocelin Ho
21 min readApr 17, 2024

--

Getting a companion is always nice. (photo credit: midjourney + my prompt)

ok, 你順利的挺過了Day 1,開始想著接下來手上的一百件事情,到底優先順序該怎麼排?身為Tech leader,雖然你很有可能非常喜歡寫code,但若團隊中已經有優秀工程師能協助開發,就必須要先更專注在其他high level的事項上。因為這是其他人相對比較難幫助到你的工作,不管是因為你的位子、你的經驗、或是你對公司的Context,Tech leader做這些事情的價值會相對更高。

這篇文章讓我們來談談這幾年我身為CTO的經驗裡,我認為在Tech方面做的對公司相對價值較高的工作。Don’t get me wrong, 這不代表你只需要做這些事就好,舉例來說,我還是花蠻大一部分時間在做開發寫code,尤其是人力比較不足的時候,不過以下挑出的三個項目: PR Review, Monitoring, Tech spec review,是相對更責無旁貸,也是我幾乎day to day都在做的事,順便藉這個機會與大家分享我個人這幾年的心法。

Daily Work: PR Review

PR Review是工程團隊互相合作不可或缺的關鍵因素之一,但我發現這件事情好像很少被系統化的規範。PR review效果的關鍵跟PR裡code”以外”的東西有很大的關係,這邊我先撇開code本身不談,專談code以外的其他面向,也就是一個好的PR該有什麼樣的特性,也可以給Tech leader做為團隊的規範參考使用。

  1. 長度

在請別人做PR review時,其實就是在要求別人理解你在做的事情,而理解的過程就必定牽涉到短暫記憶,reviewer要用大腦的工作記憶暫時記得你的PR某處的邏輯,上上下下滑動過程再隨時提取、融合、拼湊出你想表達的意思。但人類的工作記憶是出了名的爛,一旦你的PR長度太長,超出reviewer能記得的範圍,reviewer要嘛直接放棄理解,要嘛只能很草率地大概理解,沒辦法給出很深度的建議。一般來說我的建議是200行上下,超過200行的PR就建議拆解,不要造成別人coginitive太大的負擔,對你的reviewer好一點,下次你要review別人的code人家也會回報你的。

2. Description

Description我發現是大家很容易偷懶不仔細寫的部分,可能是覺得反正code都有寫,你看code就會懂了,但事實上是好的description,能為這個PR建立很清楚的context,尤其是能給出清楚的Why,也就是看code裡最難看出來的部分。這跟一般聊天溝通很像,如果你不先設定好context,對方就需要花更多的時間跟心力去理解,甚至是還需要反問你很多問題,才能理解你的意思。譬如有人跟你說:「請你給我建議」,但沒有說要提供哪方面的建議,告訴你為什麼他想要得到建議的動機(是不是被主管糾正?還是只是要準備面試?),會讓你就算真的想幫助他也不知道從何幫起,或是要花更大的力氣才能把context問出來。有給出Why,reviewer才有機會幫你一起看不只是how做的好不好,也許解決why的方式也有更好的做法。

3. Test Plan

在推PR之前做足夠多的測試我認為是author的基本工作,而能夠showcase出你測試的東西也能的大大增加reviewer的context,減輕理解的負擔,我最建議的test plan description是使用影片,如果是UI的部分當然就是showcase你做的成果,但就算是後端也可以用螢幕錄影的方式讓reviewer看到你是怎麼測試的,包含打API跟看到結果的過程等等。另外,如果時間允許,我也會建議補上before & after的比較,有時有看到差異化才更能知道這個PR的目的到底在做什麼。

以上這些都可以使用Github的 pull_request_template 來做,每個PR都會自動帶入你希望其他人填入的格式,再強硬一點甚至可以要求沒有寫足夠詳細就直接request change,越早期嚴格執行,才能越早把大家的標準都拉到一樣高。

Daily Work: Monitoring

我認為CTO,一個責無旁貸,沒有任何人應該要幫你做的工作就是monitoring。Monitoring就像健康檢查一樣,只要確保健康檢查沒大問題,身體要在短時間出現大問題的機率也會比較低,如果有任何慢性疾病的徵兆,也只有在有monitoring的狀況下才能找到,若不幸的真的出了大包,你也能夠藉由Monitoring找到過去到底發生了什麼事的足跡,不然永遠都只是在跟運氣下賭盤,看誰命比較長。

以Web Service後端來說,要monitor的東西不外乎幾個:

  1. Server health

up time通常大家建議至少要抓在99.99%,也就是一年只有最多52分鐘掛掉,但實務上來說,我其實認為startup追求這個up time不是很實際,除非你的服務就是主打high availability,因為startup就是沒那麼多資源,尤其像Cooby的服務容易受到第三方影響而跟著被改壞,如果critical的問題發生在半夜,我們也沒有足夠多的工程師輪班在半夜把東西修復,如果所以在這種狀態下,更重要的是customer support有沒有對接好,受影響的客戶能不能得到足夠多的賠償,然後確保同樣的錯誤不要再犯。當然也不是說這個數字就不用在乎,而只是在新創早期不該是大家花很多時間追求的目標,新創的本質就是不斷的在更新、挑戰改變,如果追求這個up time要在最極致的狀態,那很有可能會拖慢了整間公司的前進速度。

2. API response time

這個指標倒不太有新創 vs 大公司的差別,一般業界的benchmark大約p50在200ms。這個指標通常很難達不到,只要你沒有寫出什麼又臭又長的query基本上以現在的網路速度都不是問題,針對API response time比較需要擔心的通常是p95,或是p99的數字。如果你的p50很美,但p95一直在很誇張的數字,例如三秒五秒以上,那可能就是個潛在需要解決的問題,這代表你的service設計在某些user的使用上體驗非常差,而這些user其實很高機率是你的重度使用用戶,或是資料量很大,這種問題就是在time managment metrix上面,典型的重要但不緊急的問題。API雖然慢,但不會不work,長期下來卻可能會有很大的隱患,使用者體驗絕對是最嚴重的第一名,使用者體驗差就像慢性病一樣,很少人會馬上氣到去投訴customer support,但久而久之你在其他地方培養的正向情緒會在不知不覺之間被磨損耗盡,甚至是讓使用者跳槽的推力之一。另外,這個目前只在p95會看到的問題,其實很高機率會在的你服務越來越大、用戶越來越多之後開始擴張到p75,甚至到p50都被影響到,那就不再是「少數人」的問題了。一旦看到p95有不正常的數字出現,建議要high pri著手處理,確保有被排進近期的工作項目之中。

3. Error rate

這個應該就不用我多說了,有噴error就是代表有地方有問題需要修復,這句聽起來像是廢話,但在每天被例行性事務淹沒的工程師日曆中,這件事卻很少有辦法被落實。關於噴error這件事,有一個我認為很重要的觀念:沒打算處理的error就不要噴,或是不要噴成error

這其實就是放羊的孩子的概念,一旦狼來了叫太多次,真的狼來的時候就不會有人注意了,但是在implementation的時候,其實很容易會習慣在handle error時自動就把所有error都噴出來,但如果噴一些根本沒打算要處理(譬如是第三方的問題)的error,其實就是讓monitoring變混濁,導致真正重要的問題看不到。所有有噴的問題都要及時被處理,我認為是在做error handling的時候的中心原則。不過,剩下那些沒打算要馬上處理的error也不代表他們就應該要fail silently,而是應該要用不同的類別(ex: info),或是不同的priority來上tag,仍然保有能夠知道這些問題的空間,但不會影響到最high pri的errors。

  • 舉個例子,400 vs 500 的error就應該要分得很開,就定義上來說,400是client端的error,其實就是所謂後端「沒打算處理的error」,在做monitoring的時候就不該被定義成critical,且這些error本來就是有可能存在的。反觀500的error目標應該是降到0,也就是需要被及時處理的問題。
  • Error code的重要性:後端若收到client端的問題,仍然需要有辦法告知使用者是遇到什麼問題,在UI上才能讓使用者有retry的機會,此時前後端的error code溝通就很重要了。這其實也是在前期開發時非常容易忽略掉的部分(畢竟人總是相信happy flow一定會work),但這個溝通如果能早期就把規範定義好,會大大節省未來還要做refactoring的時間(你終究要定義error code的,那為何不一開始就認命寫好?)。在初期偷懶的時候很容易會讓前端直接顯示出後端回傳的error message,但我跟你保證,那些東西真的不是拿來給使用者看的,實在是用過太多服務在噴錯的時候噴一堆程式碼,看得我頭好痛。請在一開始就把前後端的error code定義好,且在前端寫好要讓使用者看到能retry的訊息,好好對待願意花時間在你的服務上的使用者。

4. Database health

這幾年下來的心得,我覺得DB根本可以說是後端服務的命脈,很多時候API response time的bottle neck也就在這裡。Cooby有好幾次整個服務掛掉都跟DB脫不了干係。需要被監控的數據包含但不限於:Query response time, number of connections, transaction rates, disk I/O, CPU, memory等等。DB只有一個工作,就是讓你寫入跟拿取資料,但如何拿得好拿得巧拿得漂亮,就取決於你的DB設計還有Query的寫法了。

  • 這邊可以跟大家分享一個我過去踩過的雷,大家都知道設計DB時要好好設計index,沒有index的DB就像沒索引的字典,不拖垮整個DB performance才是奇蹟。我相信沒有任何一個工程師在設計DB時不會設計對當下最好的index,但是,麻煩的是requirement會變,feature會演進,更重要的是,人會離職,雖然一開始設計db & index超有效率,只要經過足夠多的時間,還有你的產品有足夠多的演進,任何東西都是會被改變的,而這時候就考驗前人的設計能不能被好好傳達,且後人能不能輕易的pick up了。我們過去踩的一個大雷就是根據產品需求做了調整,意外地使用了沒有被index的column做query,但是大部分的使用者因為資料量不多,尤其是在測試環境裡根本不會發現這邊performance有問題,直到productionize一陣子後,默默辛苦在工作的database終於承受不住直接爆炸,這一個小query拖垮了所有主服務,我挖了好幾層才意識到是這個問題,加上index之後所有response速度直接快10倍以上,典型的一行code解萬個問題。雖然我目前為止也還沒想到好的解法,但最好是能在交接或是人離職之後,還是能不靠人工的方式做好這些檢查,才是能避免這些大問題的解方。

Bonus: Hyrum’s law

With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.

雖然跟上述不完全有關係,但剛好想到就在這裡也分享一下。這句話是出自 Software Engineering at Google這本書,由Hyrum Wright提出,大意是只要使用你的API的用戶夠多,不管你在API contract上promise哪些東西,任何觀察得到的pattern都會被拿來depend on。白話文的意思就是不管合約上我保證我會做到哪些事,只要你的API有出現過的重複特性都會被人拿來用,舉例來說,如果你的API並沒有保證output會是sorted,但因為implement的方式,大部分的狀況都會是sorted,那這個特性就一定會被未來的某個API使用者依賴,導致你不得不一直維護這個特性。

這個特性其實也不是壞事,只是API開發者必須要清楚知道這件事,不僅僅需要維護contract提到的explicit rule,連implicit rule都需要非常重視,或者是可以的話就把所有的implicit rule都當成explicit rule,直接定義清楚。

Monitoring Service

市面上最廣泛被使用的web monitoring service應該還是Datadog,我個人其實也只有用過這個,我覺得他的服務非常齊全,使用者介面也簡單易懂,從很粗略的大方向數據,到最detail的細節都有辦法monitor。我自己最常使用的就是Dashboard & Alert,Dashboard就是花一點時間把我重視的數字都搬上去以後,時不時上去看一下,如果公司有大螢幕能投放的話Dashboard也是非常適合投出來讓大家照三餐一起幫忙監測,而Alert的功能就是定義出你最關心的metric的threshold,譬如p95 API response time如果大於5秒、Error rate在X分鐘的區間裡多於Y%等等,就會發個通知串接到slack上,讓這些error主動來敲你,敲得你心裡發寒,半夜都會驚醒趕快爬起來修。這也是為什麼我前面很強調只有打算要處理的error才應該要有這些alert,不然如果你太常被不重要的問題叫醒,我跟你保證你很快就會不理這些任何的error了。至於threshold要怎麼設我認為是每個公司要自己根據自己的使用者特性來設計,通常也不可能一次到位,都是要不斷的try and error才能夠找到最符合的甜蜜點。

另外一個非常常使用的monitoring system就是AWS的Cloud Watch,雖然大部分AWS的服務(EC2, API gateway, ELB, …)我們都有串接到UI比較好的Datadog來觀測,不過畢竟Datadog的收費機制設計的關係,有些服務串過來會特別貴,譬如Lambda,而Cooby其實非常大量的在使用Lambda。於是刻苦的startup選擇省下這個錢,直接使用Cloudwatch的monitoring做觀測(當然cloudwatch也是要付錢的啦),不過好在AWS對於基本的觀測跟數據保留做的也很完善,如果需要做Slack的串接也可以透過SNS達到,唯一麻煩的是要同時維護兩邊而已。

AWS Cost Explorer

除了server的健康度,還有一個CTO不可能不重視的metrics: 💰💰。就算你的服務再好再穩定,如果是用意料之外的$$換來的那也是大事不妙,尤其是在使用會auto scaling的服務,雖然省去了很多要自己手動建置的麻煩,萬一又忘記設上限的話,這個噴錢的速度很有可能會遠遠超過你的想像。

我們自己實際經歷過的一個case是Dynamo DB的大噴錢,主因是在寫code的時候不小心寫了個bug,沒有發現做了非常多重複的read/write,在測試環境時因為資料量不大也沒辦法輕易發現,而因為Dynamo DB就是靠read/write的數量來收錢的,在有大量的read/write request時他也不會爆掉,而是Amazon會自己做scaling,應付你大量的需求,但這些scaling當然都不是免錢的(邪惡的AWS!),越方便的東西越危險,如果沒有做好即時的監測,很可能在你完全沒發現的時候錢錢已經悄悄的全部飛進AWS的口袋,一去不復返了!另外一個容易默默噴錢的服務是lambda,如果沒有設定lambda上限的話,流量一大或是又不小心有bug的時候,因為AWS會盡量避免throttle,會嘗試起非常多的lambda,讓你的帳單增長速度暴增,更危險的是如果你的lambda有跟Database做連結,預期之外大量lambda的request衝進去,很有可能直接拖垮整個DB(沒錯,這也是我們的親身經歷)。

一次經驗一次教訓,在這次事件發生後我才意識到這些事的重要性,分享給大家,這世界上已經有太多坑可以踩,能聽著前人慘痛的教訓躲一個是一個!

Daily Work: Tech Spec Review

“There are no right or wrong answers in architecture — only trade-offs.”
- Neal Ford

Software design就跟所有的design一樣,it’s more of an art not science,解決問題的方式永遠都不只有一種,也絕對不會有完美的solution存在,絕大多數的時候就是各種tradeoff之間在做抉擇而已。

不過這不代表software design就不需要經過檢視,人總是會有盲點,負責做design的工程師肯定是思考過最多,也很可能是在該領域最專業的人,但有些盲點或更高層的組織目標並不是工程師的context有辦法看到的,這時候tech leader就是最好的角色來提供刺激跟補充context,激發團隊思考的夠深,也確認大部分能想到的狀況都有被考慮到了。這邊強調一下,我不認為leader是要負責給出所有答案的人,更重要的責任反而是落在能不能問出好的問題,能不能激發團隊討論,還有能不能注意到還沒被發現的問題。畢竟沒有人能夠專精所有知識,總會有遇到自己不熟悉的領域,此時更重要的反而是有沒有能套用到各種題目的框架的應用。

以下列出一些我認為在tech spec review裡一定要包含的內容,如果在review本身沒有包含,那就是身為領導的責任來問出這些答案:

目標

  • 有沒有達到這個project原始想達到的目標?

The 7 habits of highly effective people 這本人生聖經裡,第一個要素就是以終為始,明定目標。目標就是引導一切的工具,每個到工程師手上要進行design的專案理論上都已經過了層層關卡,可能是PM跟design已經有過很長時間的辯論後確認要實作,可能是跟業務團隊討論後排入時程,也可能是跟技術團隊在幾次的monthly meeting後決定要改善的技術債。在每個project被提出的時候一定都有動機跟目標,但在進到工程設計的細節時,有時會在太多的細節中迷航,忘記最一開始的目標是什麼。有時候求好心切,想把更多問題一次解決的工程師,也會在設計中加入一些對系統更好,但不一定是跟這個project切身相關的improvements,這個時候問出「這個專案的目標是什麼」這樣的問題,就更有機會把大家拉回同一個方向,輕重緩急程度也會更明顯。

舉個例子來說(純屬虛構),假設今天PM提出一個提案,想測試改善onboarding流程對轉換率的影響,因為onboarding流程是接在login流程之後,而codebase裡的login流程有好多套不同種寫法,如果能把登入流程做個整合,onboarding process的改善也會更好寫,所以在tech spec review時工程師的設計是要把login也重構一遍,跟新的onboarding process綁在一起。此時就是很好的機會能跟團隊一起再確認一次,這個project的目標是什麼?很明顯,login process的refactor是個加分項,但不是hard requirement,在有這個共識之後,團隊仍然可以一起討論login process要不要在這次一起實作,這時的討論就可以用更多其他的tradeoff的評估,但至少要能有共識這並不是必須的。如果確認有更多的bandwidth,那有沒有其他跟這個目標更切身相關的事項,譬如metrics logging的完整性,onboarding process實作的細節深度,這些事項跟原始目標更align,應該要更hi-pri於其他非目標的優化。

實作

  • 有沒有考慮過其他種不同的implement的方式?為何選擇現在這種?

就如同沒有任何design是最佳解一樣,第一個想到的解法很有可能不會是最好的,也絕對不會是唯一的解法。此時,很重要的是確保現在正在present的不是第一個想法,而是有考慮過其他的選項,並評斷過tradeoff後有意識的選擇。每個選擇背後都應該要有個能說服人的原因,開發速度快、較穩定、跟現有的structure比較兼容、甚至是因為我就是想試試看這個技術,這些都可以是合理的原因,但絕不能夠沒有原因。舉一個常見遇到的問題是database的選擇,譬如relational, no-SQL, S3等等,各自都有各自的優劣之處,所以更重要的是你為什麼做這個選擇,有時候純粹就只是用某一種db太習慣,沒想到在其他狀況下有別的選擇也許會更適合,這就很適合在tech spec review的會議中提出來一起討論。(這也是為什麼在system design interview時很愛考這個!)

如果工程師已經有想過幾種不同的實作方式,那就可以更進一步討論每種選擇的trade off,判斷每種tradeoff的評估是否合理,需要的話也可以提供更多context來更改trade off的順序。譬如工程師原本以為PM那邊會需要開發時程越快越好,但也許你知道PM手上還有其他project正在進行測試,此時就是很好的機會提供這個context,甚至可以考慮將完整性的重要性提升至快速實作之上。

  • 實作上有沒有太樂觀估計的風險?

這個相較於其他項重要性略低,原因不是這件事不重要,而是因為負責工程師通常能做得比leader更好,除了junior或是還不熟悉codebase的工程師以外,時程評估不會是leader需要太著重擔心的事情,除非你發現跟你的直覺預估時間差距太多,仍然是好的機會能深度詢問這個評估的考量點有哪些。

潛在風險

  • 短期內(ex 三個月內)有沒有已經能看到會擴張的方向?有沒有保留延伸空間?

如果公司有做好中長期的planning,已經能看到未來會有這個產品擴張的需求,那這就是很好的時候提供context,讓團隊一起思考延展性該如何被考慮進去。增加未來的延展性的tradeoff幾乎一定就是現在的開發時程會增加,那這是不是公司現階段能夠接受的?還是說我們願意用未來更多的開發時間換取現在快速上架,為了應付短期內的緊急需求?這些都是需要從上而下,層層的目標來做guiding,才有辦法做出對於公司當下最好的選擇。

除了feature上的橫向擴張,推出後如果效果很好流量增加的話是否已經有vertical scaling的計畫,目前的back-of-the-envelop的推估是否合理且準確,也是其中一個review時需著重的點。

  • 有沒有跟其他團隊正在開發的方向有衝突的地方?

最後,由於CTO橫跨各個不同進行中的專案,更能有全局觀知道某些feature之間是否有相衝突的可能性,舉例來說,如果infra團隊正在搬遷跟升級某部分的infra,那做feature的團隊就最好能避免碰觸正在被升級的部分,以免兩個專案同時進行,要花一大堆時間解決code conflict,如果發現還要重寫一遍就更浪費時間了。這些都是在spec review時,應該儘早提出的問題。

以上是我統整針對Techonology這塊,我身為tech leader放前三多心力的地方:PR Review, Monitoring, Tech Spec Review,搭配我過去經驗的best practice。Again, 這些都不一定是正確答案,真理越辯越明,非常歡迎同道中人來找我聊天一起debate,肯定都還有能做得更好的地方。

下一步,讓我們來聊聊領導。

👩🏻‍💻 My life as a CTO Series 👩🏻‍💻

👉 Intro

👉 Technology: Day 1

👉 [You are here] Technology: Daily Work

👉 [Next] Leadership: 信任領導

✨ Follow me to get notifications for my new articles!

--

--

Jocelin Ho

Currently exploring opportunities! Ex-CTO & co-founder of Cooby, Ex-Instagram, Ex-Meta, Passionate about tech, management, psychology, and reading