Escribo esta entrada en respuesta a una consulta de nuestro amigo Jonathan en la sección de Preguntas y Respuestas.

La verdad es que mucho se ha escrito al respecto. Y cada profesional informático con años de experiencia probablemente tenga su propia opinión, algunos a favor y otros en contra de la práctica de usar Procedimientos Almacenados.

No pretendo en estas líneas hacer un gran aporte a la discusión. Solo expondré mi propia opinión para aquellos que les interese:

En primer lugar es necesario aclarar por qué existe la cuestión. Programar Procedimientos Almacenados para un motor de base de datos implica crear una dependencia del mismo. Esto es así debido a que el lenguaje SQL standard es demasiado simple, hecho que ha llevado a que los distintos fabricantes de bases de datos crearan sus propias extensiones de SQL. Sybase creó originalmente su Transact-SQL (T-SQL). Microsoft compró una versión de Transact-SQL años atrás y a partir de ahí existen 2 líneas diferentes de T-SQL (una de Sybase y otra de Microsoft). Oracle posee a su poderoso PL-SQL. IBM soporta a varios lenguajes incluyendo Cobol, Rexx e inclusive Java. De hecho las últimas versiones de productos de varios fabricantes dan soporte de una manera u otra a Java. Hasta Postgres soporta tanto a su PgSql como a Java.

Enfim, el tema es que aún no es posible programar Procedimientos Almacenados totalmente independientes del motor de base de datos. Este hecho en sí mismo tiene al menos 2 perspectivas: la pragmática y la teórica.

Desde una perspectiva pragmática o práctica, muchos opinan que las ventajas conseguidas en términos de performance y de gestión de la implementación de procedimientos almacenados superan la desventaja de depender de un fabricante de software. Estas personas suelen mencionar que son escasos los casos reales de compañías que se cambian de motor de base de datos.

Desde la perspectiva de la ingeniería y la arquitectura de software, siempre se persigue la portabilidad del código. Poder contar con la lógica de acceso a los datos en una capa de software independiente del motor de base de datos es como un Grial a alcanzar. Tiene sus desventajas en cuanto a performance (algo discutible) y mantenibilidad, pero facilita enormemente la migración a otras plataformas en caso de necesidad.

En mi experiencia personal he podido trabajar con ambas prácticas: accediendo a los datos únicamente mediante procedimientos almacenados o separando la lógica de acceso en una capa distinta obedeciendo a algún Patrón de Diseño aplicable como el Object Relational Mapping por ejemplo.

La verdad es que no se puede recomendar una práctica sobre la otra para todos los casos. Es más, antes de determinar la mejor técnica para un determinado proyecto, me parece más importante determinar el Patrón de Diseño que se utilizará. Martin Fowler en su libro Patterns for Enterprise Applications Architecture (PEAA) plantea una serie de alternativas de Patrones aplicables al acceso a datos (Aquí les dejo el link al catálogo de estos patrones). Todos esos patrones de diseño permiten la existencia tanto de sentencias SQL standard en el código como de invocaciones a procedimientos almacenados dentro de la capa que cumple el rol de Datasource.

Si debemos desarrollar una aplicación que esperamos comercializarla en el futuro, decidir usar procedimientos almacenados implicará pérdidas de tiempo importantes cuando deseemos implementar la misma aplicación en un motor de base de datos distinto. Situación que puedes estar seguro que sucederá tarde o temprano. No obstante, para ciertas consultas específicas complejas de tu sistema descubrirás que usar procedimientos almacenados incrementará la performance de manera insospechada, impresionando a tus clientes.

Dentro de una compañía con cultura de SP siempre será muy atractivo usar procedimientos almacenados. Es muy fácil realizar cambios sobre un SP sin tener que modificar ningún código compilable como Java o .NET. Sin embargo notarás que, cuando se encuentra abierta la puerta de los Procedimientos Almacenados, con el paso del tiempo la base de datos se llenará y se llenará cada vez más de lógica de negocio. Será como una bomba de tiempo. Tarde o temprano la performance de la base de datos disminuirá y nadie sabrá por qué. Y será así por el hecho de que al motor de base de datos se le ha adicionado una responsabilidad para la que no fue construido: la de servidor de aplicaciones. Alguien dirá: Escalémoslo. Averigua lo que significa escalar un motor de base de datos. No es simple ni barato. Desgraciadamente las bases de datos no responden al Scale Out tan bien como al Scale Up. Es decir, tú puedes obtener grandes cambios al mejorar la máquina donde se ejecuta tu motor de base de datos, pero no tendrás cambios significativos si agregas más máquinas.

Y esto último es precisamente una de las mayores ventajas de tener una capa intermedia de acceso a datos bajo una arquitectura como SOA, COM+ o EJB por ejemplo. Estos tipos de arquitectura sí aprovechan al máximo la escalabilidad horizontal, o sea, mientras más máquinas mejor, aunque sean de mediano poder.

¿Mi consejo final? Si desarrollas desde cero una aplicación usa un proveedor de persistencia que implemente el patrón Object Relational Mapping y ojalá también el ActiveRecord (Ejemplos: Hibernate, iBatis, Active Castle, todos con sus versiones tanto para Java como para .NET). Evita los procedimientos almacenados excepto en los casos de consultas SQL complejas y lentas de ejecutarse. Por otro lado, si desarrollas una aplicación dentro de un contexto donde se facilita, se incentiva o hasta se obliga el uso de Procedimientos Almacenados, úsalos únicamente para funciones CRUD (Create, Read, Update y Delete). No pongas por favor lógica de negocio dentro de ellos.