Il modo migliore per modellare l’indirizzo del cliente

Ogni Customer ha un indirizzo fisico e un indirizzo postale opzionale. Qual è il tuo modo preferito per modellarlo?

Opzione 1. Il Customer ha una chiave esterna per l’ Address

    Cliente (id, phys_address_id, mail_address_id)
    Indirizzo (id, via, città, ecc.)

Opzione 2. Il Customer ha una relazione uno a molti con Address , che contiene un campo per descrivere il tipo di indirizzo

    Identificativo del cliente)
    Indirizzo (id, customer_id, address_type, street, city, ecc.)

Opzione 3. Le informazioni sugli indirizzi sono de-normalizzate e memorizzate nel Customer

    Cliente (id, phys_street, phys_city, ecc. Mail_street, mail_city, ecc.)

Uno dei miei obiettivi prioritari è quello di semplificare i mapping relazionali agli oggetti, quindi mi sto orientando verso il primo approccio. Quali sono i tuoi pensieri?

Tendo al primo approccio per tutte le normali ragioni di normalizzazione. Questo approccio semplifica inoltre l’esecuzione della pulizia dei dati sui dettagli della spedizione.

Se hai intenzione di consentire più indirizzi (mail, residenziale, ecc.) O desideri poter utilizzare date efficaci, considera questo approccio

    Cliente (id, phys_address_id)
    Cust_address_type (cust_id, mail_address_id, address_type, start_date, end_date)
    Indirizzo (id, via, città, ecc.)

Un fatto importante che potrebbe essere necessario prendere in considerazione (a seconda del dominio del problema) è che le persone cambiano indirizzo e potrebbero voler informarti in anticipo del cambio di indirizzo; questo è certamente vero per aziende di servizi pubblici, società di telecomunicazioni, ecc.

In questo caso è necessario disporre di un modo per memorizzare più indirizzi per il cliente con date di validità, in modo che l’indirizzo possa essere impostato in anticipo e passare automaticamente al punto corretto. Se questo è un requisito, allora una variazione su (2) è l’unico modo ragionevole per modellarlo, ad es

 Customer (id, ...) Address (id, customer_id, address_type, valid_from, valid_to) 

D’altra parte, se non hai bisogno di provvedere a questo (e sei sicuro che non lo farai in futuro) allora probabilmente (1) è più semplice da gestire perché è molto più semplice mantenere l’integrità dei dati poiché non ci sono problemi con la garanzia che esiste un solo indirizzo dello stesso tipo e che i join diventano più semplici poiché sono solo su un campo.

Quindi, sia (1) o (2) vanno bene a seconda che tu abbia bisogno di mosse, ma eviterei (3) perché stai ripetendo la definizione di che indirizzo è nella tabella, e tu? Dovremo aggiungere più colonne se cambi l’aspetto di un indirizzo. Probabilmente è leggermente più performante, ma per essere onesti quando si hanno a che fare con join correttamente indicizzati in un database relazionale non c’è molto da guadagnare, ed è probabile che sia più lento in alcuni scenari in cui non è necessario l’indirizzo poiché le dimensioni del record per un cliente saranno maggiori.

La seconda opzione sarebbe probabilmente il modo in cui andrei. E in tal caso permetterebbe agli utenti di aggiungere ulteriori indirizzi “(se volessi lasciarli fare a loro), che potessero cambiare a piacimento per la spedizione e così via.

Preferirei il # 1. Buona normalizzazione e comunica chiaramente l’intento. Questo modello consente inoltre di utilizzare lo stesso object indirizzo (riga) per entrambi gli indirizzi, cosa che ho trovato molto utile. È troppo facile perdersi nel duplicare troppo queste informazioni.

Stiamo andando avanti con un modello come questo:

 Person (id, given_name, family_name, title, suffix, birth_date) Address (id, culture_id, line1, line2, city, state, zipCode, province, postalCode) AddressType (id, descriptiveName) PersonAddress (person_id, address_id, addressType_id, activeDates) 

