Este artículo proviene de un motor de traducción automática.

Entidad Framework

Anti-Patterns para evitar en aplicaciones de N niveles

Daniel Simmons

En este artículo se describen:

  • Descripción n niveles
  • No distribuir los objetos.
  • ¿Servicio personalizado o servicio
    RESTful?
  • Algunos los antipatrones de n niveles
En este artículo se utilizan las siguientes tecnologías:
Entidad Framework

Contenido

N-nivel de conocimiento
Anti-Pattern 1: estrecho acoplamiento
Anti-Pattern nº 2: suponiendo requisitos estáticos
Anti-Pattern nº 3: simultaneidad de Mishandled
Anti-Pattern nº 4: servicios con estado
Anti-Pattern nº 5: dos niveles Pretendiendo ser tres
Anti-Pattern nº 6: Undervaluing sencillez

como miembro de la entidad Equipo de marco de trabajo, con frecuencia Hable con los clientes sobre la creación de aplicaciones que usan el Entity Framework. Probablemente el tema que obtener pregunta acerca de algo más que nada es diseñar aplicaciones de n niveles. En este artículo, intentará establecer una base en la que puede crear para el éxito en esta parte de las aplicaciones. La mayor parte del artículo está dedicada a diseñar los antipatrones de n niveles, que normalmente son los problemas más importantes que encuentra. Éste es un tema donde hay mucho opciones y muchos problemas que tener en cuenta, por lo tanto es importante comprender el espacio total antes de tomar decisiones para la aplicación en particular. En futuros artículos, VOY a examinar los patrones de n niveles de éxito y algunas de las clave API y problemas específicos de Entity Framework y proporcionan un pico sneak en las características procedentes en Microsoft .NET Framework 4 que debe realizar n niveles considerablemente más fácil.

N-nivel de conocimiento

Antes de profundizar en los antipatrones, es importante tener un conocimiento común de n niveles.

El primer punto para ser claros en es la diferencia entre niveles y capas. Una aplicación bien diseñada tendrá varios niveles con dependencias administradas cuidadosamente. Esas capas podría reside en un solo nivel o dividirse entre varios niveles. Una capa es sólo un concepto organizativos en una aplicación, mientras que denota un nivel de separación física o al menos un diseño que permitirá la separación física si es necesario.

Cualquier aplicación que se comunica con una base de datos tiene más de un nivel a menos que dicha base de datos se ejecuta en proceso, pero la aplicación no se llama n niveles a menos que implica varios niveles que sólo la base de datos y aplicaciones. De forma similar, cada aplicación ASP.NET que implica una base de datos es técnicamente n niveles porque no existe la base de datos, el servidor Web y el explorador. A menos que presentar Windows Communication Foundation (WCF) o servicios Web, no se llamaría a que n-nivel de aplicación dado que para la mayoría de los propósitos del Web servidor y explorador pueden considerarse como un nivel de cliente único. Las aplicaciones de niveles son aquellos que tienen como mínimo un nivel de base de datos, un nivel intermedio que expone un servicio y un nivel de cliente.

Mientras lo no sonido como grande un trato en la superficie, resulta que la implementación de aplicaciones dividir en varios niveles es difícil. Hay muchas más dificultades que piensa. Estas dificultades llevó Martin Fowler, en su libro patrones de aplicación arquitectura empresarial (Addison-Wesley, 2002), para que una instrucción muy eficaz en el asunto:

No distribuir los objetos.

Martin llama la primera ley de distribuidos objetos.

Como con cada regla de diseño, sin embargo, hay ocasiones cuando se debe establecer aparte la ley. La aplicación puede tener un problema de escalabilidad que requiere varios niveles por lo que puede aplicar más recursos informáticos. Tal vez debe intercambiar datos con una aplicación de socio o cliente empresarial. Sólo es posible que haya seguridad o las restricciones de infraestructura que dividen la aplicación en varios equipos o impedir que una parte de la aplicación de hablar directamente a otro elemento. Cuando tiene varios niveles, es realmente necesario ellos.

Mientras los antipatrones presentados en este artículo pueden aplicarse a una amplia gama de aplicaciones y tecnologías, el enfoque principal se crear y consumo de servicios WCF personalizados que conservar datos mediante Entity Framework.

