patrón para compartir objetos entre la API y la aplicación

7

Tengo serias dudas sobre el diseño de mi aplicación web.

Quería separar la lógica de negocios de la interfaz, así que hice una API web que maneja todas las solicitudes a la base de datos.

Es una API web ASP.NET con Entity framework y una unidad de trabajo y un patrón de repositorio genérico. Hasta ahora, todo está bien.

PROBLEM

Donde necesito ayuda es que no puedo encontrar una manera eficiente de compartir objetos entre la API y la aplicación.

No quiero serializar directamente el objeto de entidad, pensé que sería una mala práctica porque si el modelo de entidad cambia, podría terminar con la serialización de objetos grandes sin ninguna razón.

Cómo se implementa ahora

Debido a que mi interfaz es la aplicación web ASP.NET en C # y mi API en C #, hice una biblioteca común con la definición de todas mis clases que quiero compartir entre ellas.

Sé que esa solución no funcionará cuando desarrolle una aplicación para Android, tendré que crear mis clases nuevamente en Java, pero ese no es mi mayor problema.

El problema es que siento que siempre estoy convirtiendo mis objetos.

EJEMPLO

Aquí hay un ejemplo de mi flujo de trabajo:

Comienzo con un modelo con todos los objetos y las anotaciones de datos de mi formulario, luego el usuario enviará el modelo a un controlador.

En el controlador, tengo que convertir este modelo a una clase en mi biblioteca común y luego enviar ese objeto a mi API.

Luego, un controlador en mi API captura la llamada y convierte ese objeto en un objeto de entidad para actualizar la base de datos.

Tengo 3 clases

  1. El modelo para la vista con toda la anotación de datos para la validación (Cliente)
  2. Las clases de biblioteca comunes para compartir los objetos (DLL)
  3. Las clases de entidad (API)

Tengo la sensación de que hago algo realmente mal. ¿Hay algo más elegante? Me gustaría asegurarme de que tengo una buena solución para este problema antes de que el proyecto sea demasiado grande.

    
pregunta Marc 15.05.2014 - 16:12

1 respuesta

10

Sé que puede parecer que está convirtiendo objetos de un lado a otro entre los objetos de su base de datos, sus objetos de transferencia de datos, sus objetos de cliente con lógica de validación, etc. pero diría que no, no lo está. haciendo algo mal.

Cada uno de estos objetos puede representar la misma unidad de información, pero tienen responsabilidades muy diferentes. El objeto de la base de datos es su interfaz de comunicación con la base de datos y debe mantenerse en la capa de la base de datos, ya que puede tener o no diferentes anotaciones de metadatos de la base de datos y / o detalles innecesarios sobre la implementación de la base de datos.

Su objeto de transferencia de datos es la interfaz de comunicación con sus consumidores de API. Deben estar lo más limpios posible para facilitar el consumo desde diferentes idiomas / plataformas. Esto podría imponer ciertas restricciones sobre cómo se ven y cómo se comportan, dependiendo de qué consumidores de API deseen apoyar.

Sus objetos de cliente con lógica de validación realmente no forman parte de su proyecto API, son parte de su proyecto de consumidor. En este caso, no pueden ser lo mismo que los objetos de transferencia de datos, ya que está agregando una lógica adicional específica del cliente (en este caso, atributos de validación) sobre los cuales el servidor no sabe nada (¡y no debería saber nada sobre!) No debería cuenta estos objetos como parte de tu API, porque realmente no lo son. Son aplicaciones de consumo altamente específicas y algunas aplicaciones que consumen su API en realidad ni siquiera necesitan crear estos objetos y podrían sobrevivir solo con sus objetos de transferencia de datos. Por ejemplo, si no tuviera ninguna necesidad de validación, no necesitaría una capa adicional de objetos que sean completamente idénticos a sus objetos de transferencia de datos. Por lo general, mi estrategia aquí es evolucionar el proyecto en etapas, comencé a usar los objetos de transferencia de datos como objetos de aplicación del consumidor y cuando veo la necesidad de un manejo de datos específico de la aplicación (validación, implementación de INotifyPropertyChanged, etc.) haga una refactorización rápida y agregue la nueva capa según sea necesario.

Para mí, parece que cada uno de los tres tipos de objetos se relaciona muy bien con una única responsabilidad que es una codificación limpia y una buena práctica. Lamentablemente, el código limpio y las buenas prácticas a veces significan que estás escribiendo un montón de código adicional y saltando a través de aros adicionales "solo porque". Y mientras codifica, puede ser difícil apreciar el valor que esto le está brindando, pero tan pronto como libere su aplicación y comience a admitirla o agregue nuevas funciones para la próxima versión, entonces probablemente comenzará a apreciar que se tomó el tiempo para separar estas preocupaciones correctamente en primer lugar. (Sin mencionar que evitará ciertos problemas que pueden surgir debido a una separación inadecuada de inquietudes) y, dado que ha evitado estos problemas, puede ser difícil apreciar el desorden en el que se encuentra cuando no ha separado sus inquietudes. )

También odio escribir código de conversión entre diferentes tipos de objetos como este, pero mi solución suele ser una de las siguientes:

  • Use una biblioteca que haga la mayor parte del trabajo pesado de conversión de objetos, por ejemplo, si usa C # puede usar la fantástica biblioteca de AutoMapper ( enlace ). Creo que hay un par de otras bibliotecas como esta, pero AutoMapper es la más poderosa que he visto hasta ahora.
  • Si no puede encontrar una biblioteca que lo ayude con sus conversiones de objetos, escriba un conjunto de métodos de utilidad para convertirlos. Esto podría apestar, pero a la larga vale la pena, escriba el método de conversión la primera vez que necesite convertir algo, no espere.
respondido por el wasatz 16.05.2014 - 15:21

Lea otras preguntas en las etiquetas