N-capas de aplicaciones de base de datos sin necesidad de utilizar un ORM, ¿cómo especificar la interfaz de usuario lo que necesita de los datos para mostrar?

StackOverflow https://stackoverflow.com/questions/1524367

Pregunta

Busco punteros e información aquí, voy a hacer esto CW ya que sospecho que no tiene un solo una respuesta correcta. Esto es para C #, por lo tanto, voy a hacer algunas referencias a LINQ a continuación. También pido disculpas por el largo post. Voy a resumir la cuestión aquí, y entonces la pregunta completa a continuación.

Resumen: En una UI / BLL / DAL / DB aplicación 4 capas, ¿cómo puede cambios en la interfaz de usuario, para mostrar más columnas (por ejemplo en una rejilla), evitar fugas a través de la capa de lógica de negocio y en el acceso a datos capa, para conseguir el asimiento de los datos para visualizar (suponiendo que ya está en la base de datos).


Supongamos una aplicación de capas con 3 (4) capas:

  • Interfaz de usuario (UI)
  • Capa de lógica de negocios (BLL)
  • capa de acceso a datos (DAL)
  • Base de datos (DB; la cuarta capa)

En este caso, el DAL es responsable de la construcción y ejecución de las sentencias SQL contra la base de datos, la devolución de datos.

Es la única manera de "correcta" la construcción de una capa de este tipo para hacer precisamente siempre "select *"? Para mí eso es un gran no-no, pero permítanme explicar por qué estoy preguntando.

Digamos que quiero, para mi interfaz de usuario, para mostrar todos los empleados que tienen un registro activo de empleo. Por "activo" me refiero a que los registros de empleo desde-hasta fechas contiene hoy (o tal vez incluso una fecha puedo configurar la interfaz de usuario).

En este caso, digamos que quiero enviar un correo electrónico a todas esas personas, así que tengo algo de código en el BLL que asegura que ya no he enviado un correo electrónico para las mismas personas ya, etc.

Para el BLL, que necesita una cantidad mínima de datos. Tal vez se accede a la capa de acceso de datos para conseguir que la lista de los empleados en activo, y luego una llamada para obtener una lista de los mensajes de correo electrónico se ha enviado. A continuación, se une a aquellos y construye una nueva lista. Tal vez esto se podría hacer con la ayuda de la capa de acceso a datos, esto no es importante.

Lo que es importante es que para la capa de negocio, realmente no hay muchos datos que necesita. Tal vez sólo necesita el identificador único para cada empleado, para ambas listas, para que coincida en, y luego decir "Estos son los identificadores únicos de los que están activos, que aún no lo ha enviado un correo electrónico a". ¿Debo entonces DAL construcción de código que construye sentencias SQL que sólo recuperar lo que necesita la capa de negocio? Es decir. sólo "SELECT ID de los empleados DONDE ..."?

¿Qué hago entonces para la interfaz de usuario? Para el usuario, tal vez sería mejor para incluir mucha más información, dependiendo de ¿Por qué Quiero enviar mensajes de correo electrónico. Por ejemplo, puede que desee incluir alguna información rudimentaria de contacto, o el departamento para la que trabajan, o su nombre gerentes, etc., por no decir que al menos la información del nombre y dirección de correo electrónico para mostrar.

¿Cómo funciona la interfaz de usuario de obtener esos datos? Cómo puedo cambiar el DAL para asegurarse de que vuelva suficientes datos a la interfaz de usuario? Cómo puedo cambiar el BLL para asegurarse de que devuelve los datos suficientes para la interfaz de usuario? Si las estructuras de objetos o de datos devueltos por el DAL de nuevo a la BLL se pueden enviar a la interfaz de usuario, así, tal vez el BLL no necesita mucho de un cambio, pero entonces los requisitos de los impactos de interfaz de usuario de una capa más allá de lo que debería comunicarse con . Y si los dos mundos operan en diferentes estructuras de datos, los cambios probablemente tendrían que hacerse para ambos.

Y que luego, cuando se cambia la interfaz de usuario, para ayudar al usuario aún más, añadiendo más columnas, la profundidad gustaría / debería tener que ir con el fin de cambiar la interfaz de usuario? (Está presente en la base de datos ya lo que se necesita ningún cambio no asumiendo los datos.)