No es sorprendente, muchos los antipatrones de n niveles son el resultado de perder el foco en el objetivo de la aplicación. A continuación, si no tenga en cuenta qué motivadas utilizar una arquitectura de n niveles en primer lugar, o si descuidan preocupaciones de persistencia crítica, es demasiado fácil obtener contenido de problemas. Las siguientes secciones examinará algunos problemas comunes.

¿Servicio personalizado o servicio RESTful?

REST, o estado Representational transferencia, es un tipo de servicio Web que está ganando rápidamente en popularidad. Por lo tanto es posible que pregúntese cuál es la diferencia entre los servicios RESTful y servicios Web personalizados, y por qué puede elegir un tipo a través de la otra. La diferencia clave entre los dos tipos es que servicios REST son recursos centrados en mientras servicios personalizados están centrados en para la operación. Con REST, dividir los datos en los recursos, asigne cada recurso de una dirección URL y, implementan las operaciones estándar de los recursos que permiten crear, recuperación, actualización y eliminación (CRUD). Con los servicios personalizados, puede implementar cualquier método arbitrario, lo que significa que el foco está en las operaciones en lugar de los recursos y esas operaciones puede adaptarse a las necesidades específicas de la aplicación.

Algunos servicios muy Naturalmente encajan en el modelo de REST, normalmente, cuando los recursos están obvios y gran parte del servicio implica la administración de los recursos de. Por ejemplo, Exchange Server, tiene una API REST para organizar los elementos de correo electrónico y calendario. De forma similar, hay son fotografías de compartir sitios Web de Internet que exponen las API de REST. En otros casos, los servicios menos claramente coinciden con las operaciones de REST, pero todavía se pueden realizar ajuste. Enviar correo electrónico, por ejemplo, puede realizarse agregando un recurso a una carpeta Bandeja de salida. Ésta no es la forma de forma más natural que podría piensas acerca de envío de correo electrónico, pero no es demasiado un Extender.

En otros casos, sin embargo, las operaciones de REST simplemente no encajan bien. Crear un recurso para iniciar un flujo de trabajo que conduce mensual nóminas verificación imprimir, por ejemplo, sería mucho menos natural de tener un método específico para ese propósito.

Si cabe su servicio en las restricciones del REST, si lo hace por lo que comprar una gran cantidad de ventajas. Servicios de datos ADO.NET en combinación con Entity Framework facilita crear servicios RESTful y los clientes para trabajar con ellos. El marco de trabajo puede ofrecer que mayor funcionalidad para RESTful servicios automáticamente porque los servicios están limitados para seguir un modelo específico. Además, servicios RESTful tienen un alcance muy amplia porque son tan sencillo e interoperabilidad. Funcionan especialmente bien cuando no sabe de antemano que pueden ser los clientes. Por último, se puede realizar REST para escalar a gestionar muy grandes volúmenes de operaciones.

Para muchas aplicaciones, las restricciones de REST son excesiva. En ocasiones, el dominio no dividir claramente en un único modelo de recursos o las operaciones implican varios recursos a la vez. A veces, las acciones de usuario y la lógica de negocios alrededor de ellas no se asignan también a operaciones RESTful o un control más preciso es necesario que puede caber en estas operaciones. En estos casos, servicios personalizados son la forma.

Siempre puede generar una aplicación que tiene una mezcla de REST y servicios personalizados. A menudo la solución ideal para una aplicación es una combinación de ambos.

Anti-Pattern 1: estrecho acoplamiento

Lo más probable que haya oído hablar del evils de estrecho acoplamiento. ¿Por lo que siempre esfuerzan por mantener los componentes como flexible unidas como sea posible, derecha? Sí, derecha.

Es más difícil que estrecho acoplamiento acoplamiento flexible y a menudo el rendimiento no es tan bueno. Es empezar con el mejor de intenciones, pero acaban que le pregunta si el beneficio es merece la pena el costo. ¿Presente por qué una inserción de interfaz y dependencia al sólo puede crear una instancia de la clase y llame directamente al método? ¿Por qué crear una abstracción con objetos personalizados asignados a la base de datos en lugar de rellenar una DataTable y pasándole alrededor?

