2010-08-09 13 views
10

Empecé a pensar en el seguimiento de los cambios en el gráfico de objeto complejo en la aplicación desconectada. Ya he encontrado varias soluciones pero me gustaría saber si hay alguna mejor práctica o qué solución usas y por qué? Pasé la misma pregunta al MSDN forum pero recibí una sola respuesta. Me gustaría tener más respuestas para aprender de la experiencia de otros desarrolladores.Cambios de seguimiento en el gráfico de objeto complejo

Esta pregunta está relacionada con .NET, por lo que para respuestas con detalles de implementación prefiero las respuestas relacionadas con el mundo .NET, pero creo que esto es lo mismo en otras plataformas.

El problema teórico en mi caso se define en la arquitectura de múltiples capas (no necesariamente de n niveles en el momento) de la siguiente manera:

  • capa de repositorios utilizando ORM para hacer frente a la persistencia (herramienta ORM no lo hace por el momento, pero probablemente será Entity Framework 4.0 o NHibernate).
  • Conjunto de clases puras (ignorante persistente = POCO que es equivalente a POJO en el mundo de Java) que representan objetos de dominio. Los repositorios persisten esas clases y las devuelve como resultado de consultas.
  • Conjunto de servicios de dominio que trabajan con entidades de dominio.
  • capa de fachada que define la puerta de enlace a la lógica de negocios. Internamente usa repositorios, servicios de dominio y objetos de dominio. Los objetos de dominio no están expuestos: cada método de fachada utiliza un conjunto de objetos de transferencia de datos especializados para el parámetro y el valor de retorno. Es responsabilidad de cada método de fachada transformar la entidad de dominio a DTO y viceversa.
  • Aplicación web moderna que usa capa de fachada y DTOs - Yo llamo a esta aplicación desconectada. En general, el diseño puede cambiar en el futuro, de modo que la capa Fachada estará envuelta por la capa de servicio web y la aplicación web consumirá esa transición de servicios => a 3 niveles (web, lógica comercial, base de datos).

Supongamos ahora que uno de los objetos del dominio es el pedido que tiene detalles del pedido (líneas) y pedidos relacionados. Cuando el cliente solicita el pedido de edición, puede modificar el pedido, agregar, eliminar o modificar cualquier detalle del pedido y agregar o eliminar pedidos relacionados. Todas estas modificaciones se realizan sobre datos en el navegador web - javascript y AJAX. Por lo tanto, todos los cambios se envían en una sola toma cuando el cliente presiona el botón Guardar. La pregunta es ¿cómo manejar estos cambios? La herramienta de repositorio y ORM necesita saber qué entidades y relaciones se modificaron, insertaron o eliminaron. Terminé con dos "mejores" soluciones:

  1. tienda estado inicial de DTO en campo oculto (en peor de los casos a la sesión). Al recibir una solicitud para guardar los cambios, cree un DTO nuevo basado en los datos recibidos y un segundo DTO basado en los Datos persistentes. Combina esos dos y rastrea los cambios. Envíe DTO fusionado a la capa de fachada y use la información recibida sobre los cambios para configurar correctamente el gráfico de entidad. Esto requiere algún seguimiento de cambio manual en el objeto de dominio para que la información de cambio pueda configurarse desde cero y luego pasar al repositorio; este es el punto con el que no estoy muy contento.

  2. No rastrear los cambios en DTO en absoluto. Al recibir datos modificados en la capa de fachada crear entidad modificada y cargar el estado real del repositorio (generalmente consulta adicional a la base de datos, este es el punto con el que no estoy muy contento) fusionar estas dos entidades y rastrear automáticamente los cambios por entidad proxy proporcionados por la herramienta ORM (Entity framework 4.0 y NHibernate lo permiten). Se necesita cuidado especial para el manejo de concurrencia porque el estado actual no tiene que ser el estado inicial.

¿Qué opinas sobre eso?¿Que recomiendas?

Sé que algunos de estos desafíos se pueden evitar utilizando el almacenamiento en caché en algunas capas de aplicaciones, pero eso es algo que no quiero usar en este momento.

Mi interés en este tema va incluso más allá. Por ejemplo, supongamos que la aplicación va a la arquitectura de 3 niveles y que el cliente (aplicación web) no se escribirá en .NET = las clases DTO no se pueden reutilizar. Seguir los cambios en DTO será mucho más difícil porque requerirá que otro equipo de desarrollo implemente correctamente el mecanismo de seguimiento en sus herramientas de desarrollo.

Creo que estos problemas tienen que resolverse en muchas aplicaciones, por favor comparta su experiencia.

Respuesta

3

Todo es cuestión de responsabilidad.

(No estoy seguro de si este es el tipo de respuesta que buscas, avísame si no es así para que pueda actualizarlo).

Así que tenemos múltiples capas en un sistema; cada una es responsable de una tarea diferente: acceso a datos, interfaz de usuario, lógica de negocios, etc. Cuando diseñamos un sistema de esta manera estamos (entre otras cosas) tratando de hacer futuro cambie fácilmente haciendo que cada componente sea responsable de una tarea, de modo que pueda enfocarse en esa tarea y hacerlo bien. También hace que sea más fácil modificar el sistema a medida que pasa el tiempo y se necesita un cambio.

Pensamientos similares deben tenerse en cuenta al considerar el DTO: "¿cómo hacer un seguimiento de los cambios?" por ejemplo. Así es como lo abordo: el BL es responsable de administrar las reglas y la lógica; dada la naturaleza sin estado de la web (que es donde realizo la mayor parte de mi trabajo), simplemente no estoy rastreando el estado de un objeto y buscando explícitamente cambios. Si un usuario está devolviendo datos (para guardarlos/actualizarlos), devolveré todo el lote sin importar lo que se ha cambiado.

