Ways to make your gem less useful

  • Have as many dependencies as possible. Implement dozens of questionably useful features with mandatory dependencies, with no way to opt out of using them. Bonus points if your dependencies are on specific gem versions or on gems with native extensions.
  • Couple as closely as possible with network/protocol/infrastructure libraries (Net::HTTP, EventMachine, aws-s3, Active Record) as possible. If some jerk wants to use another HTTP library, they can just fork themselves.
  • A domain-specific language is the only acceptable interface for a gem to expose. There is nothing more elegant than forcing your users to resort to metaprogramming to bypass your own metaprogramming.
  • Your library’s public API should be limited to whatever you can document in a blog post or README. This applies regardless of whether your library includes one, five, or fifty classes — only one or two of them should ever be documented.
  • Monkey-patch everything in sight. Need to do some URI generation? Well, slap five or ten methods on the URI class. Nobody else had that idea, either, so you’re free to choose a method name like #generate or #build.
  • Unambiguous module names are for Java programmers. If you’re making a library for working with XML, make your top-level module ‘XML’. If your users want to use another library with that same top-level module, it should work. Maybe. If it doesn’t, it’s their fault for doing something so stupid. Or using another gem which depends on it.

The last one here actually caused me a great deal of grief some time ago. In short, we had two different gems we depended on which each depended on a different XML parsing library (libxml-ruby and XMLParser). Both libraries had actually fixed their ambiguity issues in the past — both had started under XML::, and both later changed this. The problem was that libxml-ruby still kept an XML:: backwards compatibility layer around, and a third gem tried to monkey-patch XML::Parser thinking that it was LibXML::XML::Parser, while it was actually XMLParser.

This took some really ugly work with undef in config/environment.rb to resolve. This was pre-Bundler, of course. I don’t think there would be any way to resolve it with Bundler, actually.