Para empeorar, no normalmente piensa las dificultades de estrecho acoplamiento hasta mucho más tarde. A corto plazo, es obtener algunos eficacia y obtener el trabajo realizado, pero evolución largo plazo de la aplicación puede ser casi imposible.

Si ha sido creando software para cualquier momento, probablemente comprende las contrapartidas de acoplamiento bastante bien cuando se trata los módulos dentro de un nivel. Si tiene módulos que trabajan conjuntamente estrechamente, a veces, estrecho acoplamiento es la elección correcta, pero en otros casos, los componentes debe mantenerse en la longitud del segmento de uno de otro modo que puede contener el efecto de ripple de cambios a la aplicación.

Cuando lo que respecta a dividir partes de la aplicación en niveles independientes, el significado de acoplamiento pasa a ser mucho mayor. La razón para esto es sencilla. Niveles siempre no cambian a la misma velocidad. Si dispone de un servicio que se consume en muchos clientes y no puede garantizar que actualizarán todos los clientes a petición, a continuación, mejor asegúrese de que puede cambiar dicho servicio sin tener que cambiar los clientes. Si no es así, se encontrará con un problema que se denomina grado de recorte de tasas de cambio. Imagine la aplicación que se extraen de dos direcciones diferentes hasta que se fuerza copiado aparte.

El truco consiste en identificar qué partes de la aplicación pueden tener distintas tasas de cambio y qué partes están estrechamente emparejadas entre sí. En primer lugar, tenga en cuenta el límite entre la base de datos y la mid-tier. A medida que crece la aplicación, es muy probable que tendrá que ajustar la base de datos para mejorar el rendimiento y si nunca se comparte la base de datos entre varias aplicaciones, hay una muy buena oportunidad que le interesará evolucionar mid-tier de una aplicación sin cambiar el otro uno. Afortunadamente, uso el Entity Framework ya ayuda aquí porque su sistema de asignación proporciona una abstracción entre el código mid-tier y la base de datos. Las preguntas mismas deben considerarse entre el mid-tier y el cliente.

Un ejemplo especialmente difícil y comunes de este antipatrón de acción es una arquitectura que utiliza los adaptadores de tabla para recuperar datos de la base de datos y servicios Web que intercambiar conjuntos de datos con el cliente. El adaptador de tabla mueve los datos en un conjunto de datos con el mismo esquema (por lo tanto muy acoplamiento la base de datos para el mid-tier) y, a continuación, el servicio Web intercambia ese mismo conjunto de datos con el cliente (por lo tanto muy acoplamiento el mid-tier al cliente). Es fácil crear este tipo de sistema, hay herramientas de Visual Studio que conducirle adecuadamente a través del proceso. Pero si crear un sistema de este modo, los cambios realizados en cualquier parte del sistema son probablemente ripple a todos los otros elementos.

Anti-Pattern nº 2: suponiendo requisitos estáticos

En términos de los cambios en el sistema, en ocasiones, puede diseñar alrededor de una hipótesis que requisitos permanecerá estáticos, pero hay dos casos donde los requisitos cambiantes tener un impacto importante especialmente. Uno procede de tratar el cliente como de confianza, y la otra se produce cuando el servicio mid-tier supone que se implementará el cliente mediante una tecnología determinada.

Aunque es poco probable que los límites de confianza cambiará de forma inesperada, cuando se trata de integridad de datos, seguridad y confianza, las consecuencias de obtener incorrecta son demasiado grandes. Si realiza la validación sólo en el cliente, por ejemplo y en la confianza mid-tier que los datos que reciba son ACEPTAR para enviar directamente a la base de datos sin revalidating, la posibilidad de que algo se finalmente mal es mucho mayor que es posible que piensa. Incluso saber que el servicio sólo se ejecuta dentro de la intranet no es suficiente para mantener la información segura. Una persona puede crear otro cliente con el mismo servicio o modificar el primer cliente para llamar al servicio desde una ruta de acceso código diferente omite la validación. Quién sabe lo que puede suceder.

Además, una vez que tenga un servicio, es más probable que normal código que se utilizan de maneras que no prevé que, tanto para que la sabiduría generalmente aceptado es que se debe siempre validar y exigir cierto grado de seguridad de la mid-tier, aunque es posible que significa que validar o realizar control de acceso más de una vez.

