1 / 19
jul. 2017

El tema de los ORM1 me tiene algo confuso ya que, a pesar de su gran aceptación, yo no logro ver su utilidad. No quiero decir que no la tengan, pero por mi parte veo una capa de abstracción más que no me aporta lo que me promete.

Puede que cuando un proyecto es pequeño, con una base de datos pequeña y sin apenas relaciones, tenga sentido usarlo para abstraerte de utilizar SQL de forma directa, a fin de cuentas para pedir un valor concreto de un registro puede servir, pero para proyectos medianos o grandes con muchas tablas relacionadas no le veo tanta utilidad. Es más, a veces me parece simplemente un grado de complejidad más añadido al sistema.

Al final hay que aprender cómo utilizar el ORM, es decir, te abstrae (en toría) de saber SQL pero tienes que aprender algo nuevo. Y según aumenta lo que se puede hacer con el ORM mayor es la curva de aprendizaje del ORM. Al final es aprender a usar algo para no aprender a usar otra cosa. ¿Tiene sentido un intermediario así? Pero es que al final sí hay que saber algo de SQL para poder usar el ORM en condiciones y saber qué estamos consultando.

Es cierto que las entidades que crea el ORM en forma de clases podrían servir como repositorio de la base de datos para regenerarla, pero hay que llenarlas de anotaciones para controlar todos los argumentos de los campos de base de datos. Yo me he encontrado el siguiente caso: proyecto que usa un ORM (doctrine) en el que las modificaciones se hacen a base de ALTERS o CREATES directamente en la base de datos y luego se modifican las entidades para añadir los nuevos campos metiendo variables y getters y setters, pero sin incluir la configuración de cada campo (null, unsigned, ...) en las anotaciones. Esto ya no sirve como repositorio. Se está entre dos mundos.

Y esas entidades al final son clases sin comportamiento y sólo con estado que no son realmente objetos, ¿y el comportamiento qué hacemos con él? ¿Y si debe haber un comportamiento se mete en la entidad que es específica de una tabla y lo hacemos depender de su esquema? No lo veo. ¿Duplicamos la entidad con los mismos datos y comportamiento en el dominio del negocio? Eso sería lo más optimo, pero tampoco me gusta. No tengo una respuesta para esto.

Al final el resultado de una consulta SQL es una relación, no un objeto, pero obtenemos objetos que contienen objetos que a su vez contienen objetos manteniendo la estructura de la base de datos. Pero no son objetos como tal porque carecen de comportamiento.

Luego esas entidades, que son un reflejo del esquema de la base de datos, aparecen por toda la aplicación y se usan como si fuesen objetos del dominio. Esto no es culpa del ORM, cierto, es un mal uso, pero es tan tentador hacerlo que al final se hace. Luego haz un cambio grande en la base de datos y todos esos getters ya no sirven, y vete a buscarlos por toda la aplicación.

Sin contar lo tentador que es utilizar las consultas a la base de datos a través del ORM sin tener un único punto de acceso. Me lo he encontrado también, un método con la consulta a la base de datos metida dentro, pero como no hay SQL a la vista no queda tan mal.

Sin ir más lejos el otro día, tras tratar de hacer una consulta compleja utilizando el ORM, desistí y utilicé el método extraer conexión que tiene el ORM y lo hice a pelo en MySQL.

Otro de los problemas que le veo es que la base de datos no se define pensando en utilizar un ORM, es decir, en tener sólo objetos que se relacionan entre sí. Lo que me suelo encontrar es una base de datos relacional a la que se ataca con un ORM y este hace una pseudo-conversión a objetos.

Al final parece que todo proyecto tiene que tener un ORM porque sí, porque es lo correcto.

Bueno, esta es mi situación con los ORM. Creo que algo se me escapa o no logro ver las ventajas que tiene el ORM. ¿Cual es vuestra opinión? ¿Los usáis? ¿Los evitáis? ¿Hay más problema con el mal uso que se hace de ellos que con ellos mismos?

Aaaaaaaah con los ORM hemos topado. Este artículo24 es todo un clásico ya.

Personalmente creo que el problema no tiene solución por ese camino. Los objetos y las bases de datos relacionales se parecen como un huevo a una castaña. El camino lógico me parece que sería prescindir de una de las dos cosas: o bien de los objetos o bien de las bbdd relacionales. Cualquier otra cosa nunca va a funcionar del todo bien.

A mi me gusta trabajar con los templates del framework JDBC de Spring que te abstraen un nivel por encima (lo justito) para ahorrarte mucho boilerplate3.

Cuando hay consultas muy complejas con un ORM no solo es una locura si no que la eficiencia se resiente.

Por cierto, tengo la sensación personal de que en la industria cada vez tienen más reticencias hacia usar ORMs y buscan a personas que no se asusten con SQL más o menos directo.

Gracias por el artículo, no lo conocía, me lo guardo para leerlo con más calma.

Si soy sincero cuando la base de datos es grande me cuesta más trabajar con el ORM que con SQL a pelo.

