Shortcut Shortcuts

by Dave Kennedy

Matz recently tweeted a cartoon “Java vs Ruby vs PHP” and stated that he preferred the PHP way. I smirked and agreed, was about to move on with my life but paused as memories of when I began writing Ruby code came flooding back. I wrote a lot of PHP at that time and had exactly that attitude.

java vs. ruby vs. php

When deciding to learn Ruby, one of the big draws were Gems. The promise of all the functionality, effort and complexity removed into a single bundle install (rake gems:install in my day) was nothing short of intoxicating. It certainly played a big part in my decision to seek gainful employment writing Ruby over PHP.

So why the smirk when I read the tweet? Recently in the 1partCarbon offices we have strived to keep our Gemfiles slim. Favouring explanations over abstractions. 

I’ll address the Rails contradiction right now. It’s a gem with many dependancies, but more often than not on ruby projects Rails is the framework we go with. Rails is so popular as a framework for web applications that almost any developer with any Ruby background will be able to understand any Rails based application at a high level. It has its own conventions and structure which are sensible enough and more importantly will be familiar. Not all gems can go toe to toe with that. Even gems which I had previously thought to be equally universal such as RSpec, Devise and FactoryGirl get the heads of novice Rails developers scratching.

A common (and perfectly legitimate) argument of being pro-gems is that you gain expert knowledge in a particular domain instantly. With the greatest respect I’ll never know the author/contributors qualifications or experiences to class them as experts. I can accept the author(s) will have more knowledge than I do in a particular problem area at the time of my research, but their domain will never be my application or my customer's problem. It may be similar, but never the same. Only I will have the context of the problem at hand which always has more weight when deciding experts.

When the conundrum of “Should I add this gem?” occurs I make a mental checklist of the following:

  1. Does the gem in question require any kind of configuration?
  2. Do I use the gem via a Domain Specific Language (DSL)?
  3. Do I understand the problem?

The first two are a quick triage to weed out weak choices. Gems which require extra configuration are usually abstractions for a particular problem which then offer switches of functionality. Devise is such a gem. In fairness the generators which ship with Devise are pretty comprehensive and the configuration options are well documented. However, it also tells me that I am incorporating extras into my application. I may use some of it further down the line, I may never, who is to know? The fact is I have the potential of not using some part of the gem or worse need something that the gem doesn’t do and that is what I will have to live with.

The DSL question is usually one which I look for an alarm bell to be set off. If you have been doing it a while, writing Ruby code is simple enough. Understanding a problem and solving it using the tools to hand is the hard bit. Having to learn a DSL which then poses the risk of other developers not understanding your code because they have never used a particular gem before is always too great in my opinion. DSL’s are simple enough to write in Ruby and usually added as sugar to a gem. If anyone is going to be writing DSLs, it’s going to be me. Get off my lawn!

The third question is the “step back” moment. Do I really need this? Could I write it myself? 

I recently had the problem of measuring the distance between 2 geographic coordinates. I could have easily dropped in the Geocoder gem which has a calculations library that fitted my needs. 

It pretty much passed “Does the gem require any kind of configuration?”. Geocoder does take third party map API (google, Bing etc.) configuration, but I wouldn’t have needed that. 

Geocoder has a small DSL for ActiveRecord integration which I also wasn’t using so it made it through the “Do I use the gem via a DSL?” question. 

By the third question I already had some doubts as there was a lot in the gem I wasn’t using. I understood the problem clearly. I didn’t know the math but a web search and some tests would give me all I needed to know. Ultimately I knew adding `Geocoder` would not have been a good choice.

I should say by no means am I picking on Geocoder in this example, it's a fantastic, well written gem. I have used it with great success in the past and it was the only reason I knew it had the calculations library included. It just felt “too much” for the particular problem.

Previous to Ruby, the only third party code I was regularly exposed to was libraries. Coming from a C background this meant universal truth types of libraries such as device drivers and control algorithms. Things that I could have potentially written myself but would have been wasteful and/or risky to do so. There are few gems out there which I feel the same way about. BCrypt and database adapters (mysql2, pg etc.) are all gems which I am happy to add to any Gemfile when needed.

In closing, I recommend adding gems sparingly to your applications. By all means look at the popularity of the gem, who wrote it and best of all check the source. In my experience gems are something you have to live with well into the maturity stage of a project and it is a decision not to be taken lightly.

Dave Kennedy

Dave Kennedy

Dave is a developer from sunny Glasgow where he organises the local JavaScript meetup. Loving languages like Ruby, JS, PHP he has a lot of experience in web software applications. Motorbikes and code are the only other thing that gets Dave out of bed in the morning. Star Sign: Scorpio, Fave Colour: #14FF3F