繁體中文

開發者工具 · UUID 產生器

Nil 和 Max UUID:兩個特殊值以及何時使用它們

· 背景

uuid 開發人員工作流程 資料驗證

資料庫行指向明確全零 UUID 異常,而全 f 值在驗證邊界處停止
原始 ToolAcre 向量圖

自 2005 以來,全零 UUID 一直在標準中,全 F Max UUID 加入 2024 中。這篇文章解釋了它們的用途、它們如何與驗證器互動以及要避免的哨兵值錯誤。

ID 為 00000000-0000-0000-0000-000000000000 的行 — 佔位符如何成為生產錯誤

識別碼為 00000000-0000-0000-0000-000000000000 的行看起來是 UUID 形狀,但其意義與產生的標識符不同。如果應用程式悄悄地使用該值表示“尚未分配”,則每個未完成的行共享相同的標記。假定任何接受的 UUID 名稱是真實物件的程式碼可以請求、快取或加入佔位符,就像它是普通鍵一樣。可見的格式並不會傳達業務規則;只有明確的哨兵合約才可以。

當一層知道佔位符而另一層不知道時,生產錯誤就會開始。表單可以提交 Nil,API 可以接受它,持久層可以儲存它,而下游工作程序將每個非空字串視為可用的外鍵。失敗並不在於 Nil 畸形。 ToolAcre 故意識別它。失敗之處在於允許「有效文字」、「產生的識別碼」和「分配的關係」陷入一種未經檢查的條件。

Nil UUID — 它的定義,以及為什麼每個版本和變體檢查在技術上都失敗

在檢查的實作中,Nil 是規範的全零字串。它在測試正常 UUID 模式之前接收專用分支,因此即使正則表達式需要從 1 到 8 的版本數字以及從 8 到 b 的 RFC 變體半字節,isValidUuid 也會傳回。 spectUuid 遵循相同的例外:它報告有效值,分配版本 0,並表示 UUID 全部為零位元且不是隨機的。這是經過驗證的應用程式行為,而不是每個驗證者必須做出相同選擇的一般主張。

此分支很重要,因為 Nil 不會傳遞用於產生識別碼的普通版本和變體路由。 ToolAcre version-4 值在版本位置攜帶 4,在變體位置攜帶 8、9、a 或 b 之一; Nil 在這兩個地方都帶有零。稱這些檢查「失敗」而不提及異常會造成誤導。檢查器首先識別特殊值,然後透過設計繞過普通模式。如果消費者接受的話,他們需要同樣可見的訂購。

Nil UUID 是 ToolAcre 中的明確有效異常,報告為版本 0

all-f 字串 ffffffff-ffff-ffff-ffff-ffffffffffff 在此儲存庫中沒有接收特殊分支。它也無法正常模式,因為 f 超出了可接受的版本範圍並超出了可接受的 RFC 變體半位元組集。因此,ToolAcre 將其報告為非規範,而不是像 Nil 一樣對待它。這本工作手冊將標準化歷史和範圍邊界目的歸因於 Max,但工具記錄、實作和測試都沒有驗證這些宣告,因此本文不再重複它們。

這種差異比不受支援的歷史記錄更有用:Nil 是具有測試行為的命名常數,而 Max 是檢查器拒絕的輸入。項目可以在自己的協議中定義額外的哨兵語義,但不得從 ToolAcre 推斷出該選擇。如果互通性取決於接受全 f 值,請記錄該規則並在所屬系統中進行測試。不要假設每個庫都會對 UUID 形狀的字串進行相同的分類。

所有-f Max 值被 ToolAcre 拒絕;未斷言 RFC 歷史或預期使用範圍

只有當模式如此表示時,哨兵和空值才會回答不同的問題。 Null 可以直接表示不存在關係。哨兵保持列填充,當周圍介面不能攜帶 null 時可能很有用,但它會建立一個看起來像資料的值,因此會遍歷索引、連接、序列化器和快取。明顯的便利性將責任轉移到每個讀者身上:每個讀者都必須記住,一個接受的 UUID 並沒有命名指定的實體。

