2個動作,讓研發(fā)效率提升120%,代碼減少50%

簡介
本文以云智慧數(shù)字化運維數(shù)據(jù)平臺DODB產(chǎn)品為例,由云智慧研發(fā)團隊通過分析對比產(chǎn)品歷史版本與新版本中的Java代碼行數(shù)、Java文件個數(shù)、代碼注釋占比、發(fā)布包大小、組件依賴等關鍵數(shù)據(jù),找尋出歷史版本開發(fā)過程中存在的代碼、項目管理及開發(fā)人員等方面問題,最終梳理總結(jié)出改造代碼、制定規(guī)范等可提升研發(fā)效能的有效方法。
一、數(shù)據(jù)對比
通過下方圖表數(shù)據(jù)可以看出,在新版本中,代碼注釋占比降低了近150%,項目分支數(shù)減少了近100%,其他各項數(shù)據(jù)也均有了明顯的變化。
代碼行數(shù)統(tǒng)計
過去

現(xiàn)在

代碼注釋比例
過去

現(xiàn)在

sonar掃描
過去

現(xiàn)在

數(shù)據(jù)匯總對比
| 指標 | 過去 | 現(xiàn)在 | 對比結(jié)果 |
|---|---|---|---|
| 項目module數(shù)量 | 12 | 8 | 減少33% |
| 代碼總行數(shù) | 174252 | 136484 | 減少22% |
| Java代碼行數(shù) | 90310 | 50719 | 減少44% |
| Java文件個數(shù) | 982 | 583 | 減少41% |
| 代碼注釋占比 | 3% | 7% | 提升133% |
| sonar-bugs數(shù)量 | 92 | 0 | 減少100% |
| 對外http接口數(shù)量 | 160 | 100 | 減少37.5% |
| 對外dubbo接口數(shù)量 | 100 | 25 | 減少75% |
| 發(fā)布包大小 | 226M | 170M | 減少25% |
| 項目分支數(shù) | 300(參考) | 20 | 減少93% |
| 寫入性能(單條10K) | 88W/min | 187W/min | 提升113% |
| 組件依賴 | ignite、vertx | 刪除ignite、vertx | 5.3.1以redis替換ignite,徹底刪除vertx |
| 微服務 | 1 | 3 | 5.3.1支持服務以存儲模塊或者非存儲模塊獨立運行 |
二、歷史問題回顧
通過上述各項數(shù)據(jù)的對比分析,本章節(jié)對歷史版本開發(fā)中存在的代碼、項目管理、開發(fā)人員等各方面問題進行了回顧分析,詳細可查看下文:
代碼側(cè)問題
項目module數(shù)量多,部分不再使用的模塊仍存在;
各module模塊沒有統(tǒng)一的包名區(qū)分,導致大量全限定名一致的類存在,加載順序不一致引發(fā)各種問題;
項目中存在大量不再使用的代碼塊,增加了新人的學習成本及排查問題難度;例如dubbo接口,外部僅使用25個,對外提供了100個;
項目中重復代碼較多,相似業(yè)務復制粘貼現(xiàn)象較嚴重,維護成本較高;
重復造輪子較多,如HttpclientUtil等;
注釋率不夠,大量代碼無注釋,無測試用例;
Vertx框架改造為SpringBoot容器不徹底,仍有眾多Vertx邏輯和Springboot共存;
增加新模塊需要寫很多sql,需要手動編寫Controller、Service、Dao層的“基礎”代碼;
項目依賴ignite組集群,導致服務是有狀態(tài)的,大多人員對ignite不熟悉,導致解決問題較困難;
項目管理側(cè)問題
沒有強有力的規(guī)范無法支撐更多的成員高效的協(xié)同開發(fā);
分支管理無規(guī)范,導致分支數(shù)過多,活躍分支數(shù)量少,幾百個分支維護困難;
以分支形式交付,交付后分支仍有提交,導致追蹤發(fā)版版本困難;
無代碼管理規(guī)范,多次出現(xiàn)功能遺漏、多功能等導致分支回退;
沒有代碼review制度,無法保障代碼質(zhì)量,沖突強行解決的問題時有發(fā)生;
開發(fā)人員側(cè)問題
大多成員對代碼不夠熟悉,或僅熟悉部分代碼;
很多成員不敢修改代碼,更不敢刪除代碼;打著不影響其它功能的旗號,復制粘貼大量的重復代碼和邏輯,導致維護困難;
早期代碼設計較為合理,隨著人員不斷增加,很多代碼重copy輕設計,只求完成功能,不考慮維護性拓展性,毫無設計可言;
部分人員git不熟練,導致強行覆蓋遠程分支的情況時有發(fā)生,無權限管控;
部分問題示例
全限定名完全一致的類


