¿Cómo sugerir usar un ORM en lugar de procedimientos almacenados?

31

Trabajo en una empresa que solo usa procedimientos almacenados para todo el acceso a datos, lo que hace que sea muy molesto mantener nuestras bases de datos locales sincronizadas como cada confirmación que tenemos para ejecutar nuevos procs. He usado algunos ORM básicos en el pasado y encuentro la experiencia mucho mejor y más limpia. Me gustaría sugerirle al gerente de desarrollo y al resto del equipo que analicemos el uso de un ORM de algún tipo para el desarrollo futuro (el resto del equipo solo está familiarizado con los procedimientos almacenados y nunca ha usado nada más). La arquitectura actual es .NET 3.5 escrita como .NET 1.1, con "clases de dios" que usan una implementación extraña de ActiveRecord y devuelven conjuntos de datos sin tipo que se agrupan en archivos de código subyacente; las clases funcionan de la siguiente manera:

class Foo { 
    public bool LoadFoo() { 
        bool blnResult = false;
        if (this.FooID == 0) { 
            throw new Exception("FooID must be set before calling this method.");
        }

        DataSet ds = // ... call to Sproc
        if (ds.Tables[0].Rows.Count > 0) { 
            foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
            // other properties set
            blnResult = true;
        }
        return blnResult;
    }
}

// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...

Prácticamente no hay aplicación de ningún patrón de diseño. No hay pruebas de ningún tipo (nadie más sabe cómo escribir pruebas unitarias, y las pruebas se realizan cargando manualmente el sitio web y hurgando). Mirando a través de nuestra base de datos tenemos: 199 tablas, 13 vistas, 926 procedimientos almacenados y 93 funciones. Aproximadamente 30 tablas se usan para trabajos por lotes o cosas externas, el resto se usa en nuestra aplicación principal.

¿Vale la pena seguir un enfoque diferente en este escenario? Estoy hablando de avanzar solo porque no se nos permite refactorizar el código existente ya que "funciona", por lo que no podemos cambiar las clases existentes para usar un ORM, pero no sé con qué frecuencia agregamos módulos nuevos. de agregar / arreglar módulos actuales, así que no estoy seguro de si un ORM es el enfoque correcto (demasiado invertido en procedimientos almacenados y conjuntos de datos). Si es la elección correcta, ¿cómo debo presentar el caso para usar uno? Fuera de mi cabeza, los únicos beneficios que puedo pensar es tener un código más limpio (aunque podría no serlo, ya que la arquitectura actual no es t construido con ORM en mente, por lo que básicamente estaríamos instalando ORM con jurado en futuros módulos, pero los antiguos seguirían usando los DataSets) y menos problemas para recordar qué scripts de procedimiento se han ejecutado y cuáles deben ejecutarse, etc. pero eso es todo, y no sé cuán convincente sería un argumento. La mantenibilidad es otra preocupación, pero por la que nadie excepto yo parece estar preocupado.

Wayne Molina
fuente
8
Parece que tiene más problemas que simplemente convencer al equipo para que use ORM. Me parece que su equipo no conoce algunas buenas prácticas de desarrollo (es decir, patrones de diseño, pruebas unitarias). Estos son problemas más importantes que debe abordar.
Bernard
66
Irónicamente, creo que en unos 5 años de desarrollo solo he conocido a un puñado de personas / equipos que conocían cosas como patrones de diseño y pruebas unitarias; Por lo general, soy el único hombre de la compañía que sabe de esas cosas.
Wayne Molina
3
@Wayne M: Me parece un poco inquietante, pero tampoco estoy sorprendido por esto.
Bernard
2
Lo he encontrado muy ... descorazonador. Es extraño cuando sugieres algo y obtienes una apariencia de "venado en los faros" que indica que la otra persona no tiene la menor idea de lo que estás hablando o por qué alguien consideraría hacerlo. He tenido que pasar varias veces en el pasado.
Wayne Molina
2
Soy un gran admirador del Procedimiento almacenado, por lo que mi comentario es parcial, pero estoy completamente en desacuerdo con toda la premisa. Te gusta ORM y quieres usar esto, está bien. Sin embargo, el resto del equipo está bien con los procedimientos almacenados. ¿Por qué obligarlos a lo que te gusta?
Darknight

Respuestas:

47

Los procedimientos almacenados son malos, a menudo son lentos y aproximadamente tan eficientes como el código ordinario del lado del cliente.

