Ir al contenido principal

No hagamos repositorios para el acceso a datos

Este artículo está pensado sobre todo para el desarrollo usando el .NET Framework. Quizás aplique para los demás también, ya que casi cada Framework tiene su ORM.

Hace ya varios años que leí la opinión de Ayende Rahien acerca de que el patrón repository era el nuevo singleton. Tiempo después Jimmy Bogard también escribió sobre alternativas.

A mi entender el patrón repository consiste en abstraer el acceso a datos para que el resto del código no tenga que lidiar con los detalles del acceso a datos (conexiones, consultas, SQL, etc) al momento de acceder a colecciones de datos.

Con  el creciente uso de ORMs el patrón repository ya no es necesario. Ahora podemos usar algo como Entity Framework y dejar que se encargue de esos detalles para los que construíamos un repositorio. Entity Framework (o cualquier ORM) hacen eso y más sin que tengamos que escribir tanto código de "plomería". Escribo este post porque aun veo a programadores que intentan usar el patrón repositorio aún y cuando están usando un ORM.


No veo la utilidad de abstraer la abstracción del ORM (como EF) bajo el patrón repository. No es necesario, es querer apegarse a un patrón de diseño solo porque antes se usaba. Sí, se usaba porque era necesario; pero ya no lo es. La meta no es usar patrones, la meta es tener software funcionando que sea fácil de modificar.

Escribí un poco sobre esto cuando traté el tema de la arquitectura en capas, aunque el artículo no se trataba precisamente del patrón repositorio.

Comentarios

  1. Cuando se utiliza solo un motor de base de datos como bien dices no tiene mucho sentido, recuerdo como platicábamos incluso que la capa de datos para ti no era necesaria. Sin embargo, en una infraestructura más integral donde aprovechas las bondades de diferentes técnicas de manejo de datos hay una creciente necesidad de crear aplicaciones híbridas y allí la historia cambia.

    Un ejemplo es cuando utilizas Lucine+MSSQL+Redis para hacer aplicaciones de alto performance en búsquedas de bases de datos grandes. Mantienes la lógica de negocios debidamente en su capa y estos tres motores los manejas en la capa de datos totalmente invisibles a la capa de negocios.

    Combinaciones híbridas, como Lucine+MSSQL+Redis, hay muchas que se sustentan gracias a ese patron.

    ResponderBorrar
  2. También, lo que comentas suele ser los casos donde creas paquetes de software o arquitecturas de desarrollos a la medida cerrados. Pero en un ambiente de desarrollo "In House" donde no necesariamente se comparten los datos por medio de APIs sino por medio de ETLs, que tienen muchos sistemas con diferentes motores de base de datos y que pueden ser accedidos en aplicaciones "In House" también este patron y el de capa de datos es muy útil.

    ResponderBorrar
  3. Hola Proteo5,

    El problema que veo es cuando de entrada se arranca declarando repositorios para las consultas a la base de datos, encapsulando el ORM, lo primero que pienso en esas situaciones es YAGNI.

    A veces sí es necesario agregar una capa más a la consultas u operaciones que se necesitan con los datos. En esas ocasiones se puede agregar un objeto Consulta que obtiene los datos de las diferentes fuentes de datos y usar objetos comando para actualizar la información donde corresponda. Esto agregado por asunto (concern) no agregar el patrón a toda la aplicación. Algo similar a lo que expone Jimmy Bogard en el enlace que compartí en el artículo.

    ResponderBorrar
  4. Hola Mario, esta interesante tu artículo, pero la neta para sistemas medianos a grandes prefiero usar un ORM propio y en proyectos pequeños un ORM tipo EF o NHibernate, porque con el ORM como que es una caja negra donde exactamente no sabes el SQL que te generará esto en sistemas transaccionales no es muy bueno (esa sensación de perder el control), muy aparte de que en la consulta SQL pierdes el tema de medir el plan de ejecución (bueno lo puedes ver con un SQL Profiler pero es mas tedioso el trabajo) para ver si el query esta bien o si las llaves están indexadas, etc. Recuerdo que en un proyecto usamos NHibernate (aun no estaba estable EF) pero el sistema creció un montón y ahora el NHibernate es una piedra en el zapato. Saludos. P.D. Ahí los sigo en el podcast.

    ResponderBorrar
    Respuestas
    1. Hola Kevin, estoy de acuerdo en que para algunos proyectos usar un ORM completo no es lo mejor. Para esos existen opciones como Dapper (https://github.com/StackExchange/dapper-dot-net), otros Micro-ORM o ADO.NET directamente.

      De cualquier forma siento que no seria necesario crear clases Repository para abstraer el acceso a datos, se pueden crear clases query o command para cada una de las operaciones necesarias e implementarlas con lo que sea acorde a las necesidades.

      Gracias por compartir tu opinión y por escucharnos (aunque no seamos constantes con el podcast).

      Borrar

Publicar un comentario

Entradas más populares de este blog

Bloqueos

Una de las preguntas típicas de las juntas matutinas en los equipos de desarrollo de software es ¿Hay algún bloqueo? Si lo hay, se trata de ver qué es lo que está esperando esa persona y encontrar la forma de que se desbloquee; pero ¿Qué son los bloqueos? Los bloqueos son obstáculos que te impiden realizar o avanzar en tu trabajo. Evitan que puedas seguir progresando en el proyecto.

He notado que es común en las personas con menos experiencia decir que tienen un bloqueo cuando están batallando, debido a su poca experiencia, en la forma de resolver un problema. Han intentado varias formas y se empiezan a quedar sin ideas de como puede ser resuelto el problema o como pueden cumplir con el requerimiento especificado. Al quedarse sin opciones de qué intentar dicen que tienen un bloqueo con la tarea y que a menos que alguien les diga como resolverlo, no se puede avanzar en la tarea.

En personas con más experiencia, ese tipo de bloqueos no ocurren, una persona con experiencia ha visto pro…

Firebird 2.1 UPDATE OR INSERT

Another great feature that I like in Firebird 2.1 is the UPDATE OR INSERT statement. It's a really time saver and it makes the SQL cleaner.

For example suppose I have a products table like the one I use in my last post and an inventory table to store the product stock. Before Firebird 2.1 if I want to set the stock for a product I needed to check if a record for that product_id already exists; if the product_id already exists then I write an update. If not then I write an insert statement. So I ended up with something like this:


IF EXISTS(SELECT * FROM inventory WHERE product_id = :product_id ) THEN
UPDATE
inventory
SET
stock = :stock
WHERE
product_id = :product_id;
ELSE
INSERT INTO inventory
(product_id, stock)
VALUES
(:product_id, :stock);

In this example I only update one field but when I have to update a big table I ended up with a big chunk of code and thinking: "there should be another (better) way to do this".

Fortunately now with Firebird 2.1 there…

Database Mail en MS SQL Server 2005

Configuración de Database Mail en MS SQL Server 2005

Primero se debe de habilitar, ya que por omisión el componente esta deshabilitado, Utilizando el SSMS (SQL Server Management Studio)


Si no esta habilitado aparecerá un mensaje preguntado si lo habilita, después aparece esta ventana donde se pregunta al usuario que es lo desea hacer.


Seleccionamos la primera opción para crear un perfil.


Configuramos el perfil y le agregamos por lo menos una cuenta.


Seleccionamos el perfil como public y default.


Para mandar correo se utiliza el procedimiento msdb.sp_send_dbmail por lo tanto el usuario que intente mandar correo debe de tener permiso para la base de datos msdb.

Referencias:
http://www.sqlservercentral.com/columnists/cBunch/introtodatabasemailinsql2005.asp