不四:產品工程師的修煉之路

阿里雲開發者發表於2020-09-28

簡介: 我是不四,畢業後一直在阿里和螞蟻工作,不四是我在阿里的花名,社群中一般以另一個花名 “死馬” 出現。每一個人的成長軌跡都不一樣,一路上遇到的機遇也各不相同,這次分享也僅站在一個普通工程師的角度來分享我的成長經歷和貫穿其中的一些個人習慣。

作者 | 死馬

image.png
我是不四,畢業後一直在阿里和螞蟻工作,不四是我在阿里的花名,社群中一般以另一個花名 “死馬” 出現。工作這 8 年多來一直專注在 Node.js 和 Web 開發領域,也在社群參與了一些開源專案,包括 Koa、Egg 和 cnpm 等,非常幸運在 node 出生之初就開始參與其中,算是趕上了一波由 node 帶來的大前端變革浪潮。每一個人的成長軌跡都不一樣,一路上遇到的機遇也各不相同,這次分享也僅站在一個普通工程師的角度來分享我的成長經歷和貫穿其中的一些個人習慣。

成長曆程

image.png

實習

在 2011 年的夏天,大三暑假我來到了當時的淘寶資料平臺實習。也不知道是運氣好還是運氣差,我是以 C++ 工程師的身份被招聘的,分配到的資料產品部卻是一個做 Web 產品的團隊,還是用剛剛出生的 Node.js 作為服務端開發語言,並在實踐全棧研發,還記得那時候 node 的版本才 0.4,而我是一個連 JS 和 JSP 都分不清楚的菜鳥,大學三年只寫過黑框框的 C++,連 HTTP 是什麼都不知道,無比忐忑的開始悶頭學習 JS 基礎。

image.png

多年以後和當時看的入門教材作者成為了同事。

幸運的是,當時的團隊大牛雲集,國內第一批 Node.js 的佈道者,node party 的發起人空無、清篤、玄澄,以及國內 node 社群一直以來的核心貢獻者蘇千和樸靈等等都集中在了這個團隊。跟隨著他們的腳步,我在大半年的實習時間內,順利的將 C++ 給忘光了,成為了一名新手 JS 工程師。

資料產品部

12 年畢業後正式入職淘寶資料產品部,那是大資料最火熱的年代,我們坐在淘寶資料平臺的金山上,挖掘出來了資料魔方、淘寶指數、淘寶時光機等資料產品。隨著我慢慢的深入業務,也逐漸理解了團隊為什麼選擇 node 技術棧。大部分的資料產品本身的計算和業務邏輯相對不會太複雜,依賴大量後端資料來源提供資料,是一個典型的 IO 密集型應用。而 JS 全棧也可以帶來更高效的研發效率。

image.png
資料魔方

image.png
淘寶時光機

隨著資料產品覆蓋的場景越來越多,我們需要對接到阿里集團的各種內部系統。所以我們用 node 實現了內部的微服務框架、登入系統、配置系統等中介軟體。而隨著 node 生態的越來越繁榮,搭建一個內部的 npm 包管理系統也提上了日程。我們嘗試著用 npm 官方的解決方案搭建,但是難以運維,也不能完全滿足需求,最後我們開發了 cnpm 用來搭建內部的 npm 包管理平臺並提供了國內的 npm 映象。後來的事實證明,一個快速的 npm 包管理平臺對於促進 node 和大前端社群的繁榮起到了至關重要的作用。

剛畢業的這兩年是我技術成長非常快的時候,一方面是團隊有很多大牛可以學習,另一方面也趕上了一波 node 技術初生的福利期,我也在這裡完成了工作後的第一次晉升,從 P4 晉升到 P5。

天貓前端

在 14 年中的時候,由於團隊的一些變化,我轉崗到了天貓前端團隊。當時的天貓前端團隊其實沒有專職的 node 開發工程師,團隊遇到的一個很大挑戰是運營活動頁面之前都是執行在 php 上,隨著 php 工程師在阿里的逐漸減少,那套年久失修的 php 系統已經難以繼續支撐流量越來越誇張的雙十一活動了。所以我開始著手通過 node 實現新一代的頁面渲染服務。

新服務在 14 年雙十一的時候在天貓首頁進行驗證,從效能和穩定性上比老的 php 服務高出很多。接下來我們開始基於新的服務上層實現了新的視覺化頁面搭建系統,非常完美的支援了 15 年的雙十一,這套系統也一直服務到現在,當然已經進化的更加完備和複雜了。
image.png
當時給 php 和 Node.js 系統做的 benchmark

在天貓可以說是之前那段工作經歷積累後的爆發期,用一個全新的技術棧實現了一個重要的業務系統,並取得了很大的業務價值,所以在 15 年的時候我也從 P5 晉升到了 P7。