Molti potrebbero considerarlo eccessivo. Tuttavia, un tema comune innegabile tra le app che sviluppiamo è che avranno alcune di queste quadro fondamentali – Persone, Organizzazioni, Indirizzi, Numeri di telefono, ecc. – e tutti vogliono combinarle in modi diversi. Quindi, stiamo costruendo in qualche generalizzazione in anticipo che siamo sicuri al 100% che abbiamo casi d’uso.

La tabella Indirizzo seguirà uno schema di ereditarietà della tabella per gerarchia per differenziare gli indirizzi in base alla cultura; quindi un indirizzo degli Stati Uniti avrà uno stato e un campo zip, ma gli indirizzi canadesi avranno una provincia e un codice postale.

Usiamo una tabella di connessione separata per “dare” a una persona un indirizzo. Ciò mantiene le nostre altre quadro – Persona e Indirizzo – libere da legami con altre quadro quando la nostra esperienza tende a complicare le cose lungo la strada. Rende anche molto più semplice connettere le quadro Indirizzo a molti altri tipi di quadro (Persone, Organizzazioni, ecc.) E con diverse informazioni contestuali associate al collegamento (come ActiveDates nel mio esempio).

L’opzione 3 è troppo restrittiva e l’opzione 1 non può essere estesa per consentire altri tipi di indirizzo senza modificare lo schema. L’opzione 2 è chiaramente la scelta più flessibile e quindi la migliore.

Quando rispondo a questo tipo di domande mi piace usare le classificazioni di DDD . Se si tratta di un’entity framework dovrebbe avere un ID separato, se si tratta di un object valore che non dovrebbe.

Nella maggior parte del codice che scrivo al giorno d’oggi ogni cliente ha una sola posizione fisica. Questa è la persona giuridica che è il nostro socio in affari. Pertanto metto street, city ecc nell’object / tabella del cliente. Spesso questa è la cosa più semplice ansible che funzioni e funzioni.

Quando è necessario un indirizzo postale aggiuntivo, lo metto in un object / tabella separato per non ingombrare troppo l’object cliente.

All’inizio della mia carriera mi sono normalizzato come un matto con un ordine che fa riferimento a un cliente che fa riferimento a un indirizzo di spedizione. Ciò ha reso le cose “pulite” ma lente e poco eleganti da usare. Oggigiorno utilizzo un object ordine che contiene solo tutte le informazioni sull’indirizzo. In realtà considero questo più naturale poiché un cliente potrebbe cambiare il suo indirizzo (predefinito?), Ma l’indirizzo di una spedizione inviata nel 2007 dovrebbe sempre rimanere lo stesso, anche se il cliente si sposta nel 2008.

Attualmente implementiamo il progetto VerySimpleAddressProtocol in out per standardizzare i campi utilizzati.

Vorrei andare per la prima opzione. In queste situazioni sono molto stanco di YAGNI (non ne avrai bisogno). Non riesco a contare il numero di volte che ho visto gli schemi che hanno avuto tabelle uno-a-molti “incassare” che hanno molti anni. Se hai solo bisogno di due, usa la prima opzione; se il requisito cambia in futuro, modificalo allora.

Come in molti casi: dipende.

Se i tuoi clienti si occupano di più indirizzi, sarebbe appropriata una relazione to-many. È ansible introdurre un flag sull’indirizzo che segnala se un indirizzo è per la spedizione o il conto, ecc. Oppure si archiviano i diversi tipi di indirizzo in diverse tabelle e si hanno relazioni multiple a uno su un cliente.

Nei casi in cui hai solo bisogno di conoscere un indirizzo di un cliente, perché dovresti modellarlo a molti? Una relazione to-one soddisferà le tue esigenze qui.

Importante: denormalizza solo se riscontri problemi di prestazioni.

Vorrei andare con l’opzione 1. Se vuoi, potresti anche modificarlo un po ‘per mantenere una cronologia degli indirizzi:

 Customer (id, phys_address_id, mail_address_id) Address (id, customer_id, start_dt, end_dt, street, city, etc.) 

Se l’indirizzo cambia, basta solo terminare la data dell’indirizzo corrente e aggiungere un nuovo record nella tabella Address . phys_address_id e mail_address_id indicano sempre l’indirizzo corrente.

