Об'єкти домену як ідентифікатори створюють деякі складні / тонкі проблеми:
Серіалізація / десеріалізація
Якщо ви зберігаєте об’єкти як ключі, це зробить серіалізацію об'єктного графіка надзвичайно складним. Ви отримаєте stackoverflow
помилки, роблячи наївну серіалізацію в JSON або XML через рекурсію. Тоді вам доведеться написати спеціальний серіалізатор, який перетворює фактичні об'єкти для використання їх ідентифікаторів, а не серіалізації об’єктного об'єкта та створення рекурсії.
Передайте об'єкти для безпеки типу, але зберігайте лише ідентифікатори, тоді ви можете мати метод аксесуара, який ледачий завантажує відповідний об'єкт, коли він викликається. Кешування другого рівня забезпечить наступні дзвінки.
Тонкі довідкові витоки:
Якщо ви використовуєте об’єкти домену в таких конструкторах, ви створите кругові посилання, що буде дуже важко дозволити відновленню пам'яті для об'єктів, які активно не використовуються.
Ідеальна ситуація:
Непрозорі ідентифікатори проти int / long:
id
Повинна бути повністю непрозорим ідентифікатором , який не несе ніякої інформації про те, що вона ідентифікує. Але він повинен запропонувати певну перевірку того, що він є дійсним ідентифікатором у своїй системі.
Сирі види порушують це:
int
, long
і String
є найбільш часто використовуваними типами сировини для ідентифікаторів в системі RDBMS. Існує довга історія практичних причин, які датуються десятиліттями, і всі вони є компромісами, які або вкладаються в економію, space
або в економію, time
або в обидва.
Послідовні ідентифікатори - найгірші правопорушники:
Коли ви використовуєте послідовний ідентифікатор, ви за замовчуванням запакуєте тимчасову семантичну інформацію в ідентифікатор. Що непогано, поки його не використовують. Коли люди починають писати ділову логіку, яка сортує або фільтрує семантичну якість ідентифікатора, тоді вони створюють світ болю для майбутніх утримувачів.
String
поля є проблематичними, тому що наївні дизайнери запакуватимуть інформацію у зміст, як правило, також у часовій семантиці.
Це робить неможливим і створення розподіленої системи даних, оскільки 12437379123
вона не є єдиною в усьому світі. Шанси, що інший вузол в розподіленій системі створить запис з однаковим числом, майже гарантовані, коли ви отримаєте достатньо даних у системі.
Потім хаки починають працювати навколо нього, і вся річ перетворюється на купу пареного безладу.
Ігнорування величезних розподілених систем ( кластерів ) стає повним кошмаром, коли ви починаєте обмінюватися даними також з іншими системами. Особливо, коли інша система не під вашим контролем.
У вас з'являється та сама проблема, як зробити свій ідентифікатор глобальним.
UUID створено та стандартизовано з причини:
UUID
може страждати від усіх перерахованих вище проблем, залежно від того, якими Version
ви користуєтесь.
Version 1
використовує MAC-адресу та час для створення унікального ідентифікатора. Це погано, оскільки воно несе смислову інформацію про місце та час. Це само по собі не є проблемою, це коли наївні розробники починають покладатися на цю інформацію для ділової логіки. Це також просочує інформацію, яка може бути використана в будь-яких спробах вторгнення.
Version 2
використовує користувачів UID
або GID
domian, UID
або GUI
замість цього часу Version 1
так само погано, як і Version 1
для витоку даних та ризику використовувати цю інформацію для використання в бізнес-логіці.
Version 3
подібно , але замінить Вашу і час MAC з MD5
хеш деякого масиву byte[]
від чого - то , що , безумовно , має смислове значення. Немає витоку даних, щоб турбуватися, byte[]
їх неможливо відновити UUID
. Це дає хороший спосіб детерміновано створити UUID
форму екземплярів та якийсь зовнішній ключ .
Version 4
ґрунтується лише на випадкових числах, що є хорошим рішенням, воно не несе абсолютно ніякої смислової інформації, але не детерміновано повторно створювати.
Version 5
так само, Version 4
але використовує sha1
замість цього md5
.
Ключі домену та ключі транзакційних даних
Мої переваги для ідентифікаторів об’єктів домену - це використання Version 5
або Version 3
обмеження використання Version 5
з якоїсь технічної причини.
Version 3
чудово підходить для даних про транзакції, які можуть поширюватися на багатьох машинах.
Якщо ви не обмежені простором, використовуйте UUID:
Вони гарантовано унікальні, скидаючи дані з однієї бази даних та перезавантажуючись в іншу, вам ніколи не довелося турбуватися про дублікати ідентифікаторів, які насправді посилаються на різні дані домену.
Version 3,4,5
є абсолютно непрозорими, і саме так і має бути.
Ви можете мати один стовпчик як основний ключ з a, UUID
а потім ви можете мати складні унікальні індекси для того, що було б природним складеним первинним ключем.
Зберігання теж не повинно бути CHAR(36)
. Ви можете зберігати UUID
в рідному байті / біті / полі числа для даної бази даних, поки вона все ще індексується.
Спадщина
Якщо у вас є вихідні типи і ви не можете їх змінити, ви все одно можете їх абстрагувати у своєму коді.
Використання Version 3/5
з UUID
вас може пройти в Class.getName()
+ String.valueOf(int)
вигляді byte[]
і має непрозорий контрольний ключ , який recreatable і детерміновані.