當哨兵可以滿足外鍵形狀檢查而不滿足關係的含義時,該交易就會成為陷阱。它還可以模糊不同的狀態,例如未知、故意未分配、已刪除或尚未處理。如果這些狀態影響行為,請明確地表示它們,而不是重載一個魔術標識符。如果為了相容性而保留 Nil,則為狀態賦予一種記錄的含義,在其他地方拒絕它,並在明確擁有的邊界處對其進行轉換,而不是在整個業務代碼中分散比較。

驗證器和特殊值 - 為什麼嚴格的版本 /variant 檢查可能會拒絕 Nil 和 Max,以及如何決定您的版本是否應該

ToolAcre 在一個驗證器中示範了兩層。正常輸入被修剪,可選的外大括號被刪除,剩餘的字串根據規範的 8-4-4-4-12 佈局以及接受的版本和變體位置進行檢查。 Nil 在該模式之前被測試並被故意接受。 Max也不例外,失敗了。這意味著呼叫者無法僅從正規表示式預測特殊值策略;圍繞模式的控制流是驗證契約的一部分。

透過分離三個問題來設計您自己的政策。首先,文字是否可以以您的邊界允許的形式被識別?其次,該值是普通的 UUID 還是命名異常?第三,該欄位和操作是否允許該類別?即使診斷解析器識別出 Nil,建立端點也可能會拒絕 Nil,而匯入邊界可能會將記錄的遺留 Nil 標記轉換為 null。單獨傳回這些結果可以防止「解析器接受它」成為儲存它的意外授權。

ToolAcre 明確接受 Nil 並在其版本和變體模式下拒絕 Max

考慮一個帶有受讓人識別碼的任務表,該識別碼使用 Nil 表示「未分配」。編寫為 WHERE allocateee_id IS NOT NULL 的查詢似乎選擇分配的任務,但它也選擇每個 Nil 行,因為哨兵是一個特定字串。如果沒有使用者擁有該鍵,則聯接可能會刪除這些行,從而產生第二個不太明顯的結果。兩個查詢在本地都是合理的;他們不同意,因為模式將狀態隱藏在一個普通的標識符內,而不是直接公開賦值。

持久修復是將分配模型化為分配:在儲存協定允許時使用可空關係,或在必須區分多個狀態時新增明確狀態。如果相容性邊界仍然發送 Nil,則在持久化之前將其轉換一次,並僅針對該邊界反轉對應。然後測試產生的 version-4 值、Nil、Max、空輸入和格式錯誤的文字作為單獨的情況。應用程式應該決定每個結果,而不是繼承通用格式檢查恰好返回的任何答案。

重點:特殊值需要明確處理 - 使用 ToolAcre 產生器產生真實 ID,並將 Nil 和 Max 視為有意的異常

特殊值需要命名處理,因為它們的形狀無法承載應用程式的意圖。 ToolAcre 從 Web Crypto 產生普通版本 4 UUID,必要時從 randomUUID 回退到 getRandomValues,並拒絕使用不安全的隨機來源。然後,它的檢查器可以將產生的值與明確識別的 Nil 異常區分開來。這使得該工具對於觀察很有用,但它不會選擇資料庫哨兵策略或證明接受的識別碼屬於現有記錄。

使用新識別碼產生器,並將每個哨兵視為單獨的協定決策。在目前檢查器中,Nil 是有效的,版本 0,而且不是隨機的;麥克斯被拒絕了。在測試頁面時保留這種區別,然後將其與您的語言、資料庫和 API 的規則進行比較,然後再接受任一值。安全要點故意狹窄:產生的 ID、解析器異常、缺失的關係和業務狀態是不同的概念,強大的邊界使它們保持不同。