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