重復造輪子

三、解決問題方案
為解決產(chǎn)品歷史版本開發(fā)過程中存在的代碼、項目管理等各方面問題,云智慧研發(fā)團隊制定了開發(fā)、接口等相關規(guī)范;同時,通過限制代碼倉庫權限等其他操作也保證了規(guī)范的嚴格執(zhí)行。
制定相關規(guī)范
無規(guī)矩不成方圓,切實可行的規(guī)范是保障團隊戰(zhàn)斗力的前提。規(guī)范制定應本著提高團隊水平,又不限制成員積極性為目標。
開發(fā)規(guī)范
DODB接口規(guī)范
開發(fā)規(guī)范實行計劃
DODB版本tag命名規(guī)范
開發(fā)設計模板
提測模板
會議規(guī)范
保障規(guī)范嚴格執(zhí)行
工欲善其事必先利其器,規(guī)范里提供了相應的工具,用好可達到事半功倍的目的;同時有相關提交流程保障規(guī)范落地,不能讓規(guī)范流于形式。
設置gitlab權限,保障強制代碼review
禁止任何人向保護分支提交代碼,必須走merge流程

merge列表界面

merge詳情界面

完成后遠程分支強制刪除

以tag追蹤生產(chǎn)交付,要求測試交付時一定要有tag

禁止刪除tag

標簽tag列表

標簽tag詳情

四、如何對現(xiàn)有代碼進行改造
改造原則
不影響現(xiàn)有開發(fā)和交付進度,必須互不影響,類似于空中加油機,既要加油,飛機也不能停;
保證兼容性升級,改造后原有數(shù)據(jù)和業(yè)務不受影響;
對外接口(如dubbo)原則上不能修改,保證調(diào)用方功能正常,特殊情況可溝通配合(如dubbo方法重載必須修改);
不需要的代碼一律刪除,以后需要從歷史版本找回,禁止批量注釋掉代碼;
代碼設計要遵循 高內(nèi)聚低耦合 的原則,保證可重用性、移植性;
目標一致,改造循序漸進,保證充分測試。
部分改造邏輯
對不再使用的代碼直接刪除,歷史可在gitlog中查看,例如bdp-plugin-sdk、bdp-plugin-zabbix等模塊直接刪除;
集中解決重復造輪子的問題,對部分通用邏輯,如HttpClientUtils、db操作等使用已有工具類替換;
書寫數(shù)據(jù)庫代碼繁瑣,引入mybatis-plus操作mysql
??com.baomidou
??mybatis-plus
??${mybatis-plus.version}
對外dubbo接口bdp-rpc和bdp-rpc-model合并為bdp-rpc-core對外提供,通過編譯各調(diào)用方項目,刪除未使用的接口
徹底刪除vertx和ignite依賴


