El Blog de Trespams

Blog personal sobre tecnologia, gestió de projectes i coses que se me passen pel cap

Fer servir un ORM o no

Arrel del darrer post s'ha establert un nou fil relacionat amb la conveniència o no de fer servir un ORM en les nostres aplicacions quan l'sql directe pot ser més eficient. En Jan Carreres, el "responsable" d'aquest article fa una sèrie d'apreciacions que crec que donen per un nou post, més que res per poder mantenir la discusió en baix el seu propi concepte.

Així doncs acomodeu-vos al seient, que començam ...

Però què dimonis és un ORM

ORM són les sigles de Object Relational Mapping, és a dir, s'anomena ORM a aquella llibreria o procés que fa la conversió d'estructures de dades relacionals cap a estructures de dades orientades a objectes. És a dir, passam de fer feina amb taules i files a fer feina amb classes i instàncies d'aquestes classes. Passam de fer feina de camps a fer feina amb propietats dels objectes.

No hi ha una única aproximació als ORM. Christian Bauer i Gavin King al llibre Hibernate in Action, anomenen quatre característiques comuns a tot ORM:

  • Una API per executar operacions CRUD (Create, Retrieve, Update, Delete) en els objectes.
  • Un llenguatge o una API per especificar les consultes que fan referència a les classes i a les propietats de les classes.
  • Utilitats per especificar les metadades del mapeig entre el model relacional i el model d'objectes.
  • Una tècnica dins l'ORM per crear transaccions, fer assosicacions lazy i altres tipus d'optimitzacions.

A partir d'aqui la implementació de cada ORM potser completament diferent. Els autors, citant a Mark Fussel proposen la classificació dels ORMs en quatre tipus.

Purament Relacionals. L'ORM es construeix al voltant de la base de dades i es específic per a la nostra aplicació. Té l'avantatge que es pot optimitzar molt, però és difícilment portable entre bases de dades i presenta dificultats de manteniment. És típic d'aplicacions que tenen molta lògica dins la BD en forma de procediments amagatzemats.

Mapeig fi. Les entitats són representades com a classes i es mapegen manualment cap a les taules del model relacional. Un exemple d'aquest cas serien les aplicacions Java que fan ús del SQL/JDBC o bé en el cas de Python les que fan servir directament la DB-API de Python.

3. Mapeig mig. L'aplicació es dissenya al voltant del model d'objetes. És a dir, la base de dades és ara un suport per a la persistència dels objectes quan abans era gairebé la peça fonamental de l'aplicació. Aquest tipus d'ORM són especialment interessants quan l'aplicació té un tamany mitjà, amb transaccions complexes i sobretot quan la portabilitat entre bases de dades és un requeriment de l'aplicació.

4. Mapeig complet. S'hi arriba quan l'ORM suporta les característiques més importants i pròpies del model orientat a objectes: composició, herència, polimorfisme, ... i les implementa de manera transparent cap a la base de dades.

Si estam dins el món Java podríem dir que Hibernate està gairebé en el 4 d'aquesta classificació, Ibatis entre el 2 i el 3. En el cas de Python l'ORM de Django estaria començant a entrar en el 4 i SQLAlchemy estaria fregant el nivell d'Hibernate.

Per què fer servir un ORM

Per començar dir que un ORM no és una excusa per no saber SQL. Quan un fa feina amb aplicacions de bases de dades relacionals s'ha de conèixer al manco l'SQL estàndard, tenir molt clars els conceptes de taula, registre, selects, unions, claus primàries, etc. Es dóna per suposat que el tema de la normalització ja ho tenim ben clar.

El que fa un ORM és facilitar-nos la vida. Quan la nostra aplicació ja no es trivial, sinó que fa un ús intensiu de consultes, manipulacions de resultats, insercions, ens trobarem repetint una i una altra vegada el procés de conversió dels nostres objectes cap a sentències SQL. L'ORM fa tota aquesta feina per nosaltres, així que una de les raons més importants per a fer servir un ORM enlloc de sentències SQL a pèl per la nostra aplicació és la productivitat i evitar el DRY al llarg de la nostra aplicació.