[La aceleración generalmente se debe a la forma en que el cliente y la interfaz del procedimiento almacenado están diseñados y la forma en que las transacciones se escriben como ráfagas cortas y enfocadas de SQL].

Los procedimientos almacenados son uno de los peores lugares para poner código. Divide su aplicación en dos idiomas y plataformas de acuerdo con reglas que a menudo son aleatorias.

[Esta pregunta será rechazada para tener un puntaje de aproximadamente -30 porque muchas, muchas personas sienten que los procedimientos almacenados tienen poderes mágicos y deben usarse a pesar de los problemas que causan.]

Mover todo el código de procedimiento almacenado al cliente facilitará mucho las cosas para todos.

Todavía tendrá que actualizar el esquema y el modelo ORM de vez en cuando. Sin embargo, los cambios de esquema están aislados de los cambios de ORM, lo que permite cierta independencia entre las aplicaciones y el esquema de la base de datos.

Podrá probar, corregir, mantener, comprender y adaptar todos los procedimientos almacenados a medida que los reescribe. Su aplicación se ejecutará de la misma manera y se volverá mucho menos frágil porque ya no se está dividiendo en dos tecnologías diferentes.

Los ORM no son mágicos, y las buenas habilidades de diseño de bases de datos son absolutamente esenciales para que funcione.

Además, los programas con una gran cantidad de SQL del cliente pueden volverse lentos debido al mal pensamiento sobre los límites de las transacciones. Una de las razones por las que los procedimientos almacenados parecen ser rápidos es que los procedimientos almacenados obligan a un diseño muy, muy cuidadoso de las transacciones.

Los ORM no fuerzan mágicamente un diseño de transacción cuidadoso. El diseño de la transacción aún debe realizarse con el mismo cuidado que cuando se escribían los procedimientos almacenados.

S.Lott
fuente
19
+1 porque los procedimientos almacenados son un dolor total para trabajar
Gary Rowe
3
: '(No tengo ningún problema con los procedimientos almacenados. Es solo otra capa de abstracción para mí.
Mike Weller
3
Si creamos SP, el motor de base de datos lo almacena como un formulario compilado y crea una ruta de ejecución para que se ejecute lo más rápido posible. Pero ORM envía SQL cada vez que necesita ser compilado y ejecutado por un motor de base de datos. Creo que será más lento usar un ORM en lugar de un Procedimiento almacenado.
DeveloperArnab
44
Gracioso. Cambiamos de un ORM a procedimientos almacenados solo por ... VELOCIDAD. No es la cantidad de tiempo que necesitamos para programar, sino el tiempo que un ORM necesita para cosas como materializar objetos, buscar un objeto, actualizarse en diferentes clientes. SP donde mucho más rápido. Un ejemplo: leer 30,000 objetos de DB con un nuevo ORM moderno necesita ... oh, bueno. tiempo de espera después de 2 minutos. Llamar al procedimiento almacenado y obtener el resultado: 2 segundos. Sí - existen muchos trucos como paginación para reducir callign a mucho de un DB - pero gran diferencia si son simplemente un ORM que se puede utilizar o para
Offler
2
@DeveloperArnab: Eso puede haber sido cierto hace 20 años, pero los motores DB modernos son bastante sofisticados y pueden reconocer consultas ejecutadas previamente y reutilizar planes de ejecución, la diferencia de velocidad hoy en día es tan leve que apenas justifica la molestia adicional de los SP.
whatsisname
20

Los procedimientos almacenados son buenos, son rápidos y muy eficientes y son el lugar ideal para colocar su código relacionado con los datos. Mover todo ese código al cliente hará que las cosas sean un poco más fáciles para usted como desarrollador del cliente (un poco, ya que aún tendrá que actualizar el esquema y el modelo ORM cuando commit los cambie) pero perderá todo ese código existente y hará su aplicación es más lenta y probablemente más frágil teniendo en cuenta la pérdida de todas esas habilidades sql.

Me pregunto si los DBA están sentados allí diciendo "oh, cada confirmación, tengo que retirar el cliente nuevamente, deberíamos mover todo el código a los formularios de base de datos".

En su caso, debería poder reemplazar el ORM personalizado existente (es decir, sus clases divertidas) con el de otra persona sin ninguna pérdida, excepto los cambios en la forma en que se escribe el código subyacente. También puede mantener los SP como la mayoría (¿todos?) ORM los llamará con gusto. Por lo tanto, recomendaría reemplazar esas clases "Foo" con un ORM y continuar desde allí. No recomendaría reemplazar sus SP.

