提振精神
所有錯誤的上方應該都很實用。這是他們唯一的存在 否則我們會認為失敗,讓所有人都知道發生了什麼事。
錯誤應提供使用者需要採取適當行動的相關資訊。使用者有時會成為程式碼中的 match
,有時也會是查看記錄緩衝區的人類。想為他們提供實用的內容
就必須顧及他們的需求
您只要遵守以下原則即可:
- 錯誤會變得更有意義
- 錯誤更容易處理
- 元件管理員的程式碼集更容易讀取
- 這些錯誤將避免更多錯誤
- 會更容易修正觸發錯誤的錯誤
原則
下列原則只是準則 (儘管遠大的原則),說明如何製作有意義的實用錯誤。如果您認為這些規範在某種程度上有誤,請善用您的判斷力,更新這份文件。
請勿謹慎使用 panic!
、assert!
、unwrap(...)
和 expect(...)
元件管理員不應當機。如果元件管理員當機,系統會重新啟動,使用者資料可能會遺失。
在極少數情況下可發生當機情形:
- 對內部不變性進行斷言或許是適當的,如果違反變數就會破壞元件管理員行為的基本假設
- 這並不安全,可能會公開使用者資料,或讓攻擊者持續利用漏洞。
- 範例:元件狀態
- 範例:引數驗證
- 例如:系統其他階段的預期
- 範例:元件管理員設定
fidl::endpoints::create_*
方法可以放心解除包裝。他們會建立 Zircon 管道,並等待封包在已建立的通道上。- 如果測試的結果產生簡潔程式碼,則可以在已驗證的變化版本中進行斷言。
- 範例:檢查
map.contains_key(key)
是否為 true,然後呼叫map.get(key).unwrap()
或map[key]
。 - 請盡可能使用
if let
或match
重新編寫程式碼,這樣就不需要解除包裝/恐慌。
- 範例:檢查
請勿使用 println!
雖然 println!
與元件管理員中的 debuglog 整合,但 tracing log library
提供更多功能,且廣泛用於程式碼集。tracing
程式庫也會與偵錯記錄檔整合,提供便利的巨集,並支援結構化記錄。
println!
。這項操作目前受到 Lint 規則保護。
請勿使用 anyhow
程式庫
透過 anyhow
程式庫,您無法建構結構良好的錯誤類型並加以比對。
這項規則沒有任何已知的例外狀況。
請使用 thiserror
程式庫建立自訂錯誤類型
thiserror
程式庫會自動針對自訂錯誤類型自動實作 std::error::Error
。避免手動實作 std::error::Error
。
這項規則沒有任何已知的例外狀況。
請在元件管理服務中為特定功能/動作建立自訂錯誤類型
自訂錯誤類型有助於列舉功能/動作的所有可能錯誤狀態。不會與元件管理員的其他區域綁定,且可獨立於程式碼集的其餘部分進行維護。
請考量是否需要為自訂錯誤類型導入 Into<ModelError>
ModelError 有許多不同錯誤類別的列舉變化版本。您不需要將自訂錯誤類型新增到 ModelError。
請勿在 ModelError
中加入精確錯誤
最好建立自訂錯誤類型來代表功能/動作的所有錯誤,就算您目前只有一個錯誤也一樣。如果直接將精確錯誤新增至 ModelError,開發人員可能會失去錯誤適用範圍的背景資訊。
請勿儲存 CloneableError
等一般錯誤類型
一般錯誤類型無法建構結構良好的錯誤。這些泛型類型沒有慣用的比對方式。
這項規則的唯一例外狀況,是錯誤來自使用一般錯誤類型的外部程式庫。可能無法變更外部程式庫,因此可以儲存一般程式庫。
thiserror
的 #[from]
屬性。這可讓您輕鬆地將所有錯誤轉換為一般錯誤。請改用 #[source]
並執行明確的轉換。請勿將現有錯誤類型用於「夠近」的行為
元件管理員中造成根本原因的錯誤時,如錯誤描述世界狀態的錯誤,將導致系統難以偵錯,尤其是在元件管理員中。建議您建立錯誤類型,以精確描述不同的錯誤狀態。另一個選項是在現有錯誤類型中新增列舉,以提供額外分類。
這項規則沒有任何已知的例外狀況。
務必考量是否一定要記錄記錄功能
您可以將元件管理員想成一種是多元化的超程式庫。程式庫通常是由元件管理員「無法」得知錯誤是否具有意義。舉例來說,如果 UDP 程式庫為每個捨棄的封包記錄了記錄,就會發生什麼情況。
雖然目前沒有通用的建議,但元件管理員仍有一些注意事項:
- 使用記錄功能時保持保守。
- 如果記錄是為了協助開發/偵錯而建立,就必須先移除這些記錄,或設為
DEBUG
記錄層級才能提交。 - 請避免在熱程式碼路徑中新增記錄。這可能會產生垃圾記錄和垃圾內容。
- 如果 FIDL 也傳回錯誤給用戶端,且詳細資料數量相同,則不要記錄該錯誤。
- 反之,如果在透過 FIDL 傳送錯誤時遺失了某些細節,則可以記錄詳細的錯誤訊息。
- 此外,也請考慮客戶未收到詳細錯誤的原因。
- 記錄未涉及用戶端的錯誤,且該項錯誤可能對問題偵錯十分重要。
- 遵循 RFC-0003 中設定的記錄準則
務必在記錄和錯誤中新增元件 ID
元件管理員通常會產生與特定元件相關的錯誤。確認錯誤包含元件 ID,方便偵錯。如果是記錄,請使用元件範圍記錄器,或在訊息中加入元件 ID。
可接受的元件 ID (依偏好順序排序):車輛、元件網址、執行個體 ID
請勿列印記錄訊息中的 Debug
物件字串
Debug
特徵和對應的 {:?}
格式指定碼只應用於互動式偵錯。將對等的 JSON 物件輸出到記錄中,會讓物件更難理解。最好將使用者可理解的錯誤訊息列印到記錄中。
這項規則沒有任何已知的例外狀況。
「請勿」儲存字串化的錯誤訊息
請勿儲存錯誤的 Debug
或 Display
字串。字串錯誤沒有可靠的結構,而且無法進行比對。請一律依原樣儲存錯誤。
外部程式庫中的部分錯誤不會實作 Clone
或 PartialEq
等必要的特徵。在這種罕見情況中,如果無法將這些特徵加入外部程式庫,您可以改為將錯誤訊息字串字串,並改為儲存。
請勿為每個錯誤變化版本建立函式
錯誤變數的建立函式不需要使用。可讓您對部分類型的隱含轉換進行隱含轉換,同時隱藏欄位名稱。想要直接建立錯誤類型並手動設定欄位名稱。
這項規則沒有任何已知的例外狀況。
思考如何稱霸戰士
元件管理員是一個大型 Crate。我們已將轉送功能移至各自的 Crate,日後可能會執行更多工作。如果您正在處理的特定程式碼部分是專屬 Crate 的一部分,請考慮使用哪種錯誤類型。針對 crate 中的邏輯集合,這屬於合理的錯誤類型?