La mejor manera de modelar la dirección del cliente <->

Cada Customer tiene una dirección física y una dirección postal opcional. ¿Cuál es tu forma preferida de modelar esto?

Opción 1. El Customer tiene una key externa para Address

    Cliente (id, phys_address_id, mail_address_id)
    Dirección (identificación, calle, ciudad, etc.)

Opción 2. El Customer tiene una relación uno a muchos con la Address , que contiene un campo para describir el tipo de dirección

    Identificación del cliente)
    Dirección (id, customer_id, address_type, street, city, etc.)

Opción 3. La información de la dirección se desnormaliza y se almacena en Customer

    Cliente (id, phys_street, phys_city, etc. mail_street, mail_city, etc.)

Uno de mis principales objectives es simplificar las asignaciones relacionales de objects, por lo que me inclino por el primer enfoque. ¿Cuáles son tus pensamientos?

Tiendo hacia el primer acercamiento por todas las razones usuales de normalización. Este enfoque también facilita la limpieza de datos en los detalles de correo.

Si posiblemente va a permitir varias direcciones (correo, residencial, etc.) o desea poder usar dates efectivas, considere este enfoque

    Cliente (id, phys_address_id)
    Cust_address_type (cust_id, mail_address_id, address_type, start_date, end_date)
    Dirección (identificación, calle, ciudad, etc.)

Un hecho importante que quizás deba considerar (dependiendo del dominio de su problema) es que las personas cambien de dirección, y es posible que desee informarle con antelación sobre el cambio de dirección; esto es cierto para las empresas de services públicos, las empresas de telecomunicaciones, etc.

En este caso, debe tener una forma de almacenar varias direcciones para el cliente con dates de validez, de modo que la dirección se pueda configurar con anticipación y cambiar automáticamente al punto correcto. Si esto es un requisito, entonces una variación en (2) es la única forma sensata de modelarlo, por ej.

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

Por otro lado, si no necesita atender esto (y está seguro de que no lo hará en el futuro), entonces probablemente (1) es más fácil de administrar porque es mucho más fácil mantener la integridad de los datos ya que no hay problemas. con la garantía de que solo existe una dirección del mismo tipo, y las uniones se vuelven más simples ya que solo están en un campo.

Entonces, o bien (1) o bien (2) están bien dependiendo de si necesitas movimientos de casa, pero me mantendría alejado de (3) porque entonces estás repitiendo la definición de qué dirección hay en la tabla, y tú " Tendré que agregar varias columnas si cambias el aspecto de una dirección. Posiblemente sea un poco más eficiente, pero para ser honesto, cuando se trata de uniones correctamente indexadas en una database relacional, no hay mucho que ganar, y es probable que sea más lento en algunos escenarios donde no se necesita la dirección ya que el tamaño de logging para un cliente será mayor.

Descubrí que lo que parece ser un layout inicialmente "maestro de clientes" a menudo se rompe más tarde porque: trata previamente a una empresa a medida que el cliente evoluciona para tratar a empleados individuales como clientes, o un cliente cambiará / dividirá / fusionará direcciones, o una empresa cambia su nombre pero aún queremos consolidar totales de performance antiguos y nuevos, o una dirección de envío y de facturación ahora debe expandirse para include una dirección de soporte, o los operadores olvidan o confunden un propósito de dirección por otro, o un cliente quiere para usar una dirección de envío especial solo de manera temporal, etc.

Como resultado, he abandonado la idea de un file maestro de clientes. En cambio, la información del nombre / compañía / dirección nunca son loggings maestros (excepto para aplicaciones como facturación de services públicos o impuestos a la propiedad donde una dirección física específica nunca se puede editar en otra dirección), son solo campos que indican el contacto en uso AT A PARTICULAR POINT IN TIEMPO, generalmente dentro de algo así como un logging de órdenes de venta. Cada pedido de venta está encadenado al pedido anterior y siguiente para ese cliente, incluso cuando el cliente cambia su nombre o dirección. La ventaja es que todos los pedidos se pueden consolidar / totalizar / analizar a lo largo de todo el historial de transactions del cliente, aunque cada pedido puede variar el nombre o la dirección del contacto. Es contradictorio, especialmente cuando se trata de complacer a los diseñadores de db para normalizar, pero termina siendo muy flexible y conveniente.

