作者 | 死馬

我是不四,畢業後一直在阿裡和螞蟻工作,不四是我在阿裡的花名,社群中一般以另一個花名 “死馬” 出現。工作這 8 年多來一直專注在 Node.js 和 Web 開發領域,也在社群參與了一些開源項目,包括 Koa、Egg 和 cnpm 等,非常幸運在 node 出生之初就開始參與其中,算是趕上了一波由 node 帶來的大前端變革浪潮。每一個人的成長軌迹都不一樣,一路上遇到的機遇也各不相同,這次分享也僅站在一個普通工程師的角度來分享我的成長經曆和貫穿其中的一些個人習慣。
成長曆程
實習
在 2011 年的夏天,大三暑假我來到了當時的淘寶資料平台實習。也不知道是運氣好還是運氣差,我是以 C++ 工程師的身份被招聘的,配置設定到的資料産品部卻是一個做 Web 産品的團隊,還是用剛剛出生的 Node.js 作為服務端開發語言,并在實踐全棧研發,還記得那時候 node 的版本才 0.4,而我是一個連 JS 和 JSP 都分不清楚的菜鳥,大學三年隻寫過黑框框的 C++,連 HTTP 是什麼都不知道,無比忐忑的開始悶頭學習 JS 基礎。
多年以後和當時看的入門教材作者成為了同僚。
幸運的是,當時的團隊大牛雲集,國内第一批 Node.js 的布道者,node party 的發起人空無、清笃、玄澄,以及國内 node 社群一直以來的核心貢獻者蘇千和樸靈等等都集中在了這個團隊。跟随着他們的腳步,我在大半年的實習時間内,順利的将 C++ 給忘光了,成為了一名新手 JS 工程師。
資料産品部
12 年畢業後正式入職淘寶資料産品部,那是大資料最火熱的年代,我們坐在淘寶資料平台的金山上,挖掘出來了資料魔方、淘寶指數、淘寶時光機等資料産品。随着我慢慢的深入業務,也逐漸了解了團隊為什麼選擇 node 技術棧。大部分的資料産品本身的計算和業務邏輯相對不會太複雜,依賴大量後端資料源提供資料,是一個典型的 IO 密集型應用。而 JS 全棧也可以帶來更高效的研發效率。
資料魔方
淘寶時光機
随着資料産品覆寫的場景越來越多,我們需要對接到阿裡集團的各種内部系統。是以我們用 node 實作了内部的微服務架構、登入系統、配置系統等中間件。而随着 node 生态的越來越繁榮,搭建一個内部的 npm 包管理系統也提上了日程。我們嘗試着用 npm 官方的解決方案搭建,但是難以運維,也不能完全滿足需求,最後我們開發了 cnpm 用來搭建内部的 npm 包管理平台并提供了國内的 npm 鏡像。後來的事實證明,一個快速的 npm 包管理平台對于促進 node 和大前端社群的繁榮起到了至關重要的作用。
剛畢業的這兩年是我技術成長非常快的時候,一方面是團隊有很多大牛可以學習,另一方面也趕上了一波 node 技術初生的福利期,我也在這裡完成了工作後的第一次晉升,從 P4 晉升到 P5。
天貓前端
在 14 年中的時候,由于團隊的一些變化,我轉崗到了天貓前端團隊。當時的天貓前端團隊其實沒有專職的 node 開發工程師,團隊遇到的一個很大挑戰是營運活動頁面之前都是運作在 php 上,随着 php 工程師在阿裡的逐漸減少,那套年久失修的 php 系統已經難以繼續支撐流量越來越誇張的雙十一活動了。是以我開始着手通過 node 實作新一代的頁面渲染服務。
新服務在 14 年雙十一的時候在天貓首頁進行驗證,從性能和穩定性上比老的 php 服務高出很多。接下來我們開始基于新的服務上層實作了新的可視化頁面搭建系統,非常完美的支援了 15 年的雙十一,這套系統也一直服務到現在,當然已經進化的更加完備和複雜了。
當時給 php 和 Node.js 系統做的 benchmark
在天貓可以說是之前那段工作經曆積累後的爆發期,用一個全新的技術棧實作了一個重要的業務系統,并取得了很大的業務價值,是以在 15 年的時候我也從 P5 晉升到了 P7。
螞蟻體驗技術部
可能還是有想做更底層一點技術的念頭,我在 16 年初的時候決定從天貓前端團隊轉崗到螞蟻的體驗技術部給大前端團隊做内部的 Web 架構和 BFF 研發模式的支援。其實在去螞蟻之前,我也一直在維護者 Koa 和一些 Web 架構生态和中間件的服務,到螞蟻之後參與做的第一件事情就是從當時螞蟻的 Web 架構 Chair 中抽出來了 Egg.js,以統一阿裡經濟體各不同 BU 的大前端 Web 研發體系。Egg.js 也随後面向社群開源。
Egg.js 生态
通過兩年多時間的發展,BFF 研發模式也慢慢的被螞蟻、阿裡經濟體甚至是國内接受了。我也在這裡晉升到了 P8。
語雀
随着一次内部組織架構調整的機會,我來到了語雀團隊。它是螞蟻體驗技術部内部的一個創新孵化項目,為十萬阿裡人提供知識協同和文檔管理的服務,18 年的時候,語雀也開始對外服務。兜兜轉轉的走了一圈,我又回到了使用 JS 全棧進行應用開發。在語雀團隊,我們踐行着産品工程師文化,高效的完成産品研發。
語雀産品工程師文化
簡短的總結畢業後的這 8 年,我在一個公司内兜兜轉轉,但是一直專注在一個技術領域上,并在底層技術、基礎服務、産品研發等不同的方向做探索。成長過程中可能有很多的幸運,你能遇到什麼樣的團隊和老闆,可以做什麼樣的事情,這些可能我們都很難完全控制,但是我們能夠控制的是作為一個工程師,你如何提升自己的技術能力,做好抓住機會的準備。
工程師成長密碼
回過頭再來看這幾年,我在工作和社群中養成了一些習慣,這些習慣可能是對我的技術成長影響非常大的。
堅持寫代碼
顯而易見,作為一個工程師,我們最重要的職責就是寫代碼。熟能生巧,堅持寫代碼一定是工程師成長手冊中最重要的一點。不論是在做技術項目還是帶團隊,寫代碼一定是我日常工作中最重要的一部分。
然而低品質的重複是毫無意義的,我們要堅持寫代碼,更要堅持寫好代碼。
什麼是好的代碼?這個問題可能不同的人眼中有不同的答案,對我而言,好的代碼起碼要滿足這三個條件:
- 好的代碼是簡單的,簡單的代碼架構清晰,并且讓編碼變的更輕松;
- 好的代碼是給人看的,絕大部分的應用都是要持續維護的,不給别人挖坑,也是不給未來的自己挖坑;
- 好的代碼是可測試的,通過編寫單元測試,既保障代碼的邏輯完備,減少 Bug,也利于後期維護與重構。
保持代碼簡潔
先從簡單說起,簡單的代碼是容易了解的,然而想要編寫簡單的代碼,架構起來又是更複雜的。這是給自己提出更高的要求,不斷優化重構,在這個過程中得到成長。當遇到一些複雜需求的時候,我始終堅信一點:如果一個邏輯我們作為實作者都很難梳理清楚,代碼中一堆的 if else 條件判斷,那使用者也一定是無法了解的。
是以當遇到這種情況,我們需要從産品側和架構側去思考,到底是什麼原因導緻了複雜度?我們應該是去優化産品需求還是去優化底層架構。這也會迫使我們在産品和架構上有更深入的思考。
Code Review
另外一個我和團隊一直在堅持的習慣是 Code Review。CR 是一個非常好的提升代碼品質的方式,它是需要團隊投入大量精力的事情,但是一定收獲不菲。
我們直面 CR 的靈魂三問:
- 為什麼要做 CR?業務催的那麼緊,哪有時間做 CR?
- 誰來做 CR?是團隊的主管、核心工程師才能幫别人 CR 嗎?
- CR 是一件很費精力的事情,如何才能堅持下來呢?
Code Review 的主體是人, Review 的對象是代碼
- 對于代碼送出者的人來說,當你知道你的代碼會被其他人看到的時候,是肯定會更加注重代碼品質的。我還記得我開始向社群成熟開源項目送出代碼的時候感受到的巨大壓力,它會讓你在送出代碼前更仔細的設計和編碼。經過一次次的 CR 後,你會發現你的代碼品質會飛速提升。
- 對于評審人來說,每一次 CR 都可以增加你對整體代碼庫或者不同業務的熟悉程度,還可以傳授經驗、提升團隊影響力。
- 最後,通過 Code Review,我們可以提升項目代碼的品質與可維護性,統一團隊的代碼風格,并讓每一個業務邏輯都能盡量找到 back up。CR 是一件三赢的事情。
CR 是一件很有意義的事情,但是我們應該怎麼去做呢?
第一步還是要從自己做起,通過自己的主動與堅持,帶動團隊一起參與。在送出代碼的時候,寫好 commit message,做好自測,注意代碼的可讀性。抽時間來 Review 團隊其他人的代碼,為每一行代碼負責。
但是 CR 畢竟還是一個團隊的事情,如何保持團隊 CR 的品質呢?我們一定要嚴抓新人的第一次 CR。一般來說我們團隊新人的第一個 PR 都會收到比較大的挑戰。新人對代碼不熟悉,編碼風格也和團隊可能不一緻,第一次 CR 非常重要,需要讓大家都對齊對代碼品質的标準和要求。
對新人重拳出擊
除了代碼之外,更上層的設計與架構也需要做 Review,讓每一次系統功能設計、架構更新都經過 Review,不僅可以讓系統更穩定,也可以快速提升自己的系統架構能力。
Unit Tests
- 你的代碼品質如何度量?
- 你是如何保證代碼品質?
- 你敢随時重構代碼嗎?
- 你是如何確定重構的代碼依然保持正确性?
- 你是否有足夠信心在沒有測試的情況下随時釋出你的代碼?
如果對這些問題沒有答案,或者沒有 100% 的信心,那你需要給你的代碼做單元測試。
現在說起單元測試,大家其實還是有體感的。然而在 12、13 年我剛工作的時候,單元測試還是一個相對陌生的概念,但是當時的 node 開源社群其實已經慢慢開始流行起來寫單元測試了,當你給其他開源項目送出代碼的時候,沒有測試是不可能被合并的。當時高産的 TJ 不僅僅提供了 express connect 等 Web 架構,同時也提供了一系列底層配套的測試子產品,包括測試用例驅動器 Mocha,斷言庫 should.js,http 請求測試庫 supertest 等等。
跟随社群一起,我們很早就把單元測試引入了我們的工作中,基本上從我正式工作開始編寫的第一行項目代碼開始就在寫單元測試了,這個習慣讓我在 8 年的工作經曆中保持了不錯的代碼品質,在沒有測試工程師測試過我的代碼的情況下,沒有搞出重大故障被阿裡開除。
說起對業務代碼寫單元測試,可能大家的第一反應還是哪有時間寫單元測試啊?其實寫單測真的沒有那麼耗時,隻要你找對工具和方法。對于單元測試來說,隻需要四個步驟:
- 建立一些初始資料;
- 對外部依賴進行 mock;
- 最小粒度的執行要測試的方法;
- 對結果做斷言。
剩下的就是按照這個方式構造測試用例輸入,盡可能的覆寫代碼中的每一個分支和邊緣場景。
Web 應用中的單元測試更加重要,在 Web 産品快速疊代的時期,每個測試用例都給應用的穩定性提供了一層保障。API 更新,測試用例可以很好地檢查代碼是否向下相容。對于各種可能的輸入,一旦測試覆寫,都能明确它的輸出。代碼改動後,可以通過測試結果判斷代碼的改動是否影響已确定的結果。我們在做 Egg.js 的時候,最重要的一件事情就是給它編寫對應的測試架構,讓業務方能夠更簡單、沒負擔的寫單測來保障代碼品質。
而把代碼的覆寫率提高,看到測試覆寫率的報告全綠,不僅對上線代碼更有信心了,同時也是一件很有成就感的事情。
持續分享
如果說堅持寫代碼是練習和輸入,那另一個對我成長幫助很大的習慣就是分享,這看起來是一個對外的輸出,但在我看來它更是一個非常好的學習機會。
在我剛工作在資料産品部的時候,我們團隊組織了一個 Show Me The Code 的内部分享沙龍,是一個形式非常随意的分享會,不需要準備正式的 PPT,不需要很長的分享時長,就簡單的分享一下最近學到的新知識,看到的有趣的代碼。這個培養了我去分享的習慣。那時候經常為了找一個分享的話題,去主動研究一些新的子產品,看他的源碼,自己也會去造一些小的輪子來解決實際工作中遇到的重複性工作。而現在在語雀團隊,我也在組織内部雙周分享會,已經堅持了一年多的時間了。
再小的分享也會有收獲
工作的這些年我也陸陸續續在外面的會議進行了不少的外部分享。基本上每一次分享,都需要自己先認真的對要分享的内容查漏補缺,并嘗試着将它準備到淺顯易懂。每一次演講過後,都會讓你對這個演講主題的領域有更深的感受。
分享對我來說更多的是給我提供了一個非常好的階段性總結的機會,最好的學習方法就是教會别人,因為誰也不想在台上出糗對吧。去聽一場技術分享,聽到的知識轉眼就忘了,而你認真的去準備一場演講,那場演講收獲最大的一定是你自己。
參與開源
對我的技術成長影響很大的另一個因素是開源,當然開源本質上也是一種分享。
現在是一個百花齊放的年代,開源世界的項目越來越多,根據 GitHub 的資料,2019 年有 4400 萬個新項目被建立。每一個有技術追求的工程師可能都想過要去 GitHub 上寫點什麼。但是開源并不是指的在 GitHub 上送出代碼,開源更多的是一種心态。
- 開源意味着你要将你的代碼給所有的開發者審閱,就像前面 Code Review 的時候說的,把代碼給别人看是一件很有壓力的事情,更何況送出到 GitHub 後,所有人都能看到,你的同僚、面試官都能看到。一定要認真的對待每一行代碼,每一次送出。
- 同時當有人使用你的開源項目時,意味着你要承擔起責任。盡管開源協定可能是很寬松的 MIT,但還是要對你寫的代碼負責。
- 開源應該讓你感受到 “痛苦”,需要對開源代碼提出更嚴格的要求,追求最優的代碼架構,測試完備,描述清晰,編寫高品質代碼的過程會讓你感受到痛苦,但是會有更快的成長。
可能我們有時候很難自己想到一個很好的想法,或者很難自己實作一個那麼高品質的開源項目,不要着急,參與開源的門檻其實也沒那麼高。
第一步,挑選一個工作中可以用到的領域的高品質開源項目,為什麼工作中可以用到很重要,因為這樣你才能更好的找到改進的方向,找到痛點。例如我當時選擇深入參與的開源項目是 Koa,因為我工作的重點也是在 Web 研發領域,而我覺得 Koa 當時基于 co 提供的那套異步程式設計模型一定是未來的趨勢。
第二步,逐漸參與進去,一開始可能隻是修一下文檔,找找 Bug 修複一下,補充幾個測試用例。慢慢的随着你對代碼和周邊生态的完善,可以進一步去實作一些缺失的周邊生态,嘗試根據自己實際遇到的問題給項目送出一些功能改善。
國外有很多高品質的項目,我們也可以幫他們做文檔的翻譯。不要小瞧文檔翻譯,翻譯一遍文檔就意味着你要深入了解這個項目,其實也是一件很難并且很有收獲的事情,還能夠提升社群影響力。
開源是一個成就感驅動的事情,因為你無法從中獲得看得着的收益。是以能夠持續的參與開源最重要的一點是你要能夠從中找到成就感。
和團隊一起成長
說了這麼多個人成長的事情,我還是想再稍微說一下團隊。我們作為個人在團隊中工作,隻有幫助團隊一起成長,拿到業務價值,才能将我們的技術成長 “變現”。而之前提到的 Code Review 亦或是單元測試,都是需要團隊一起來配合的。
如果你的團隊還沒有内部的分享會,嘗試着自己去組織一個定期的内部分享會;
從現在開始做 CR 和單測,用自己來影響團隊;
嘗試着在團隊中建立契合團隊的工程師文化。
前兩點其實在之前的分享中都已經提及到了,這也是我們團隊一直在堅持和倡導的。我想說一下語雀的團隊文化,在語雀我們希望每一個工程師都是産品工程師,他是産品的技術合夥人,參與産品讨論、完成産品功能研發,同時他也是某一個具體領域的技術專家,例如前端 UI 元件、編輯器領域、服務端領域等等。在我們的工作流程中,所有的工程師都是以全棧的身份參與項目研發,跟進項目從産品設計、到系統分析、研發自測,CR 以及上線的全流程。通過産品工程師文化,我們鼓勵每一個工程師都能夠在業務和技術上找到自己的成長方向,并陪着團隊和業務一起快速成長。
個人成長很重要,同時想要取得好的結果得到晉升,一定要将個人的成長和團隊的成長綁定起來。通過把自己的事情做到極緻,幫助團隊創造業務價值,在這個過程中提升自己在團隊内外的影響力。找到那個個人和團隊雙赢的點去發力,可以得到事半功倍的效果。
本文來自 螞蟻集團進階前端技術專家 不四在前端早早聊成長晉升專場的分享。
關注「Alibaba F2E」
把握阿裡巴巴前端新動向