Fer servir un ORM implica escriure menys codi nosaltres mateixos i sovint que el codi que hem escrit sigui més bo de llegir. Això es tradueix en una millor mantenibilitat de l'aplicació. Jan diu que si un es dedica a fer apliccions de BD ha de conèixer l'SQL i és veritat, però no té per què tenir a la ment tots els camps que hi ha a la taula. Imaginem-nos un entorn amb molts programadors fent feina a la mateixa aplicació. Aplicació amb moltes taules i amb taules amb molts de registres. Picant SQL a pel és tenim molts números de deixar-nos un camp a l'hora de fer una consulta. L'ORM manté la llista de camps per nosaltres, quan accedim a un objecte el ja se n'encarrega de fer les selects oportunes a la base de dades i obtenir-ne tots els camps.

Encara que hi ha casos en que escriure el codi SQL directament pot significar un guany considerable en el rendiment d'una consulta concreta, el més habitual és que l'ORM que facen servir ja tengui considerat dins la seva estructura les optimitzacions més habituals, de manera que l'sql que es genera pot ser fins i tot més eficient que el que generaríem a mà. Pensar que nosaltres sempre generarem millors sentències SQL és si més no agoserat, i per mi representa una optimització prematura. L'avantatge de productivitat i mantenibilitat que ens dóna l'ORM és el que s'ha de considerar primer. Després sempre hi som a temps d'optimitzar, però els nostres esforços s'han de concentrar en aquelles consultes o accions que torben més temps o que s'executen més sovint. És a dir, l'ORM i l'augment de productivitat que implica ens permet guanyar temps i poder optimitzar allà on interessar realment.

Molt relacionat amb tot això ens trobam la navegabilitat. La navegabilitat que ens permet el model orientat a objectes és d'aquelles coses que xoquen més amb el que ens proporciona el model relacional. Els ORM permeten navegar entre les associacions d'objetes de manera transparent, generant les sentències necessàries i sovint permetent-nos optimitzar aquesta navegabilitat, els select_related de Django n'és un exemple, o les cachés d'Hibernate. Pensem amb el senzill que és posar un objecte dins una plantilla i anar accedint a les seves propietat, anar fins a la propietat que representa una clau forana de la base de dades, fer-ne referència i obtenir-ne les propietats de l'objecte associat. Ara pensem en la quantiatat de codi SQL que ens hem estalviat.

I finalment l'altra gran motiu per fer servir un ORM és el d'independitzar-nos de la base de dades. Podria parèixer que quan un coneix SQL ja pot fer anar qualsevol base de dades, però realment això no és així, cada BD té petites diferències en la implementació de l'SQL que fan que sovint el codi SQL no sigui directament portable entre bases de dades. Un ORM crea una capa d'abstracció entre la nostra aplicació i la base de dades, generant i utilitzant les sentències SQL més adients a cada una.

L'argument que "un tria una BD i l'utilitzes sempre" per la meva experiència passa poc. Una empresa gran pot triar Oracle, però segurament per motius de cost algunes aplicacions les voldrà amb un altra BD. Si comercialitzam una aplicació limintar-nos a una base de dades concreta limita les possibilitats de comercialització. Fent servir un ORM podem desplegar la nostra aplicació contra diferents clients i fins i tot contra diferents versions d'una base de dades.

Resistir la temptació

Quan un comença a programar aplicacions de gestió és difícil resistir la temptació d'optimitzar-ho tot, d'escriure sql a pel optimitzant-ho per la nostra base de dades, és cert, però resistiu!

Si feim sql a pel a poc que l'aplicació creix el procés serà el seguent:

Ens adonarem que tenim sql repartits per tot. Així que farem una refactorització i posarem tot l'sql dins un sols arxiu que contindrà totes les funcions.

Després ens adonarem que aquest arxiu té molt de codi repetit, feim sempre la conversió de taules a objectes i ho refactoritzarem per a no repetir codi.

Després ens adonarem que feim sovint les mateixes consultes i que també es pot refactoritzar.

Seguirem i seguirem refactoritzant....

Al final acabarem amb un ORM del tipus 2 que ens haurà duit una feinada en refactoritzacions i que no té encara els avantatges d'un ORM del tipus 3 ó 4.

Costa resistir la temptació, fa peresa estudiar una llibreria d'ORM, però pensem que probablement el camí que seguirem serà aquest i s'ho paga l'esforç inicial.

blog comments powered by Disqus