PD. Parece que tiene mucho código común en las clases de código subyacente, lo que los convierte en un patrón de diseño en sí mismos. ¿Qué crees que es un patrón de diseño en primer lugar? (ok, puede que no sea el mejor, o incluso uno bueno, pero sigue siendo un DP)

Editar: y ahora con Dapper , cualquier razón para evitar sprocs sobre un ORM de peso pesado se ha ido.

gbjbaanb
fuente
3
+1, el primer paso obvio es pasar a un ORM y usarlo para asignar los resultados de los procedimientos almacenados existentes a los objetos. Deshágase de toda esa ds.Tables[0].Rows[0]["FooName"].ToString()basura. Gerente ama los procedimientos almacenados? Él se las queda. Pero sería físicamente imposible argumentar que mover todo ese repetitivo código repetitivo a algo generado por, por ejemplo, LINQ to SQL, fue algo malo.
Carson63000
11
Bueno, no puedo creer cuánto "mal" hay en tu publicación. Su comparación con un DBA quejándose de tener que extraer el código es inapropiada y completamente insensata. En primer lugar, la base de datos es un SERVICIO destinado a almacenar y recuperar datos, al final de la historia. La LÓGICA, como su nombre lo indica, entra en la Capa de lógica de negocios, que es parte del código API. ¿La aplicación más frágil se está alejando de los sprocs? ¿Hablas en serio o solo estás trolleando? TDD una aplicación con lógica en sprocs y dime cuán divertido es eso. Además, los ORM no deben cambiarse. Las bases de datos son, ya que son solo un SERVICIO.
Matteo Mosca
55
Realmente no puedo entender por qué algunas personas piensan que la base de datos es una especie de tierra santa donde todo es sagrado. Piensa sobre esto. Cuando una empresa externa le expone un servicio, ¿le dan acceso directo a su base de datos o lo ocultan detrás de una API? Para usar un ejemplo popular, tome cualquier servicio de Google. Usted, desarrollador, se conecta a su API pública, ni siquiera sabe qué base de datos hay debajo, o si hay una base de datos. Así es como diseñas un software sólido y desacoplado. Las bases de datos no están destinadas a ser accedidas directamente por las aplicaciones. Los niveles medios están ahí para eso.
Matteo Mosca
55
@Matteo Mosca: claro, pero ¿cómo accede el middleware a la base de datos? ... es un cliente de la base de datos. "cliente" no significa "GUI" o "aplicación de escritorio". Hay muchas áreas grises en los niveles de aplicación: ¿coloca la validación en la GUI o en la lógica empresarial / del servidor? Debe ir en el servidor para ser un diseño limpio, pero eso será realmente pobre para el rendimiento y la capacidad de respuesta del usuario. Del mismo modo, a menudo pone algo de lógica en la base de datos cuando mejora el rendimiento y (en este caso) la corrección de los datos.
gbjbaanb
44
Lo siento pero aún no estoy de acuerdo. El día que tiene que implementar su aplicación en un entorno diferente, donde no tiene la misma tecnología de base de datos que usó, se encuentra en una situación en la que su aplicación no puede ejecutarse porque no tiene todos esos sprocs en la nueva base de datos .. e incluso si los recrea (lo cual es un dolor total) podrían ser diferentes, debido a las diferencias de los dialectos SQL, etc. Una API centralizada con lógica y validación, expuesta a través de un estándar (como SOAP o REST) ​​resuelve esto problema, y ​​agrega capacidad de prueba, versiones y consistencia.
Matteo Mosca
13

Parece que está tratando de llevar a su equipo de un extremo (procedimientos almacenados y conjuntos de datos) a otro (un ORM completo). Creo que hay otros cambios más incrementales que puede establecer para implementar para mejorar la calidad del código de su capa de acceso a datos, que su equipo podría estar más dispuesto a aceptar.

El código de implementación de registro activo a medio cocer que ha publicado no es particularmente elegante: recomendaría investigar el Patrón de repositorio que es fácil de entender e implementar, y es muy popular entre los desarrolladores de .NET. Este patrón a menudo se asocia con ORM, pero es igual de fácil crear repositorios usando ADO.NET simple.

En cuanto a DataSet's - ¡qué asco! Será mucho más fácil trabajar con sus bibliotecas de clases si devuelve objetos tipados estáticamente (o incluso dinámicos). Creo que esta ilustración explica mi opinión sobre DataSet mejor de lo que podría.

