ORMs vs MicroORMs vs ADO.NET: Cuándo usar cada uno

A raíz de mi último post en el que comparaba el rendimiento de NHibernate y Dapper, surgió una entretenida discusión en Twitter sobre si usar o no ORMs. Como Twitter no es el mejor medio para discutir cosas complicadas, me ha parecido más cómodo escribir este post para explicar mi postura y así la próxima vez sólo tengo que twittear un enlace.

Cuándo usar un ORM

Por definición un ORM es una herramienta que permite mapear un modelo relacional a un modelo de objetos. Eso implica que para que tenga sentido usar un ORM necesitamos dos cosas: un modelo relacional y un modelo de objetos.

Puede parece una tontería, pero es que muchas veces no se tiene (ni se necesita) un modelo real de objetos, sino simplemente una representación directa de las tablas, con clases que sólo actúan como meros contenedores de datos y sin apenas relaciones entre sí.

Aunque hay ocasiones que se ve el ORM como algo que simplemente evita escribir sentencias SQL y escribir código para mover datos de un DataReader a nuestros objetos, un ORM es mucho más que eso.

Una de las características más importantes de todo ORM que se precie es la implementación del identity map, que nos garantiza que cuando cargamos dos veces una misma entidad desde la base de datos obtenemos el mismo objeto.

El otro aspecto fundamental de un ORM es la gestión del Unit of Work, que nos permite trabajar con los objetos en memoria y hacer el seguimiento de los cambios que hemos realizado.

Además de esto, el ORM nos facilita la navegación por las relaciones entre entidades con técnicas como lazy load o utilizando distintas estrategias de carga de datos para optimizar el número de consultas lanzadas a la base de datos. También nos ofrece funcionalidades muy útiles como persistencia por alcance y seguimiento de cambios.

Todo esto no es gratis e introduce una complejidad adicional en la aplicación, por lo que si no hay un modelo real de objetos, puede no merecer la pena.

Lo que nunca puedes olvidar es que por mucho ORM que tengas, al final estás tratando con una base de datos y eso impone ciertas restricciones a la hora de trabajar con el ORM. Aunque tengamos la ilusión de que estamos tratando con objetos, la base de datos sigue ahí y no puedes olvidarte por completo de ella. Este es el motivo de que mucha gente considere el ORM como una leaky abstraction.

Como ya he dicho en otras ocasiones, utilizar un framework para aumentar el nivel de abstracción no te exime de comprender aquello que se está abstrayendo. Si usas un ORM pensando que no hay base de datos, se volverá en tu contra.

Cuándo usar un MicroORM

Antes de nada, quiero dejar claro que no me gusta el término MicroORM, porque realmente no se trata de un ORM. Si un ORM se encarga de salvar la impedancia entre dos modelos, un MicroORM lo único que hace es mover datos de un sitio a otro, pero usando el mismo modelo. Más que un ORM, un MicroORM es un DataMapper.

Dejando de lado la nomenclatura, un MicroORM también tiene su utilidad. Hay aplicaciones en las cuales no tiene sentido crear un modelo complejo de objetos y podemos limitarnos a replicar el modelo relacional en memoria. Para este tipo de aplicaciones, un MicroORM, o incluso Active Record, es una buena salida porque nos permite evitar código repetitivo y genera por nosotros gran parte de las sentencias SQL para leer y escribir en la base de datos.

En un MicroORM generalmente no tenemos implementación del identity map y, si existe, la implementación de Unit Of Work es bastante más básica que la de un ORM completo.

Esta reducción en funcionalidades tiene sus ventajas. Un MicroORM es mucho más ligero que un ORM y suele estar más optimizado, ofreciéndonos un rendimiento muy bueno, prácticamente igual que ADO.NET.

Además su API es más limpia y es muy fácil de utilizar, aunque a cambio tendremos que hacer más cosas a mano, sobre todo por no tener seguimiento de cambios ni navegación por las relaciones de los objetos.

Cuándo usar ADO.NET

Otra alternativa es tirar por la calle de en medio y no emplear ninguna librería, sino usar directamente ADO.NET. La ventaja es que evitas tener más dependencias y puedes exprimir al máximo el rendimiento.

Sin embargo, usar ADO.NET me parece una pérdida de tiempo en la mayoría de los casos. Está claro que si tienes una aplicación sumamente sencilla que sólo usa una o dos tablas, es una opción viable, pero en cuanto la aplicación tiene un número razonable de tablas, resulta poco rentable.

Al final la mejora de rendimiento no es tan grande y el trabajo adicional que hay que realizar es aburrido y aporta poco valor.

Una situación bastante frecuente es empezar usando ADO.NET y acabar implementando nuestro propio pseudo MicroORM. Cuando uno ha escrito 15 veces el mismo código para pasar datos de un DataReader a objetos, empieza a plantearse si no se podría hacer por reflection, o mejor aún usando generación dinámica de código para no perder eficiencia y al final… pues al final te has implementado tu propio Dapper.

