definicion - soa architecture example
Unidad de trabajo con múltiples fuentes de datos? (1)
Es posible (incluso probable) que no esté asimilando por completo el concepto de una "unidad de trabajo". Básicamente, lo veo como una especie de transacción amplia utilizada en un entorno orientado a objetos. Comience la unidad de trabajo, interactúe con los objetos, comprométase o retráigase. Pero, ¿cómo se relaciona esto con las transacciones reales en los almacenes de datos detrás de esos objetos?
En un sistema con una única base de datos y un ORM (como NHibernate) es fácil. La transacción se puede mantener a través del ORM. Pero, ¿qué ocurre con un sistema en el que los modelos de dominio personalizado ocultan muchas fuentes de datos dispares? Y no todas esas fuentes de datos son bases de datos relacionales? (Aquí se hace mucho en el sistema de archivos).
En este momento estoy atascado en la idea de que "simplemente no se puede mantener una transacción en una base de datos SQL2005, una base de datos SQL2000, una base de datos DB2 y el sistema de archivos, todo en la misma operación comercial ''atómica''". Así que, por ahora, es responsabilidad de los desarrolladores del equipo (que generalmente trabajan de forma independiente) mantener las transacciones manualmente en el código. Cada DB puede tener transacciones apropiadas en él, pero la operación del negocio como un todo se verifica manualmente y se balancea en cada paso significativo del camino.
Sin embargo, con la complejidad cada vez mayor en el dominio y la rotación del desarrollador estándar, este enfoque será cada vez más difícil y propenso a errores a lo largo del tiempo.
¿Alguien tiene algún consejo o ejemplos de cómo un dominio como este podría abordarse mejor, o cómo se ha abordado antes? El "dominio" real en este caso todavía está en su infancia, evolucionando como un prototipo para expandir y consumir / reemplazar un gran ecosistema de aplicaciones legacy dispares. Así que hay mucho espacio para rediseñar y volver a factorizar.
Como referencia, una vista de 10,000 pies del diseño al que estoy apuntando actualmente es: una gran colección de pequeñas aplicaciones de cliente tan tontas como sea posible que llamen a un servicio central basado en mensajes. El servicio es la entrada al "núcleo del dominio" y puede considerarse como una gran aplicación de estilo MVC. Las solicitudes se hacen al servicio (al igual que las "acciones") que son recogidas por los controladores (al igual que los "controladores"). Todo lo procesal va allí. Interactúan con los modelos, que contienen todas las reglas comerciales. Los modelos publican eventos que los oyentes ("servicios", esta parte aún está nublada en el diseño y sujeto a mejoras) recogen y manejan mediante la interacción con repositorios (base de datos x, base de datos, sistema de archivos, correo electrónico, cualquier recurso externo). Todo alegremente, inyectado en dependencia en consecuencia.
Perdón por toda la verborrea :) Pero si alguien tiene algún consejo, me encantaría escucharlo. Incluso (especialmente) si ese consejo es "su diseño es malo, intente esto en su lugar ..." ¡Gracias!
Anteriormente trabajé en un sistema que podría lograr esto, y es bastante sencillo. Dado que su proyecto está en sus primeras etapas, tal vez esta podría ser información útil para usted. Lamentablemente, ya no tengo acceso al código, pero aún me siento cómodo al describir cómo funcionó.
Lo que hice fue construir mis repositorios utilizando una implementación de patrón de repositorio genérico. El tipo de repositorio base siempre será referenciado por los servicios y UoW. En aras de la discusión, lo llamaremos BaseRepository. "T" estaría restringido a las implementaciones de IEntity, que denotaba un objeto de dominio. Desde BaseRepository, había creado otro conjunto de clases base para la composición, como SqlBaseRepository, XmlBaseRepository, etc.
A UoW solo le preocupa que algo sea del tipo BaseRepository, que es donde existiría la funcionalidad principal. Se representaría CUD básico (de CRUD), proporcionando los equivalentes para Crea, Actualizaciones y Eliminaciones. Lo que haría cada uno de ellos sería crear un delegado y colocarlo en una cola dentro de la UoW, también transmitiendo información sobre qué tipo de transacción iba a ser y los datos necesarios para completarla. La UoW comenzaría a mantener una lista de los repositorios que necesitarían estar involucrados en la transacción, pero todavía no le importaba qué tipo era. Eficazmente, hacer cola aquí es como alistarse en una transacción.
El BaseRepository definió un método abstracto llamado algo así como .ApplyChange (). Una vez que se llamó a .Commit () en la UoW, crearía un TransactionScope () y comenzaría a llamar a los delagates en la lista, devolviendo la información a .ApplyChange (). La implementación real de .ApplyChange () existe en la base de repositorio específico, es decir, SqlRepositoryBase, etc., y también puede ser anulada por la implementación.
Donde se puso complicado, al menos para mí, estaba retrocediendo. Solo traté con una única base de datos, pero a veces tenía cambios basados en archivos que se realizaron. Agregué un método .RevertChange () y comencé a rastrear el estado original y los estados modificados para poder aplicar un delta inverso para volver a donde estaba en la pila de archivos.
Ojalá pudiera ser más específico sobre la implementación, pero ha pasado más de un año desde que vi el código ahora. Puedo decirles que la base para el código original proviene del libro, .NET Dominio de diseño con C #: Problema - Diseño - Solución , por Tim McCarthy. Una gran parte de la implementación de mi repositorio se basó en sus ejemplos, con una gran mayoría de mi personalización en las UoW y su implementación.
¡Espero que eso ayude, de alguna manera! :-)