Además, puede deshacerse de los procesos almacenados sin saltar a un ORM; no hay nada de malo en usar SQL parametrizado. De hecho, definitivamente lo favorecería sobre el uso de procesos almacenados a menos que tenga procedimientos complejos que ahorren en múltiples viajes de ida y vuelta al servidor. Yo también odio cuando abro una base de datos heredada y veo una lista interminable de procedimientos CRUD.

No estoy desalentando el uso de ORM, generalmente los uso en la mayoría de los proyectos en los que trabajo. Sin embargo, puedo ver por qué puede haber mucha fricción al tratar de introducir uno en este proyecto y su equipo, lo cual, por decirlo amablemente, parece que dejaron de aprender cosas nuevas hace aproximadamente 8 años. Habiendo dicho eso, definitivamente echaré un vistazo a la nueva generación de "Micro ORM" como Dapper (utilizado para potenciar este sitio no menos) y Massive , los cuales son increíblemente fáciles de usar y lo mantienen más cerca del SQL que un ORM típico lo hace, y que su equipo podría estar más dispuesto a aceptar.

richeym
fuente
2
Creo que el problema es que cuando se escribió la aplicación, no había ORM reales notables para .NET, por lo que se hizo de la otra manera (la manera de ASP.NET 1.1), y nadie pensó en hacerlo de manera diferente (o cualquier otra cosa) de manera diferente hasta que me uní hace unos meses.
Wayne Molina
1
+1 para Dapper. Acabo de comenzar a usarlo en un proyecto y es extremadamente fácil de implementar y usar. Ya soy un gran admirador.
SLoret
4

Estoy en una situación similar, en realidad nuestro hardware, poder y política se inclinan hacia el lado de la base de datos, por lo que todo pasa por un procedimiento almacenado. Desafortunadamente, son un dolor para un codificador, especialmente cuando se trata de metadatos y generación de código, ya que no hay metadatos tan ricos en procedimientos almacenados como tablas.

De todos modos, aún puede escribir código elegante y limpio utilizando los procedimientos almacenados. Actualmente estoy implementando el patrón Repository con todos los procedimientos almacenados. Sugeriría buscar en FluentAdo.net su brillante idea al mapear desde el lector de datos a sus objetos comerciales. Tomé un pedazo de esa idea y la reutilicé para mi solución local.

Justin
fuente
3

JFTR: soy un humilde desarrollador de PHP, pero esto parece un problema predominantemente político.

Dada la escala de la "podredumbre" que apuntala la aplicación, entonces, aparte de las mejores prácticas , habría una sobrecarga significativa para erradicarla. Esto suena como si estuviera bordeando el territorio de reescritura.

¿Puede garantizar que la alternativa que sugiere produciría beneficios para justificar el costo para el negocio? Sospecho que el ROI de esta empresa puede ser difícil de vender al negocio. A menos que la aplicación sea inestable, o pueda probar el mérito de la revisión en términos financieros, esto podría resultar difícil.

¿Es ORM la única alternativa a SPROCS? Hay un par de patrones de diseño entre un ORM completo y SQL vanilla. Quizás pueda comenzar el proceso llevando estos SPROCS gradualmente fuera de la base de datos a una DBAL. Existe el peligro, por supuesto, de que esto se convierta en un ORM casero con el tiempo, pero habría dado un paso más cerca del objetivo.

sunwukung
fuente
2

Cambiamos de SP a ORM hace unos años.

En un caso tuvimos que actualizar 80 tablas. El antiguo modelo de estimación habría estimado 80 horas para esto con entlib y SP. Lo hicimos en 10 :)

Nos ha dado una reducción del 80% en la cantidad de tiempo que usamos para desarrollar la capa de acceso a datos.

Shiraz Bhaiji
fuente
1
¿Y por qué no pudo escribir la actualización de la tabla?
Darknight
Esto tomaba un objeto complejo en la memoria y lo guardaba como una base de datos relacional para informes. Escribimos un programa que hizo una reflexión sobre el objeto para crear la estructura de la tabla.
Shiraz Bhaiji
-1

Me parece más que el problema subyacente es que sus implementaciones no funcionan correctamente y de forma automática.

Puede ser más fácil configurar un motor de construcción continua que sepa cómo manipular las bases de datos según sea necesario después de cada confirmación.


fuente