El segundo problema, el bloqueo del cliente en una tecnología específica, es más probable que sea un problema. Las tecnologías siempre cambiar. Si una aplicación sobrevive tiempo suficiente, algo ocurrirá que obliga a los ajustes de tecnología y los clientes son especialmente susceptibles. Puede diseñar inicialmente la aplicación como una aplicación de escritorio de cliente enriquecido y, a continuación, más adelante encuentra que necesita moverlo a un teléfono móvil o Silverlight. Si estaban en el caso, y ha diseñado el servicio de conjuntos de datos de exchange, a continuación, cerebral principal se necesitaría para el servicio y todos los clientes existentes.

Anti-Pattern nº 3: simultaneidad de Mishandled

Aunque hay una desventaja estrecho acoplamiento para intercambiar conjuntos de datos, concurrencia es un área complejo, pero-importante que el conjunto de datos controla bien. Por desgracia muchos desarrolladores no comprender las nuances de administración de concurrencia y para hacer cosas peor, un error de coincidencia es el tipo de problema que se muestre con frecuencia sólo una vez que la aplicación está en producción. Si estás suerte, se manifiesto como un error obvio. Si no, provocar daños en los datos durante un largo período de tiempo sin que se ha detectado.

En esencia, administración de concurrencia es bastante sencilla: garantizar la integridad de los datos incluso si dos clientes intenta modificar los mismos datos aproximadamente al mismo tiempo. Los lectores especialmente attentive se tenga en cuenta que estos problemas también surjan en los casos que no están n niveles relacionados con, pero los problemas de simultaneidad son especialmente importantes para los diseños de n niveles Entity Framework, porque tratamiento de Entity Framework de escenarios de n niveles crea los desafíos de simultaneidad único.

Para la mayoría de las aplicaciones, la técnica de administración de concurrencia de elección es concurrencia optimista. Incluso si muchos clientes pueden acceso al mismo tiempo la base de datos, el número de veces cuando se modifique la misma entidad exacta de formas en conflicto es muy pequeño. Por lo que supone todo lo que se averiguar, pero tomar medidas para detectar si algo va mal.

Detección está controlada por uno o más propiedades, denominados el token de simultaneidad, que cambia cuando cambia cualquier parte de la entidad. Cuando la aplicación lee una entidad, guarda el valor del token de simultaneidad. Posteriormente, cuando desea escribir dicha entidad en la base de datos, en primer lugar comprueba para asegurarse de que el valor del token de simultaneidad de la base de datos es el mismo ahora que se estaba cuando la entidad se ha leído originalmente. Si es así, la actualización continuará. Si no, la actualización se detiene y produce una excepción.