螞蟻體驗技術部

可能還是有想做更底層一點技術的念頭,我在 16 年初的時候決定從天貓前端團隊轉崗到螞蟻的體驗技術部給大前端團隊做內部的 Web 框架和 BFF 研發模式的支援。其實在去螞蟻之前,我也一直在維護者 Koa 和一些 Web 框架生態和中介軟體的服務,到螞蟻之後參與做的第一件事情就是從當時螞蟻的 Web 框架 Chair 中抽出來了 Egg.js,以統一阿里經濟體各不同 BU 的大前端 Web 研發體系。Egg.js 也隨後面向社群開源。

image.png
Egg.js 生態

通過兩年多時間的發展,BFF 研發模式也慢慢的被螞蟻、阿里經濟體甚至是國內接受了。我也在這裡晉升到了 P8。

語雀

隨著一次內部組織架構調整的機會,我來到了語雀團隊。它是螞蟻體驗技術部內部的一個創新孵化專案,為十萬阿里人提供知識協同和文件管理的服務,18 年的時候,語雀也開始對外服務。兜兜轉轉的走了一圈,我又回到了使用 JS 全棧進行應用開發。在語雀團隊,我們踐行著產品工程師文化,高效的完成產品研發。

image.png
語雀產品工程師文化

簡短的總結畢業後的這 8 年,我在一個公司內兜兜轉轉,但是一直專注在一個技術領域上,並在底層技術、基礎服務、產品研發等不同的方向做探索。成長過程中可能有很多的幸運,你能遇到什麼樣的團隊和老闆,可以做什麼樣的事情,這些可能我們都很難完全控制,但是我們能夠控制的是作為一個工程師,你如何提升自己的技術能力,做好抓住機會的準備。

工程師成長密碼

回過頭再來看這幾年,我在工作和社群中養成了一些習慣,這些習慣可能是對我的技術成長影響非常大的。

堅持寫程式碼

顯而易見,作為一個工程師,我們最重要的職責就是寫程式碼。熟能生巧,堅持寫程式碼一定是工程師成長手冊中最重要的一點。不論是在做技術專案還是帶團隊,寫程式碼一定是我日常工作中最重要的一部分。
image.png
然而低質量的重複是毫無意義的,我們要堅持寫程式碼,更要堅持寫好程式碼。

什麼是好的程式碼?這個問題可能不同的人眼中有不同的答案,對我而言,好的程式碼起碼要滿足這三個條件:

  1. 好的程式碼是簡單的,簡單的程式碼架構清晰,並且讓編碼變的更輕鬆;
  2. 好的程式碼是給人看的,絕大部分的應用都是要持續維護的,不給別人挖坑,也是不給未來的自己挖坑;
  3. 好的程式碼是可測試的,通過編寫單元測試,既保障程式碼的邏輯完備,減少 Bug,也利於後期維護與重構。

保持程式碼簡潔

先從簡單說起,簡單的程式碼是容易理解的,然而想要編寫簡單的程式碼,架構起來又是更復雜的。這是給自己提出更高的要求,不斷優化重構,在這個過程中得到成長。當遇到一些複雜需求的時候,我始終堅信一點:如果一個邏輯我們作為實現者都很難梳理清楚,程式碼中一堆的 if else 條件判斷,那使用者也一定是無法理解的。

所以當遇到這種情況,我們需要從產品側和架構側去思考,到底是什麼原因導致了複雜度?我們應該是去優化產品需求還是去優化底層架構。這也會迫使我們在產品和架構上有更深入的思考。

Code Review

另外一個我和團隊一直在堅持的習慣是 Code Review。CR 是一個非常好的提升程式碼質量的方式,它是需要團隊投入大量精力的事情,但是一定收穫不菲。
image.png
我們直面 CR 的靈魂三問:

  1. 為什麼要做 CR?業務催的那麼緊,哪有時間做 CR?
  2. 誰來做 CR?是團隊的主管、核心工程師才能幫別人 CR 嗎?
  3. CR 是一件很費精力的事情,如何才能堅持下來呢?

image.png
Code Review 的主體是人, Review 的物件是程式碼

  • 對於程式碼提交者的人來說,當你知道你的程式碼會被其他人看到的時候,是肯定會更加註重程式碼質量的。我還記得我開始向社群成熟開源專案提交程式碼的時候感受到的巨大壓力,它會讓你在提交程式碼前更仔細的設計和編碼。經過一次次的 CR 後,你會發現你的程式碼質量會飛速提升。
  • 對於評審人來說,每一次 CR 都可以增加你對整體程式碼庫或者不同業務的熟悉程度,還可以傳授經驗、提升團隊影響力。
  • 最後,通過 Code Review,我們可以提升專案程式碼的質量與可維護性,統一團隊的程式碼風格,並讓每一個業務邏輯都能儘量找到 back up。CR 是一件三贏的事情。

