2012-07-27 30 views
11

He buscado mucha información sobre el patrón DAO y entiendo el punto. Pero siento que la mayoría de las explicaciones no cuentan toda la historia y me refiero a dónde usarías realmente tu DAO. Así por ejemplo, si tengo una clase de usuario y una UserDAO correspondiente que es capaz de guardar y restaurar los usuarios para mí, que es la forma correcta:Patrón DAO y objetos modelo

  • El controlador crea el objeto de usuario y la pasa al UserDAO a guardarla en la base de datos

  • el controlador crea el objeto de usuario y en su constructor del objeto de usuario hace una llamada a la UserDAO con el fin de salvar a sí mismo en la base de datos

  • Este es un olor de código y que son falta un "UserManager" de clase extra que el controlador pedirá para crear el usuario. El UserManager es responsable de crear el usuario y pidiendo al UserDAO para guardarlo

Realmente siento que la tercera opción es la mejor, porque todo lo que el controlador es responsable de es delegar la solicitud al modelo de objeto correcto . ¿Cuál es tu forma favorita? Me estoy perdiendo de algo ?

Respuesta

12

Desde mi experiencia con DAO, el primer enfoque es la única correcta. La razón es que tiene las responsabilidades más claras y produce el menor desorden (bueno, algunos programadores muy respetables consideran que los DAO son un caos. Adam Bien ve el patrón DAO original ya implementado en el EntityManager y DAO adicionales como "conductos" innecesarios)

Enfoque 2 vincula el modelo a la DAO, creando una "dependencia en sentido ascendente". Lo que quiero decir es que generalmente los modelos se distribuyen como paquetes separados y son (y deberían ser) ignorantes de los detalles de su persistencia. Un patrón similar al que está describiendo es el Active Record pattern. Es ampliamente utilizado en Ruby on Rails, pero no se ha implementado con la misma elegancia y simplicidad en Java.

Aproximación 3 - ¿Cuál es el objetivo del UserManager? En su ejemplo, el Administrador realiza 2 tareas: tiene las funciones de una fábrica de Usuario y es un proxy para las solicitudes de persistencia. Si es una fábrica y la necesita, debe ponerle el nombre UserFactory sin imponer tareas adicionales en ella. En cuanto al proxy, ¿por qué debería necesitarlo?

En mi humilde opinión la mayoría de las clases nombradas ...Manager tienen un olor. El nombre en sí mismo sugiere que la clase no tiene un propósito claro. Cada vez que tengo ganas de nombrar una clase ...Manager, es una señal para mí encontrar un nombre que se ajuste mejor o pensar mucho sobre mi arquitectura.

+1

Solo para agregar a esto; Por lo general, también creo un objeto UserServices que es responsable de gestionar la sesión/transacción. Luego tengo el UserDAO que solo es responsable de hacer las consultas invocadas desde UserServices. – sbrattla

+0

@sbrattla - Si está utilizando transacciones de usuario, esto definitivamente puede tener sentido. Estaba asumiendo automáticamente transacciones EJB, aunque OP no las mencionó. Kneejerk :) – kostja

+0

@Tom si no está de acuerdo, por favor elabore – kostja

0

El objeto de acceso a datos (DAO) se debe utilizar más cerca de la capa de acceso a datos de su aplicación. El objeto de acceso a datos realmente realiza las actividades de acceso a datos.Por lo tanto, es parte de la capa de acceso a datos.

Las capas de arquitectura anteriores a DAO pueden variar en los proyectos.

Los controladores son básicamente para controlar el flujo de solicitudes. Entonces están más o menos cerca de UI. Aunque, un Manager, Handler es una mala idea, aún podríamos agregar una capa entre el controlador y DAO. Por lo tanto, el controlador preprocesará los datos que provienen de una solicitud o salen (cordura de los datos, seguridad, localización, i18n, transformación a JSON, etc.). Envía datos al servicio en forma de objetos de dominio (Usuario en este caso). El servicio invocará cierta lógica comercial en este usuario o la usará para cierta lógica empresarial. Y luego lo pasaría a DAO.

Tener la lógica de negocio en capa del controlador no es bueno si usted está apoyando a varios clientes como JSP, servicios web, dispositivos de mano, etc.

0

Suponiendo controlador significa la "C" en MVC, su tercera opción es la correcta enfoque. En términos generales, el código del controlador amplía o sigue las convenciones de un marco. Uno de los ideales de MVC es intercambiar marcos, que en realidad es el Controlador, debería ser relativamente fácil. Los controladores solo deben mover los datos hacia adelante y hacia atrás entre el modelo y las capas de visualización.

Desde una perspectiva de modelo, los controladores deben interactuar con un service layer - a contextual boundary - en el frente de sesión del domain model. El objeto UserManager sería un ejemplo de una pieza que consideraría parte de su capa de servicio, que es la API pública del modelo de dominio.

0

Para el primer acercamiento; En mi humilde opinión, el controlador que llama a un método en un objeto DAO no es un buen diseño. Los controladores deben preguntar objetos de nivel de "servicio" sobre negocios. Cómo persisten estos "servicios", los datos no son una preocupación para el controlador.

Para el segundo enfoque; a veces puede querer simplemente crear el objeto, por lo que el deber del constructor y el deber persistente no deben estar estrechamente unidos de esta manera.

Por último, el administrador o los objetos de servicio es una buena abstracción para la arquitectura en capas. De esta forma, puede agrupar los flujos de negocios en las clases y métodos apropiados.

Pero para Play, los objetos complementarios de las clases de casos también son un buen candidato para usar como DAO. La naturaleza única de estos objetos lo convierte en un buen candidato.

case class TicketResponse(appId: String, ticket: String, ts: String) 

object TicketResponse{ 
    implicit val ticketWrites = Json.writes[TicketResponse] 

    def save(response: TicketResponse) = { 

    val result = DB.withConnection { 
     implicit connection => 

     SQL("insert into tickets(ticket, appid, ts)" 
      + " values ({ticket},{appid},{ts})") 
      .on('ticket -> response.ticket, 'appid -> response.appId, 'ts -> response.ts).executeInsert() 
    } 

    } 

} 
Cuestiones relacionadas