In questo modo puoi conservare una cronologia degli indirizzi, potresti avere più indirizzi di posta archiviati nel database (con il valore predefinito in mail_address_id ), e se l’indirizzo fisico e l’indirizzo postale sono identici ti basterà indicare phys_address_id e mail_address_id allo stesso record .

Buona discussione Ho passato un po ‘di tempo a contemplare lo schema più adatto e ho concluso che la soluzione di quentin-starin è la migliore tranne che ho aggiunto i campi start_date e end_date a quella che sarebbe stata la sua tabella PersonAddress. Ho anche deciso di aggiungere note , attive e cancellate .

cancellato è per la funzionalità di eliminazione software perché penso di non voler perdere traccia degli indirizzi precedenti semplicemente cancellando il record dalla tabella di giunzione. Penso che sia abbastanza saggio e qualcosa che gli altri potrebbero voler prendere in considerazione. Se non fatto in questo modo, potrebbe essere lasciato alla revisione di documenti cartacei o elettronici per cercare di rintracciare le informazioni sull’indirizzo (cosa che è meglio evitare).

nota che penso di essere qualcosa di un requisito, ma potrebbe essere solo una preferenza. Ho trascorso un po ‘di tempo in esercizi di backfill verificando gli indirizzi nei database e alcuni indirizzi possono essere molto vaghi (come gli indirizzi rurali) che penso sia molto utile per consentire almeno le note su quell’indirizzo da tenere nell’indirizzo del record.

Una cosa su cui vorrei sentire le opinioni è l’indicizzazione univoca della tabella degli indirizzi (di nuovo, facendo riferimento alla tabella con lo stesso nome nell’esempio di quentin-starin. Pensi che dovrebbe essere l’indice univoco da applicare (come indice composto presumibilmente attraverso tutti i campi non nulli / obbligatori) Questo sembrerebbe ragionevole ma potrebbe essere ancora difficile fermare i dati duplicati, indipendentemente dal fatto che i codici postali / postali non sono sempre unici per una singola proprietà. popolati da dati di riferimento (che sono nel mio modello), le differenze di ortografia nelle righe di indirizzo potrebbero non essere corrispondenti. L’unico modo per evitare questo potrebbe essere quello di eseguire una o più query DB dai campi modulo in entrata per vedere se è stato trovato un ansible duplicato.Un’altra misura di sicurezza sarebbe dare all’utente la possibilità di selezionare dall’indirizzo nel database già collegato a quella persona e usarlo per auto-compilare.Penso che questo potrebbe essere un caso in cui puoi essere solo ragionevole e prendere prec autions per fermare la duplicazione ma solo accettarlo può (e probabilmente lo farà) prima o poi.

L’altro aspetto molto importante di questo per me è la modifica futura dei record della tabella degli indirizzi . Diciamo che hai 2 persone entrambe elencate a: –

11 Whatever Street Whatever City Z1P C0D3

Non dovrebbe essere considerato pericoloso consentire che lo stesso record della tabella di indirizzi venga assegnato a quadro diverse (persona, azienda)? Quindi diciamo che l’utente capisce che una di queste persone vive a 111 Whatever Street e che c’è un refuso. Se cambi questo indirizzo, lo cambierà per entrambe le quadro. Vorrei evitarlo. Il mio suggerimento sarebbe di avere il modello nel MVC (nel mio caso, PHP Yii2) cercare i record di indirizzo esistenti quando viene creato un nuovo indirizzo noto per essere correlato a quel cliente (SELECT * FROM address INTERNO JOIN personaddress ON personaddress.address_id = address.id WHERE personaddress.person_id = {current person being edit ID}) e fornire all’utente l’opzione di utilizzare quel record (come essenzialmente suggerito sopra).

Ritengo che colbind lo stesso indirizzo a più quadro diverse sia solo per chiedere guai, in quanto potrebbe essere il caso di rifiutare in seguito la modifica del record dell’indirizzo (non pratico) o di rischiare che la modifica futura del record possa corrompere i dati relativi ad altre quadro al di fuori di chi sta registrando l’ indirizzo è in corso di modifica.

Mi piacerebbe sentire i pensieri delle persone.