主頁 > 移動端開發 > 怎樣寫好Flutter代碼

怎樣寫好Flutter代碼

2021-09-22 16:15:01 移動端開發

緣起

代碼規范作為一個研發團隊的核心基因,怎樣在團隊中高效傳承是一個挑戰,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關鍵字能讓編譯器做更多優化,提升代碼的整體性能,

風格一致

多人開發的團隊中,每個人都有自己的喜好,代碼管理應該避免出現“破窗效應”,一個人把代碼寫爛了,后面的同學照著寫都爛了,正所謂,無規矩不成方圓,基礎代碼的表達,不追求絕對的對與錯,追求的是在風格上的盡可能統一,這里有太多典型例子:

  1. 命名規范大體遵循駝峰的方式【camel_case_types,non_constant_identifier_names,constant_identifier_names 】

  2. 控制流中盡量使用大括號【curly_braces_in_flow_control_structures】


  3. import順序按照先dart參考,再package參考,再相對參考方式分模塊,模塊內參考按字母表排序【directives_ordering】


  4. required 關鍵字標識的變數請排到前面 【always_put_required_named_parameters_first】

  5. flutter布局中優先使用SizedBox而不是Container【sized_box_for_whitespace】

  6. flutter顏色定義使用8位16進制整數標識顏色值【use_full_hex_values_for_flutter_colors】


  7. 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規則,給大家一點參考,

命名

161fc17b03552b17c772f1207de66c97.png

排序

e09fa2b097a5908353db1c43b85edab8.png

格式化

52424f7150c7bbec6d6c2e95ffef3ba3.png

評論

dac2ff8744d7971e83b0f9b1fe8dc59f.png

庫使用

9aaab9e586ebf59f58f90641db936c15.png

NULL

74a3a397ec63e3a6c9759747e2dfb2a8.png

字串

cf0712b62476289fb6f50e9c86dd3e17.png

集合

d186831e37009ced58192bed481af498.png

函式

e04c1dffd335b02c25581942676d99b6.png

成員變數

715dfd1b4668ba806764c828d228b399.png

建構式

c0971d960a47fe56ec4ffadcd552b806.png

例外處理

3de8065153c4107163e70ac0cdea3246.png

Mixin

47dacab52932ea9c8e5f0871d12c4c8d.png

型別

b548127c3c939003b18d774a41bb3676.png

引數

c01c363b3e6635810d6bd330f4034f7a.png

質量

d64d10c1cc44f4656e40f05049538ac4.png

Core集合融合部分

99ef9408a810c09f6b138b25c25373b9.png

Recommended 集合融合部分

2396f0629754616586bec937865dc255.png

Flutter 集合融合部分

19e2ca6270693ebdb1c6086f6e9cf197.png

其他規則融合部分

b39fef0842d32131e2c7c05b221dc390.png

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

4cdcc7074cbaa57b17cc5f627a2a4f7f.png

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/302087.html

標籤:其他

上一篇:Android注冊登錄頁面

下一篇:WiFi6 MTK方案初試