Por ejemplo, cuando el cliente X primero realiza un pedido, no se crea ningún logging de cliente. En su lugar, se crea un logging de order de venta que contiene la información de nombre / compañía / dirección necesaria en el momento del pedido. Cuando el cliente X realiza su segundo pedido, no buscamos un file de cliente, buscamos en el file de pedido de cliente y luego lo copymos / encadenamos para crear su segundo pedido de cliente. Si quiere cambiar su información de nombre / compañía / dirección, está bien, solo editamos esos campos en el pedido de venta n. ° 2 y el pedido de venta n. ° 1 no cambia. Ahora es localizable bajo cualquier variación (order 1 o 2).

Para otras consideraciones al tratar de decidir si dos loggings de clientes son realmente iguales, consulte http://semaphorecorp.com/mpdd/mpdd.html

La segunda opción probablemente sería la forma en que iría. Y, por si acaso, les permitiría a los usuarios agregar direcciones adicionales '(si querías dejar que lo hicieran), que podrían cambiar a voluntad para el envío y demás.

Prefiero el # 1. Buena normalización y comunica intención claramente. Este model también permite que se use el mismo object de dirección (fila) para ambas direcciones, algo que considero que es bastante valioso. Es demasiado fácil perderse duplicando demasiado esta información.

Estamos avanzando con un model como este:

 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) 

La mayoría puede considerar esto excesivo. Sin embargo, un tema común innegable entre las aplicaciones que desarrollamos es que tendrán algunas de estas entidades fundamentales: personas, organizaciones, direcciones, numbers de teléfono, etc., y todas quieren combinarlas de diferentes maneras. Entonces, estamos construyendo en cierta generalización por adelantado que estamos 100% seguros de que tenemos casos de uso para.

La tabla de direcciones seguirá un esquema de inheritance tabla por jerarquía para diferenciar direcciones basadas en cultura; por lo tanto, una dirección de Estados Unidos tendrá un campo de estado y postal, pero las direcciones de Canadá tendrán una provincia y un código postal.

Usamos una tabla de connection separada para "dar" a una persona una dirección. Esto mantiene nuestras otras entidades, Persona y Dirección, libres de vínculos con otras entidades cuando nuestra experiencia es que esto complica las cosas en el futuro. También hace que sea mucho más simple conectar entidades de Dirección a muchos otros types de entidades (Personas, Organizaciones, etc.) y con diferente información contextual asociada con el enlace (como activeDates en mi ejemplo).

Al responder ese tipo de preguntas, me gusta usar las clasificaciones de DDD . Si se trata de una entidad, debe tener una identificación separada; si es un object de valor, no debería serlo.

En la mayoría de los códigos que escribo actualmente, cada cliente tiene una única location física. Esta es la entidad legal que es nuestro socio comercial. Por lo tanto, puse street, city, etc. en el object / tabla del cliente. A menudo, esta es la cosa más simple posible que funciona y funciona.

Cuando se necesita una dirección de correo adicional, la pongo en un object / tabla aparte para no saturar mucho el object del cliente.

Al principio de mi carrera me normalicé como loco teniendo un pedido que hace reference a un cliente que hace reference a una dirección de envío. Esto hizo las cosas "limpias" pero lentas y poco elegantes de usar. Hoy en día utilizo un object de pedido que contiene toda la información de la dirección. De hecho, considero que esto es más natural ya que un cliente puede cambiar su dirección (¿pnetworkingeterminada?), Pero la dirección de un envío enviado en 2007 siempre debe permanecer igual, incluso si el cliente se muda en 2008.

Actualmente implementamos el proyecto VerySimpleAddressProtocol in out para estandarizar los campos utilizados.

Yo iría por la primera opción. En estas situaciones, estoy muy cansado de YAGNI (no lo va a necesitar). No puedo contar la cantidad de veces que he visto esquemas que tienen tablas uno a muchos "por si solo" que tienen muchos años. Si solo necesitas dos, solo usa la primera opción; si el requisito cambia en el futuro, cámbielo entonces.

Como en muchos casos: depende.

Si sus clientes manejan múltiples direcciones, entonces una relación de muchos sería apropiada. Puede introducir un indicador en la dirección que indica si una dirección es para envío o factura, etc. O puede almacenar los diferentes types de direcciones en diferentes tablas y tener múltiples relaciones uno a uno en un cliente.

En los casos en que solo necesita conocer una dirección de un cliente, ¿por qué modelaría eso para muchos? Una relación uno a uno satisfaría sus necesidades aquí.