No me malinterpretéis, a veces está bien reinventar la rueda (yo lo acabo de hacer con TinyTwitter), pero no hay que olvidar el objetivo es aportar valor al negocio, no implementar capas de acceso a datos (a menos que ese sea tu negocio o sea un aspecto crítico del mismo).

Conclusión

A los desarrolladores nos suele gustar mucho hacer analogías con herramientas físicas y hablamos de martillos para los que todo son clavos o de navajas suizas.

Es muy importante entender que ninguna de las técnicas, ni ORMs, ni DataMappers, ni ADO.NET, es una navaja suiza que nos sirva para todo, pero sí podemos verlas como distintas hojas de una misma navaja suiza para resolver nuestras necesidades de acceso a datos.

9 comentarios en “ORMs vs MicroORMs vs ADO.NET: Cuándo usar cada uno

  1. Interesante artículo.

    Parece que las alternativas a acceso a datos son MicroORMs , Entity Framework (ORM), ADO.NET. Y obsoleto quedó Linq to Sql.

  2. kiquenet, tienes otros ORMs que funcionan muy bien, como NHibernate. Aunque no tenga soporte para algunas de las cosas más «modernas», sigue siendo muy superior a Entity Framework en algunas áreas.

  3. Bueno muy bien explicado, pero hay personas que en verdad no investigan, no me lo tomen a mal, pero si se compara el performance de linq con dapper, pues me voy por dapper, ya que en la vida real lo que el usuario final quiere rapidez.

  4. Pregunton Cojonero dijo:

    Incluyo comentario de Jorge Gamba como brainstorming…

    «De acuerdo en que en algunos casos, tal vez la mayoría pensando en la facilidad de mantenimiento del código base, importa más la legibilidad del código. Desde que uno no esté haciendo ya un twitter (aunque las aplicaciones que hacemos son cada vez más para uso masivo), es mejor algo más limpio siempre que la diferencia en rendimiento no sea muy significativa.

    Una cosa en la que no estoy de acuerdo es en donde se dice respecto a un select algo complejo que se compara implementándolo con EF y Dapper: “la implementación con EntityFramework es mucho más limpia y orientada a objetos”… Es que en general (99.99% de los casos), las consultas no son un asunto “orientado a objetos” si no “orientado a datos». Yo suelo preguntar:

    ¿En donde se ve mejor un código con lógica de negocios? en C# o en SQL (SPs + cursores)?

    ¿En donde se ve mejor un código de consulta? en C# (LINQ) o en SQL?

    Cada uno es mejor en uno de los dos terrenos, para el que fueron concebidos y bien pensados. Entonces una consulta que comienza a ponerse compleja es mejor en una simple vista desde el motor de base de datos, se le pone un nombre descriptivo y desde el código de aplicación pues hasta con purito ADO.NET, tal vez envuelto en un pequeño helper (o bueno un microORM), queda claro. En ese caso me parece que el código SQL tiene tanto mejor rendimiento como mayor legibilidad.

    Entonces faltó considerar que no todo es ORM o microORM. Por supuesto para consultas sencillas de a una tablita y algo más allá, no vale la pena armarle una vista o SP, entonces estaría bien algo en el nivel de aplicación. Como todo en la vida, los extremos pues son malos.

    Por lo general el código de comandos pues va mejor en aplicación (para tu ejemplo en C#) mientras que el de consultas complejas y algo menos (en SQL para tu ejemplo que es en el contexto «relacional»).»

    http://www.eltavo.net/2016/04/dapper-vs-entityframework-debo-usar-un.html

    Son diversas visiones sobre el acceso a datos.

    Lo que veo que hay que combinar ORM – MicroORM – ADO.NET con generación de código básica para los típicos Insert – update – Delete por tabla.

  5. Pregunton Cojonero dijo:

    Update: Añadir por interés, el enlace a la discusión de Twitter, para ver las distintas posturas :-)

  6. Pregunton Cojonero dijo:

    Existe una guía de Microsoft (by Cesar de la Torre),
    «NET Technology Guide for Business Applications» , comenta distintas tecnologías de acceso a datos.

    Third-party O/RM technologies: There are many other good technologies (such as O/RMs like NHibernate, LinqConnect,
    DataObjects.net, BLToolkit, OpenAccess, and Subsonic)

    ADO.NET:

    Microsoft Sync Framework:

    NoSQL databases and technologies:

    NoSQL APIs:

    Big data:

    Lo que toca es profundizar.

    Para qué queremos la MSDN si tenemos Stackoverflow.

  7. Francisco, en realidad el rendimiento no es taaaan dispar. Si, dapper es rápido, mas rápido que un ORM, pero no todo es eso, depende del proyecto seleccionas la herramienta.

    Una cosa que no se menciona, o que se menciona mal, es el uso de Linq. Linq no se usa «para no aprender SQL», de hecho los conocimientos de SQL ayudan a escribir mejores consultas en Linq, pero la principal ventaja de Linq es que tienes consultas fuertemente tipeadas, cosa que no tienes con SQL puro, por ejemplo con Dapper.

Comentarios cerrados.