vista utilizar uso servicio modelo mapear ejemplos ejemplo dominio controlador como capa basico spring oop

utilizar - Spring y el modelo de dominio anémico



uso de jsp en java (3)

Creo que hay un patrón de refactorización simple que resolverá su problema.

  1. Inyecta tu servicio en tu repositorio.
  2. Antes de devolver su Foo, configure su ''FooService''
  3. Ahora haz que tu FooController solicite el Foo apropiado del FooRepository
  4. Ahora llama a los métodos que quieras en ti Foo. Si no puede implementarlos por sí mismo, haga que llame al método apropiado en FooService.
  5. Ahora elimine todas las llamadas al FooService a través de lo que me gusta llamar métodos de "puente de cubos" en Foo (simplemente pasa los parámetros junto con el servicio).
  6. A partir de ahora, cada vez que quiera agregar un método, agréguelo a Foo.
  7. Solo agregue cosas al servicio cuando realmente lo necesite por motivos de rendimiento. Como siempre, estos métodos deben invocarse a través del objeto modelo.

Esto lo ayudará a evolucionar hacia un modelo de dominio más rico. También conserva el principio de responsabilidad única, ya que todo el código dependiente de la base de datos permanece en las implementaciones de FooService y lo ayuda a migrar la lógica empresarial de FooService a Foo. Si desea cambiar su back-end a otro DB o en memoria o simulación (para probar), no necesita cambiar nada más que la capa FooService.

^ Supongo que FooService hace llamadas DB que serían demasiado lentas para hacer desde un ORM como seleccionar el Foo más reciente que comparte la propiedad X con un Foo dado. Así es como la mayoría de los que he visto funcionan.

Ejemplo

En lugar de:

class Controller{ public Response getBestStudentForSchool( Request req ){ Student bestStudent = StudentService.findBestPupilForSchool( req.getParam( "schlId" ).asInt() ); ... } }

Te moverás hacia algo como esto:

class Controller{ public Response getBestStudentForSchool( Request req ){ School school = repo.get( School.class, req.getParam( "schlId" ).asInt() ); Student bestStudent = school.getBestStudent(); ... } }

Lo cual espero que usted acepte ya parece más rico. Ahora está haciendo otra llamada a la base de datos, pero si mantiene la escuela en la memoria caché, la penalización es insignificante. Me temo que cualquier modelo verdaderamente OOP será menos eficiente que el modelo anémico que está utilizando, pero la reducción de errores a través de la claridad del código debería valer la pena. Como siempre, YMMV.

Entonces, he notado que definitivamente tengo una tendencia a modelar mis objetos de pila Spring / Hibernate como este:

  • El controlador Foo realiza una llamada a "FooService"
  • FooService llama al método FooRepository.getById () para obtener algunos Foos.
  • FooRepository realiza algunas llamadas de Hibernate para cargar objetos Foo.
  • FooService realiza algunas interacciones con los Foos. Puede usar un TransactionalFooService relacionado para manejar cosas que deben hacerse juntas en una transacción.
  • FooService le pide a FooRepository que guarde los Foos.

El problema aquí es que los Foos no tienen ninguna lógica real. Por ejemplo, si un correo electrónico debe enviarse cada vez que caduca un Foo, no hay una llamada a Foo.expire (). Hay una llamada a FooService.expireFoo (fooId). Esto es por una variedad de razones:

  • Es molesto acceder a otros servicios y objetos de un Foo. No es un Spring Bean, y fue cargado por Hibernate.
  • Es molesto hacer que un Foo haga varias cosas de forma transaccional.
  • Es difícil decidir si Foo debería ser responsable de elegir cuándo salvarse. Si llama a foo.setName (), ¿debería persistir el cambio? ¿Debería esperar hasta que llame a foo.save ()? ¿Debería foo.save () invocar FooRepository.save (this)?

Entonces, por este tipo de razones, mis objetos de dominio Spring tienden a ser básicamente estructuras glorificadas con alguna lógica de validación. Quizás esto está bien. Tal vez los servicios web están bien como código de procedimiento. Tal vez a medida que se escriben nuevas funciones, es aceptable crear nuevos servicios que traten los mismos objetos antiguos de nuevas maneras.

Pero me gustaría escapar de este tipo de diseño, y me pregunto qué otros usos de Spring hacen al respecto. ¿Lo combaten con trucos de fantasía como el tejido en tiempo de carga (con el que no estoy tan cómodo)? ¿Tienes algún otro truco? ¿Crees que el procedimiento está bien?


Parece que su aplicación está diseñada según los principios de codificación de procedimientos. Esto solo obstaculizará cualquier programación orientada a objetos que estés tratando de hacer.

Es posible que un Foo no tenga ningún comportamiento que controle. También es aceptable no utilizar un patrón de modelo de dominio si su lógica comercial es mínima. Un patrón de secuencia de comandos de transacción a veces tiene sentido.

El problema entra cuando esa lógica comienza a crecer. Refactorizar una secuencia de comandos de transacción en un modelo de dominio no es lo más fácil, pero ciertamente no es lo más difícil. Si tienes toneladas de lógica en torno a Foo, te recomendaría pasar al patrón del Modelo de dominio. Los beneficios de encapsulamiento hacen que sea muy fácil entender qué está pasando y quién está involucrado con qué.

Si desea tener Foo.Expire() , cree un evento en su clase Foo, como OnExpiration . foo.OnExpiration += FooService.ExpireFoo(foo.Id) tu foo.OnExpiration += FooService.ExpireFoo(foo.Id) a la creación de objetos, posiblemente a través de una fábrica utilizada por el FooRepository .

Realmente piense primero. Es muy posible que todo esté en el lugar correcto ... por ahora.

¡Buena suerte!


Puede hacer que Spring inserte sus servicios en sus instancias instanciadas de Hibernate, usando AOP. También puede hacer que Hibernate haga lo mismo utilizando Interceptores.

Ver http://www.jblewitt.com/blog/?p=129

En cuanto a "Es molesto hacer que un Foo haga varias cosas de forma transaccional", esperaría que las implementaciones de tu servicio conozcan / se preocupen por las transacciones, y si ahora estás utilizando las interfaces de servicio dentro de tu modelo de dominio, eso no debería ser del todo cierto. muy molesto.

Sospecho que decidir cuándo se debe guardar un modelo de dominio depende de qué es y qué está haciendo con él.

FWIW Tengo una tendencia a producir el mismo tipo de estructuras anémicas, pero estoy llegando, ahora sé que es posible hacerlo de una manera más sensata.