Noticias Weblogs Foros Wiki Código

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Sponsors

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin

Koalite's blog

Demasiada abstracción

Enero 23rd, 2012 - [Enlace local]

Hay veces que llegamos a un punto en que intentamos abstraer demasiado las cosas y acabamos teniendo lo que se suele llamar una leaky abstraction. Se trata de casos en los cuales el mecanismo de abstracción no es efectivo, aquello que queremos abstraer acaba traspasando la capa de abstración y lo único que conseguimos es una complicación innecesaria.

Recientemente he padecido un caso claro de esto usando la API de consultas QueryOver de NHibernate. QueryOver está diseñado como una implementación del patrón Query Object aprovechando expresiones lambda para hacer static reflection y conseguir así que el API sea type-safe y refactor friendly.

QueryOver intenta abstraer el acceso a la base datos, pero a la vez trata de mantener toda la potencia del SQL, por lo que en cuanto las consultas se complicando un poco acaba siendo un lío y la ganancia que tenemos por ser type-safe y refactor friendly no compensa la pérdida de legibilidad.

Veamos un ejemplo concreto bastante simpe. Supongamos que tenemos el típico modelo de clientes y pedidos y queremos lanzar una consulta para obtener el número de pedidos y el importe total pedido por cada cliente. La implementación con QueryOver es algo así:

Customer customer = null;
var stats = s.QueryOver()
    .JoinAlias(x => x.Customer, () => customer)
    .SelectList(lst => lst
                            .SelectGroup(() => customer.Id)
                            .SelectGroup(() => customer.Name)
                            .SelectSum(x => x.Total)
                            .SelectCount(x => x.Id))
    .List();

El resultado es bastante feo. Para poder hacer el equivalente al inner join de forma type-safe, tenemos que declarar una variable de tipo Customer que usamos únicamente como alias para usarla luego en las expresiones lambda. Además, para construir la lista de columnas a devolver se usa un builder (lst) que simplifica un poco las cosas pero no acaba de resultar claro.

Si la misma consulta la lanzamos con el equivalente HQL, el lenguaje de consultas de NHibernate, tenemos:

var stats = s.CreateQuery(@"select c.Id, c.Name, sum(o.Total), count(o.Id)
                            from Order o right join o.Customer c
                            group by c.Id, c.Name")
             .List();

Para cualquiera que esté acostumbrado a manejar SQL, está claro que la consulta resulta mucho más legible. Es cierto que no es type-safe no refactor friendly, pero en mi opinión la legibilidad lo compensa.

Parece que nuestra tendencia natural como desarrolladores es siempre abstraerlo todo, pero a veces hay que tener cuidado porque puede que estemos causando más problemas de los que solucionamos.




Compartir enlace:
Facebook Twitter Email

No hay posts relacionados.

» Leer más, comentarios, etc...

Información legal y técnica