Una de las sugerencias que ha surgido es el uso de LINQ a SQL y IQueryable, por lo que si el DAL, que se ocupa de lo que (como en qué tipos de datos) y por qué (como en WHERE cláusulas) regresó IQueryables, la BLL puedan volver los hasta la interfaz de usuario, lo que podría construir una consulta LINQ que recuperar los datos que necesita. El código de la interfaz de usuario a continuación, podría tirar de las columnas que necesita. Esto haría work ya que con IQuerables, la interfaz de usuario terminaría de ejecutar realmente la consulta, y se podría utilizar "seleccione nueva {X, Y, Z}" para especificar lo que necesita, e incluso unirse a otras tablas, si es necesario.

Esto se ve complicado para mí. Que la interfaz de usuario ejecuta el código SQL en sí, a pesar de que se ha ocultado detrás de una interfaz de LINQ.

Sin embargo, para que esto suceda, el BLL o el DAL no se debe permitir que cerrar las conexiones de bases de datos, y en un tipo de la COI mundo, el DAL-servicio podría obtener dispuesto de un poco antes de lo que el código de interfaz de usuario le gustaría , de manera que LINQ consulta sólo podría terminar con la excepción "no se puede acceder a un objeto desechado".

Así que estoy buscando para los punteros. Qué lejos estamos? ¿Cómo estás tratando con esto? Considero que el hecho de que los cambios en la interfaz de usuario se escape a través de la BLL y en el DAL una muy mala solución, pero en este momento no se parece a lo que podemos hacer mejor.

Por favor, dime lo estúpidos que somos y demostrar que estoy equivocado?

Y cuenta que este es un sistema heredado. Cambiar el esquema de base de datos no está en el ámbito de años, sin embargo, por lo que una solución a utilizar objetos ORM que esencialmente haría el equivalente de "select *" no es realmente una opción. Tenemos algunas tablas de gran tamaño que nos gustaría para evitar tirar hacia arriba a través de toda la lista de capas.

¿Fue útil?

Solución

Utilice el concepto de un modelo de vista (o los objetos de transferencia de datos) que son los casos de consumo de interfaz de usuario. Será el trabajo de la BLL a tomar estos objetos y si los datos son incompletos, solicitar datos adicionales (que denominamos modelo). A continuación, el BLL puede tomar decisiones correctas sobre qué modelos vistas a devolver. No deje que su modelo (datos) específicos impregnan a la interfaz de usuario.

UI <-- (viewmodel) ---> BLL <-- (model) --> Peristence/Data layers

Este desacoplamiento permite a la escala que mejor aplicación. La independencia persistencia Creo que de manera natural se sale de este enfoque, como la construcción y la especificación de los modelos de vista podría hacerse de manera flexible en el BLL utilizando linq2ql u otra tecnología ORM.

Otros consejos

Esto no es en absoluto un problema fácil de resolver. He visto muchos intentos (incluido el enfoque IQueryable describes), pero ninguno que sea perfecto. Por desgracia, todavía a la espera de la solución perfecta. Hasta entonces, tendremos que conformar con la imperfección.

I completamente de acuerdo que las preocupaciones DAL no se debe permitir a filtrarse a través de las capas superiores, por lo que un BLL aislante es necesario.

Incluso si usted no tiene el lujo de la redefinición de la tecnología de acceso a datos en su proyecto actual, todavía ayuda a pensar en el modelo de dominio en términos de persistencia ignorancia. Un corolario de la Persistencia La ignorancia es que cada objeto de dominio es una unidad autónoma que no tiene noción de cosas como las columnas de base de datos. Es mejor para hacer cumplir integretiy datos como invariantes en tales objetos, pero esto también significa que un objeto de dominio instanciado tendrá todos sus datos constitutivos cargados. Es una o la otra proposición, por lo que la clave es encontrar un buen modelo de dominio que se asegura de que cada bodega de objetos de dominio (y debe ser cargado con) una cantidad 'adecuada' de los datos.

objetos demasiado granulares pueden conducir a interfaces DAL hablador, pero los objetos demasiado de grano grueso pueden conducir a datos demasiado irrelevantes están cargando.

Un ejercicio muy importante es analizar y modelar las magnitudes del modelo de dominio para que el justo equilibrio correctamente. El libro Diseño contiene algunos análisis muy esclarecedores de los agregados de modelado de dominio impulsada.

Otra estrategia que puede ser útil en este sentido se fija el objetivo de aplicar el Principio de Hollywood tanto como sea posible. El principal problema que se describe se refiere a las consultas, pero si puede cambiar su enfoque a ser más Comando-orientado, es posible que pueda definir algunas interfaces más de grano grueso que no lo hace requieren que cargue siempre demasiados datos.

No estoy al tanto de cualquier solución simple a este desafío. Hay técnicas como las que he descrito anteriormente que pueden ayudar a abordar algunos de los problemas, pero al final todavía es un arte que requiere experiencia, habilidad y disciplina.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top