2010-11-24 16 views
7

Estoy pensando si realmente necesito una capa de servicio.Capa de servicio en la aplicación java swing

Estoy usando spring + hibernate para una aplicación de columpio de escritorio y en este momento tengo capa de gui/swing-> capa de servicio-> capa de dao. Utilizo la primavera solo para el soporte @Transactional y para la inyección IOC

Las mejores prácticas dicen que tengo que escribir un servicio para usar mis daos y poner toda la administración de transacciones en el servicio.

Pero me estoy dando cuenta de que muy a menudo, la capa de servicio sólo se replica Dao métodos, así por ejemplo:

// a DAO example 
@Repository 
public class CustomerHibernateDAO extends BaseHibernateDAO implements CustomerDAO { 

public List<Customer> findAllCustomerILikeName(String name){ 
    return getSession() 
    .createCriteria(Customer.class) 
    .add(Restriction.ilike("name", name)) 
    .list(); 
} 
} 

// Customer service to use this dao... 
@Service 
@Transactional 
public class CustomerService { 

@Autowired 
CustomerDAO customerDAO; 

// Why i can't call DAO instead the service? 
public List<Customer> getAllCustomersByName(String name){ 
     return customerDAO.findAllCustomerILikeName(name); 
} 

} 

Este es un uso típico de la mina capa de servicio ... Hibernate es DB-agnóstico, la primavera es agnóstica de la tecnología: ¿entonces realmente la necesito?

¿Qué tal una única clase de servicio para gestionar todos los DAO? Creo que esto puede ser un buen compromiso, o ¿es una mala práctica?

Sé puso en @Transactional DAO es una mala manera, pero en este momento tengo que escribir los servicios sólo para poner en ella ... @Transactional

EDITAR

Más información Sobre mi aplicación

Mi aplicación es un software de gestión y gestión de registro de usuarios, productos, pedidos y otros similares. En la práctica, contiene una gran cantidad de lecturas entidad-> editar-> guardar entidad o crear-> editar-> guardar operaciones, y, gracias a Hibernate, estas operaciones son administradas por ONE dao la mayor parte del tiempo, debido a que hibernate con @manyto ... collection y cascade.save_update permiten guardar dos o más entidades en la misma operación de persistir.

Así, por ejemplo, en mis artículos JFrame donde puedo insertar, modificar o crear un elemento (un producto para vender) hay:

public ItemFrame(){ 
// the constructor 
itemService=springAppContext.getBeans(ItemService.class); 
} 

public boolean validateForm(){ 
// test if the gui is correctly filled by user 
} 

public boolean save(){ 
// create an Item entity taking value from swing gui(JTextField etc) 
Item item=new Item(); 
item.setName(nameTextField.getText()); 
item.setEtc... 
// ItemService ' save method is a wrap around itemDao.save(item)... 
itemService.save(item); 
} 

private void saveItemActionPerformed(ActionEvent evt){ 
// When i press SAVE button 
if(validateForm()){ 
    save(); 
} 
} 

Esto es lo que tengo en la mayoría de los casos, así que creo que caí en anémico dominio antipatrón ...

Gracias.

+0

en mi opinión lo está haciendo correctly.Services debería estar allí por Wil entity.It Mantengo un patrón estándar + si hay cambios en DB, solo estará construyendo la capa DAO, + 1 por cierto –

+0

Si hay cambios en DB y no uso los servicios, ¿cuál es el problema? Voy a reconstruir mi DAO y todo está bien ... ¿o no? – blow

+0

Me estoy saliendo un poco del tema aquí, pero ¿cuál es el motivo para obtener el frijol del contenedor usted mismo en el constructor de ItemFrame? No puedo ver ningún beneficio de este enfoque sobre obtener el frijol inyectado por el contenedor. – prasopes

Respuesta

3

Si su capa de servicio duplica dao, no está utilizando capa de servicio en absoluto. Cometí el mismo error en algunas de mis aplicaciones, me preguntaba "por qué la capa de servicio se ve tan fea, y es duplicación de DAO" ...

La capa de servicio debe ser la interfaz para su aplicación, esto significa que, algunos métodos no son los mismos en dao y en servicio, pero la parte principal es significativamente diferente. No puedo decir esto sin ver el resto de tu código, pero con tu pregunta (que es casi la misma que hace unos meses), me parece que estás usando anemic domain model antipattern. En un modelo de dominio anémico, su modelo solo contiene campos y captadores, ningún método real (comportamiento), que viola los principios fundamentales orientados a objetos (objeto == datos + comportamiento) ... su comportamiento probablemente se encuentre en algo que se parece al script de transacciones en servicio capa, pero debe estar en su modelo (capa de dominio).