Por una parte, esto puede parecer ineficiente, pero como la cantidad de datos no es amplia, no es un problema; en el otro lado, hay menos "partes móviles", menos pueden salir mal ya que el proceso es mucho más simple.

¿Cómo devuelvo los datos? -

  • Yo uso DTO (o quizás POCO sería más preciso); cuando intercambio datos entre BL y DAL (a través de interfaces/DI) los datos se intercambian como DTO (o colección de ellos). Específicamente, estoy usando una estructura para una sola instancia y una colección de estas estructuras para múltiples.

  • Los DTO se definen en una clase común que tiene muy pocas dependencias.

  • Intento deliberadamente limitar el número de DTO a crear para un objeto específico (como "Pedir"), pero al mismo tiempo crearé nuevos si hay una buena razón. Normalmente tendré un DTO "gordo" que contiene la mayoría de los datos disponibles para ese objeto, probablemente también tenga uno mucho más delgado que esté diseñado para ser utilizado en colecciones (para listas, etc.). En ambos casos, estos DTO son puros para devolver información para "leer". Debe tener en cuenta las responsabilidades: cuando BL solicita datos, generalmente no intenta escribir datos al mismo tiempo; así que el hecho de que el DTO sea "de solo lectura" se trata más de conformarse a una interfaz y arquitectura limpias que a una regla de negocios.

  • Siempre defino DTO separados para Inserción y Actualización, incluso si comparten exactamente los mismos campos. De esta forma, lo peor que puede pasar es la duplicación de algún código de trival, en lugar de tener dependencias y múltiples casos de reutilización para desenredar.

Finalmente, no confunda el funcionamiento de DAL con la interfaz de usuario; Deje que ORM haga lo suyo, solo porque almacenen los datos de una manera determinada no significa que sea la única manera.

Lo más importante es especificar interfaces significativas entre las capas.

Administrar lo que ha cambiado es el trabajo de la BL; deje que la interfaz de usuario funcione de la mejor manera para sus usuarios y deje que BL averigüe cómo quiere lidiar con eso, y el DAL (a través de su interfaz limpia y nítida con DI) simplemente hace lo que se le dice.

+1

Hola, gracias por muy buena respuesta. Me gusta. Está muy cerca de mi arquitectura, excepto que en mi caso estoy usando DTO entre UI y BL y objetos/entidades de Dominio entre BL y DAL. Entiendo su explicación, el único punto que me falta es la respuesta a la pregunta principal: ¿cómo hacer un seguimiento de los cambios en el gráfico de objetos complejos? Usted recibe DTO y tiene que encontrar de alguna manera lo que ha cambiado. Si su DTO es un objeto simple, no necesita rastrearlo, pero ¿qué pasa con DTO que contiene una colección de otros DTO? Debes saber qué ha cambiado en esa colección. –

+0

Cambios RE en el objeto Gráfico - Espero Hay patrones de diseño que manejarán esto pero no recuerdo ninguno - me viene a la mente Momento, de lo contrario tal vez sea un modelo impulsado por eventos. –

+0

En el modelo tradicional de ASP.NET, las páginas tienden a construirse desde cero cada vez (y por lo tanto, está cargando todos los datos, independientemente de cuál sea el cambio), y si está persistiendo datos en viewstate, tiende a tratar eso como "los datos", por lo que no he estado en la posición de querer buscar cambios específicos en la forma en que está sugiriendo (?). El otro enfoque es uno basado en AJAX, pero esto es similar.El patrón del observador también podría ser de interés. –

3

nuestra arquitectura es muy similar a la suya, pero utilizando un cliente de Silverlight que contiene los mismos objetos de dominio (que no es exacto, el código se comparte) en el cliente y el servidor. Los puntos clave de nuestra arquitectura es en definitiva

  • El cliente tiene el modelo de dominio y los cambios se rastreó usando mi propio marco de seguimiento implementado (utiliza AOP para que pueda utilizar POCOs en el lado del cliente: No lo hago conozco un marco para eso y quiero que el modelo de dominio sea persistente ignorante)
  • Este modelo completo se almacena en una especie de repositorio remoto en el cliente. Cuando guardamos esos cambios, un árbol de cambios será extraído (por mi marco de seguimiento de cambios) y traducido en DTO (exactamente DataContracts, pero eso no importa) usando ensambladores. Los DTO tienen un indicador de estado de seguimiento (nuevo, modificado, eliminado).
  • En el lado del servidor (la capa de servicio está implementada por los servicios web WCF), los DTO se traducen a objetos de dominio y se adjuntan a ORM (NHibernate en nuestro caso). Debido a este proceso adjunto, necesito el estado de seguimiento. Que los cambios adicionales se pueden hacer y persistieron a través de ORM

Actualmente es difícil unir gráficos complejos en el ORM, pero voy a esperar que el motivo es que no tenemos mucha experiencia en el uso de NHibernate.

Aún no hemos terminado, pero parece ser prometedor.

Para el acceso a los datos hemos intentado utilizar WCF Dataservices. Pero no creo que los usemos porque un requisito es usar DataContract. Esto lleva a una traducción de consultas LINQ basadas en DataContract a consultas LINQ basadas en objetos de dominio. No es práctico y demasiado difícil de implementar si el modelo de dominio y los datos son muy diferentes (ese será el caso en algunas iteraciones).

¿Alguna pregunta?

Cuestiones relacionadas