Effective Dart
在過去幾年中,我們編寫了大量的 Dart 程式碼,並學習了很多關於什麼有效、什麼無效的知識。我們在此與您分享,讓您也能編寫一致、穩健、快速的程式碼。其中有兩個總體主題:
保持一致性。 當涉及到格式設定和大小寫等問題時,關於哪個更好的爭論是主觀的且不可能解決。我們確實知道的是,保持一致性在客觀上有幫助。
如果兩段程式碼看起來不同,那應該是因為它們在某些有意義的方式上確實不同。當一小段程式碼突出並吸引您的目光時,它應該是為了有用的原因而這樣做。
保持簡潔。 Dart 的設計旨在讓人感到熟悉,因此它繼承了與 C、Java、JavaScript 和其他語言相同的許多陳述式和表達式。但我們建立 Dart 是因為這些語言提供的功能還有很大的改進空間。我們新增了一系列功能,從字串插值到初始化形式參數,以幫助您更簡單、更輕鬆地表達您的意圖。
如果有多种方式表达同一件事,您通常应该选择最简洁的方式。但这并不是说您应该程式碼高爾夫,将整个程序塞进单行代码中。目标是精简而不是密集的代码。
指南
#我們將指南分成幾個不同的頁面,以便於消化
風格指南 – 這定義了程式碼的版面配置和組織規則,或至少是
dart format
無法為您處理的部分。風格指南還指定了識別碼的格式設定方式:camelCase
、using_underscores
等。文件指南 – 這告訴您關於註解內的所有知識。包括文件註解和常規、普通的程式碼註解。
用法指南 – 這教您如何充分利用語言功能來實作行為。如果它在陳述式或表達式中,則此處涵蓋。
設計指南 – 這是最寬鬆的指南,但範圍最廣。它涵蓋了我們在為函式庫設計一致、可用的 API 方面所學到的知識。如果它在類型簽名或宣告中,則此處會說明。
有關所有指南的連結,請參閱摘要。
如何閱讀指南
#每個指南都分為幾個章節。章節包含指南清單。每個指南都以以下其中一個詞開頭
DO 指南描述了應始終遵循的做法。幾乎永遠沒有正當理由偏離它們。
DON'T 指南則相反:幾乎永遠不是好主意的事情。希望我們不像其他語言那樣有那麼多這類指南,因為我們的歷史包袱較少。
PREFER 指南是您應該遵循的做法。但是,在某些情況下,否則可能更有意義。只是在您這樣做時,請務必了解忽略指南的全部含義。
AVOID 指南是「prefer」的雙重含義:您不應該做的事情,但在極少數情況下可能有充分的理由這樣做。
CONSIDER 指南是您可能想要或可能不想遵循的做法,具體取決於情況、先例和您自己的偏好。
有些指南描述了規則不適用的例外情況。列出時,例外情況可能並不詳盡——您可能仍然需要在其他情況下使用您的判斷。
這聽起來像是如果你的鞋帶沒有正確繫好,警察就會破門而入。事情沒有那麼糟糕。這裡的大多數指南都是常識,而且我們都是理性的人。一如既往,目標是良好、可讀且可維護的程式碼。
Dart 分析器提供了一個 linter,以幫助您編寫遵循這些和其他指南的良好、一致的程式碼。如果存在一個或多個 linter 規則 可以幫助您遵循指南,則該指南會連結到這些規則。連結使用以下格式
Linter 規則:unnecessary_getters_setters
若要瞭解如何使用 linter,請參閱啟用 linter 規則和linter 規則清單。
詞彙表
#為了保持指南簡潔,我們使用了一些簡寫術語來指稱不同的 Dart 結構。
函式庫成員是頂層欄位、getter、setter 或函式。基本上,任何在頂層但不是類型的東西。
類別成員是在類別內部宣告的建構子、欄位、getter、setter、函式或運算子。類別成員可以是實例或靜態、抽象或具體。
成員是函式庫成員或類別成員。
變數,當一般使用時,指的是頂層變數、參數和區域變數。它不包括靜態或實例欄位。
類型是任何具名類型宣告:類別、typedef 或列舉。
屬性是頂層變數、getter(在類別內部或在頂層、實例或靜態)、setter(相同)或欄位(實例或靜態)。大致上是任何「類似欄位」的具名結構。
所有規則摘要
#風格
#識別碼
- DO 使用
UpperCamelCase
為類型命名。 - DO 使用
UpperCamelCase
為擴充功能命名。 - DO 使用
lowercase_with_underscores
為套件、目錄和原始碼檔案命名。 - DO 使用
lowercase_with_underscores
為匯入前置詞命名。 - DO 使用
lowerCamelCase
為其他識別碼命名。 - PREFER 對於常數名稱使用
lowerCamelCase
。 - DO 將長度超過兩個字母的縮寫字和縮寫詞像單字一樣大寫。
- PREFER 對於未使用的回呼參數使用萬用字元。
- DON'T 對於非私有的識別碼使用前導底線。
- DON'T 使用前置字母。
- DON'T 明確命名函式庫。
排序
格式設定
文件
#註解
文件註解
- DO 使用
///
文件註解來記錄成員和類型。 - PREFER 為公用 API 撰寫文件註解。
- CONSIDER 撰寫函式庫層級的文件註解。
- CONSIDER 為私有 API 撰寫文件註解。
- DO 以單句摘要開始文件註解。
- DO 將文件註解的第一句話分隔成自己的段落。
- AVOID 與周圍上下文的冗餘。
- PREFER 以第三人稱動詞開始函式或方法註解。
- PREFER 以名詞詞組開始非布林變數或屬性註解。
- PREFER 以「Whether」後跟名詞或動名詞詞組開始布林變數或屬性註解。
- DON'T 為屬性的 getter 和 setter 都撰寫文件。
- PREFER 以名詞詞組開始函式庫或類型註解。
- CONSIDER 在文件註解中包含程式碼範例。
- DO 在文件註解中使用方括號來參照範圍內的識別碼。
- DO 使用散文來解釋參數、傳回值和例外狀況。
- DO 將文件註解放在 Metadata 註解之前。
Markdown
寫作
用法
#函式庫
Null
- DON'T 明確將變數初始化為
null
。 - DON'T 使用
null
的明確預設值。 - DON'T 在相等運算中使用
true
或false
。 - AVOID 如果您需要檢查
late
變數是否已初始化,請避免使用。 - CONSIDER 對於使用可為 Null 的類型,請考慮類型提升或 Null 檢查模式。
字串
集合
- DO 盡可能使用集合字面值。
- DON'T 使用
.length
來查看集合是否為空。 - AVOID 將
Iterable.forEach()
與函式字面值一起使用。 - DON'T 除非您打算變更結果的類型,否則不要使用
List.from()
。 - DO 使用
whereType()
按類型篩選集合。 - DON'T 當附近的運算可以完成時,不要使用
cast()
。 - AVOID 使用
cast()
。
函式
變數
成員
- DON'T 不必要地將欄位包裝在 getter 和 setter 中。
- PREFER 使用
final
欄位來建立唯讀屬性。 - CONSIDER 對於簡單的成員使用
=>
。 - DON'T 除了重新導向到具名建構子或避免遮蔽之外,不要使用
this.
。 - DO 盡可能在其宣告處初始化欄位。
建構子
- DO 盡可能使用初始化形式參數。
- DON'T 當建構子初始化清單可以完成時,不要使用
late
。 - DO 對於空的建構子主體使用
;
而不是{}
。 - DON'T 使用
new
。 - DON'T 冗餘地使用
const
。
錯誤處理
- AVOID 沒有
on
子句的 catches。 - DON'T 從沒有
on
子句的 catches 中捨棄錯誤。 - DO 僅針對程式設計錯誤擲回實作
Error
的物件。 - DON'T 明確捕捉
Error
或實作它的類型。 - DO 使用
rethrow
重新擲回捕捉到的例外狀況。
非同步
設計
#名稱
- DO 一致地使用術語。
- AVOID 避免使用縮寫。
- PREFER 優先將最具描述性的名詞放在最後。
- CONSIDER 考慮使程式碼讀起來像句子。
- PREFER 對於非布林屬性或變數使用名詞詞組。
- PREFER 對於布林屬性或變數使用非祈使動詞詞組。
- CONSIDER 對於具名的布林參數,考慮省略動詞。
- PREFER 對於布林屬性或變數使用「肯定」名稱。
- PREFER 對於主要目的是副作用的函式或方法使用祈使動詞詞組。
- PREFER 如果傳回值是函式或方法的主要目的,則使用名詞詞組或非祈使動詞詞組。
- CONSIDER 如果您想引起對函式或方法執行的工作的關注,則考慮使用祈使動詞詞組。
- AVOID 避免以
get
開頭的方法名稱。 - PREFER 如果方法將物件的狀態複製到新物件,則將方法命名為
to___()
。 - PREFER 如果方法傳回由原始物件支援的不同表示法,則將方法命名為
as___()
。 - AVOID 避免在函式或方法的名稱中描述參數。
- DO 在命名類型參數時遵循現有的助憶約定。
函式庫
類別和 Mixins
- AVOID 當簡單的函式可以完成時,避免定義單成員抽象類別。
- AVOID 避免定義僅包含靜態成員的類別。
- AVOID 避免擴充不打算作為子類別化的類別。
- DO 使用類別修飾詞來控制您的類別是否可以擴充。
- AVOID 避免實作不打算作為介面的類別。
- DO 使用類別修飾詞來控制您的類別是否可以作為介面。
- PREFER 優先於
mixin class
定義純mixin
或純class
。
建構子
成員
- PREFER 使欄位和頂層變數成為
final
。 - DO 對於概念上存取屬性的運算使用 getters。
- DO 對於概念上變更屬性的運算使用 setters。
- DON'T 不要定義沒有對應 getter 的 setter。
- AVOID 避免使用執行階段類型測試來偽造多載。
- AVOID 避免沒有初始化器的公用
late final
欄位。 - AVOID 避免傳回可為 Null 的
Future
、Stream
和集合類型。 - AVOID 避免從方法傳回
this
只是為了啟用流暢介面。
類型
- DO 為沒有初始化器的變數加上類型註解。
- DO 如果類型不明顯,則為欄位和頂層變數加上類型註解。
- DON'T 不要冗餘地為初始化的區域變數加上類型註解。
- DO 在函式宣告上註解傳回類型。
- DO 在函式宣告上註解參數類型。
- DON'T 不要為函式表達式上推斷的參數類型加上註解。
- DON'T 不要為初始化形式參數加上類型註解。
- DO 為未推斷的泛型調用撰寫類型引數。
- DON'T 不要為已推斷的泛型調用撰寫類型引數。
- AVOID 避免撰寫不完整的泛型類型。
- DO 使用
dynamic
註解,而不是讓推斷失敗。 - PREFER 在函式類型註解中使用簽名。
- DON'T 不要為 setter 指定傳回類型。
- DON'T 不要使用舊版的 typedef 語法。
- PREFER 優先於 typedef 使用內聯函式類型。
- PREFER 對於參數使用函式類型語法。
- AVOID 避免使用
dynamic
,除非您想要停用靜態檢查。 - DO 對於不產生值的非同步成員,使用
Future<void>
作為傳回類型。 - AVOID 避免使用
FutureOr<T>
作為傳回類型。
參數
- AVOID 避免使用位置布林參數。
- AVOID 如果使用者可能想要省略較早的參數,則避免使用選用位置參數。
- AVOID 避免使用接受特殊「無引數」值的必要參數。
- DO 使用包含起始值和排除結束值的參數來接受範圍。
相等性
除非另有說明,否則本網站上的文件反映 Dart 3.7.1 版本。頁面上次更新時間:2024-05-06。 檢視原始碼 或 回報問題。