Ufff... yo no creo que sea lo correcto. Según mi propia experiencia es más bien al contrario :confused:

En mi caso, a lo largo de lo años he usado bastantes ORMs en múltiples proyectos y en algunos casos sí que tenía sentido, en otros en cambio ha sido un via crucis (por decir algo suave).

Para que te hagas una idea, mi proyecto actual no es pequeño precisamente (sector financiero y han sido casi 3 años de desarrollo) y se empezó con un ORM, concretamente Entity Framework. Bien, pues al cabo de más de 6 meses de desarrollo se terminó cambiando por un mini ORM como Dapper (de los creadores de stack overflow), el cual te recomiendo si alguna vez desarrollas en C#.

Ya no sólo ha sido el tiempo y recursos empleados en aprender a usar el ORM y a 'tunearlo' porque si no lo usas bien es muy fácil experimentar problemas de rendimiento... el problema viene cuando (como bien has dicho) las entidades se usan como entidades de dominio, y el código empieza a acoplarse por todos lados :frowning:

En resumen, yo soy más partidario de no usarlos que de usarlos... :smiley:

Y por cierto, uses o no uses un ORM debes conocer profundamente la BD que estés usarndo, relacional o no, y su derivado de SQL Que no es lo mismo PL-SQL que T-SQL que el de MySQL, todos tienen 'sus cositas'.

Pues los ORM son imprescindibles si quieres seguir un enfoque DDD para un proyecto. Ciertamente podrías implementar " a mano" los patrones de PoEAA, pero bueno... suerte si lo intentas.

Voy a hacer algunas apreciaciones:

Pero es que al final sí hay que saber algo de SQL para poder usar el ORM en condiciones y saber qué estamos consultando.

Todas las abstracciones fugan y los ORMs pueden tener sus fugas también. Aunque si usas bien un buen ORM no necesitas casi nunca usar SQL.... excepto en casos específicos (que los hay obviamente) en los que dices "voy a romper toda la abstracción y usaré SQL directamente por la razón que sea" (que hay muchas de válidas).

Yo me he encontrado el siguiente caso: proyecto que usa un ORM (doctrine) en el que las modificaciones se hacen a base de ALTERS o CREATES directamente en la base de datos y luego se modifican las entidades para añadir los nuevos campos metiendo variables y getters y setters, pero sin incluir la configuración de cada campo (null, unsigned, ...) en las anotaciones.

Eso es una rotura de DRY, así que es lógico que haya problemas. Por supuesto que se pueda seguir DRY en este punto o no dependerá del ORM y de otros factores. Pero si DRY se rompe siempre aparecerán fricciones. De todos modos ¿usando SQL a pelo se soluciona eso?

Luego esas entidades, que son un reflejo del esquema de la base de datos, aparecen por toda la aplicación y se usan como si fuesen objetos del dominio

Un buen ORM te permite precisamente usar tus entidades de dominio para acceder a datos. Precisamente el trabajo de un ORM es traducir tus entidades de dominio a tablas de BBDD. Si tus entidades están acopladas a la BBDD, entonces o no estás usando el ORM bien o el ORM tiene carencias (o ambas cosas).

Pero no son objetos como tal porque carecen de comportamiento.

Ese es el ejemplo de libro de "anemic domain model", un antipatrón cuando se usa ORMs. Cuando se usa (bien) un ORM las entidades (que son las de dominio, pues no hay otras) tienen comportamiento.

¿Duplicamos la entidad con los mismos datos y comportamiento en el dominio del negocio?

Esa es la clave a entender: No debería haber esa duplicidad. Tus entidades son solo unas: las de dominio. El ORM es infrastructura que transforma esas entidades en consultas SQL y viceversa.

Luego haz un cambio grande en la base de datos

Hay dos motivos que pueden implicar "un cambio grande" en la BBDD. El primero es funcional y en este caso lo obvio es que tus entidades de dominio se veran afectadas, pues el dominio ha cambiado. El segundo es que has diseñado mal la BBDD. Si este es el caso, no deberías necesitar tocar "para nada" tus entidades de dominio (ojo con las comillas xD).
Pero aunque tengas qué cambiarlas... ¿no afecta un cambio grande en la BBDD si usas un micro-ORM o SQL directammente?

Al final parece que todo proyecto tiene que tener un ORM porque sí, porque es lo correcto.

Ni por asomo. Solo aquellos proyectos que tengan una entidad suficiente para ser abordados con técnicas sacadas de DDD. Si haces un CRUD usar un ORM es tirarte piedras contra tu tejado.

¿Los usáis? ¿Los evitáis?

Pues depende del proyecto. E incluso dentro de un mismo proyecto lo uso solo en determinadas partes. No son (ni creo que pretendan ser) una solución universal. El gran problema es que hoy en día ves continúamente ejemplos donde no son necesarios. Y creo que es porque (dejando de lado que nos puedan intentar "vender" el ORM) montar un ejemplo lo suficientemente complejo que justifique usar un ORM no es nada que se pueda hacer en un par de posts de un blog :wink:

Pues los ORM son imprescindibles si quieres seguir un enfoque DDD para un proyecto. Ciertamente podrías implementar " a mano" los patrones de PoEAA, pero bueno... suerte si lo intentas.

Creo que es importante no mezclar cosas. En efecto, si pillas PoEAA y quieres aplicar los "Object-Relational Metadata Mapping Patterns", pues es mucho más fácil hacerlo si usas un ORM porque precisamente es lo que hacen. Pero:

1) Que unos patrones salgan en un libro con un título chulo no quiere decir que sea necesario utilizarlos siempre.
2) Que puedan ser patrones útiles en muchísimos escenarios no quiere decir que sea la única forma eficiente y válida para afrontar la persistencia. Por ejemplo, en cuanto uses algo que no sea relacional, pierde muchísimo el sentido.

Se puede aplicar DDD sin usar bases de datos relacionales y se puede aplicar usando bases de datos relacionales sin ORMs. Es más, muchos "expertos" en DDD prefieren hacerlo sin ORMs.

Como ejemplo de argumentación en esa línea: https://vaughnvernon.co/?p=9425

Ojo, no es más que un ejemplo de la opinión de una persona. No creo en el argumento de autoridad, pero tampoco es el único que opina así (yo también opino que no es necesario).

Vamos, por si no ha quedado clara mi postura: se puede aplicar DDD sin un ORM, con un ORM metido hasta la cocina del hexágono, con un ORM aislado en los repositorios y con persistencias que no son ni relacionales. Todo tiene sus pros y sus contras y al final son decisiones que dependen del del contexto y del proyecto, pero desde luego todas esas decisiones van a tener concesiones en algún punto.

Es más, teniendo en cuenta que cuando busco un enfoque DDD suele ser en proyectos complejos con recorrido, crecimiento, etc. meter el ORM hasta la cocina del hexágono me da mucho miedo precisamente por las concesiones que implica. Ejemplo tonto, ¿soportará mi ORM bien que quiera empezar a explotar las capacidades de persistencia en JSON de mi base de datos? ¿Cuál será el coste de deshacer? ¿Y el de evolucionar?

Como digo, al final son todo decisiones para las que no creo que exista una respuesta sencilla. Personalmente, me gusta llevar poco peso en la mochila.

Gracias por las respuestas, ahí es dónde quería llegar, a entender que sí hay casos en los que sería util, incluso necesario, usar un ORM. Pero entendiendo que no en todos los casos.

Por mi parte los ORM siempre los he recibido implementados y con la base de datos ya montada, y lo que ponía antes es lo que me he encontrado, por eso no llego a ver su utilidad. No soy experto en ORMs y DDD es una tarea que tengo aún pendiente, de ahí que no valorase ahí su uso.

Lo que mas me agrada descubrir en la respuesta de @eiximenis es que queda claro que no es trivial usar un ORM, ni por cómo usarlo ni por el ORM elegido. Y esa sorpresa viene porque leyendo sobre ORMs parece que son algo maravilloso que sirve para todos los proyectos y que te simplifica mucho la vida, te hace todo más facil, pero veo que usarlos o se hace bien y en el sitio adecuado o lo que hacen realmente es complicarlo todo. Y viendo la respuesta de @msanjuan veo que hay debate sobre el tema :wink:

Que unos patrones salgan en un libro con un título chulo no quiere decir que sea necesario utilizarlos siempre.

Por supuesto :wink: Eso mismo digo al final de mi respuesta.

Se puede aplicar DDD sin usar bases de datos relacionales

Cierto... pero no consideraba este escenario, porque hablando de ORMs, la R de relacional se supone implícita. Si nos metemos con arquitecturas con almacenamientos no relacionales, está claro que un ORM no tiene cabida.

P. ej. el tema del JSON que planteas... si vas a usar almacenamiento en JSON, aunque sea aprovechando capacidades de un motor relacional, ese almacenamiento es no-relacional. Un ORM no va ayudarte ahí, al contrario. En el artículo que mencionas de Vernon se centra en almacenamiento JSON. Esperar que un ORM te ayude ahí, es pedirle peras al olmo.
Personalmente, si tuviese que aplicar DDD en un motor relacional, preferiría contar con la ayuda de un ORM. Otro tema es cuando usar DDD y otra adicional cuando un motor relacional para la persistencia. Y eso, sin contar que en un mismo proyecto se pueden mezclar aproximaciones distintas para partes distintas.

:wink:

Tengo una pregunta @eiximenis:

Simplificando y suponiendo que todas las decisiones depende de ti, si en un proyecto nuevo consideraras que aplicar DDD es fundamental... ¿te decantarías por un repositorio relacional apoyándote en un ORM o buscarías una alternativa y así evitar utilizar un ORM?

Por lo que leo @msanjuan preferiría evitar el ORM.

Ya sé que todo depende (depende, gran palabra en este mundillo) del proyecto y sus condiciones pero es por ver por donde van los tiros.

Saludos!