Buscar
Social
Ofertas laborales ES

Foro sobre Java EE > Patrón (o antipatrón) DTO

Buenas.

Trabajo en una empresa informática, y hemos heredado un sistema de otra empresa. Es una aplicación bastante grande y con muchos años de desarrollo.
Será que los informáticos somos un poco ególatras, o no se, pero estamos viendo que los patrones aplicados no son los adecuados. Para empezar, tiene demasiadas capas, muchas sin sentido. Mezcla SpringFramework con EJB 3.0, JNDI...

Pero lo principal es que nos encontramos con el patrón DTO-VO, altamente extendido. La capa de negocio recupera los DTO de los DAO, los convierte a VO y los envía a la capa superior (que no es la de presentación, ya comenté que tiene demasiadas capas para mi gusto).
El problema derivado de este patrón es que los VO son idénticos a los DTO, por lo que se utilizó una librería llamada dozerMapping, que realiza las conversiones de forma automática. Peeero, el problema es que lo hace a través de reflexión, y el tiempo de ejecución es de orden exponencial. Tarda más la conversión que la recuperación de los propios datos de base de datos...
Así que hemos tenido que quitar el uso de esta librería, y hacer las conversiones "a pelo", personalizadas para cada clase. Un auténtico infierno, que genera cientos de lineas de código absurdas.

Nos estamos planteando borrar la capa DTO de la aplicación, y enviar a la capa superior los objetos directamente, aunque implique invertir tiempo extra.
Mi duda es, ¿como veis eliminar este patrón de una aplicación?. ¿Realmente lo veis útil?, ¿creeis que a la larga es peor?.

A mi personalmente me parece un patrón muy poco útil. Si se necesita adaptar un objeto... debería hacerse a través de decoradores en la capa de presentación, y no realizar conversiones sin sentido en la lógica de negocio. Creo que usar DTOs y VOs no desacopla más que no usarlos, pero ¿que opinais?.

¿Qué haríais?.

Un saludo.

septiembre 28, 2012 | Unregistered CommenterMayantigo

No nos estás explicando cuál es la justificación de esa transformación. ¿Pretenden evitar los "lazy initialization exceptions"?

septiembre 28, 2012 | Registered Commenterantoniovl

La aplicación fue heredada... con estas transformaciones implementadas. Hemos añadido unas cuantas entidades en el modelo, y se optó por continuar con este procedimiento para "homogeneizar" las capas de la aplicación.
La justificación de la transformación... yo no la veo. Nunca la he entendido. Parece como si únicamente hayan aplicado este patrón porque lo leyeron en algún libro.
Intuyo que querían "separar" una capa de otra, pero no veo en que afecta eso a la separación entre capas, si al final las entidades son prácticamente las mismas. Y si se necesitara en la vista decorar alguna de las entidades... Pues se aplica un decorator sobre ESE objeto, y no por defecto en toda la capa de negocio.

No se lo que pretendían, pero hay muchas cosas en la aplicación que a priori no me cuadran, y tampoco estoy seguro de que sea útil o no, y pido un poco de consejo por si no veo el motivo... (como mezclar Spring con EJB, tener varias capas que únicamente contienen beans que delegan los métodos a otros servicios idénticos sin ningún tratamiento especial, etc).

¡Un saludo!.

octubre 1, 2012 | Unregistered CommenterMayantigo

Recuerda que al pasar por las capas debes mantener la integridad del objeto, esa parte de integridad debe incluir la seguridad, no puedes pasar un objeto directamente por que este puede ser accedido desde la capa (Ej: Un objeto Entidad pasar por Objeto Web directamente), lo que deberias validar es si realmente lo que te causa demoras es la reflexion, alli es donde se debe revisar el cuello de botella que tienes, no conozco la libreria dozerMapping, pero de seguro se debe revisar que la informacion del objeto que estas transportanto debe tener un reflejo de la representacion en base de datos, mi consejo puedes validar esa info, y tambien utilizar un modelo para la conversion de objetos (definir en velocity, ecore, etc).

octubre 2, 2012 | Unregistered CommenterAnonimo

Si, está claro es necesario mantener la integridad del objeto.

Y si, lo que provoca el enorme retardo es la librería dozerMapping. Hemos realizado pruebas de carga y varios profiling a la aplicación.

La cosa es, ¿realmente matiene la integridad?.
Lo pregunto porque he escuchado más de una vez que el patrón DTO está sobrevalorado y realmente no aporta mucho (por mucho que cada capa tenga sus "entidades"). Hasta hoy para mi era un paradigma inamovible, pero lo estoy oyendo bastante, y de gente a la que considero bastante seria y experimentada. Hasta he oido que es mejor que las entidades implementen algún tipo de interfaz, que realizar conversiones "per se".

EJB tiene herramientas de securización de peticiones, ¿no?. Y realmente, si es necesario realizar alguna modificación de las entidades, lo que ocurra de las interfaces de negocio para abajo queda "escondido", ¿no? (ojo, pregunto porque tengo muchísimas dudas ahora, no porque me parezca mejor o peor, solo quiero saber vuestra opinión).

La cosa es, ¿debería ser la capa de presentación la que "adapte" las entidades a su necesidad?, ¿o realmente es necesario duplicar clases y hacer las conversiones en la capa de negocio?.

Un saludo, ¡y gracias por las respuestas!.

octubre 2, 2012 | Unregistered CommenterMayantigo

puedes usar algo como esto en vez de dozer maapings:

http://www.java2s.com/Code/Java/Apache-Common/UseBeanUtilstogetpropertyvaluefromobject.htm
o asi:

http://www.java2s.com/Code/Java/Apache-Common/BeanUtilsgetPropertyfromDynamicBeans.htm

o asi:

http://www.java2s.com/Code/Java/Apache-Common/BeanUtilsdealwithcollections.htm

o asi desde base de datos:

http://www.itjungle.com/mgo/mgo071902-story02.html

o asi:

ResultSet rs = ...;
ResultSetDynaClass rsdc = new ResultSetDynaClass(rs);
Iterator rows = rsdc.iterator();
while (rows.hasNext()) {
DynaBean row = (DynaBean) rows.next();
... process this row ...
}
rs.close();

o mejor asi:


ArrayList results = new ArrayList(); // To hold copied list
ResultSetDynaClass rsdc = ...;
DynaProperty[] properties = rsdc.getDynaProperties();
BasicDynaClass bdc =
new BasicDynaClass("foo", BasicDynaBean.class,
rsdc.getDynaProperties());
Iterator rows = rsdc.iterator();
while (rows.hasNext()) {
DynaBean oldRow = (DynaBean) rows.next();
DynaBean newRow = bdc.newInstance();
PropertyUtils.copyProperties(newRow, oldRow);
results.add(newRow);
}

octubre 23, 2012 | Unregistered Commentergcubillos