對各module的功能和命名做了統(tǒng)一規(guī)范,對原有代碼做統(tǒng)一修改調(diào)整
| 模塊名稱 | 功能 | 包名前綴 |
|---|---|---|
| bdp-api | Restful API和業(yè)務邏輯實現(xiàn)、只能被bdp-standalone依賴 | com.cloudwise.bdp.api |
| bdp-base | 業(yè)務對象和接口定義 | com.cloudwise.bdp.base |
| bdp-commons | 通用工具common util | com.cloudwise.bdp.commons |
| bdp-pipeline | pipeline數(shù)據(jù)處理實現(xiàn) | com.cloudwise.bdp.pipeline |
| bdp-rpc-core | rpc接口聲明及rpc實體類定義,不能依賴其它模塊,對外rpc接口請慎重修改 | com.cloudwise.bdp |
| bdp-standalone | 主項目,DODB主入口類為DodbServiceApplication | com.cloudwise.bdp.standalone |
| bdp-store-ck | ClickHouse存取實現(xiàn) | com.cloudwise.bdp.store.ck |
| bdp-store-common | 數(shù)據(jù)層存儲接口聲明 | com.cloudwise.bdp.store.common |
調(diào)用gitlab-api對長期不活躍分支集中清理備份
?/**
?*?github-api
?*?https://github.com/help/api/api_resources.md
?*/
private?static?final?String?GITLAB_URL?=?"https://github.com/api/v4/projects/2393/repository";
private?static?final?String?PRIVATE_PARAM?=?"*****************";
?/**
?*?清理分支,已合并分支直接刪除,其余刪除前以tag形式備份
?*/
@Test
public?void?cleanBranches()?{
????Map?paramMap?=?Maps.newHashMap();
????paramMap.put("private_token",?PRIVATE_PARAM);
????paramMap.put("per_page",?10086);
????String?body?=?HttpUtil.get(GITLAB_URL?+?"/branches",?paramMap);
????List?branches?=?JSON.parseArray(body,?Branche.class);
????//?按最后一次提交時間由小到大排列
????branches.sort(Comparator.comparingLong(o?->?o.getCommit().getCommitted_date().getTime()));
????log.error("分支數(shù)量:{}",?branches.size());
????branches.forEach(item?->?log.info("{}",?item));
????//?清理長期不活躍分支
????.....
}
發(fā)布包進行瘦身
首先了解發(fā)布包是如何構(gòu)建的,參看assembly.xml配置
發(fā)布包里有什么

不要把配置文件重復打入jar包中
???org.apache.maven.plugins
???maven-jar-plugin
???
??????
?????????com/cloudwise/bdp/**
??????
??????
?????????
????????????true
????????????${start-class}
????????????../lib/
?????????
??????
???
重點關注lib包,可從以下幾個方面排查
重點關注過大的包是否是項目必須的

是否有重復依賴問題
*例如netty-all是眾多netty-的合集,不要去重復依賴,如果版本不一致還會引發(fā)問題;

batik-all是batik-*的合集,排除各個子包

排查后通過相關插件追查依賴源,精確排除
???org.apache.maven.plugins
???maven-dependency-plugin
???${maven.dependency.version}
1、開發(fā)人員應清楚依賴包是做什么的,不要不管三七二十一依賴一堆沒用的包,無謂增加發(fā)布包大小,還會帶來隱患;
2、代碼審核時,依賴文件(maven工程的pom.xml文件)的修改需要重點關注,禁止隨意引入和修改依賴;
3、各產(chǎn)品線可在統(tǒng)一各依賴版本的基礎上,調(diào)整構(gòu)建方式,大幅減小集成包的大小。
改造總結(jié)
優(yōu)化不求一步到位,可逐步進行,目標明確即可; 復雜是一切問題的根源,能用一行代碼解決的問題,就不用兩行; 一切功能都是靠代碼實現(xiàn)的,寫好代碼很重要,不能把寫好代碼當成一件小事,只是為了完成所需功能而堆砌代碼很簡單,但編寫清晰易懂且能完成所需功能的代碼并不簡單; 你永遠無法編寫出“完美”的代碼,要用工具和流程規(guī)范來保證這一切,要充分測試;
文章轉(zhuǎn)載:來自投稿
(版權歸原作者所有,侵刪)


點擊下方“閱讀原文”查看更多
