[Rubygems-developers] What is right and wrong with dependencies definitions?

Chad Woolley thewoolleyman at gmail.com
Sat Nov 10 14:26:00 EST 2007

On 11/9/07, Eric Hodel <drbrain at segment7.net> wrote:
> On Nov 9, 2007, at 16:08 , Chad Woolley wrote:
> > I don't want to force everyone who uses it
> > to install the dozen-plus build- and deploy- and test-time
> > dependencies I have.  This
> > would freak some people out when they installed it and make them not
> > want to use the gem.
> I've installed things that easily have more dependencies than that.
> I think lots of dependencies with a small gem is a good thing, since
> it means the author is probably being a good citizen.

Hmm.  Interesting, and still a matter of opinion :)

Why does that make you a good citizen?  Because you are reusing code?
Or because you are being explicit about your dependencies?

In my experience, I've found that LESS actual dependencies is a good
thing, because that's less opportunity for me to get in dependency
hell (incompatibilities that I don't understand or can't resolve).
For example, I started using needle on my project, but then rolled my
own DI so I wouldn't have that dependency, and it was simpler and
better-tested.  Granted, this is probably a somewhat-unnecessary
holdover from my Java days, because it's much easier to deal with this
in ruby by monkey-patching.

> > Plus, it's very likely (especially in the case
> > of Rspec) that one of my dependency versions conflicts with something
> > else on their system, and unless they have their rspec version locked
> > down everywhere (unlikely) the mere installation of my gem will screw
> > them if it auto-installs a newer version of rspec that's incompatible
> > with their old specs.
> I believe that RubyGems has the ability to handle this gracefully
> with sane versioning schemes combined with the existing requirement
> specifiers (including '~>'), and that this is primarily a gem author
> education problem.  When severity of changes doesn't match changes in
> version numbers, everybody is going to suffer.

Sorry, I've gotta disagree here (and I'm_definitely not bikeshedding
here, because my and my shop, which includes an rspec committer, are
early rspec adopters, and we have been along for the whole ride).
Even if rspec had sane versiong schemes (which they really don't), it
wouldn't solve the problem I mentioned:

1. I force a newer version of rspec to be installed with my gem
because it's a test dependency
2. User installs my gem, and they could care less about ever building
or testing it, they just want to use it
3. The newer version of rspec breaks all my user's tests, because they
don't have their rspec version locked down in their app
4. User gets pissed because my gem "broke" them.  Yes, it's their
fault for not locking down their rspec version, but the user is always
right!  Plus, they have a somewhat valid reason to be pissed, because
the newer version of rspec is completely unnecessary for my gem to
work correctly for them.

This scenario is amplified with rspec, which has no compunctions about
drastically changing their API (sane versioning aside, there's nothing
fundamentally wrong with that), but it can apply to any library that
is primarily used as a development dependency.

To me, the "right" thing to do is not force the installation of a gem
that I know is unnecesary at runtime, and is likely to spew
deprecation if not break many users.  I'm being a better citizen if I
reliabily make sure the right dependencies is installed and used
whenever somebody DOES want to build or test my gem, and don't force
an unnecessary runtime dependency.  And (pimpmode) this is really easy
to do with GemInstaller.

> FreeBSD's ports has run and build dependencies.  I think its fine for
> RubyGems to have an equivalent.  Retrofitting the distinction on is
> complicated, though.
> Again, I don't think it's too hard, but it is harder than people
> think.  Or, it's easy, once we know exactly what it is supposed to do
> (which is hard).

Right.  Now we just need someone to get on that :)

> > Ok, pimp-mode on: I think that my GemInstaller tool
> > (http://geminstaller.rubyforge.org) is perfect for this
> For production Rails apps, I tend manually lock down versions
> explicitly.  `gem lock` is a lightweight way to generate the #gem
> calls for this (which I discovered recently), but doesn't handle all
> the other issues that your tool does.

Yes - we do lots of cool stuff with it that's handy in a large, Agile
Rails shop - like:

* locking down all apps' dependencies in a standard yaml file with
common bits extracted across apps
* allowing apps with different dependency version requirements to run
without hassles across a variety of shared pair-stations
* overriding to use a specified beta rails gem based on a env var,
auto-installing all new required gems across all dev/ci/demo/prod
* centrally dealing with silly issues so every app in the shop doesn't
have to deal with them individually (like the latest Edge Rails gem
requiring soap4r to be installed even though it's not used)

Thanks for the thoughtful response,
-- Chad

More information about the Rubygems-developers mailing list