There's a gem for this or how we got spoiled by the ecosystem
by Paweł Świątkowski
23 Mar 2016
Some time ago I was preparing to write yet another simple web app - listing craft beers available in a local bar (the list was being changed quite frequently, at least few times per week). As I suspected that people using the admin panel will be too lazy to enter all data about a beer (name, brewery, type etc.) in orderly manner, I was going to use some existing database to fetch the data. I evaluated Untappd and Rate Beer and decided to go with the latter.
Then, of course, I googled ratebeer api gem
…
Let me stop here for a moment. I suppose you might not see anything unusual here yet. Neither did I at the time. The realization came later. But let’s look at the requirements again. I needed, as you might guess, to find a beer by name and fetch information about it to my application. This is at worst two API calls (I believe it’s one, actually), yet I was this close to pull a full gem to my Gemfile (you can’t see it but I’m showing a very small distance with my fingers right now). As a bonus I’d probably get some dependencies or at least a bunch of classes I’d never use. The gem covers full API (user reviews etc.), I just needed one endpoint.
Ruby ecosystem is vast. It’s definitely not a bad thing, although obviously when quantity rises, quality usually falls down on average. But it is really great to have your problems solved by other people. It saves time, sometimes adds some kind of external support and we are just used to develop this way. Too much used, actually.
What if the gem did not exist? This is a common situation for me for example in D or Elixir, which do not have such wide variety of packages. I would have to write those two HTTP/JSON calls myself. Is it hard? No. Would it take much time? No. Would I have exactly what I need, without addition of users, ratings, reviews etc. which I would never use? Yes. You see where I’m going?
Instead of grasping existing solution, which might be bloated, badly designed or simply covering too much, consider for a while rolling out your own simple and to-the-point solution. This might save you from some unneeded dependencies, unused classes or simply an interface you don’t like. Mike Perham wrote excellent blog posts about cutting dependencies in gems you develop. This is the other side of the story: don’t bloat your app or you’ll hate yourself later.
The Gem Jar
There is a story circulating in the company I currently work for. One team set up a jar in their space. The rule was that every time you add a gem to any project’s Gemfile, you have to put 2€ in the jar. This is not much and you should not feel bad on giving up on this money when you really need the gem. But on the other hand, due to how human nature works, you are going to hesitate for at least a few seconds before doing it. And that might save you (and your team) some pain later.
So my advice: make your own gem jar. Of course if you work on your own it doesn’t make sense to invent the same rules. Subconciously you will still know that eventually you’ll spend the money on booze so there won’t be any psychological block connected with putting cash inside. Instead, donate it finally to charity. Or make 30 pushups. Or take your SO to the dinner. It does not need to (and should not, in fact) be unpleasant, but needs to show you that adding “just this little gem” has its consequences. Your future self will thank you.
Beware of NIH, though
Every story has its other side. In this case it’s Not-Invented-Here Syndrome. It basically means that you write everything by yourself, because you don’t trust solutions created by others. There might be various reasons behind that, but most of them can be summarized as bold statement that I can do it better. Guess what? You usually can’t.
I was in the project where a buttload of invented here solutions. Own background jobs, own mailing, own authentication and authorization, even own templating system. Creation of them at the time when decision was being made might have been justified. But few years later it meant for me: unsecure authentication, background jobs that scaled poorly, cumbersome templates etc. Suggestion to replace them with some established solutions usually met at least a hostile look, if not immediate decline.
The bottom line is that widely adopted solutions are usually widely adopted for a reason. You should not throw them away easily and decide to replicate their functionality with your awesome programming skills. This is like creating Yet Another JavaScript Framework, which would be awesome for one project, but probably unusable for every other. So while you evaluate the necessity to adopt a gem for your project, do not exaggerate in opposite direction. And especially, do not pull in the library that has eleven lines of code and won’t ever have more (update 2022: it actually has 17 now!).