標籤雲
其他(123570) Java(13369) Python(12731) C(7545) 區塊鏈(7372) JavaScript(7059) 基礎類(6313) AI(6244) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4120) MySQL(4012) Linux(3394) C語言(3288) C++語言(3117) Java相關(2746) 疑難問題(2699) 單片機工控(2479) Web開發(1951) 網絡通信(1793) 數據庫相關(1767) VB基礎類(1755) PHP(1727) 開發(1646) 系統維護與使用區(1617) .NETCore(1586) 基礎和管理(1579) JavaEE(1566) C++(1527) 專題技術討論區(1515) Windows客戶端使用(1484) HtmlCss(1466) ASP.NET(1428) Unity3D(1354) VCL組件開發及應用(1353) HTML(CSS)(1220) 其他技術討論專區(1200) WindowsServer(1192) .NET技术(1165) 交換及路由技術(1149) 語言基礎算法系統設計(1133) WindowsSDKAPI(1124) 界面(1088) JavaSE(1075) Qt(1074) VBA(1048) 新手樂園(1016) 其他開發語言(947) Go(907) HTML5(901) 新技術前沿(898) 硬件設計(872) 區塊鏈技術(860) 網絡編程(857) 非技術版(846) 一般軟件使用(839) 網絡協議與配置(835) Eclipse(790) Spark(750) 下載資源懸賞專區(743)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 如何在C中找到鍵/值字典的大小

    我對 C 很陌生,我正在學習使用結構和指標,但我似乎無法弄清楚我在這里做錯了什么。所以我試圖找到每次呼叫 main 函式時都會重置的字典的大小。當我嘗試手動運行代碼時,它會說...

    uj5u.com 2021-10-16 17:05:42 more
  • 如何在將指標作為引數的函式內釋放結構指標

    編輯*我正在學習結構和指標,我正在處理的部分任務要求我釋放 malloc 的空間以用于結構指標。指標作為函式內部的引數傳遞,我想知道是否可以釋放函式內部的空間?指標在主檔案中...

    uj5u.com 2021-10-16 17:05:10 more
  • 同時擁有名稱和指向結構的指標是否有意義?

    typedef struct net_path_s{ uint8 path_len; /* network path length */ uint8 net_path[2 * MAX_ROUTE_LEN]; /* network path */} net...

    uj5u.com 2021-10-16 17:04:34 more
  • Python的記憶體行為

    我有一個串列,它會變得非常大。所以我會將串列保存在我的硬碟上,然后繼續使用一個空串列。我的問題是:當我執行 myList[] 時,舊資料會被洗掉還是會保留在 Ram 上的某個地方。我...

    uj5u.com 2021-10-16 17:04:05 more
  • 僅使用帶有鍵的unordered_map來存盤指標(忽略值)

    我正在實施一種演算法,該演算法檢查網格中的節點是否具有特定值。要存盤有關我已經檢查過的節點的資訊,我想使用 unordered_map 并將指向該節點的指標作為鍵。然后我可以簡單...

    uj5u.com 2021-10-16 17:03:06 more
  • 如何在同一頁面上向下滾動并顯示章節?

    我正在開發一個單頁網站,當用戶點擊一個特定的按鈕時,應該向下滾動到頁面的另一個部分。
    因為我使用了粘性標題,所以該部分的標題被隱藏在橫幅后面,所以我使用下面的代碼在點擊...

    uj5u.com 2021-10-16 15:31:29 more
  • 是否有辦法在gradle.build檔案中擴展或創建不同的jib配置?

    我正在使用jib插件來為我的springboot應用構建docker鏡像。然而,我希望在我的構建檔案中有一個新的任務,它將呼叫不同的構建jib任務。
    其原因是,根據我在 gradle 中創建的任務,...

    uj5u.com 2021-10-16 15:31:10 more
  • 未生成Apollo目錄

    我在初步實施中遇到了困難。
    我的問題是,下面的構建無法生成apollo目錄。
    用這個gradle(應用程式級別)
    plugins {
    id 'com.android.application'/span>
    id 'kotlin-androi...

    uj5u.com 2021-10-16 15:30:57 more
  • 引數型別'PointerEvent'不能分配給引數型別'PointerDownEvent'。

    最近,我更新到了flutter 2.5和最新的androids studio,并試圖將我的flutter專案編譯到android設備上。Android studio向我拋出了下面的錯誤。如果我在終端寫flutter run,編譯到...

    uj5u.com 2021-10-16 15:30:43 more
  • 如何使用then()并在Cypress中獲取數值

    我有一個span元素,它的值是2,我想檢查它的值是否大于0,但在網上查詢并實施了所有方法后,它沒有作業......
    下面是我記錄$span時的控制臺> 2</span>
    </div>

    cy.get(" .badge....

    uj5u.com 2021-10-16 15:28:04 more