緣起
代碼規范作為一個研發團隊的核心基因,怎樣在團隊中高效傳承是一個挑戰,Flutter作為移動端持續火熱的新型框架,正吸引越來越多的研發同學進入這個領域,但是面對全新的技術框架和之前幾乎很少接觸的dart語言,怎樣寫好Flutter代碼困擾了無數Flutter初學者,文本就著重分享一下閑魚Flutter團隊在基礎代碼規范方面所做的一些實踐,
Flutter靜態代碼掃描
Native開發同學都知道Android/iOS都有配套的Linter檢查機制,開發者可以通過Linter檢查,統一代碼風格,檢查代碼中的明顯缺陷,Flutter同樣具備這樣的能力,通過Linter檢查機制,是統一代碼風格最簡單高效的方式,
Flutter Linter機制
Flutter Linter檢查的機制植根于Dart Linter檢查,同時做了大量的功能拓展,Flutter的Linter規則記錄在工程一級目錄的analysis_options.yaml檔案中,大家可以通過對該檔案的定制來獲得適合自己團隊的代碼規則,
Flutter Linter 規則都從屬于三個主要的集合:
1.ERROR
規則標識的是代碼中可能出現的錯誤
2.Style
規則標識的是代碼風格的問題
3.Pub
規則標識的是Flutter包管理相關的問題
需要注意的是,考慮到實際開發場景中的穩定性,調整Linter規則的時候需要關注規則對應的成熟度,目前主要的成熟度等級包括:
Stable - 穩定
Experimental - 實驗性規則,可能會不太穩定
Deprecated - 不再推薦使用的規則,建議廢棄
常見的Linter規則集
1.effective_dart
effective_dart是dart語言配套的Linter 規則,規則來源于Effective Dart檔案,該檔案中有對Dart語言高效使用的各種規范,effective_dart[2] 規則比較老,目前已經廢棄,
2.pedantic
google內部dart開發規范集合,目前也已經廢棄,
3.flutter_lints
是Flutter團隊推薦的Flutter相關規則集,推薦大家在Flutter apps, packages, and plugins中廣泛使用,本身是dart recommended 規則集合的拓展版本,該規范會影響到發布到 pub.dev[5] 中 package的得分,
4.lints[6]
Dart團隊推薦使用的規則集,核心包括兩個子集:core & recommended,
閑魚規范的取舍
在眾多Liner規則中,選擇符合團隊需要的規則是一個很大的挑戰,閑魚在做的程序中,遵循了一些基本原則,
表達簡潔
在語意等效的情況下,充分利用dart語言的各種高級語法來降低表達的復雜度,簡潔表達不僅能提升編碼效率,同時也可以提升代碼的閱讀效率,舉幾個典型例子:
去除冗余new關鍵字【unnecessary_new】
閑魚代碼庫中有大量的代碼都是使用new關鍵字來進行類初始化的,這一方面是因為閑魚切入Flutter比較早,有歷史包袱;另一方面也是因為客戶端同學將其他語言(例如java)的編碼習慣帶到了Flutter,雖然要修改的地方有很多,但是為了表達簡潔,我們依然堅定的加入這條規則,
高效null處理【prefer_conditional_assignment, prefer_null_aware_operators】
dart語法中有很多null處理的語法糖,能大幅提升判空的效率,提升代碼的健壯性,這里包括?的判斷,??的判空,以及null safety,需要不斷引導團隊同學更多使用這樣的語法來提升效率,而不是繼續使用if else的冗雜表達,
減少歧義
代碼表達需要準確,同學之間的理解盡可能一致,減少代碼之外的“以為”,增加字里行間上的“確定”,典型列子如下:
顯式變數型別【always_specify_types】
是否要明確變數型別,團隊內部不同技術堆疊背景的同學有比較大的分歧,前端背景的同學傾向于通過推斷的方式進行變數命名,好處是表達簡潔,客戶端背景同學傾向于直接明確定義,好處是直觀,減少不必要的推斷,最終經過激烈討論,大家還是決定采用明確變數型別的方案,從實踐角度出發,直接明確變數型別雖然從表達上略冗雜,但是歧義確實更少,
變數/函式狀態堅持最小化表達 【annotate_overrides,prefer_const_declarations,prefer_final_fields】
一個變數或者方法如果重寫了,請明確加上override注解,一個變數如果確定是const變數,請加上const關鍵字,一個變數如果沒有再被賦值,請定義成final,堅持最小化表達,有如下幾點收益:
最小化變數狀態表達能精準刻畫變數狀態
最小化變數狀態是指用最嚴格的屬性描述變數,例如一個變數從之前的多處賦值,改為一處賦值,那么變數其實自帶了final的隱形屬性,最小化狀態表達要求必須加上final關鍵字,而不是推斷是final,因為一旦加上final關鍵字,后續在賦值就會報錯,這能減少不必要的理解成本,最大限度避免變數狀態的隱形改變,
提升代碼性能
增加的final const關鍵字能讓編譯器做更多優化,提升代碼的整體性能,
風格一致
多人開發的團隊中,每個人都有自己的喜好,代碼管理應該避免出現“破窗效應”,一個人把代碼寫爛了,后面的同學照著寫都爛了,正所謂,無規矩不成方圓,基礎代碼的表達,不追求絕對的對與錯,追求的是在風格上的盡可能統一,這里有太多典型例子:
命名規范大體遵循駝峰的方式【camel_case_types,non_constant_identifier_names,constant_identifier_names 】
控制流中盡量使用大括號【curly_braces_in_flow_control_structures】
import順序按照先dart參考,再package參考,再相對參考方式分模塊,模塊內參考按字母表排序【directives_ordering】
required 關鍵字標識的變數請排到前面 【always_put_required_named_parameters_first】flutter布局中優先使用SizedBox而不是Container【sized_box_for_whitespace】
flutter顏色定義使用8位16進制整數標識顏色值【use_full_hex_values_for_flutter_colors】
flutter widget在建構式中加入key引數【use_key_in_widget_constructors】
這里的每一條都不具有非這樣不可的理由,但是在閑魚寫代碼就必須遵循這個規范,不為別的就為了風格的統一,為了提升團隊同學業務輪轉的效率,
代碼質量
Linter檢查的另一個重要的目標是發現潛在的代碼缺陷,這對代碼管理來說就更為重要了,因為這直接關系到穩定性的大局,穩定性是開發人員的底線,再怎么小心也不為過,同樣舉幾個典型的例子:
1.避免給void賦值 【void_checks】
2.變數比較之前先判斷型別 【unrelated_type_equality_checks】
3.避免catch 空實作【empty_catches】
4.避免使用隱形型別傳遞 【avoid_shadowing_type_parameters】
5.避免await 非future物件 【await_only_futures】
6.集合的remove需要傳遞符合集合的型別的引數【list_remove_unrelated_type】
如果這些問題代碼帶到生產環境,輕者出現exception,重則功能不可用,防患于未然,在代碼最開始撰寫階段,就及時處理這些問題,代碼才能更健壯,
維護成本
效率對一個團隊固然很重要,但是追求一時的效率,而不顧及代碼生命周期內整體的效率是非常短視的行為,我們今天越發關注代碼在后期的維護成本,基于此,檔案&注釋的重要性正越發凸顯出來,一個好的注釋,能省下很多的答疑,很多的試錯,很多的猜疑,不斷引導大家寫并維護檔案及注釋,是閑魚代碼規范明確的目標,舉幾個明確的例子:
1.Deprecated函式需要給出明確的注釋[provide_deprecation_message]
2.注釋中的變數參考,符合參考的約束[comment_references]
規則權威
閑魚團隊Liner規則的制定,不是一家之言,邀請了團隊所有同學參與到規則的制定程序,一個規則的權威性來源于所有執行者發自內心的認同,舉一個典型例子:
在討論標準格式化的時候,團隊同學集中討論了一個規則:
【- lines_longer_than_80_chars # 爭議規則,每行長度不超過80字符】
大家認同統一格式化代碼風格的重要性,大家爭議的焦點是:80字符在很多高解析度顯示幕上太短了,這會導致很多不必要的換行,降低代碼閱讀體驗,我們聽取了開發同學反饋,把該條規范去掉了,改為統一android studio配置來執行,最終標準是12號字,一行最多160字符,
寫在最后
當然僅僅做到上面的部分,僅僅是萬里長征的第一步,基礎代碼規范這件事,我們并不追求規則的多,而是更在意規則實際的效率收益,規則制定的程序中,我們聽取了開發同學真實的反饋,洗掉了很多并不必要的規則,簡單,高效,并不為了規范而規范是我們核心的目標,當然最終確定的規則,要盡最大努力保證執行,目前我們正在積極建設更完善的CI體系,將規范規則化,通過持續快速檢測,實時給使用者反饋,降低規范落地的成本,代碼是研發團隊的核心資產,需要我們共同守護,
附錄
上面介紹的規則細節,如果有不清楚的,可以在下面的鏈接中找到更詳細的解釋,
linter-rules[7]
閑魚核心Liner規則
附上閑魚的核心Liner規則,給大家一點參考,
命名

排序

格式化

評論

庫使用

NULL

字串

集合

函式

成員變數

建構式

例外處理

Mixin

型別

引數

質量

Core集合融合部分

Recommended 集合融合部分

Flutter 集合融合部分

其他規則融合部分

References
[1] effective_dart: https://pub.dev/packages/effective_dart[2] effective_dart: https://pub.dev/packages/effective_dart[3] pedantic: https://pub.dev/packages/pedantic[4] flutter_lints: https://pub.dev/packages/flutter_lints[5] pub.dev: https://pub.dev/[6] lints: https://pub.dev/packages/lints[7] linter-rules: https://dart.dev/tools/linter-rules#lints
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/302087.html
標籤:其他
上一篇:Android注冊登錄頁面
下一篇:WiFi6 MTK方案初試