Importante: Desnormalización solo si tiene problemas de performance.

La opción 3 es demasiado restrictiva y la opción 1 no se puede ampliar para permitir otros types de direcciones sin cambiar el esquema. La opción 2 es claramente la más flexible y, por lo tanto, la mejor opción.

Me gustaría ir con la opción 1. Si lo desea, incluso podría modificarlo un poco para mantener un historial de direcciones:

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

Si la dirección cambia, simplemente finalice la date de la dirección actual y agregue un nuevo logging en la tabla de Address . phys_address_id y mail_address_id siempre apuntan a la dirección actual.

De esta forma puede mantener un historial de direcciones, puede tener múltiples direcciones postales almacenadas en la database (con el valor pnetworkingeterminado en mail_address_id ), y si la dirección física y la dirección postal son idénticas, solo phys_address_id y mail_address_id en el mismo logging .

Buen hilo. He pasado un time contemplando el esquema más adecuado y he llegado a la conclusión de que la solución de quentin-starin es la mejor, excepto que he agregado los campos start_date y end_date a lo que sería su tabla PersonAddress. También he decidido agregar notas , activas y eliminadas .

borrado es para la funcionalidad de eliminación suave, ya que creo que no quiero perder el rastro de las direcciones anteriores simplemente eliminando el logging de la tabla de unión. Creo que es bastante sabio y algo que otros pueden querer considerar. Si no se hace de esta manera, podría dejarse a la revisión de documentos en papel o electrónicos para intentar rastrear la información de la dirección (algo que se debe evitar mejor).

notas , creo que es algo así como un requisito, pero eso podría ser solo preference. Pasé time en ejercicios de relleno verificando direcciones en bases de datos y algunas direcciones pueden ser muy vagas (como direcciones rurales) que creo que es muy útil para, al less, permitir que las notas sobre esa dirección se guarden en la dirección del logging.

Una cosa sobre la que me gustaría escuchar opiniones es la indexing única de la tabla de direcciones (una vez más, refiriéndose a la tabla del mismo nombre en el ejemplo de quentin-starin. ¿Cree que debería ser único el índice debe aplicarse (como un índice compuesto)? presumiblemente en todos los campos no obligatorios / obligatorios)? Esto parecería sensato, pero aún podría ser difícil detener la duplicación de datos independientemente de que los códigos postales / postales no siempre sean exclusivos de una sola propiedad. Incluso si los campos de país, provincia y ciudad son rellenado a partir de datos de reference (que están en mi model), las diferencias de ortografía en las líneas de dirección pueden no coincidir. La única forma de evitar esto podría ser ejecutar una o varias consultas DB desde los campos de formulario entrantes para ver si Se ha encontrado un posible duplicado. Otra medida de security sería darle al usuario la opción de seleccionar una dirección en la database ya vinculada a esa persona y usarla para autopoblar. Creo que este podría ser un caso en el que solo se puede ser sensato y tomar prec para detener la duplicación, pero simplemente acepte que puede (y probablemente sucederá) tarde o temprano.

El otro aspecto muy importante de esto para mí es la edición futura de los loggings de la tabla de direcciones . Digamos que tiene 2 personas que figuran en:

11 Cualquiera que sea la ciudad sea cual sea la ciudad Z1P C0D3

¿No debería considerarse peligroso permitir que el mismo logging de la tabla de direcciones se asigne a diferentes entidades (persona, empresa)? Entonces digamos que el usuario se da count de que una de estas personas vive en 111 Whatever Street y hay un error tipográfico. Si cambia esa dirección, la cambiará para ambas entidades. Me gustaría evitar eso. Mi sugerencia sería que el model en el MVC (en mi caso, PHP Yii2) busque loggings de direcciones existentes cuando se crea una nueva dirección que se sabe que está relacionada con ese cliente (SELECCIONAR * dirección FROM INNER JOIN direcciónpersonal EN direcciónpersonal.address_id = address.id WHERE personaddress.person_id = {persona actual que se está editando ID}) y le da al usuario la opción de usar ese logging (como se sugirió esencialmente arriba).

Siento que vincular la misma dirección a múltiples entidades diferentes es solo pedir problemas, ya que podría ser un caso de rechazar la edición posterior del logging de dirección (poco práctico) o arriesgar que la edición futura del logging pueda dañar datos relacionados con otras entidades fuera de el que está grabando la dirección está siendo editado.

Me encantaría escuchar los pensamientos de la gente.