Podczas tworzenia Star Trek API szybko doszedłem do wniosku, że nie mogę ujawniać klientom API ID-ków bazodanowych. Powodem było to, że ID-ki te nieustannie się zmieniały. Ilekroć robiłem zasilenie od nowa, było niemal pewne, że dostanę nieco inne zestaw stron, które zostaną przetworzone w innej, niż poprzednio, kolejności. Wydało mi się oczywiste, że gdybym sam chciał skorzystać z danych tego typu, jak udostępniane przez moje API, oczekiwałbym, że ID będą stałe. Chciałbym je gdzieś zapisywać i posługiwać się nimi w przyszłej komunikacji z API.
Zadanie
Trzeba było wymyślić sposób na to, aby generować stałe, lub przynajmniej w ogromnej większości przypadków stałe identyfikatory dla wszystkich encji. Dodatkowym bonusem byłoby to, aby identyfikatory były unikalne w obrębie całego API.
Wykonanie
Memory Alpha i Memory Beta mają własną numerację stron, którą na szczęście ujawniają. Każda strona ma ID, który nie zmienia się przez cały cykl jej życia, nawet wówczas, gdy strona zostanie przeniesiona pod inną nazwę. Identyfikatory stron z z wiki mogły więc zostać pierwszą ważną częścią identyfikatora, który już wówczas zacząłem nazywać GUID-em, a któremu ostatnio zmieniłem nazwę na UID, by nie było wątpliwości, że to co innego, niż GUID.
Od razu było jasne, że potrzebuję jeszcze czegoś, co identyfikowałoby encję w unikalny sposób. ID-ki z Memory Alpha i Memory Beta mogły się powtarzać. Do UID-ów dołączyłem więc 2 znaki, które reprezentowały encję, oraz 2 znaki, które reprezentowały źródło. W ten sposób powstał na przykład UID, który wyglądał tak: CLMA0000108985
. Dwa pierwsze znaki, CL
, oznaczały encję ComicCollection, dwa kolejne, MA
, oznaczały, że źródłem jest Memory Alpha. Natomiast 10 cyfr to ID z wiki. Razem zawsze 14 znaków, co wydało mi się wystarczające na API tej wielkości.
Pierwsze, i na razie jedyne, kłopoty
Pierwszy i na razie jedyny problem, który napotkałem, dotyczył bytów, które nie mapowały się na dokładnie jedną stronę z wiki. Chodziło o encje reprezentujące numery ISBN i ASIN. Na jednej stronie mogło występować kilka takich numerów.
Na szczęście numery ISBN mają 10 lub 13 znaków, a numery ASIN – 10 znaków. Łatwo było z nich wygenerować 14-znakowe UID-y. 10-znakowym numer ISBN mają po prostu format ISBN160010603X
, 13-znakowe ISBN-y format I9781566199094
, a 10-znakowe numery ASIN-y – format ASINB008L4YH4W
. Można więc w dalszym ciągu zagwarantować unikalność UID-u w systemie.
Implementacja
Ostatecznie wszystkie te wymagania zostały zaimplementowany w klasie UidGenerator. Klasa jest wołana zawsze, zanim encja zostanie pierwszy raz zapisana, i w ten sposób UID zawsze jest obecny.
UID-y zastępują w API bazodanowe identyfikatory. To nimi pyta się o pojedyncze REST-owe i SOAP-owe obiekty. UID-y też, wraz z nazwami lub tytułami, trafiają do encji nagłówkowych, takich jak MovieHeader. Na ich podstawie, gdy ktoś będzie chciał, będzie mógł pobrać więcej danych na temat interesującej encji.
UidGenerator
podczas inicjowania aplikacji sprawdza, czy będzie potrafił wygenerować unikalne identyfikatory dla wszystkich encji. Jeśli nie, trzeba dodatkowo dodać identyfikator skrócony identyfikator encji w statycznej mapie. W nieprawdopodobnym przypadku, gdy ID strony z Memory Alpha lub Memory Beta będzie większy, niż 9999999999, zostanie rzucony wyjątek, którym będzie trzeba się zająć. Ale to temat na odległą przyszłość.