CR 是一件很有意義的事情,但是我們應該怎麼去做呢?

第一步還是要從自己做起,通過自己的主動與堅持,帶動團隊一起參與。在提交程式碼的時候,寫好 commit message,做好自測,注意程式碼的可讀性。抽時間來 Review 團隊其他人的程式碼,為每一行程式碼負責。
image.png
但是 CR 畢竟還是一個團隊的事情,如何保持團隊 CR 的質量呢?我們一定要嚴抓新人的第一次 CR。一般來說我們團隊新人的第一個 PR 都會收到比較大的挑戰。新人對程式碼不熟悉,編碼風格也和團隊可能不一致,第一次 CR 非常重要,需要讓大家都對齊對程式碼質量的標準和要求。
image.png
對新人重拳出擊

除了程式碼之外,更上層的設計與架構也需要做 Review,讓每一次系統功能設計、架構升級都經過 Review,不僅可以讓系統更穩定,也可以快速提升自己的系統架構能力。

Unit Tests

  • 你的程式碼質量如何度量?
  • 你是如何保證程式碼質量?
  • 你敢隨時重構程式碼嗎?
  • 你是如何確保重構的程式碼依然保持正確性?
  • 你是否有足夠信心在沒有測試的情況下隨時釋出你的程式碼?

如果對這些問題沒有答案,或者沒有 100% 的信心,那你需要給你的程式碼做單元測試。

現在說起單元測試,大家其實還是有體感的。然而在 12、13 年我剛工作的時候,單元測試還是一個相對陌生的概念,但是當時的 node 開源社群其實已經慢慢開始流行起來寫單元測試了,當你給其他開源專案提交程式碼的時候,沒有測試是不可能被合併的。當時高產的 TJ 不僅僅提供了 express connect 等 Web 框架,同時也提供了一系列底層配套的測試模組,包括測試用例驅動器 Mocha,斷言庫 should.js,http 請求測試庫 supertest 等等。

跟隨社群一起,我們很早就把單元測試引入了我們的工作中,基本上從我正式工作開始編寫的第一行專案程式碼開始就在寫單元測試了,這個習慣讓我在 8 年的工作經歷中保持了不錯的程式碼質量,在沒有測試工程師測試過我的程式碼的情況下,沒有搞出重大故障被阿里開除。

說起對業務程式碼寫單元測試,可能大家的第一反應還是哪有時間寫單元測試啊?其實寫單測真的沒有那麼耗時,只要你找對工具和方法。對於單元測試來說,只需要四個步驟:

  1. 建立一些初始資料;
  2. 對外部依賴進行 mock;
  3. 最小粒度的執行要測試的方法;
  4. 對結果做斷言。

image.png
剩下的就是按照這個方式構造測試用例輸入,儘可能的覆蓋程式碼中的每一個分支和邊緣場景。

Web 應用中的單元測試更加重要,在 Web 產品快速迭代的時期,每個測試用例都給應用的穩定性提供了一層保障。API 升級,測試用例可以很好地檢查程式碼是否向下相容。對於各種可能的輸入,一旦測試覆蓋,都能明確它的輸出。程式碼改動後,可以通過測試結果判斷程式碼的改動是否影響已確定的結果。我們在做 Egg.js 的時候,最重要的一件事情就是給它編寫對應的測試框架,讓業務方能夠更簡單、沒負擔的寫單測來保障程式碼質量。

而把程式碼的覆蓋率提高,看到測試覆蓋率的報告全綠,不僅對上線程式碼更有信心了,同時也是一件很有成就感的事情。
image.png

持續分享

如果說堅持寫程式碼是練習和輸入,那另一個對我成長幫助很大的習慣就是分享,這看起來是一個對外的輸出,但在我看來它更是一個非常好的學習機會。

在我剛工作在資料產品部的時候,我們團隊組織了一個 Show Me The Code 的內部分享沙龍,是一個形式非常隨意的分享會,不需要準備正式的 PPT,不需要很長的分享時長,就簡單的分享一下最近學到的新知識,看到的有趣的程式碼。這個培養了我去分享的習慣。那時候經常為了找一個分享的話題,去主動研究一些新的模組,看他的原始碼,自己也會去造一些小的輪子來解決實際工作中遇到的重複性工作。而現在在語雀團隊,我也在組織內部雙週分享會,已經堅持了一年多的時間了。

image.png
再小的分享也會有收穫

