深入前端研发效能治理:数据化运营思路及其实践
簡介:?數(shù)據(jù)中臺(tái)前端研發(fā)無不讓人厚重真實(shí)地感受到“唯一不變的是變化”。拿集團(tuán)的數(shù)據(jù)資產(chǎn)服務(wù)平臺(tái)來說,業(yè)務(wù)上經(jīng)過兩年的發(fā)展,已由單一的數(shù)據(jù)管理和使用平臺(tái)發(fā)展成了集團(tuán)具有一定規(guī)模和影響力的全域數(shù)據(jù)要素交易所,而從前端技術(shù)側(cè),僅從代碼提交報(bào)表就能明顯看到,今年的代碼提交量平均是去年的 2-3 倍,可見其業(yè)務(wù)擴(kuò)張速度之快。
作者 | 杭歌
來源 | 阿里技術(shù)公眾號(hào)
一 背景
數(shù)據(jù)中臺(tái)前端研發(fā)無不讓人厚重真實(shí)地感受到“唯一不變的是變化”。拿集團(tuán)的數(shù)據(jù)資產(chǎn)服務(wù)平臺(tái)來說,業(yè)務(wù)上經(jīng)過兩年的發(fā)展,已由單一的數(shù)據(jù)管理和使用平臺(tái)發(fā)展成了集團(tuán)具有一定規(guī)模和影響力的全域數(shù)據(jù)要素交易所,而從前端技術(shù)側(cè),僅從代碼提交報(bào)表就能明顯看到,今年的代碼提交量平均是去年的 2-3 倍,可見其業(yè)務(wù)擴(kuò)張速度之快。
代碼提交量暴漲的背后,是團(tuán)隊(duì)、技術(shù)和研發(fā)過程的發(fā)展。研發(fā)團(tuán)隊(duì)從最初的 2-3 人,發(fā)展到了如今約 10 人規(guī)模;項(xiàng)目的前端工程也經(jīng)歷了從常規(guī)的 React+TypeScript+數(shù)據(jù)流架構(gòu),到支持多獨(dú)立業(yè)務(wù)模塊的 Monorepo 微前端形式,再到 Pro-Code 與搭建結(jié)合的開發(fā)模式;流程上也經(jīng)歷過月級(jí)別的大迭代與周級(jí)別的敏捷開發(fā),有過單人負(fù)責(zé)與多人協(xié)作開發(fā),甚至與外包同學(xué)遠(yuǎn)程跨業(yè)務(wù)領(lǐng)域廣泛協(xié)作,經(jīng)歷了不少難題。
1 為什么要數(shù)據(jù)化運(yùn)營?
遇到的困難中,今日且不談這些具體的難題,業(yè)務(wù)的增長帶來技術(shù)和團(tuán)隊(duì)的種種變化,再平常不過了。不妨換個(gè)思路,跳出研究問題本身,先找一找問題產(chǎn)生的根本性原因:
- 覺得一天到晚都在處理代碼評(píng)審,為什么?是業(yè)務(wù)需求多,節(jié)奏快,還是開發(fā)者的習(xí)慣或研發(fā)流程節(jié)奏出現(xiàn)了問題?
- 代碼評(píng)審問題那么多,處理了兩三天還不斷有新的問題,為什么?是開發(fā)者代碼水平問題還是自己評(píng)審的方式存在不妥的地方?
- 一個(gè)開發(fā)同學(xué)同樣的問題每次總是出現(xiàn),為什么?是業(yè)務(wù)邏輯本身限制還是編碼流程和規(guī)范培訓(xùn)得不到位?
我們當(dāng)然希望每個(gè)問題都能準(zhǔn)確找到它們的根本原因,因此我們經(jīng)常找開發(fā)同學(xué)尋求反饋,但反饋效果往往比較局限。例如,我不去問,對(duì)方不會(huì)反饋問題;我覺得不需要優(yōu)化的點(diǎn),對(duì)方覺得需要;我打算以某種方式解決某效率問題,但常常是解決得不徹底或者根本沒有解決。
這個(gè)問題的根本原因在于,我們都是站在自己的視角來審視問題,而沒有一個(gè)更高的俯視視角來幫助我們看清全局,甚至是洞察一些規(guī)律性、預(yù)測性的變化。越來越多的訴求指向了“數(shù)據(jù)化運(yùn)營”這個(gè)概念。
2 明確目標(biāo)
上面我們提到,希望通過研發(fā)效能的數(shù)據(jù)化運(yùn)營思路,通過真實(shí)的研發(fā)效能數(shù)據(jù)來看清團(tuán)隊(duì)的整體大盤和明細(xì)指標(biāo),就能從更高的位置審視團(tuán)隊(duì)的業(yè)務(wù)研發(fā),隱藏的問題就能夠在數(shù)據(jù)中暴露,問題的原因就能夠在數(shù)據(jù)中自現(xiàn),從而使人更好地思考如何解決,更加準(zhǔn)確定位到根本,最終使研發(fā)效能得到提升。
作為數(shù)據(jù)中臺(tái)前端團(tuán)隊(duì)業(yè)務(wù)開發(fā)者與研發(fā)流程管控者中的一員,本次和大家分享在團(tuán)隊(duì)中我們?nèi)绾芜\(yùn)用數(shù)據(jù)化運(yùn)營的思路來管理研發(fā)流程與研發(fā)質(zhì)量,達(dá)到提升研發(fā)效能的目標(biāo)。
二 研發(fā)效能數(shù)據(jù)化運(yùn)營全鏈路
1 設(shè)計(jì)指標(biāo)
要提升研發(fā)效能,我們需要定義出關(guān)鍵的數(shù)據(jù)指標(biāo)。通常的研發(fā)效能指標(biāo)涵蓋了整個(gè)研發(fā)流程中的不同環(huán)節(jié),相輔相成。如“代碼質(zhì)量分(代碼 Lint 問題數(shù))”“需求研發(fā)周期”“敏捷迭代交付周期”“研發(fā)活動(dòng)效率”“發(fā)布耗時(shí)”等。
限于篇幅,本文以“研發(fā)活動(dòng)效率”這一指標(biāo)為研究對(duì)象,探討結(jié)合團(tuán)隊(duì)實(shí)際情況,我們能做什么。
研發(fā)活動(dòng)是團(tuán)隊(duì)平常進(jìn)行最多的事,映射到具體的研發(fā)流程,則是代碼 Commit 和提交代碼評(píng)審。評(píng)審人負(fù)責(zé)代碼評(píng)審的質(zhì)量把控,并最終通過評(píng)審并合并代碼到主分支,一次“研發(fā)活動(dòng)”即告捷。經(jīng)過團(tuán)隊(duì)大量實(shí)踐表明,最能影響研發(fā)活動(dòng)效率的是代碼評(píng)審的提交頻率和處理時(shí)間。
首先,對(duì)開發(fā)者,代碼評(píng)審需要規(guī)約。我們規(guī)定以 1 天或 2 天為代碼評(píng)審提交周期,以每個(gè) Aone 缺陷或需求為最小粒度,隔一段時(shí)間就提一個(gè),否則會(huì)造成新開發(fā)代碼量的積壓,造成評(píng)審人壓力過大,若是問題較多,或是邏輯出現(xiàn)方向性問題,更難以控制項(xiàng)目進(jìn)度和風(fēng)險(xiǎn);相反,如果頻率過高,中途不斷打斷評(píng)審人正常的工作,也會(huì)對(duì)其造成困擾。
其次,對(duì)代碼評(píng)審人,也需要一定的約定。例如代碼評(píng)審提交過來,可能有些評(píng)審?fù)瑢W(xué)會(huì)忘記或暫時(shí)擱置,造成提交的代碼久久無人處理,與此同時(shí)開發(fā)同學(xué)又提交了新的業(yè)務(wù)代碼,就回到了上面提到的代碼積壓問題,造成評(píng)審阻塞的惡性循環(huán)。
聊到這兒,相信大家已經(jīng)知道了團(tuán)隊(duì)的痛點(diǎn):在 5+ 業(yè)務(wù)領(lǐng)域,8+ 需求并行,加以外包協(xié)作的 10 人(正式同學(xué))前端研發(fā)團(tuán)隊(duì)中,我們明確代碼評(píng)審暴露的問題,但我們不知道量化出來具體是怎么樣的情況,到底耗時(shí)多久,也不知道是哪些開發(fā)同學(xué)或評(píng)審?fù)瑢W(xué)的節(jié)奏出現(xiàn)了異常,問題只有現(xiàn)象沒有切入點(diǎn)。因此我們走一個(gè)數(shù)據(jù)化運(yùn)營的完整流程,來嘗試解決上述問題。
2 埋點(diǎn)上報(bào)
明確了要觀察的指標(biāo),下一步是對(duì)整個(gè)指標(biāo)進(jìn)行拆解,確定在研發(fā)流程中需要上報(bào)哪些數(shù)據(jù)。對(duì)“代碼評(píng)審處理時(shí)長和頻率”,我們可以分解出如下信息:
- 代碼評(píng)審提交時(shí)間
- 代碼評(píng)審?fù)ㄟ^時(shí)間
- 代碼提交人
- 代碼評(píng)審人
- 該輪代碼評(píng)審是否被合并
- 該輪代碼評(píng)審的輪次
- 其他必要的信息,如提交的評(píng)審屬于哪個(gè)分支,哪個(gè)需求,哪個(gè)項(xiàng)目等。
如何收集這些數(shù)據(jù)呢?
團(tuán)隊(duì)研發(fā)效能工具簡介
得益于團(tuán)隊(duì)的研發(fā)效能基建(見上圖),我們通過研發(fā)效能工具 DT-Hornet,實(shí)現(xiàn)了團(tuán)隊(duì)研發(fā)流程管控的“大一統(tǒng)”。
- 在調(diào)用自定義 NPM Script 的“req”(需求管理,requirements manage)命令進(jìn)行分支創(chuàng)建和維護(hù)時(shí),能夠收集到分支和對(duì)應(yīng)的需求相關(guān)信息,甚至讓開發(fā)者預(yù)先填好需求的聯(lián)調(diào)、提測、發(fā)布等時(shí)間節(jié)奏;
- 在調(diào)用“cr”(提交代碼評(píng)審,code review)命令提交代碼評(píng)審時(shí),工具能夠通過開發(fā)者所在的分支自動(dòng)識(shí)別到其對(duì)應(yīng)需求并自動(dòng)確認(rèn)目標(biāo)分支,自動(dòng)收集 Commit 信息,觸發(fā) Aone 相關(guān)提交邏輯,方便地創(chuàng)建代碼評(píng)審并發(fā)送釘釘通知到群;
- 在調(diào)用“pub”(發(fā)布,publish)命令時(shí)通過自動(dòng)識(shí)別到的開發(fā)者和需求信息,自動(dòng)發(fā)布準(zhǔn)確的預(yù)發(fā)環(huán)境(團(tuán)隊(duì)內(nèi)是多套前端環(huán)境并存,互不干擾)。
CR命令層埋點(diǎn)邏輯
下面聊一些技術(shù)細(xì)節(jié)。當(dāng)開發(fā)者提交 CR 時(shí),經(jīng)過如下步驟的自動(dòng)化處理:
- 校驗(yàn)工作區(qū)是否干凈,判斷當(dāng)前分支有效性;
- 找到對(duì)應(yīng)需求,確認(rèn)目標(biāo)分支;
- 訪問持久化數(shù)據(jù),檢查是否有前置 CR(即,前一次 CR 未合并,本次有新的 Commit,提交后仍然是同一個(gè)CR);
-
查找是否有未上報(bào)的已完成 CR 信息,并收集其中有用的信息并上報(bào):
- 在此過程中,會(huì)計(jì)算前一次 CR 的最新 Commit ID 是否已經(jīng)包含在目標(biāo)遠(yuǎn)程分支的 Commit Log 集合中,若包含則表示代碼已合并,即 CR 已完成;
- 若有已完成的 CR 信息,則從持久化 CR 信息中取得 CR 提交時(shí)間,從目標(biāo)分支的 Commit Log 中取得代碼合并結(jié)點(diǎn)的提交時(shí)間作為代碼合并時(shí)間,即可作為準(zhǔn)確的 CR 通過時(shí)間;
- 代碼檢查,自動(dòng)合并目標(biāo)分支代碼,若產(chǎn)生代碼沖突則報(bào)錯(cuò)返回;
- 執(zhí)行真正的提交 CR 邏輯,并將 CR 所有信息合在一起做數(shù)據(jù)上報(bào)和持久化存儲(chǔ),后續(xù)釘釘通知到群;
- 最后對(duì) CR Commit 進(jìn)行打標(biāo),方便后續(xù)通過 Tag 找到 Commit ID。
監(jiān)控平臺(tái)使用及技術(shù)層邏輯簡介
在上述 CR 提交與埋點(diǎn)邏輯的基礎(chǔ)上,借助集團(tuán)監(jiān)控平臺(tái)ARMS的能力(封裝了通用能力 Trace-SDK),我們能夠輕易地上報(bào)數(shù)據(jù)。
要使用監(jiān)控平臺(tái),需要在其中注冊(cè)一個(gè)應(yīng)用,獲得一個(gè) PID 唯一標(biāo)識(shí)。在埋點(diǎn)上報(bào)邏輯中,在 Trace-SDK 實(shí)例化時(shí)傳入該 PID,埋點(diǎn)處調(diào)用其 log API 即可完成上報(bào)。如下代碼展示了效能工具內(nèi)核如何調(diào)用 Trace-SDK 來聲明其通用埋點(diǎn)上報(bào)邏輯。
/** 效能工具內(nèi)核類聲明(與埋點(diǎn)上報(bào)監(jiān)控平臺(tái)相關(guān)的部分) */ class HornetCore {/** 監(jiān)控單實(shí)例聲明 */private static traceInstance: TraceSdkType = null;/** HornetCore 監(jiān)控初始化 */public static initTrace = (): void => {HornetCore.traceInstance = new TraceLiteSdk({ pid: '<研發(fā)效能工具PID>' });};/** 上報(bào)參數(shù)給監(jiān)控平臺(tái) */public static sendTraceLog = async (/*** 上報(bào)類型*/type: string,/*** 上報(bào)的參數(shù)*/params?: TraceLogParamType,): Promise<void> => {try {// 操作人工號(hào)const uid = DYNAMIC_NAMES.ADMIN_WORK_ID;// 操作人const c1 = DYNAMIC_NAMES.ADMIN_NAME;// 應(yīng)用名const c2 = DYNAMIC_NAMES.PROJECT_NAME;// 分支名const c3 = DYNAMIC_NAMES.BRANCH_NAME;let c4: any;let c5: any;let c6: any;let c7: any;let c8: any;// 工具是否最新版const c9 = HornetCore.isLatestVersion.toString();// 工具內(nèi)核版本號(hào)const c10 = HornetCore.version;switch (type) {case TRACE_LOG_TYPE.CR: {const { targetBranch, crAdmins, crAdminCnt, currentReqName, crSequence } = params || {};[c4, c5, c6, c7, c8] = [targetBranch, crAdmins, crAdminCnt, currentReqName, crSequence];break;}case TRACE_LOG_TYPE.CR_HANDLING: {const { targetBranch, currentReqName, crCount, crStartTime, crEndTime } = params || {};[c4, c5, c6, c7, c8] = [targetBranch, currentReqName, crCount, crStartTime, crEndTime];break;}default:[c4, c5, c6, c7, c8] = [null, null, null, null, null];}const logParams = { type, uid, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 };return HornetCore.traceInstance.log(logParams);} catch (e) {BasicMessage.error(`上報(bào)數(shù)據(jù)錯(cuò)誤: ${SPLIT_VALUE.BREAK}${e}`);return Promise.reject();}}; }如代碼所示,工具組織各個(gè)不同的 C 字段(自定義上報(bào)字段)來搭配不同的上報(bào)類型進(jìn)行上報(bào),在 CR 上報(bào)的場景中,需要兩種類型,CR 用來上報(bào)按“次”來計(jì)算的 CR 的詳細(xì)信息,而 CR_HANDLING 用來上報(bào)計(jì)算后的按“輪”來計(jì)算的 CR 信息,一“輪” CR 中可能包含多“次” CR。
在監(jiān)控平臺(tái)側(cè),對(duì)應(yīng)地配置了上報(bào)類型和 C 字段的別名,方便后續(xù)的數(shù)據(jù)拉取和處理。如下圖所示。
埋點(diǎn)上報(bào)數(shù)據(jù)即發(fā)送請(qǐng)求。一般是請(qǐng)求服務(wù)端某個(gè) 1*1 像素的圖片,并在請(qǐng)求發(fā)送時(shí)帶上所有需要上報(bào)的信息。這里除了 CR 信息,還包括一些通用的系統(tǒng)層面的信息。
監(jiān)控平臺(tái)接收到數(shù)據(jù),將數(shù)據(jù)通過日志服務(wù)存儲(chǔ)到 HBase 集群,數(shù)據(jù)在 ARMS 平臺(tái)即可通過即席查詢獲取到。
3 數(shù)據(jù)處理
歸功于 ARMS 監(jiān)控平臺(tái),上述步驟已完成了數(shù)據(jù)的采集和存儲(chǔ),接下來要進(jìn)行數(shù)據(jù)的同步回流和初步處理等操作。每天上報(bào)到監(jiān)控平臺(tái)的實(shí)時(shí)數(shù)據(jù)將存儲(chǔ)到相應(yīng)的離線小時(shí)表中,我們申請(qǐng)對(duì)應(yīng)表的權(quán)限,通過查詢表的視圖,能夠獲取到效能工具 PID 下采集的所有明細(xì)數(shù)據(jù)。
離線數(shù)據(jù)同步
由于監(jiān)控平臺(tái)存儲(chǔ)成本有限,只能保留近 30 天的數(shù)據(jù),且原表包括了監(jiān)控平臺(tái)中所有 PID 上報(bào)的數(shù)據(jù),數(shù)據(jù)量非常大,造成視圖查詢較慢,且查詢時(shí)若條件不嚴(yán)格,很容易因資源不足而發(fā)生查詢錯(cuò)誤。因此我們考慮在 Dataworks 上建立一個(gè)周期任務(wù),將我們需要的數(shù)據(jù)定期同步到自己創(chuàng)建的表中,即可解決問題。
在周期任務(wù)中,我們通過 INSERT OVERWRITE 語句,按照 ds 字段規(guī)定的分區(qū)范圍,每天向表 source_table 中寫入數(shù)據(jù),且不會(huì)產(chǎn)生重復(fù)數(shù)據(jù)。將該任務(wù)發(fā)布后,它每天就會(huì)生成一個(gè)周期實(shí)例,穩(wěn)定地為我們提供所需的監(jiān)控?cái)?shù)據(jù)。
數(shù)據(jù)分析 SQL 設(shè)計(jì)
我們利用 FBI 平臺(tái)來做數(shù)據(jù)分析。在 FBI 數(shù)據(jù)集編輯中,我們可以方便地基于剛才創(chuàng)建的 ODPS 表聲明 SQL,進(jìn)一步解析自己想要的字段。
我們將 C 字段全部語義化,并運(yùn)用簡單的內(nèi)置函數(shù),對(duì)數(shù)據(jù)進(jìn)行空值處理或格式化處理,以備進(jìn)一步利用。代碼評(píng)審數(shù)據(jù)明細(xì)分析表、代碼評(píng)審處理數(shù)據(jù)明細(xì)分析表和代碼評(píng)審匯總分析表分別聲明如下:
/*代碼評(píng)審數(shù)據(jù)明細(xì)分析表 */ SELECTa.stat_date,a.ds,a.log_day,substr(a.log_hour, 9) as log_hour,substr(a.log_time, 9) as log_time,substr(a.log_second, 9) as log_second,a.c1 as admin_name,b.c2 as project_name, -- 項(xiàng)目中文名信息由維表提供a.c2 as project_en_name,a.c3 as branch_name,a.c4 as target_branch,a.c5 as cr_admins,substring_index(c5, ',', 1) as cr_first_admin, -- 取得第一個(gè)評(píng)審人為主要評(píng)審人信息a.c6 as cr_admin_cnt,a.c7 as cur_req_name,concat(c4, ' ', c7) as cur_branch_and_req_name,a.c8 as cr_sequence,a.c9 as latest_version_flag,a.c10 as cur_version FROMsource_table aLEFT OUTER JOIN (SELECTcode,c1,c2FROMsource_table_dim -- 維表存儲(chǔ)不經(jīng)常更改的維度信息) b ON a.c2 = b.c1 WHEREa.code = 'code_review'AND b.code = 'project_name'AND a.c4 != 'develop' -- 過濾掉提交到主發(fā)布分支的 CR,因?yàn)槠洳皇顷P(guān)鍵信息AND a.ds > 20210630; -- 限定有數(shù)據(jù)的 ds 范圍,增加查詢性能/*代碼評(píng)審處理數(shù)據(jù)明細(xì)分析表 */ SELECTa.stat_date,a.ds,a.log_day,substr(a.log_hour, 9) as log_hour,substr(a.log_time, 9) as log_time,substr(a.log_second, 9) as log_second,a.c1 as admin_name,b.c2 as project_name,a.c2 as project_en_name,a.c3 as branch_name,a.c4 as target_branch,a.c5 as cur_req_name,concat(a.c4, ' ', a.c5) as cur_branch_and_req_name,concat(b.c2, ' ', a.c5) as cur_project_and_req_name,c.c1 as cur_req_admin_name,a.c6 as cr_count,a.c7 as cr_start_time,a.c8 as cr_end_time,datediff(to_date(a.c8, 'yyyy-mm-dd hh:mi:ss'),to_date(a.c7, 'yyyy-mm-dd hh:mi:ss'),'mi') as cr_duration, -- 使用 datediff 函數(shù)來計(jì)算CR處理時(shí)長a.c9 as latest_version_flag,a.c10 as cur_version fromsource_table aLEFT OUTER JOIN (SELECTcode,c1,c2FROMsource_table_dimWHEREcode = 'project_name' -- 關(guān)聯(lián)項(xiàng)目名稱信息) b ON a.c2 = b.c1LEFT OUTER JOIN (SELECTdistinct code,c1,c2,c3,c4FROMsource_tableWHEREcode = 'requirements' -- 關(guān)聯(lián)需求信息) c ON a.c5 = c.c4 WHEREa.code = 'code_review_handling'AND a.c4 != 'develop'AND a.c8 IS NOT NULL -- 沒有CR結(jié)束時(shí)間的定義為廢棄CR,此處過濾掉AND a.c8 != 'null'AND a.ds > 20210720;/*代碼評(píng)審匯總分析表 */ SELECTstat_date,project_name,project_name_and_req_name,cur_req_name,admin_name,COUNT(admin_name) as cr_cnt -- 統(tǒng)計(jì)CR提交次數(shù) FROM(SELECTa.stat_date,a.ds,a.log_day,substr(a.log_hour, 9) as log_hour,substr(a.log_time, 9) as log_time,substr(a.log_second, 9) as log_second,a.c1 as admin_name,b.c2 as project_name,a.c2 as project_en_name,a.c3 as branch_name,a.c4 as target_branch,a.c5 as cr_admins,substring_index(a.c5, ',', 1) as cr_first_admin,a.c6 as cr_admin_cnt,a.c7 as cur_req_name,concat(b.c2, ' ', a.c7) as project_name_and_req_name,a.c8 as cr_sequence,a.c9 as latest_version_flag,a.c10 as cur_versionFROMsource_table aLEFT OUTER JOIN (SELECTcode,c1,c2FROMsource_table_dim) b ON a.c2 = b.c1WHEREa.code = 'code_review'AND a.c4 != 'develop'AND a.ds > 20210715AND b.code = 'project_name') GROUP BY -- 選擇日期、項(xiàng)目名稱、需求名稱、開發(fā)者等維度stat_date,project_name,cur_req_name,admin_name,project_name_and_req_name;4 設(shè)計(jì)報(bào)表
產(chǎn)出了分析數(shù)據(jù),接下來就可以進(jìn)行報(bào)表設(shè)計(jì)與搭建了。FBI 平臺(tái)提供了豐富的圖表可供選擇,在使用時(shí)需要明確它們的含義。
圍繞著代碼評(píng)審,我們?cè)O(shè)計(jì)了以下總體和細(xì)分指標(biāo)的報(bào)表。
代碼活動(dòng)總覽報(bào)表
- CR 平均處理時(shí)長及健康狀況,認(rèn)為 24 小時(shí)以下為健康;
- CR 平均頻次及健康狀況,認(rèn)為每人每天 1-3 次為健康;
- CR 平均處理時(shí)長按開發(fā)者、需求的排行榜;
- CR 平均頻次按開發(fā)者的排行榜(為避免內(nèi)卷,當(dāng)頻次由高到低排列時(shí),只展示超出健康度范圍外的數(shù)據(jù))。
代碼活動(dòng)明細(xì)報(bào)表
- 項(xiàng)目粒度的代碼活動(dòng)健康度(CR 平均處理時(shí)長、CR 平均頻次);
- 項(xiàng)目下各需求 CR 占比;
- 項(xiàng)目 CR 提交時(shí)間分布;
- 項(xiàng)目粒度的需求 CR 流轉(zhuǎn)情況(需求-開發(fā)者-主要評(píng)審人);
- 項(xiàng)目下各開發(fā)者的 CR 提交頻數(shù)與負(fù)責(zé)需求數(shù)對(duì)比等。
除此之外,報(bào)表頁面還搭建了查詢?cè)敿?xì)數(shù)據(jù)的明細(xì)列表,支持搜索各項(xiàng)維度數(shù)據(jù),如項(xiàng)目名稱、開發(fā)者等。
5 問題洞察與解決
經(jīng)過以上的報(bào)表搭建和優(yōu)化,我們能初步解決首要的“看數(shù)”問題——不再擔(dān)心代碼評(píng)審產(chǎn)生的成本無法量化,能夠明確代碼評(píng)審具體耗時(shí)多久,也能從報(bào)表中發(fā)現(xiàn)和洞察潛在的問題。
案例一:總覽分析
從有數(shù)據(jù)記錄以來,發(fā)現(xiàn)從 7 月初到 9 月初,團(tuán)隊(duì)的代碼活動(dòng)明顯提升,若項(xiàng)目是固定的,CR 頻數(shù)卻上升了,則說明需求量可能有上升趨勢(shì),再對(duì)比 CR 涉及的項(xiàng)目數(shù)趨勢(shì),跟 CR 提交趨勢(shì)線基本吻合,說明有更多的項(xiàng)目利用效能工具的能力,而需求研發(fā)可以認(rèn)為對(duì)于項(xiàng)目粒度的研發(fā)是表現(xiàn)正常的,但整體趨勢(shì)是項(xiàng)目增多,也要關(guān)注團(tuán)隊(duì)同學(xué)們的業(yè)務(wù)壓力。
獲得了上述信息后,結(jié)合團(tuán)隊(duì)中實(shí)際研發(fā)的項(xiàng)目,可逐一觀察項(xiàng)目粒度的明細(xì)報(bào)表數(shù)據(jù),進(jìn)一步了解業(yè)務(wù)研發(fā)情況。
案例二:異常洞察
研發(fā)效能管理者和項(xiàng)目負(fù)責(zé)人會(huì)關(guān)注一些異常的數(shù)據(jù),例如超出健康度的 CR 處理時(shí)長、CR 頻次等信息。項(xiàng)目負(fù)責(zé)人可以立即提醒相應(yīng)的開發(fā)同學(xué)或需求的對(duì)應(yīng)負(fù)責(zé)人,讓其關(guān)注項(xiàng)目的進(jìn)展情況,使該項(xiàng)目需求研發(fā)回到健康的狀態(tài)。
案例三:項(xiàng)目級(jí)效率研判
項(xiàng)目負(fù)責(zé)人也可以關(guān)注自己項(xiàng)目的代碼活動(dòng)健康狀況。上圖中 A 項(xiàng)目 CR 平均處理時(shí)長在 4 小時(shí)左右,基本上當(dāng)天問題能夠當(dāng)天解決,且 CR 平均頻次為 1.8 次,說明該項(xiàng)目的代碼評(píng)審基本能夠無問題通過,或者一次把問題解決。項(xiàng)目的健康度較高。
而 B 項(xiàng)目的數(shù)據(jù)相對(duì)一般,CR 平均處理時(shí)長超過了 1 天,且平均每輪 CR 頻次達(dá)到了 5.5 次,不是一個(gè)健康的狀態(tài)。這時(shí)項(xiàng)目負(fù)責(zé)人就需要引起關(guān)注,深入項(xiàng)目中尋找是什么因素導(dǎo)致了異常,并對(duì)項(xiàng)目未來的進(jìn)展做一些研判和決策:
- 項(xiàng)目排期是否正常?
- 項(xiàng)目開發(fā)者是否遇到了困難?
- 開發(fā)習(xí)慣和模式是否需要調(diào)整?等等。
三 思考:如何利用數(shù)據(jù)化運(yùn)營解決問題?
1 數(shù)據(jù)化運(yùn)營的本質(zhì)是沉淀或驗(yàn)證經(jīng)驗(yàn)
當(dāng)我們接觸一個(gè)新的領(lǐng)域,或者對(duì)于某些業(yè)務(wù)邏輯、用戶體驗(yàn)不知道當(dāng)前的產(chǎn)品設(shè)計(jì)能否真正服務(wù)到客戶,就可以嘗試用數(shù)據(jù)化運(yùn)營來幫助觀測效果,沉淀經(jīng)驗(yàn),知道什么樣的設(shè)計(jì)是好的,什么樣的設(shè)計(jì)并沒有價(jià)值。
或者,借助埋點(diǎn)上報(bào)的真實(shí)統(tǒng)計(jì)數(shù)據(jù),我們可以更客觀地驗(yàn)證產(chǎn)品設(shè)計(jì)的價(jià)值。例如,某個(gè)數(shù)據(jù)表配置頁面,一開始用戶需要一個(gè)一個(gè)配置,效率很低;后續(xù)經(jīng)過用戶調(diào)研,設(shè)計(jì)添加了一個(gè)自動(dòng)同步元數(shù)據(jù)的按鈕,一鍵添加即可,用戶可能只需要修改部分字段的信息即可提交。我們通過埋點(diǎn)觀察用戶從打開編輯頁面到點(diǎn)擊保存按鈕的時(shí)間間隔變化趨勢(shì),即能夠驗(yàn)證該優(yōu)化的價(jià)值所在。
2 避免過度依賴數(shù)據(jù)的誤區(qū)
數(shù)據(jù)化運(yùn)營的優(yōu)點(diǎn)可見一斑,但也需要避免一刀切地過度使用和依賴數(shù)據(jù)。當(dāng)我們熟悉了所在的業(yè)務(wù)領(lǐng)域,通過多次的數(shù)據(jù)驗(yàn)證形成經(jīng)驗(yàn)后,再遇到類似的場景,即可快速高效地決策。
3 數(shù)據(jù)化運(yùn)營能給研發(fā)效能治理帶來什么
研發(fā)效能治理是一個(gè)長期的、持續(xù)的過程。隨著團(tuán)隊(duì)支持的業(yè)務(wù)日新月異千變?nèi)f化,我們也多次迭代了效能工具來通過技術(shù)手段間接地支持著業(yè)務(wù)。
現(xiàn)階段,團(tuán)隊(duì)所有業(yè)務(wù)的前端研發(fā)都采用現(xiàn)行的研發(fā)效能工具體系和數(shù)據(jù)化運(yùn)營方案。搭建的數(shù)據(jù)報(bào)表主要解決“看數(shù)”的問題,可以從中主動(dòng)發(fā)現(xiàn)異常并找到問題的根源,但數(shù)據(jù)化運(yùn)營提供的能力不僅于此。
自動(dòng)化信息同步機(jī)制
以往發(fā)布需求,發(fā)布負(fù)責(zé)人會(huì)運(yùn)行效能工具的功能命令來打印出將要發(fā)布的需求信息,這個(gè)流程需要手動(dòng)操作,且算上規(guī)范化流程中的“新建發(fā)布計(jì)劃文檔”“新建自測報(bào)告文檔”等操作,流程成本較高。
利用數(shù)據(jù)化運(yùn)營,將創(chuàng)建的需求信息上報(bào)到監(jiān)控平臺(tái),即可利用數(shù)據(jù)進(jìn)行每周定期群播報(bào),在上線時(shí)間準(zhǔn)確的情況下,能夠讓所有開發(fā)同學(xué)看到待上線的需求,做到信息同步。再通過周期任務(wù)機(jī)制自動(dòng)化創(chuàng)建相應(yīng)發(fā)布日期的文檔,發(fā)布流程上的成本即可大大降低。
工程化串聯(lián)
研發(fā)效能報(bào)表能做的內(nèi)容遠(yuǎn)不止 CR 效率。結(jié)合工程化整體流程,我們能夠加入需求、構(gòu)建、發(fā)布、效能工具使用等相關(guān)指標(biāo),建設(shè)為報(bào)表站點(diǎn)。我們借此對(duì)整個(gè)工程化體系進(jìn)行數(shù)據(jù)化運(yùn)營,不斷優(yōu)化體驗(yàn),例如提升構(gòu)建速度、發(fā)布效率等,跳出研發(fā)流程管控本身,放眼更全局的視角。
實(shí)時(shí)告警和跟進(jìn)
我們可以通過實(shí)時(shí)告警進(jìn)一步提升主觀能動(dòng)性,例如當(dāng)開發(fā)者合并代碼出錯(cuò)時(shí),立即實(shí)時(shí)上報(bào)錯(cuò)誤,項(xiàng)目負(fù)責(zé)人就能第一時(shí)間知道是代碼沖突、權(quán)限還是其他原因,并敦促需求負(fù)責(zé)人和開發(fā)者高效解決,避免阻塞項(xiàng)目進(jìn)度。
當(dāng)效能工具、工程化框架本身出現(xiàn)邏輯錯(cuò)誤時(shí),也能夠通過實(shí)時(shí)告警及時(shí)通知到工具開發(fā)人,無需用戶反饋即可排查和解決工具 Bug。
效能工具無人值守
進(jìn)一步地,利用數(shù)據(jù)化運(yùn)營,我們能夠找出最經(jīng)常出現(xiàn)的問題,沉淀出自查文檔,在效能工具運(yùn)行報(bào)錯(cuò)的 catch 邏輯中為用戶提示出文檔鏈接,幫助其自主解決問題。經(jīng)過一段時(shí)間到沉淀,效能工具即可做到無人值守的運(yùn)營,更加提升研發(fā)效能。
綜上,我們以代碼評(píng)審效率洞察的例子了解了如何通過數(shù)據(jù)化運(yùn)營的手段管控研發(fā)效能,它能夠做到平時(shí)開發(fā)準(zhǔn)確記錄,發(fā)現(xiàn)問題及時(shí)解決;在解決問題的同時(shí)對(duì)團(tuán)隊(duì)未來研發(fā)效能發(fā)展趨勢(shì)有了新的思考和規(guī)劃。
還是那句話,研發(fā)效能治理是一個(gè)長期的、持續(xù)的過程,我們希望能運(yùn)用類似數(shù)據(jù)化運(yùn)營這樣的有效方法,廣泛地實(shí)踐研發(fā)流程,深入地定義、了解、克服其中遇到的問題,使團(tuán)隊(duì)研發(fā)猶如常青藤一般持續(xù)健康地發(fā)展壯大。
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的深入前端研发效能治理:数据化运营思路及其实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成中集团线下IDC迁移上云
- 下一篇: 复杂推理模型从服务器移植到Web浏览器的