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

9

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.

PROBLEMA

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 serializando objetos grandes sin ningún motivo.

Cómo se implementa ahora

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

Sé que la solución no funcionará cuando desarrolle una aplicación de 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 para mi formulario, luego el usuario PUBLICARÁ ese modelo en 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.

Entonces tengo 3 clases

  1. El modelo para la vista con todas las anotaciones 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 tener una buena solución para este problema antes de que el proyecto sea demasiado grande.

Bagazo
fuente
Si mi pregunta no es clara, no dude en hacer preguntas.
Marc
Para mí no está claro qué arquitectura implementó (tal vez sea la redacción .net lo que me desconcierta): ¿es una arquitectura de 3 niveles: cliente, servidor, base de datos?
Andy
Sí, tengo una aplicación web que usa una API web. La API es la que tiene la lógica empresarial con la base de datos.
Marc

Respuestas:

12

Sé que puede parecer que está convirtiendo objetos de un lado a otro todo el tiempo entre sus objetos de base de datos, sus objetos de transferencia de datos, sus objetos de cliente con lógica de validación, etc., pero yo diría que no, que no está haciendo nada 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 API. Deben ser 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 se comportan según los consumidores de API que desee admitir.

Sus objetos de cliente con lógica de validación realmente no son parte de su proyecto API, son parte de su proyecto de consumidor. En este caso, no pueden ser los mismos que los objetos de transferencia de datos, ya que está agregando 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!). cuente estos objetos como parte de su API, porque realmente no lo son. Son altamente específicas para aplicaciones de consumo 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.

Para mí, parece que cada uno de los tres tipos de objetos se correlaciona muy bien con una única responsabilidad, que es la codificación limpia y las buenas prácticas. Lamentablemente, el código limpio y las buenas prácticas a veces significan que está escribiendo una gran cantidad 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á dando, pero tan pronto como lance su aplicación y comience a admitirla o a agregar nuevas características para la próxima versión, probablemente comenzará a apreciar que se tomó el tiempo para separe estas preocupaciones adecuadamente en primer lugar. (Sin mencionar que tú '

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 realice la mayor parte del trabajo pesado de conversión de objetos por usted; por ejemplo, si usa C #, puede usar la fantástica biblioteca AutoMapper ( http://automapper.org/ ). 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 convertir entre ellos. Esto puede ser una mierda, pero a la larga vale la pena, escriba el método de conversión la primera vez que necesite convertir algo, no espere.
wasatz
fuente
Gracias por sus explicaciones, pero todavía me cuesta entender algo. No entiendo por qué la capa para la transferencia de datos no tiene ninguna validación. ¿Qué sucede si olvido algunas validaciones para mi próxima aplicación móvil? Al menos no se validaría cuando llame a la API en lugar de hacer una excepción en mi modelo de base de datos. No estoy seguro de entenderlo.
Marc
1
No estoy diciendo que no debas validar a nivel API. Para ser honesto, ese es el lugar más importante para validar. La validación en su aplicación es solo una "buena característica" para ayudar a sus usuarios a no cometer errores, la validación de sus objetos de transferencia de datos es para evitar la entrada de datos maliciosos y erróneos. Dado que estos son diferentes casos de uso, sin embargo, puede que tenga que utilizar diferentes marcos de validación (que va a utilizar diferentes marcos de validación si su aplicación y su API no está escrito en el mismo idioma) y es posible validar cosas ligeramente diferentes en cada nivel (Cont en el siguiente comentario)
wasatz
1
Por lo tanto, debe validar sus objetos de transferencia de datos. Pero también debe asegurarse de que la forma en que los valida no introduce accidentalmente ninguna dependencia en ningún otro marco . Y, por supuesto, como dije anteriormente, realmente no puede estar seguro de que sus objetos de transferencia de datos hayan sido validados o que hayan sido validados por el mismo marco, por lo que debe "validar dos veces".
wasatz
2
Principalmente, debe intentar ver su aplicación y su API como dos aplicaciones completamente diferentes y separadas. Es posible que los esté desarrollando al mismo tiempo, y pueden estar en la misma solución de estudio visual / proyecto de eclipse. Pero en realidad son dos programas completamente separados. Cuando trabaje en su aplicación, intente "olvidar" que usted es quien creó la API y úsela como lo haría con una API de terceros normal. De esa manera, tendrá una mejor oportunidad de ver cómo se sentirán los demás al usar su API y corregir las peores partes desde el principio.
wasatz
1
Y, por supuesto, lo mismo es cierto cuando trabaje en su proyecto de API, intente imaginar que está escribiendo un servicio que muchos desarrolladores de terceros van a utilizar. Intente no pensar demasiado en su aplicación actual, sino más bien mantener su mente más en "qué servicios estoy brindando" y asumir que todos los que usan su API (incluido usted) son personas malvadas que están tratando de matar su servidor y hacerte borrar toda tu base de datos.
wasatz