La manera de salir de esto es usar el modelo de dominio enriquecido (beans inyectados al modelo a través de @Configurable). Usted puede decir que esto viola el patrón de capas y probablemente sea correcto. Pero estoy convencido de que deberíamos pensar en nuestra aplicación (dominio + servicio dao +) como un solo componente (ver Alistair Cockburn Hexagonal architecture/Ports and adapters).

Su aplicación swing/cliente web será entonces un cliente para su componente principal, luego puede cambiarlos sin ninguna limitación (porque todo lo que los datos modiefies están en el núcleo).

Pero hay una limitación/inconveniente con este enfoque. Si va a usar algún tipo de seguridad (seguridad Spring) o registros activos a través de hibernación, entonces debe comunicarse con todos los clientes a través de DTO (no las entidades en sí), porque cuando se contacta con la entidad, puede llamar al servicio, que se activará a través de transaccional y puede modificar la base de datos (omitir su seguridad).

Espero que haya adivinado su arquitectura, si no, lamento haber inventado la rueda aquí, pero esta publicación puede ayudar a alguien que no sabe esto (como hacía unas pocas polillas).

EDITAR

a tu edición: Incluso en la aplicación CRUD sencillo, algún tipo de acciones debe estar en la capa de servicios - por ejemplo, la validación (no la validación "se trata de un número", pero algunos de validación específica de negocio) Esto no debería estar a su vista, porque si lo cambia, tendrá que copiarlo & pegarlo de nuevo. Cuando mires tu código, deberías preguntar "si decido escribir thin client (ver en el navegador web)", ¿hay algún código que deba copiar? Si es la respuesta SÍ, entonces debe crear un método de servicio para esta posible llamada remota.

La otra cosa que debe/puede hacer en la capa de servicio es la autorización (el usuario con esta función le permite eliminar esta entrada). Luego tendrá que tener una capa de servicio para casi todas sus entidades, porque el usuario simple debería poder editar (eliminar) sus entradas, pero probablemente no debería eliminar a otros usuarios. Pero el usuario en el rol de administrador puede hacer esto.

Ejemplo de código (parte de la interfaz de servicio artículo en mi aplicación (seguridad de primavera)):

@Secured("ROLE_EDITOR") 
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails); 

En comentario a todo el mundo de servicios puede guardar sus comentarios a los artículos ....

Y una última nota : probablemente debería considerar, si necesita la capa de servicio. Cuando está escrito de una manera agradable, su aplicación obtendrá muchas cualidades en cuanto a flexibilidad, reutilización y mantenibilidad. Pero es bastante difícil y lleva mucho tiempo escribirlo.Si no quieres hacer esto todo este material (seguridad, modelo de dominio rico, llamando desde más interfaces (cambio de vista de la implementación)), se puede vivir sin ella :-)

+0

gracias muy útiles, agrego más información a mi primera publicación, ¡dejen un comentario al respecto! ¡Gracias! – blow

+0

Mis entidades contienen solo getter y setter, pero my daos contiene más métodos que CRUD, por lo que son un repositorio real (de acuerdo con DDD, diseño domanin controlado). Cuando escribo entidad, intento siempre pensar en OO. Entonces tengo una mezcla de modelo anémico y de dominio. – blow

+0

Gran enlace, no sabía que Fowler tenía un artículo sobre esto. – prasopes

0

Eventualmente, tendrá que coordinar el comportamiento entre múltiples DAO. También puede introducir cierta complejidad en las reglas de su negocio (por ejemplo: no actualice [esto], si [eso] está en un estado particular). Aquí es donde la capa de servicio es útil.

Dicho esto, técnicamente no hay nada de malo en eliminar por completo la capa de servicio. Solo será un poco más doloroso cuando finalmente decidas que lo necesitas.

1

En algún momento, su aplicación querrá cierta lógica comercial. Además, es posible que desee validar la entrada para asegurarse de que no se solicite nada malo o no satisfactorio. Esta lógica pertenece a su capa de servicio.

Además, es posible que su DAO sea bastante genérico, por lo que solo tiene uno o dos métodos que no cambian demasiado. Esto reduce el riesgo de hacer algo terriblemente incorrecto en sus clases DAO cada vez que quiera agregar/cambiar la funcionalidad de la aplicación.

El DAO es para acceder a los datos. El Servicio es para lógica de negocios. Mantenlos separados y serás más feliz a la larga.

0

En lugar de hacer cumplir

ui -> service -> DAO 

para cada operación, lo que permite considerar tanto

ui -> DAO 
ui -> service -> DAO 

este último siendo usada para operaciones más complejas

Cuestiones relacionadas