Ho pensato anche a me stesso. Ecco i miei pensieri vaghi finora, e mi chiedo cosa pensano gli altri.
xAL (e la sua sorella che include nomi personali, XNAL) viene utilizzato da entrambi i servizi di geocodifica di Google e Yahoo, dandogli un certo peso. Ma poiché lo stesso indirizzo può essere descritto in xAL in molti modi diversi, alcuni più specifici di altri, allora non vedo come xAL stesso sia un formato accettabile per l'archiviazione dei dati. Alcuni dei suoi nomi di campo potrebbe essere utilizzato, tuttavia, ma in realtà l'unico formato di base che può essere utilizzato tra i 16 paesi che le mie navi aziendali a è la seguente:
enum address-fields
{
name,
company-name,
street-lines[], // up to 4 free-type street lines
county/sublocality,
city/town/district,
state/province/region/territory,
postal-code,
country
}
Questo è abbastanza facile per mappare in un unico tabella di database, consentendo solo NULL sulla maggior parte delle colonne. E sembra che questo sia il modo in cui Amazon e molte organizzazioni conservano effettivamente i dati degli indirizzi. Quindi la domanda che rimane è come dovrei modellare questo in un modello di oggetto che è facilmente utilizzato dai programmatori e da qualsiasi codice della GUI. Abbiamo un tipo Address
di base con sottoclassi per ogni tipo di indirizzo, ad esempio AmericanAddress
, CanadianAddress
, GermanAddress
e così via? Ognuno di questi tipi di indirizzo saprebbe come formattare se stessi e opzionalmente saprebbe un po 'sulla convalida dei campi.
Essi potrebbero anche tornare un certo tipo di metadati su ognuno dei campi, come ad esempio la seguente struttura di dati pseudocodice:
structure address-field-metadata
{
field-number, // corresponds to the enumeration above
field-index, // the order in which the field is usually displayed
field-name, // a "localized" name; US == "State", CA == "Province", etc
is-applicable, // whether or not the field is even looked at/valid
is-required, // whether or not the field is required
validation-regex, // an optional regex to apply against the field
allowed-values[] // an optional array of specific values the field can be set to
}
Infatti, invece di avere oggetti di indirizzi singoli per ogni paese, potremmo prendere la un approccio leggermente meno orientato all'oggetto di avere un oggetto Address
che si rifiuta.Proprietà NET e utilizza un AddressStrategy
stabilire regole di formattazione e convalida:
object address
{
set-field(field-number, field-value),
address-strategy
}
object address-strategy
{
validate-field(field-number, field-value),
cleanse-address(address),
format-address(address, formatting-options)
}
Quando si imposta un campo, che Address
oggetto avrebbero richiamare il metodo appropriato sul suo AddressStrategy
oggetto interno.
Il motivo dell'utilizzo di un approccio al metodo SetField()
anziché di proprietà con getter e setter è che è più semplice che il codice imposti effettivamente questi campi in modo generico senza ricorrere a istruzioni di riflessione o di commutazione.
si può immaginare il processo in corso qualcosa di simile:
- codice della GUI chiama un metodo factory o qualcosa del genere per creare un indirizzo basato su un paese. (Il menu a discesa paese, quindi, è la prima cosa che il cliente seleziona, o ha una buona preselezione preselezionata per loro in base alle informazioni sulla cultura o all'indirizzo IP.)
- GUI chiama
address.GetMetadata()
o un metodo simile e riceve un elenco di le strutture AddressFieldMetadata
come descritto sopra. Può utilizzare questi metadati per determinare quali campi visualizzare (ignorando quelli con is-applicable
impostato su false
), cosa etichettare quei campi (utilizzando il membro field-name
), visualizzare quei campi in un ordine particolare ed eseguire la convalida di livello di presentazione rapida su tali dati (utilizzando i membri is-required
, validation-regex
e allowed-values
).
- La GUI chiama il metodo
address.SetField()
utilizzando field-number
(che corrisponde all'enumerazione precedente) e ai relativi valori. L'oggetto Address
o la sua strategia possono quindi eseguire alcune convalida degli indirizzi avanzata su quei campi, richiamare pulitori di indirizzo, ecc
Ci potrebbero essere lievi variazioni su quanto sopra, se vogliamo rendere l'oggetto in sé Address
comportarsi come un immutabile oggetto una volta creato. (Che probabilmente cercherò di fare, dato che l'oggetto Address
è davvero più simile a una struttura dati e probabilmente non avrà mai alcun vero comportamento associato a se stesso.)
Tutto ciò ha senso? Mi sto allontanando troppo dal percorso OOP? Per me, questo rappresenta un compromesso piuttosto ragionevole tra l'essere così astratti che l'implementazione è quasi impossibile (xAL) rispetto a essere rigorosamente di stampo americano.
Update 2 anni dopo: alla fine ho finito con un sistema simile a questo e ha scritto su di esso a my defunct blog.
Mi sento come se questa soluzione fosse il giusto equilibrio tra dati legacy e archiviazione dati relazionali, almeno per il mondo dell'e-commerce.
In quale paese/paesi? La formattazione e la composizione degli indirizzi varia molto tra i diversi paesi. Se hai a che fare con un solo paese, il modello può essere molto più semplice di quello che vuoi se memorizzi gli indirizzi di qualsiasi paese in modo strutturato ... – KristoferA
La Francia sarebbe perfetta ;-) Hai ragione: un solo paese gli indirizzi (credo che gli Stati Uniti sarebbero i più comuni, credo) sarebbero un ottimo punto di partenza. – Mac