天天看點

提升使用者體驗的UUID設計政策

作者:閃念基因
本文翻譯自 The UX of UUIDs,作者:Andreas Thomas, 略有删改。

唯一辨別符在從使用者身份驗證到資源管理的所有應用程式中起着至關重要的作用。雖然使用标準UUID将滿足您的所有安全問題,但我們可以為使用者改進很多。

這篇文章讨論了唯一辨別符(UUID)在應用程式中的重要性,以及如何通過一些改進來增強使用者體驗。

提升使用者體驗的UUID設計政策

確定唯一性

唯一辨別符對于區分系統中的各個實體至關重要。它們提供了一種可靠的方式,確定每個項目、使用者或資料片段都有一個獨特的身份。通過維持唯一性,應用程式可以有效地管理群組織資訊,使操作更加高效,并促進資料的完整性。

任何安全生成的128位UUID對我們來說都足夠了,有很多庫可以生成UUID,或者你可以使用你選擇的程式設計語言的标準庫。在這篇部落格中,我将使用Typescript示例,但基本思想适用于任何語言。

const id = crypto.randomUUID()
// '5727a4a4-9bba-41ae-b7fe-e69cf60bb0ab'
           

我們也可以止步于此,但我們做的更好,通過一些小的改進來增強使用者體驗:

  • 使它們易于複制
  • 添加字首
  • 更高效的編碼
  • 改變長度

複制UUID很麻煩

嘗試通過輕按兩下它來複制以下UUID:

c6b10dd3-1dcf-416c-8ed8-ae561807fcaf

如果你幸運的話,你能複制整個UUID,但對大多數人來說,他們隻得到了一個部分,提高唯一辨別符可用性的一種方法是使它們易于複制。

這可以通過從UUID中移除連字元來實作,允許使用者簡單地輕按兩下辨別符來複制。通過這個小改變可以大大改善使用者在處理辨別符時的體驗。

在代碼中移除連字元很簡單,以下是如何在js/ts中做到這一點:

const id = crypto.randomUUID().replace(/-/g, "")
// fe4723eab07f408384a2c0f051696083
           

現在再試試複制它,感覺好多了!

添加字首

我們可以通過添加一個有意義的字首來幫助使用者區分不同環境或系統中的資源。例如,Stripe使用像sk_live_這樣的字首來表示生産環境的密鑰,或者使用cus_來表示客戶辨別符。通過增加這樣的字首,我們可以確定清晰度并減少混淆的可能性,特别是在多個環境共存的複雜系統中。

const id = `hello_${crypto.randomUUID().replace(/-/g, "")}`
// hello_1559debea64142f3b2d29f8b0f126041
           

命名字首就像命名變量一樣是一門藝術。你想要有描述性,但盡可能短。我稍後會分享我們的命名政策。

使用base58編碼

除了使用十六進制表示辨別符,我們還可以考慮更高效的編碼方式,比如base58。Base58編碼使用更大的字元集并避免使用模糊的字元,例如大寫字母I和小寫字母l,進而在不犧牲可讀性的情況下生成更短的辨別符字元串。

例如一個8個字元長的base58字元串,可以存儲大約30,000倍于8個字元十六進制字元串的狀态。在16個字元時,base58字元串可以存儲889,054,070種組合。

你很可能仍然選擇使用你語言的标準庫來做到這一點,但你也可以使用像nanoid這樣的庫,它适用于大多數語言。

import { customAlphabet } from "nanoid";

export const nanoid = customAlphabet("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");

const id = `prefix_${nanoid(22)}`
// prefix_KSPKGySWPqJWWWa37RqGaX

           

我們在這裡生成了一個22個字元長的ID,它可以編碼大約是UUID的100倍的數量,同時比UUID短10個字元。總數越多,說明可能重複的情況就越少。

-字元長度總數UUID16322^122 = 5.3e+36Base58582258^22 = 6.2e+38

改變長度

并非所有辨別符都需要有高水準的碰撞抵抗力。在某些情況下,較短的辨別符就足夠了,這取決于應用程式的具體要求。通過減少辨別符的長度,我們可以生成更短的ID,同時仍然保持可接受的唯一性水準。

減少ID的長度可能是好的,但你需要小心,并確定你的系統能夠抵禦ID沖突。幸運的是這一點可以在資料庫層很容易做到,在我們的MySQL資料庫中,我們主要将ID用作主鍵,資料庫保護我們免受沖突。如果一個ID已經存在,我們隻需生成一個新的并重試。如果我們的沖突率顯著上升,我們可以簡單地增加所有未來ID的長度。

長度示例總狀态nanoid(8)re6ZkUUV1.3e+14nanoid(12)pfpPYdZGbZvw1.4e+21nanoid(16)sFDUZScHfZTfkLwk1.6e+28nanoid(24)u7vzXJL9cGqUeabGPAZ5XUJ2.1e+42nanoid(32)qkvPDeH6JyAsRhaZ3X4ZLDPSLFP7MnJz2.7e+56

實際使用

最後我想分享一下我們在這裡的實作以及我們如何在代碼庫中使用它。我們使用一個簡單的函數,它接受一個類型化的字首,然後為我們生成ID。這樣我們可以確定我們總是對同類型的ID使用相同的字首。當你的系統中有多種類型的ID時,這特别有用。

import { customAlphabet } from "nanoid";

export const nanoid = customAlphabet("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");

const prefixes = {
  key: "key",
  api: "api",
  policy: "pol",
  request: "req",
  workspace: "ws",
  keyAuth: "key_auth", // <-- 這是内部的,不需要短或漂亮
  vercelBinding: "vb",
  test: "test", // <-- 僅用于測試
} as const;

export function newId(prefix: keyof typeof prefixes): string {
  return [prefixes[prefix], nanoid(16)].join("_");
}
           

當我們在代碼庫中使用它時,我們可以確定總是對正确類型的ID使用正确的字首。

import { newId } from "@unkey/id";

const id = newId("workspace")
// ws_dYuyGV3qMKvebjML

const id = newId("keyy")
// 無效,因為`keyy`不是有效的字首名稱
           

最後

本文讨論了在應用程式中使用唯一辨別符(UUID)時通過以下方式提升使用者體驗。

  1. 簡化複制:通過去除UUID中的連字元,可以讓使用者更容易地通過輕按兩下複制整個辨別符。
  2. 添加字首:使用有意義的字首可以幫助使用者區分不同環境或資源,例如Stripe使用特定的字首來區分生産環境密鑰和客戶辨別符。
  3. 高效編碼:考慮使用如base58這樣的編碼方式,它使用更大的字元集并避免使用易混淆的字元,進而生成更短且可讀性強的辨別符字元串。
  4. 改變長度:根據應用的具體需求,可以通過減少辨別符的長度來生成更短的ID,同時保持足夠的唯一性。
  5. 資料庫層的保護:在資料庫層面,可以使用主鍵限制來防止ID沖突,如果沖突率上升,可以通過增加未來ID的長度來解決。

通過實施這些改進,我們可以增強應用程式中唯一辨別符的可用性和效率。這将為使用者和開發者提供更好的體驗,因為他們與系統中的各種實體進行互動和管理。無論是輕松複制辨別符、區分不同環境,還是實作更短、更易讀的辨別符字元串,這些政策都可以促進一個更使用者友好和健壯的識别系統。

看完本文如果覺得有用,記得點個贊支援,收藏起來說不定哪天就用上啦~

作者:南城

來源-微信公衆号:南城大前端

出處:https://mp.weixin.qq.com/s/m0IMJY_F4CcFFJ2KNIO15A

繼續閱讀