來源:Alibaba F2E
作者:梧忌
回顧自己近幾年的工作經曆,從最早 17 年在團隊内部建立 Iceland[注1] ,到 19 年在開源社群參與 ICE 的由 1 到 10,再到 20 年由 0 到 1 建立了 AppWorks。其間也曾在阿裡巴巴前端委員會參與了 低代碼引擎[注2] 早期的共建。這些經曆都屬于技術産品建設的範疇。
我見過一些有趣的想法和優秀的技術實作,但由于産品的定位問題,最終沒有獲得世俗意義上的成功;也經曆過有非常系統性規劃的項目,但由于分工和執行問題,最終錯過了發展的時間視窗。服務好開發者确非易事,他們極其挑剔。把優秀的工程師們聚集在一起工作也并不容易,他們特立獨行。
在如何服務好開發者群體、如何管理大型的多人協作項目問題上,自己不敢說有多少成功的經驗,但也算是踩過不少的坑。當我再次面對技術産品化需求時,期望能系統性地梳理技術産品的建設方法,總結自己的經驗為日後所用,也許對于其他同學來說也有些參考價值,是以寫下了這篇文章。
在這篇文章當中,筆者将介紹「如何做」的方法論,不會讨論「為什麼要做」的動機。由于筆者的工作經曆主要以打造開源技術産品為主,是以在文章中又會主要以「開源技術産品」為例,但相信這些經驗對于内部技術産品也是适用的。
一個技術産品的打造,涉及到設計産品、設計架構、管理項目、編寫文檔、開發官網、營運産品、管理需求和缺陷等多個環節。要把這幾個環節都做好,才有可能成功。技術産品項目在不同的階段又有不同的關注點,比方說前期更側重設計,釋出後更側重營運,穩定期則更側重需求管理和答疑,開源後則更側重項目管理。
下面筆者将按照這幾個環節來展開介紹相關的方法論和工具,并且會提供一些示例。
設計産品
打造技術産品的第一步是明确使用怎樣的手段來解決目标使用者的問題,即要 「做什麼」,其本質是完成使用者産品的設計。
在此階段可以進行一些輸入,例如可以通過使用者調研和市場調研的方式來得出:使用者關注的問題當中,哪些是重要且緊急的?市面上有沒有相關的産品來解決這些問題,目前解決得怎麼樣?由此可以明确,我們要打造的技術産品,定位是什麼,提供哪些特性。
關于産品的特性,不妨思考:哪些功能是别人有我們也有的(We too)?哪些功能是别人有但我們可以做得更好的(We better)?哪些功能又是我們獨有的(We only)?
如果是圖形界面類産品(例如開發者工具),則可以産出産品的互動稿:包含哪些功能子產品,使用者的使用流程是怎樣的?如果是代碼類産品(例如架構),則可以産出官網互動稿和文檔大綱:設計産品官網的過程就是明确産品組織結構、核心能力及産品價值的過程,編寫文檔大綱的過程就是以客戶視角審視産品使用者體驗的過程。對于基礎庫,還可以先明确對外 API 的設計:提供哪些屬性、方法和事件?
總結一下,在産品設計環節主要傳遞的産物是:
- 市場調研報告,示例:《人工智能自動程式設計調研報告》
- 使用者調研報告,示例:《淘系技術部前端外包現狀調研報告》 [注3]
- 産品互動稿,示例:《Iceworks 研發工作台産品互動稿》
- 官網互動稿,示例:ICE 官網
- 文檔大綱,示例:ICE 教程
設計架構
産品設計回答了「做什麼」的問題,接下來要去考慮 「怎麼做」,其本質是完成軟體架構的設計。
軟體架構的重要性不言而喻,它是系統實作的藍圖、溝通協作的基礎,決定了産品的品質。
關于如何設計一個好的架構以及怎麼描述你的架構設計,有非常多成熟的方法論,這裡就不再贅述了,筆者也在學習實踐當中。在架構設計環節筆者的一個思路是:先做競品調研,再做架構制圖。
做競品調研,産出的是調研報告。通過調研去了解相關競品的架構模式,甚至是程式實作。目前技術資訊發達、開源社群活躍,太陽底下沒有新事物。我們要做的事情,可能已經被人用好幾種方式實作了好幾個版本。在有限的時間内,找到問題域中最好的幾個實作進行調研,站在巨人的肩膀上思考,事半功倍。示例:《螞蟻 Could IDE 調研報告》 [注4]
做架構制圖,産出的是架構圖。架構制圖方法與工具有很多,UML 應該是大部分人最熟悉的制圖方法,UML 由以下兩大類圖組成:
- 結構圖(Structural Diagrams):通過對象、屬性、操作和關系等方式,強調系統的靜态結構,其中最常見的類型包括類圖(Class Diagram)、元件圖(Component Diagram)和部署圖(Deployment Diagram)。
- 行為圖(Behavioral Diagrams):通過展示對象之間的協作關系以及對象内部的狀态改變,強調系統的動态行為,其中最常見的類型包括用例圖(Use Case Diagram)、活動圖(Activity Diagram)、時序圖(Sequence Diagram)和狀态機圖(State Machine Diagram)。
例如,可以把這兩類圖應用到我們的程式設計當中:
- 結構圖:程式中包含哪些類、對象和函數,它們之間的關系如何?=>類圖(Class Diagram)
- 行為圖:程式的運作流程是怎樣的?=> 時序圖(Sequence Diagram)
示例:VS Code 插件 Time Master 的程式設計(來源:#PR 620)
最後關于架構制圖,推薦一些方法論和小工具:
- 方法論:楚衡(pengqun.pq) 老師的《架構制圖:工具與方法論》 一文,系統性地梳理了架構制圖的方法和工具,值得一再閱讀。
- 語雀富文本的文本繪圖功能,支援 PlantUML。PlantUML 是一種繪圖語言,可以讓作者以類編寫 Markdown 的方式自然地畫圖,可進行多人協作和版本跟蹤,受到各知識系統的廣泛支援:
管理項目
完成了産品和架構的設計後,開始進入項目開發的環節。這個環節主要關注的是:如何組織開發和怎樣進行協作。前者無論是個人還是團隊項目都是通用的,後者取決于項目的規模。
▐ 組織項目開發
- 倉庫劃分
倉庫的劃分是軟體架構設計在代碼組織層面的落地,需要有預見性,避免未來進行大規模的倉庫遷移。
倉庫的組織形式有兩種:多倉庫和單倉庫。單倉庫又多包(monorepo)和單包的差別。比方說 React ,就是多倉庫的組織形式:有主倉庫 facebook/react 是多包存儲庫,還有存放周邊倉庫的組織 reactjs/*。
這裡面沒有一成之規和好壞之分,主要取決于項目的規模和協作上的便利,或者說有時候純粹是個人喜好問題。比方說有些技術産品将自己的插件、示例、官網都放到單獨的倉庫進行管理,有些則傾向于放到一起。
示例:AppWorks 的倉庫劃分
- 分支管理
為了更好地利用 Git 這樣的源碼版本管理系統來進行多人協作,我們需要制定分支管理政策。分支管理政策的目的是規範化工作流程,讓大家高效地進行合作,使得項目井井有條地發展下去。
分支管理政策包含了以下内容:
- 有哪些分支類型?
- 分支類型間的合并關系如何?
- 基于分支的疊代路徑是怎樣的?
常見的 Git 工作流有 Centralized Workflow 、 Feature Branch Workflow、Gitflow Workflow、Forking Workflow 等等。Atlassian 的 Comparing Workflows 這篇文章對以上幾種工作流進行了比較。
目前社群上廣泛采用的是最早由 Vincent Driessen 提出的 Gitflow Workflow:
- Git 規約
項目基于 Git 進行源碼版本管理,還需要關注分支和标簽的命名、送出日志格式等問題。它們的規範性可以使得項目運作井井有條,項目成員對 Git 資訊的了解保持一緻。社群有很多 Git 規約,它們之間沒有好壞之分,主要關注規約的覆寫度即可。
Git 送出日志格式規約包含的内容有:日志的格式、字數的限制、語言的選擇等。
在社群中應用得比較廣泛的日志格式是:
<type>[optional scope]: <subject>
[optional body]
[optional footer(s)]
其中 type 是用來描述本次送出的改動類型,一般可選值及對應含義如下:
- feat: 新增功能
- fix: 修複 bug
- docs: 文檔相關的改動
- style: 對代碼的格式化改動,代碼邏輯并未産生任何變化(例如代碼縮進,分号的移除和添加)
- test: 新增或修改測試用例
- refactor: 重構代碼或其他優化舉措
- chore: 項目工程方面的改動,代碼邏輯并未産生任何變化
- revert: 恢複之前的送出
Git 送出日志格式規約的完整版本,可參考 AngularJS Git Commit Message Conventions。
在項目工程上可以使用指令行工具 commitlint ,結合 Git 送出日志格式規約包 commitlint-config-ali,以及 Git Hooks 來進行送出卡口:
安裝指令行工具:
$ npm i --save-dev @iceworks/spec @commitlint/cli husky
建立送出日志格式規約檔案 .commitlintrc.js:
const { getCommitlintConfig } = require('@iceworks/spec');
// getCommitlintConfig(rule: 'common'|'rax'|'react'|'vue', customConfig?);
module.exports = getCommitlintConfig('react');
添加 Git Hooks 配置到 package.json:
{
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS" }
}
}
1.@iceworks/spec 是淘系前端規約包,内部引用了 commitlint-config-ali
- Husky 是一個簡易配置 Git Hooks的工具
- 工程方案
項目工程方案主要包括了代碼規約、本地工程和 CI&CD 的内容。
代碼規約
在多人協作項目中保持代碼風格的一緻性是必要的。前端領域關于代碼規約的讨論和沉澱都已經比較成熟,阿裡前端委員會标準化小組制定了《前端編碼規約》 [注5] ,包括了語言(HTML/CSS|Sass|Less/JavaScript)和架構(React/Rax)的部分。淘系前端基于此規約進行拓展,産出了 @iceworks/spec 這個 npm 包,結合 ESLint、StyleLint、Prettier 等指令行工具來提供本地工程方面的配套保障。當我們進行項目開發時,隻需要引用該包和相應的指令行工具,做一些簡單的配置即可:
$ npm i --save-dev @iceworks/spec eslint stylelint prettier husky
配置 package.json
{
"scripts": {
"lint": "npm run eslint && npm run stylelint",
"eslint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./",
"stylelint": "stylelint ./**/*.scss",
"prettier": "prettier **/* --write"
},
"husky": {
"hooks": {
"pre-push": "npm run lint"
}
}
}
本地工程
本地開發工程任務的設定是為了提升開發效率并将團隊規約落實到開發中,通常包括以下部分:
- setup: 初始化工程環境
- dev: 啟動調試并預覽示例
- lint: 執行靜态代碼分析
- test: 執行單元測試
- build: 執行源碼建構
- publish: 釋出代碼
前端開發在本地工程配套設施上已經非常成熟,面向不同的項目類型都有相應的工程方案。常見的項目類型和相應的工程示例:
1.前端應用:
- React 應用:使用 ice.js 方案
- Rax 應用:使用 rax-app 方案
2.前端業務元件:使用 build-scripts + build-plugin-component 方案
- Rax 業務元件模闆: https://github.com/ice-lab/material-- templates/tree/master/packages/template-rax/template/component
- React 業務元件模闆: https://github.com/ice-lab/material-templates/tree/master/packages/template-react-ts/template/component
3.全棧應用:使用 Midway Hooks 方案
- 移動端全棧應用: https://github.com/midwayjs/midway-serverless-examples/tree/master/integration/rax/boilerplate)
- PC 端全棧應用: https://github.com/ice-lab/react-materials/tree/master/scaffolds/midway-faas
4.npm 子產品:使用 tsc + webpack 方案
CI&CD
持續內建 (CI) 和持續部署 (CD) 是自動化工作流程的重要組成部分。
在 Github 中,持續內建主要是通過 Actions 來實作的。當然還有另外一些選擇或結合,例如 Travis、Appveyor、Circleci 等等。Github Actions 非常強大,可以在任意的 Github Event 下運作。例如可以在送出代碼到倉庫時、分支合并時、PR 建立時等等。基于 Github Actions 的任務通常包括:
- 功能測試及代碼覆寫率
- 代碼建構
- 代碼檢查(文法檢查、安全性檢查)
- 資源部署(CDN 釋出、npm 釋出)
例如 VS Code 套件 AppWorks Pack 的 Actions:
- PR 建立時:執行代碼檢查和功能測試任務
- 送出代碼到 beta 分支時:執行代碼建構(建構插件安裝包)和資源部署(将安裝包上傳到 CDN)任務
- 送出代碼到 main 分支時:執行代碼建構(建構插件安裝包)和資源部署(将安裝包釋出到 VS Code 插件市場)任務
在阿裡内部,CI&CD 主要由 DEF[注6] 統一管理,根據不同的項目類型(Assets/WebApp/Serverless)有統一的自動化工作流程。
▐ 建立協作機制
上圖是筆者 2019 年在 Github 上的 Activity Overview,可以看到有比較多的精力是配置設定在了與溝通協作的部分(Issues/PR/CR)。對于多人協作開發的項目,前期建立協作機制是提升團隊整體工作效率的必然要求。項目開源後,建立貢獻指南則可以讓外部開發者參與到項目的開發當中。這兩者是前後關聯的,在有些開源項目中是統一的。
一些社群的貢獻指南參考:
- Contributing Guide for React
- Contributing Guide for VS Code
在協作機制裡面,筆者認為幾個重點的内容有:RFC 機制、PR 規約和 CR 指南。
- RFC 機制
部分技術産品采取 RFC(Request For Comments) 的形式進行項目的技術方案設計、讨論與疊代,例如 React RFCs、Yarn RFCs、Rust RFCs 等等。RFC 是一種文檔優先的工作方式,并且讓方案在項目早期得到充分的讨論和論證。
RFC 機制主要包括了幾個方面的内容:
- 明确範疇:什麼時候需要 RFC
- 設定流程:有哪些環節(送出、審查、實施或延期)及要求,在各環節中各個角色的職責是什麼
- 提供模闆:RFC 的大綱
- PR 規約
PR 規約的設定目的是為了提升 PR 的品質和提高 CR 的效率。規範化的 PR 還可以基于内容産出産品的更新日志。PR 規約通常包含以下内容:
- 内容格式的規約:标題和描述應該遵循怎樣的格式
- 送出代碼的規約,例如新添加功能需提供測試用例、更新代碼需更新包版本号、每次 PR 的檔案數和代碼行數限制等
- 合并的規約,例如需要哪些人 approved 才能合并
一些開源項目将 PR 的規約通過 Github App 來進行保障,例如觀察測試代碼覆寫率的變化。
- CR 指南
高度規範化的 CR 會扼殺生産力,但毫無要求的 CR 又往往是無效的。建立 CR 指南的目的是為了提高 CR 的效率和有效性,在兩者之間尋找某種平衡。CR 指南可以包含以下内容:
- 代碼審查标準是什麼?
- 如何确定審稿人?
- 在代碼審查中應該看什麼内容?
- 在代碼審查中有哪些檔案導航的方法?
- 代碼審查的響應速度應該怎麼樣限定?
- 如何編寫代碼審查評論?
- 如何處理代碼審查中的回執?
示例:《Google 的 CR 指南》。
CR 的有效性則可以通過完整閱讀率、評論率、平均行評審時長等名額來衡量,為項目建立一定的資料名額來限制 CR 行為。
CR 的效率與具體的代碼托管平台有關,可以在指南中提供平台功能文檔和相應的小技巧。例如 Github 有完善的 CR 功能介紹文檔。
異步與實時
大多數開源項目采用異步的方式來進行協作,而不是集中辦公。這當然有所利弊,且取決于項目的性質和階段。如果采用了異步協作的方式,由于開發者個人素質和工作習慣的不同,需要有一定的機制來保障項目開發的品質和效率。
不妨參照成熟開源項目的運作模式,比方說 VS Code 制定了年度的 Roadmap,并且将工作計劃細化到了月或周的次元;有明确的分工,無論是功能子產品還是流程處理(Iusse/PR);對需求和問題的回報都有一定的管理手段。
還可以通過一些的方式來實時同步項目的狀态,例如将項目的進度等資訊通過機器人同步到線上聊天室(如釘釘群):
編寫文檔
技術産品面向使用者最重要的東西就是文檔。打造技術産品在文檔上需要考慮的問題是:如何給使用者提供好的閱讀體驗以及如何提高開發者文檔編寫和審閱的效率。
目前國内主流的技術文檔閱讀(消費)途徑是:語雀、自建網站和 Git 倉庫;編寫(生産)途徑是:在語雀上編寫或在 Git 倉庫上編寫。從生産到消費的鍊路有:
- 在語雀上編寫,在語雀上閱讀,自建站點,請求語雀的接口擷取文檔内容後渲染成網頁
- 在倉庫上編寫,在倉庫内閱讀,自建站點,将 Markdown 渲染成網頁
對比這幾個鍊路的優缺點是:
大型項目或有開源的計劃,通常會選擇第四種方案。
開發官網
技術産品大多都需要一個官網來承載産品資訊,又或者在「編寫文檔」上選擇了第四種方案,則需要考慮如何基于 Markdwon 來生成網站用于展示。目前社群上有很多文檔網站的方案,例如 Docusaurus、VuePress、Docsify 等等。在進行選型的時候可以考量的點是:
- 是否支援多主題?
- 是否支援自定義頁面?
- 是否支援生成靜态站點?
- 是否支援寫多語言和多版本的文檔?
- 是否支援在文檔中渲染示例?
- 上手門檻如何?
- 定制能力如何,使用何種技術棧進行定制?
- 部署成本如何?
參考:《Docusaurus 與其他工具的對比》
開源項目普遍的選擇是部署到 GitHub Pages 上,資源托管和通路域名的問題都搞定了。但是國内通路 Github 實在太慢了,有一種解決方式是利用國内的代碼托管平台(例如 gitee 或 coding)的 Pages 服務 來進行部署。可以将 Github 的倉庫代碼同步到這些平台上去。
在阿裡内網,主要是通過 DEF 進行部署,針對文檔站點,有以下幾個方案:
對于内部技術産品來說,沒有必要将 CDN 資源釋出到外網,是以當下在 DEF 鍊路下選擇第三種方案是比較合适的。
營運産品
▐ 應持何種心态
完成了技術産品後,需要我們主動去營運它。可能很多程式員不擅長這個環節,覺得有些嘩衆取寵,黃婆賣瓜自賣自誇。
- 筆者的觀點是:
- 技術營運是一種技術自信和擔當。
- 酒香也怕巷子深,尤其是在資訊爆炸的今天。
- 當然技術營運應該是真實的、适度的:
- 真實是指不誇大自己産品的功能,找到目标使用者并解決他們的問題;
- 适度是指營運的目的是為了争取曝光獲得潛在的使用者,而不是騷擾他人或诋毀對手。
- 一些值得商榷的行為:
- 做的産品跟 A 開發者群體八根子都打不着,但挨個私聊發廣告;
- 在營運文章中自我摽榜,把競對貶的一文不值;
- 到各種競對的營運文章下瘋狂貼牛皮癬。
▐ 輸出什麼樣的内容
技術營運的内容上,軟文和幹貨自然能夠獲得技術媒體更多的轉發,這類文章通常都是從開發者切身關注的問題和技術熱點入手,通過方案的輸出吸引讀者,例如筆者寫過的《如何用“心流”提升編碼工作效率》、《10 VS Code 使用技巧》、《從生産到消費,基于物料的前端開發鍊路》等等。硬廣也必不可少,這類文章主要講述産品的功能,通過講事實擺道理的方式直抒胸臆,例如《淘系前端研發工具 AppWorks 正式釋出》、《Iceworks: 從 GUI 開發工具到內建研發工作台》等等。
毫無疑問,一個好的标題能為文章獲得更多的閱讀量。比方說筆者的兩篇文章:《淘系自研前端研發工具 AppWorks 正式釋出》就比《Iceworks: 多端研發套件》閱讀量和互動率高出一個檔次。同樣的,「如何快速打造爆款技術産品」的文章标題可能又比「如何打造技術産品」更具吸引力。甚至有些時候,我會在不同的投放管道使用不同的文章标題或内容組織形式:嚴肅官媒、大衆傳媒和灌水社群的閱聽人對标題的敏感度和内容的喜好傾向是不同的。
▐ 有哪些途徑
作為技術産品的作者,應該主動尋找更多更廣更合适的管道來進行技術宣發。遵循由小範圍到大範圍,逐漸鋪開的宣發思路。法海(fahai) 老師著有一篇 《技術寫作如何宣發》[注7],從内網、公網、私域等方面梳理宣發管道,改思路值得參考。
最後,一個技術産品的營運既需要有爆點,也需要有持續性。例如進入産品成熟期的 ICE 和 Rax 就通過月報、工作群釋出産品更新日志等形式持續同步産品的動态。
管理需求和權限
技術産品上線後,使用者可能會送出新的需求或回報遇到的問題。怎樣以更高效的方式使得使用者獲得更好的服務體驗是一個必須面對的問題。這方面筆者也沒有一個好的答案,這裡主要講講筆者看到的一些實踐。
開源項目通常通過 Issue 來收集使用者的需求和問題。Github 有 Issue Template 的功能可以讓開發者通過模闆定義不同類型 Issue 的内容格式,由此來引導使用者建立更高品質的 Issue:
此外,通過标簽的方式來對 Issue 進行歸類整理也是比較普遍的管理形式。
Issue 的定位有點類似于商業産品的「工單模式」。開源項目的維護者沒有辦法回應所有使用者的需求和問題,更期望社群使用者能夠互相幫助解決問題,是以會建立線上溝通途徑讓使用者們彼此交流。例如國外開源項目常使用 Stack Overflow 或 Github Discussions 建立線上讨論區,使用 Discord 建立實時線上聊天室。國内社群的「互助模式」主要是使用各類辦公溝通軟體(如釘釘)建立使用者群。
阿裡内部技術産品普遍做法是通過 Aone [注8] 來跟蹤需求和缺陷,接入研發小蜜[注9] 來提供答疑服務。得益于這些工具,在阿裡内部,技術産品的需求和缺陷的管理已經可以線上化了,未來完全可以數字化地評估技術團隊在這方面的投入和産出,例如中台團隊可以将答疑解決率、Aone 需求/缺陷處理率等名額納入到績效考核中。公司内部的技術産品也理應以商業産品的标準來要求自己。
寫在最後
封面圖是筆者在參加某次手工活動時制作的木制品。我清楚地記得,車子的成型非常容易,隻需要使用大型切割工具進行作業,幾步即可完成。但要讓它真正地成為一個工藝品,則需要耐心和大量的時間去磨平它的菱角。我想做技術産品也是如此吧。正文所言的條條框框僅僅是讓技術産品有一個大體的輪廓,要讓它真正能為開發者所用所喜愛,還需點點滴滴、持續疊代的精雕細琢。
注釋
注1:Iceland 是淘系内部的界面設計平台
注2:阿裡低代碼引擎是面向低代碼領域的 SDK
注3:《淘系技術部前端外包現狀調研報告》是一份内部文檔,報告了淘系外包的研發現狀
注4:《螞蟻 Could IDE 調研報告》是一份内部文檔,Could IDE 是螞蟻一個以代碼為中心、專業高效的雲端研發平台
注5:《前端編碼規約》是一份内部文檔,是阿裡前端标準化文檔的一部分
注6:DEF 是阿裡内部的前端工程研發平台
注7:《技術寫作如何宣發》是一篇内部文章,介紹了如何運用阿裡内部的媒體管道進行技術宣發
注8:Aone 是阿裡内部的一站式研發協同平台
注9:研發小蜜是阿裡内部一款面向内部服務與支援場景的 SaaS 解決方案平台