Bulky, heavy, fat ORMs

Arseni Mourzenko
Founder and lead developer
176
articles
December 31, 2017
Tags: productivity 36

A long time ago, I wrote the fol­low­ing in the de­scrip­tion of Or­seis.

I nev­er liked ORMs. They are bulky, heavy, fat. They build SQL queries be­hind my back, and I don't like it. I want to be in con­trol.

Re­cent­ly, a per­son asked on SE.SE how is it pos­si­ble that we still write SQL by hand, de­spite the pres­ence of lots of very ca­pa­ble ORMs. An in­ter­est­ing as­pect in this ques­tion is the com­par­i­son with oth­er do­mains where de­vel­op­ers rely heav­i­ly on an ab­strac­tion lay­er: in gen­er­al, one doesn't send an e-mail by play­ing with SMTP, and doesn't write web ap­pli­ca­tions by pro­cess­ing raw HTTP.

This leads to a sub­ject of ab­strac­tions: what do they bring, how do they leak, and what it means for busi­ness. Al­low me to start with a short sto­ry which has noth­ing to do with ORMs: my ex­pe­ri­ence with ASP.NET Web­Hooks li­brary.

A few months ago, I was con­tribut­ing to an API which need­ed to re­ceive some events from the un­der­ly­ing API. Web­Hooks be­ing a hype, it was de­cid­ed to use them for the task, and since the API uses ASP.NET Web API, any­thing with “ASP.NET” in its name was a manda­to­ry choice any­way. So I strug­gled with ASP.NET Web­Hooks for a week be­fore re-im­ple­ment­ing a large part of the func­tion­al­i­ty we need­ed by hand.

From there, it ap­peared that:

This is an ex­cel­lent ex­am­ple of a harm­ful ab­strac­tion. It pre­tends to sim­pli­fy things, and it ac­tu­al­ly does as soon as you stay with­in its lim­its—with­in the area the ab­strac­tion was ex­plic­it­ly de­signed for. With­in this area, it saves you time, and a lot of time. Hours of work writ­ing code which doesn't nec­es­sar­i­ly have enough tests to be re­lied upon, you write two-three lines of code, and that's it; it works, flaw­less­ly. How­ev­er, as soon as you need some­thing else, the ab­strac­tion harms you and makes you waste days or weeks, or sim­ply makes it im­pos­si­ble to do what you want.

This phe­nom­e­non is glob­al, and prac­ti­cal­ly every li­brary or frame­work has this flaw. Help­ing a team who uses An­gu­lar, I'm of­ten sur­prised that they pre­fer to have a poor user in­ter­face, be­cause do­ing oth­er­wise would of­fend An­gu­lar. If a choice of a frame­work means that I can't do cer­tain things I can do with a dozen lines of code with jQuery, I say: “throw the frame­work.” Users mat­ter more than frame­works.

Every ab­strac­tion could short­en the amount of time it takes to de­sign a part of soft­ware, and make it longer to de­sign oth­er parts. Take a sim­ple ex­am­ple. Green bars in­di­cate the time it takes to de­vel­op six parts of a soft­ware prod­uct with­out us­ing a spe­cif­ic frame­work or li­brary. Blue bars show the time it takes to de­vel­op the same parts while us­ing the frame­work or li­brary.

Any suc­cess­ful sales­man would em­pha­size how the li­brary helps with the part E. It's fan­tas­tic: with the help of the li­brary, in­stead of spend­ing time de­vel­op­ing all the stuff your­self, you just write a line of code and, mag­i­cal­ly, it works.

The same sales­man won't men­tion any­thing about the parts A and C which takes much more time, but where the li­brary doesn't help. And, ob­vi­ous­ly, he will stay silent on the neg­a­tive con­se­quences of the li­brary on the parts B, D and F. But if you do the math, it ap­pears that the li­brary is maybe not that fan­tas­tic af­ter all:

Agreed, it saved you time be­cause you didn't have to de­vel­op the part E, but over­all, you spent more time adapt­ing the prod­uct to this li­brary. Not nice.

There are sit­u­a­tions where a giv­en li­brary only wastes your time. My ex­pe­ri­ence with ASP.NET Web­Hooks is ex­act­ly that: days in­stead of hours of work. Sev­er­al fac­tors could cause that. In some rare cas­es, it comes from poor­ly writ­ten, poor­ly doc­u­ment­ed li­braries. More fre­quent­ly, it comes from the in­ad­e­qua­cy be­tween the tasks the li­brary is de­signed for and the con­text where the li­brary is used. This is why it is es­sen­tial for the au­thors of a li­brary to be very spe­cif­ic about the li­brary lim­its. This is ex­act­ly what I did when re­leas­ing the nicecall li­brary:

Note that nicecall is not a sub­sti­tute to subprocess, be­cause much of subprocess func­tion­al­i­ty doesn’t ex­ist. For in­stance, one can’t use stdin or pipes with nicecall. The goal is not to re­place subprocess, but only to pro­vide an easy way to do the most com­mon tasks.

In the same way, the au­thors of ASP.NET Web­Hooks li­brary should have spec­i­fied that the li­brary is good to re­ceive no­ti­fi­ca­tions from GitHub or Azure, but is a poor choice for any­thing out­side the very ba­sic cas­es. Ob­vi­ous­ly, many au­thors of li­braries are re­cal­ci­trant to put clear in­for­ma­tion about the li­brary scope, be­cause of a sales­per­son men­tal­i­ty.

How a li­brary or a frame­work would im­pact your soft­ware prod­uct de­pends on hor­i­zon­tal and ver­ti­cal ad­e­qua­cy and on hor­i­zon­tal and ver­ti­cal cost.

We would all pre­fer deal­ing with ab­strac­tions which have a large hor­i­zon­tal and ver­ti­cal ad­e­qua­cy (i.e. they have all we need, and do it great), and no hor­i­zon­tal and ver­ti­cal cost (i.e. they don't con­strain us in the parts of the ap­pli­ca­tion where we don't need those ab­strac­tions and they are easy to set up). But more of­ten than not, ab­strac­tions tend to be cost­ly, and bring ques­tion­able ben­e­fits in nar­row sit­u­a­tions.

What does all that have to do with ORMs?

ORMs have a small hor­i­zon­tal cost but a con­sid­er­able ver­ti­cal cost.

As for their ad­e­qua­cy:

I would love an ORM which could fig­ure how to store the data, be able to cross the bound­aries of SQL and move to data­bas­es such as Mon­goDB or Re­dis as well. I would love it to an­a­lyze the data and the re­quests and de­ter­mine how the schema should be op­ti­mized based on the cur­rent us­age. I would love sim­ply telling: “Hey, ORM, please store this ob­ject for me” or “Hey, ORM, could you tell me all the records of this type for the last two weeks” and nev­er have to look un­der the hood. Un­for­tu­nate­ly, this isn't hap­pen­ing soon.

What hap­pens soon is that ORMs stay among the great tools which do a great job in spe­cif­ic sit­u­a­tions, for spe­cif­ic pro­jects. As I don't de­vel­op in As­sem­bler, be­cause Java or Python com­pil­ers do a much bet­ter job for me, I hard­ly see my­self writ­ing SQL by hand for an or­di­nary busi­ness ap­pli­ca­tion. But there are cas­es where you need to dive into As­sem­bler be­cause you need spe­cif­ic per­for­mance op­ti­miza­tions, and there are cas­es where you need to write SQL by hand. Dur­ing my ca­reer, it ap­peared that none of my pro­jects led me to write As­sem­bler code, and that near­ly every pro­ject I did led me to hand-made SQL. Pos­si­bly de­vel­op­ers work­ing on em­bed­ded soft­ware do use As­sem­bler and don't write SQL. YMMV.