Entity Framework admite concurrencia optimista mediante seguimiento transparente el valor original de simultaneidad símbolos (token) cuando se consultan las entidades y comprobación de conflictos antes que las actualizaciones de la base de datos. El problema con las aplicaciones de n niveles es que este proceso funciona transparente sólo siempre que una sola instancia de ObjectContext se utiliza para realizar un seguimiento de la entidad desde el momento en que se consulta hasta el momento se llama a SaveChanges. Si se serializa las entidades un nivel de otra, el modelo recomendado es mantener el contexto alrededor en el mid-tier sólo suficiente para una llamada de método de servicio único como. Las llamadas posteriores se girar hasta una nueva instancia del contexto para completar cada tarea. (Crear una nueva instancia contexto de cada operación de servicio es una recomendación importante en su propia derecha, por cierto. Para obtener más información, consulte Anti-Pattern # 4: servicios con estado.)

Una vez a los desarrolladores empezar a aprender cómo funcionan las API de Entity Framework para este tipo de operación desconectado, desconectado en el sentido de que las entidades están desconectadas del contexto después de la consulta, envía a otro nivel y, a continuación, re-connected cuando llega el momento para guardar, hay una tendencia que se dividen en un modelo desagradable:

  1. Consultar la entidad y serializarlo en el cliente. En este momento, valor actual del token de concurrencia es el mismo que el valor original, y que es el valor sólo enviado al cliente.
  2. El cliente recibe la entidad, realiza cambios y, envía una versión modificada de la entidad a la mid-tier.
  3. Puesto que ni el cliente como el servicio explícitamente mantiene un seguimiento del token de simultaneidad o qué propiedades se han modificado, las consultas de servicio de la base de datos para obtener el estado actual de la entidad en un contexto recién creado, compara, a continuación, los valores entre la entidad actual de la base de datos y los envían volver desde el cliente.
  4. El servicio llama a SaveChanges, que realiza optimista de concurrencia comprueba al conservar los cambios.

¿Se verá el problema? En realidad hay dos problemas.

En primer lugar, cada vez se actualiza una entidad, tiene que leerse de la base de datos dos veces: una vez cuando se está en primer lugar consultan y un segundo derecho de tiempo antes de la actualización, que crea una carga adicional importante en el sistema.

En segundo lugar y lo que es más importante, el "original valor" utilizado por el Entity Framework para comprobar si la entidad se ha modificado en la base de datos procede de la segunda consulta en lugar de la primera. Es decir, que procede de la consulta que se encuentren derecho antes de la actualización. Por lo que el resultado es que casi nunca se producirá un error la comprobación de concurrencia optimista realizada por el Entity Framework. Si alguien modifica la entidad entre la primera consulta y el segundo, el sistema no detectará el conflicto porque el valor utilizado para la comprobación de concurrencia es de tras la modificación del otro cliente en lugar de antes.

Todavía hay una ventana pequeña (entre la segunda consulta y la actualización) cuando la comprobación de concurrencia optimista pudo detectar un problema, por lo que todavía debe escribir el programa para controlar la excepción, pero que no se realmente ha protegido los datos de daños en.

El modelo correcto es bien para realizar una copia de la entidad en el cliente y enviar nuevo tanto la versión original sin modificaciones y la versión modificada o para escribir el cliente de tal manera que no modifica el token de simultaneidad. Si el símbolo de simultaneidad se actualiza por un desencadenador de servidor o automáticamente porque es un número de versión de fila (probablemente la mejor planear todos modos), a continuación, no hay ningún motivo para modificarlo en el cliente. El valor actual de la propiedad se puede dejar intacta y utiliza como almacenamiento para el valor original.

Éste es un enfoque razonablemente sonido porque si un error en el cliente hace que el valor que puede modificar accidentalmente, es muy improbable que obtendrá un éxito es false. Dicho error podría causar que obtenga un error en false, pero que es mucho más aceptable de éxito es false.

Para hacer que este enfoque funciona, cuando el mid-tier recibe la entidad de cliente, necesitará adjuntarlo al contexto y luego vaya a través de sus propiedades, manualmente a marcar como modificado. En ambos casos, sin embargo, se corregirá ambos de los problemas con el antipatrón a la vez. Ya no se consultar la base de datos dos veces y la comprobación de concurrencia se basará en el valor correcto del token de (de la consulta inicial) en vez de algún valor de una versión posterior.

Anti-Pattern nº 4: servicios con estado

Dada la facilidad comparativa de desarrollo de soluciones de cliente / servidor, la siguiente antipatrón surge cuando los desarrolladores intentan simplifican las cosas al mantener el contexto de alrededor de entre varias llamadas de servicio. Esto parece interesante en primer lugar porque sidesteps los problemas de simultaneidad. Si mantiene el contexto de actividad en el mid-tier, a continuación, contener los correcta original entidad valores. Cuando reciba una entidad volver desde el cliente, puede comparar la entidad actualizada con la versión de la entidad en el contexto y aplicar los cambios según sea apropiado. Cuando se guarda la entidad, se realizarán la comprobación de concurrencia adecuado y no es necesaria ninguna consulta de base de datos adicionales.

Aunque este enfoque parece sencillo en la superficie, hay un número de problemas que se encuentren. Administración de la duración de contexto puede obtener complicado rápidamente. Si tiene varios clientes al llamar a los servicios, debe mantener un contexto separado para cada cliente o riesgo colisiones entre ellos. Y incluso si se soluciona estos problemas, se acabar con problemas de escalabilidad importante.

Estos problemas de escalabilidad no son sólo el resultado de que afecte a los recursos del servidor para cada cliente. Además debe protegerse contra la posibilidad de que un cliente puede iniciar una unidad de trabajo, pero nunca completar, creando un esquema de caducidad. Además, si decide tiene que escalar su solución fuera mediante un conjunto de varios servidores mid-tier, entonces tendrá que mantener la afinidad de sesión para mantener un cliente asociado con el mismo servidor donde empezaron la unidad de trabajo.

Se ha dedicado mucho esfuerzo y tecnología especializado en resolver estos problemas cuando, de hecho, la mejor solución es evitarlos totalmente manteniendo sus implementaciones de servicio mid-tier sin estado. Cada vez que se realiza una llamada de servicio, el mid-tier debe girar hasta los recursos necesarios, controlar la llamada y, a continuación, liberar todos los recursos específicos de llamada. Si necesita alguna información que se deben mantener para una unidad de trabajo que se extiende por varias llamadas de servicio, a continuación, que se debe mantener información del cliente en lugar de la mid-tier por lo que no es afinidad de sesión, no es necesario para que caduque sin terminar las unidades de trabajo y no hay ningún servidor los recursos de utilizar para un cliente en particular entre servicio llama a.

Anti-Pattern nº 5: dos niveles Pretendiendo ser tres

Otro antipatrón que encuentre con bastante frecuencia también se intenta simplificar este proceso. Normalmente, se muestra como una solicitud similar, "¿por qué no realiza Entity Framework serializar las consultas en niveles?" seguido casi inmediatamente por, " Oh, y mientras está en él, puede admitir inicial actualizaciones desde otro nivel así? "

Estos son probablemente las características de que Microsoft puede agregar a Entity Framework, pero si detener y piense en ellas durante un minuto en vista de otros problemas que he tratado, tendrá que pregunta si es una buena idea.

Si puede crea una ObjectContext de Entity Framework en el nivel de cliente, ejecutar cualquier consulta de Entity Framework para cargar las entidades en dicho contexto, modificar esas entidades y, a continuación, tienen SaveChanges insertar una actualización desde el cliente a través de la mid-tier en el servidor de base de datos, si puede lo todo lo que, ¿por qué tener el mid-tier en absoluto? ¿Por qué no sólo expone la base de datos directamente?

Recuerde primera ley del Fowler de objetos distribuidos. Tenga en cuenta que la única vez que este tipo de arquitectura tiene sentido es cuando lo realmente, realmente necesita. Si realmente necesita, deberá mejorar la seguridad o la capacidad de escalar con varios servidores o otra cuestión que sugieren no se realmente resolverse mediante la introducción de un mid-tier que es simplemente un fino proxy para la base de datos. Se puede utilizar esta técnica para dañar una restricción impuesta sobre la por una directiva corporativa, pero apenas captura el espíritu de una aplicación de n niveles. Mi sugerencia es bien invertir en crear una aplicación de n niveles para satisfacer una necesidad concreta o, si se puede obtener inmediatamente con él, evite n niveles por completo.

Anti-Pattern nº 6: Undervaluing sencillez

Esto me lleva a la última antipatrón de n niveles. En el nombre de evitar todo los antipatrones descritos anteriormente, es fácil decidir que necesita crear el más detenidamente architected multi-tier, completamente separado, re-validating, super diseño que puede surjan con. A continuación, se puede dedicar todos los su tiempo generación de infraestructura y ninguno de su tiempo realmente proporcionar valor a los usuarios.

Es importante pensar sobre los objetivos y tener en cuenta si se va a necesita el n inversión niveles requiere. Simple es bueno. A veces, una aplicación de dos niveles es simplemente lo. A veces, necesita más niveles que, pero todo lo que está bajo su control y de confianza o tiene un AJAX, Silverlight o haga clic en una sola cliente que automáticamente se implementa para que no tengan que preocuparse por las tasas de cambio del grado de recorte.

Si puede realizar el problema más sencilla, hacerlo. Poner en todo el esfuerzo para la solución completa si debe, pero en el mismo token asegúrese de que colocar en suficiente esfuerzo para realizar el trabajo de forma que cumple los objetivos.

Danny Simmons es administrador de desarrollo para el equipo de Entity Framework de Microsoft. Se pueden leer más de sus ideas sobre Entity Framework y otros temas enblogs.msdn.com/dsimmons/.