工作的這些年我也陸陸續續在外面的會議進行了不少的外部分享。基本上每一次分享,都需要自己先認真的對要分享的內容查漏補缺,並嘗試著將它準備到淺顯易懂。每一次演講過後,都會讓你對這個演講主題的領域有更深的感受。
image.png
分享對我來說更多的是給我提供了一個非常好的階段性總結的機會,最好的學習方法就是教會別人,因為誰也不想在臺上出糗對吧。去聽一場技術分享,聽到的知識轉眼就忘了,而你認真的去準備一場演講,那場演講收穫最大的一定是你自己。

參與開源

對我的技術成長影響很大的另一個因素是開源,當然開源本質上也是一種分享。

現在是一個百花齊放的年代,開源世界的專案越來越多,根據 GitHub 的資料,2019 年有 4400 萬個新專案被建立。每一個有技術追求的工程師可能都想過要去 GitHub 上寫點什麼。但是開源並不是指的在 GitHub 上提交程式碼,開源更多的是一種心態。

  1. 開源意味著你要將你的程式碼給所有的開發者審閱,就像前面 Code Review 的時候說的,把程式碼給別人看是一件很有壓力的事情,更何況提交到 GitHub 後,所有人都能看到,你的同事、面試官都能看到。一定要認真的對待每一行程式碼,每一次提交。
  2. 同時當有人使用你的開源專案時,意味著你要承擔起責任。儘管開源協議可能是很寬鬆的 MIT,但還是要對你寫的程式碼負責。
  3. 開源應該讓你感受到 “痛苦”,需要對開原始碼提出更嚴格的要求,追求最優的程式碼架構,測試完備,描述清晰,編寫高質量程式碼的過程會讓你感受到痛苦,但是會有更快的成長。

可能我們有時候很難自己想到一個很好的想法,或者很難自己實現一個那麼高質量的開源專案,不要著急,參與開源的門檻其實也沒那麼高。

第一步,挑選一個工作中可以用到的領域的高質量開源專案,為什麼工作中可以用到很重要,因為這樣你才能更好的找到改進的方向,找到痛點。例如我當時選擇深入參與的開源專案是 Koa,因為我工作的重點也是在 Web 研發領域,而我覺得 Koa 當時基於 co 提供的那套非同步程式設計模型一定是未來的趨勢。

第二步,逐步參與進去,一開始可能只是修一下文件,找找 Bug 修復一下,補充幾個測試用例。慢慢的隨著你對程式碼和周邊生態的完善,可以進一步去實現一些缺失的周邊生態,嘗試根據自己實際遇到的問題給專案提交一些功能改善。

國外有很多高質量的專案,我們也可以幫他們做文件的翻譯。不要小瞧文件翻譯,翻譯一遍文件就意味著你要深入理解這個專案,其實也是一件很難並且很有收穫的事情,還能夠提升社群影響力。

開源是一個成就感驅動的事情,因為你無法從中獲得看得著的收益。所以能夠持續的參與開源最重要的一點是你要能夠從中找到成就感。
image.png

和團隊一起成長

說了這麼多個人成長的事情,我還是想再稍微說一下團隊。我們作為個人在團隊中工作,只有幫助團隊一起成長,拿到業務價值,才能將我們的技術成長 “變現”。而之前提到的 Code Review 亦或是單元測試,都是需要團隊一起來配合的。

如果你的團隊還沒有內部的分享會,嘗試著自己去組織一個定期的內部分享會;
從現在開始做 CR 和單測,用自己來影響團隊;
嘗試著在團隊中建立契合團隊的工程師文化。
前兩點其實在之前的分享中都已經提及到了,這也是我們團隊一直在堅持和倡導的。我想說一下語雀的團隊文化,在語雀我們希望每一個工程師都是產品工程師,他是產品的技術合夥人,參與產品討論、完成產品功能研發,同時他也是某一個具體領域的技術專家,例如前端 UI 元件、編輯器領域、服務端領域等等。在我們的工作流程中,所有的工程師都是以全棧的身份參與專案研發,跟進專案從產品設計、到系統分析、研發自測,CR 以及上線的全流程。通過產品工程師文化,我們鼓勵每一個工程師都能夠在業務和技術上找到自己的成長方向,並陪著團隊和業務一起快速成長。

個人成長很重要,同時想要取得好的結果得到晉升,一定要將個人的成長和團隊的成長繫結起來。通過把自己的事情做到極致,幫助團隊創造業務價值,在這個過程中提升自己在團隊內外的影響力。找到那個個人和團隊雙贏的點去發力,可以得到事半功倍的效果。

本文來自 螞蟻集團高階前端技術專家 不四在前端早早聊成長晉升專場的分享。

相關文章