Minimizing Library Dependencies - slides for presentation at Rails Meetup in Stockholm 2010-10-25
Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
assets
bin
config
content
filters
post_processors
script
templates
.gitignore
README
Rakefile

README

############################################################################################
### MINIMIZING LIBRARY DEPENDENCIES
############################################################################################

These are my slides for a presentation held at the Rails Meetup in Stockholm on October 25:th
2010, see: http://rails.se/rails/show/SHRUG+25+Oktober+2010

############################################################################################
### NOTES
############################################################################################

h1. Weighing In At
Ruby developers are in the mindset of minimizing lines of code. For some reason they tend to apply this to their application but not to libraries.
Rails Library Creep. A cousin of Feature Creep and Software Bloat. Ironic. Aren't we supposed to be lean?
We Ruby developers are supposed to be lean and simple. Less is more, right?
Libraries Accumulate and can Become a Liability Over Time

h1. Library Smells
How do you decide if to use a library? How do you evaluate libraries? Like other code, since after all, libraries are code. How do you evaluate code?
How many different XML, JSON, etc. parsers do you end up with?
Review your libraries and understand them! Libraries cannot be treated as a black box. They are too tightly coupled with the rest of your system.
Version incompatibility is a message like: "can't activate , already activated gherkin-2.2.0"
"warning: HTTParty depends on version 0.1.7 of crack, not 0.1.6"
Intertwining, when everybody talks to everybody.
Convetions, Idioms, and Consistency: Always make HTTP requests the same way, Always parse JSON the same way, Always implement state machines the same way, Always do pagination the same way
We are lured by the magic of the libraries and their pretty DSLs. and by short term productivity boosts. Model macros - has_amazing_feature.
Search engine upgrades
Treating libraries as black boxes doesn’t really work so well in Rails land.
A typical Rails library is developed quickly (over night) by a single Rails developer in his free time, then further developed and maintained for a couple of months, then mostly abandoned, sometimes forked if it’s popular. A typical library is highly coupled to Rails. The library landscape is messy.
Example: globalize2 - globalize2_hacked
Can you maintain it?

The Ruby web development landscape has gotten a lot more diversified over the last five years. There used to be only two popular books (AWR and the Pickaxe). Now there are hundreds. There used to be one Ruby interpreter, now there are several. There used to be only one major Rails version, now there are three. There used to be few alternatives to Rails, now there are many other popular frameworks. Everybody used to use RDBMS databases, now NoSQL databases are all the rage. A typical Rails system used to be a single simple app, now service oriented architectures with several apps are popular.

h1. Advantages to Rolling Your Own
You have less code because you only write code you need.
Model layer independent of the framework (Rails)? Independent of the persistence layer? Why should your business logic depend on Rails? 
Libraries that are coupled and have a lot of dependencies don’t age well.
The fewer dependencies your code has, the longer it can live.
Can you install your app anywhere? A dependency is a sort of binding.
Making it more difficult for a new Rails developer to take over and maintain your application.

h1. 1. Application Level Libraries (Engines)
I personally don't like having to look for application level stuff (controllers and views) outside the app.
Which levels in the stack belong in a library and which belong in your application? The engine discussion.

h1. 2. Libraries To Make Your App More DRY
Seems like a fairly legit category of libraries.

h1. 3. Wrapper Libraries (Ruby DSLs)
Ruby gems, especially Rails gems, tend to come and go like fashion.
Learning the underlying API has more lasting value.
Lack of conventions and consensus when it comes to libraries. Rapidly changing landscape. The rug being swept away under your feet.
Start by learning the underlying technology rather than the wrapping technology, the fundamentals. Lives longer.
Another advantage to using the underlying library is that you are in control of the version.
Ruby developers over optimize for pretty DSLs. You can have pretty DSLs without libraries. Underrated: writing your own application DSL.

h1. Specifying Version Dependency
A category 1 change (implementation detail) will increment the build number.
A category 2 change (backwards compatible) will increment the minor version number and reset the build number.
A category 3 change (incompatible) will increment the major build number and reset the minor and build numbers.
Example: httparty going from 0.4.3 to 0.6.0
Commit message: “Rolling back httparty to version 0.4.3 for compatibility with Clicky API (don't ask)”
The approach Rails takes.

h1. Look at all the libs I'm Not Installing
The s3_swf_upload story. Forked first to get rid of aws-s3 dependency. Then ripped out only the one file needed from the library. Mostly a generator. Had Ruby patch example 32 bit Integer shift. Was not Ruby 1.9.2 compatible. Then replaced hundreds of lines
with a one-liner that was Ruby 1.9.2 compatible and got rid of the gem.
FasterCSV example - not needed in Ruby 1.9.2!
Examples of use of global variables (s3_swf_upload, logworm_amqp)
The fog library in turn depends on: excon, formatador, net-ssh, and nokogiri.
Alternative to carrierwave: @brand.bucket.put("test-thumb.png", params[:thumb_image].open)
MiniMagick is a light weight alternative to RMagick. Here is a light weight alternative to MiniMagick:
identify mag-plus/popular-photo/thumb_com.bonnier.magplus.PPHiTune001D.PPH1110D.20101014-20.png
=> mag-plus/popular-photo/thumb_com.bonnier.magplus.PPHiTune001D.PPH1110D.20101014-20.png PNG 80x80 80x80+0+0 8-bit DirectClass 13.5kb
rsolr (492 LOC) - sunspot (6889 LOC) - sunspot-rails (1237 LOC)
httparty (903 LOC) - crack (1073 LOC)
logworm_amqp is not Ruby 1.9.2 compatible. It made my Gemfile.lock grow from 108 146 lines! See content/logworm_amqp.diff.
I started depending on JSON without realizing that dependency was only there because of logworm.

############################################################################################
### REFERENCES
############################################################################################

* "Feature creep":http://en.wikipedia.org/wiki/Feature_creep
* "Software bloat":http://en.wikipedia.org/wiki/Software_bloat
* "
Using >= Considered Harmful (or, What’s Wrong With >=)":http://yehudakatz.com/2010/08/21/using-considered-harmful-or-whats-wrong-with
* "Semantic Versioning":http://semver.org
* "RubyGems Versioning Policies":http://docs.rubygems.org/read/chapter/7