Gli oggetti di dominio come ID creano alcuni problemi complessi / sottili:
Serializzazione / deserializzazione
Se si memorizzano oggetti come chiavi, la serializzazione del grafico degli oggetti sarà estremamente complicata. Riceverai stackoverflow
errori quando esegui una serializzazione ingenua in JSON o XML a causa della ricorsione. Dovrai quindi scrivere un serializzatore personalizzato che converta gli oggetti effettivi per utilizzare i loro ID invece di serializzare l'istanza dell'oggetto e creare la ricorsione.
Passa gli oggetti per la sicurezza dei tipi ma archivia solo gli ID, quindi puoi avere un metodo di accesso che pigra l'entità correlata quando viene chiamata. La memorizzazione nella cache di secondo livello si occuperà delle chiamate successive.
Perdite di riferimento sottili:
Se usi oggetti di dominio in costruttori come quelli che hai lì creerai riferimenti circolari che saranno molto difficili da consentire alla memoria di essere recuperata per oggetti che non vengono utilizzati attivamente.
Situazione ideale:
ID opachi vs int / long:
An id
dovrebbe essere un identificatore completamente opaco che non contiene informazioni su ciò che identifica. Ma dovrebbe offrire una verifica che sia un identificatore valido nel suo sistema.
I tipi grezzi rompono questo:
int
, long
E String
sono i tipi prime più comunemente utilizzati per gli identificatori nel sistema RDBMS. C'è una lunga storia di ragioni pratiche che risalgono a decenni fa e sono tutti compromessi che si adattano al risparmio space
o al risparmio time
o entrambi.
Gli ID sequenziali sono i peggiori trasgressori:
Quando si utilizza un ID sequenziale, si impacchettano le informazioni semantiche temporali nell'ID per impostazione predefinita. Il che non è male fino a quando non viene utilizzato. Quando le persone iniziano a scrivere una logica aziendale che ordina o filtra la qualità semantica dell'id, allora stanno creando un mondo di dolore per i futuri manutentori.
String
i campi sono problematici perché i progettisti ingenui comprimeranno le informazioni nei contenuti, di solito anche la semantica temporale.
Ciò rende impossibile creare anche un sistema di dati distribuito, perché non12437379123
è univoco a livello globale. Le probabilità che un altro nodo in un sistema distribuito crei un record con lo stesso numero è praticamente garantita quando si ottengono abbastanza dati in un sistema.
Quindi gli hack iniziano a aggirarlo e l'intera cosa si trasforma in un mucchio di caos fumante.
Ignorare enormi sistemi distribuiti ( cluster ) diventa un incubo completo quando si inizia a provare a condividere i dati anche con altri sistemi. Soprattutto quando l'altro sistema non è sotto il tuo controllo.
Ti ritrovi con lo stesso identico problema, come rendere il tuo ID unico a livello globale.
UUID è stato creato e standardizzato per un motivo:
UUID
può soffrire di tutti i problemi sopra elencati a seconda di quale Version
si utilizza.
Version 1
utilizza un indirizzo MAC e l'ora per creare un ID univoco. Ciò è negativo perché contiene informazioni semantiche su posizione e tempo. Questo non è di per sé un problema, è quando gli sviluppatori ingenui iniziano a fare affidamento su tali informazioni per la logica aziendale. Ciò perde anche informazioni che potrebbero essere sfruttate in qualsiasi tentativo di intrusione.
Version 2
utilizza un utente UID
o GID
domian UID
o GUI
al posto del tempo da Version 1
questo è altrettanto grave come Version 1
per la perdita di dati e il rischio di queste informazioni da utilizzare nella logica aziendale.
Version 3
è simile ma sostituisce l'indirizzo MAC e l'ora con un MD5
hash di una matrice di byte[]
qualcosa che ha sicuramente un significato semantico. Non vi è alcuna perdita di dati di cui preoccuparsi, il byte[]
non può essere recuperato dal UUID
. Questo ti dà un buon modo per creare in modo deterministico UUID
forma istanze e chiave esterna di qualche tipo.
Version 4
si basa solo su numeri casuali che rappresentano una buona soluzione, non trasporta assolutamente alcuna informazione semantica, ma non è deterministicamente ricostruibile.
Version 5
è come Version 4
ma usa sha1
invece di md5
.
Chiavi di dominio e chiavi di dati transazionali
La mia preferenza per gli ID oggetto di dominio è di utilizzare Version 5
o, Version 3
se limitato, Version 5
per qualche motivo tecnico.
Version 3
è ottimo per i dati di transazione che potrebbero essere distribuiti su molte macchine.
A meno che tu non sia limitato dallo spazio, usa un UUID:
Sono garantiti univoci, scaricando dati da un database e ricaricandoli in un altro, senza mai doverti preoccupare di ID duplicati che fanno effettivamente riferimento a dati di dominio diversi.
Version 3,4,5
sono completamente opachi ed è così che dovrebbero essere.
Puoi avere una singola colonna come chiave primaria con un UUID
e quindi puoi avere indici univoci composti per quella che sarebbe stata una chiave primaria composita naturale.
Bagagli non non deve essere CHAR(36)
neanche. È possibile archiviare il campo UUID
in un byte / bit / numero nativo per un determinato database purché sia ancora indicizzabile.
eredità
Se hai tipi non elaborati e non puoi modificarli, puoi comunque estrarli nel tuo codice.
Usando uno Version 3/5
di UUID
voi puoi passare il Class.getName()
+ String.valueOf(int)
come a byte[]
e avere una chiave di riferimento opaca che è ricreabile e deterministica.