Contracts in a gem?

My experience in developing libraries has taught me to code (very) defensively, and in particular, to detect and respond to errors as early as possible.

To that end, I usually use Ruby gem contracts to guard against caller type errors. (Btw, the contracts’ type checking is very flexible.)

Now I’m building a Ruby gem, and would like to use contracts in it, but I don’t find other gems that do so.

Would using contracts in a gem be poor practice?


I feel that it’s a weird dependency to have.

I can see the beauty in having something, that’ll tell people, that they are using your gem “wrong”. However, I wouldn’t inject it in like this. When I write code, that is going to be used by other developers like this, I usually also code a bit more defensively, but I would much rather do something like this:

# Short description about the function
# @param arg1 A number to be used (actual description, of what it's used for)
# @param arg2 A string to be used --||--
def my_function(arg1, arg2)

And then, if you really like, you can return nil or raise if the arguments doesn’t match the signatures

def my_function(arg1, arg2)
  fail unless Numeric === arg1
  fail unless String === arg2

I do however feel that this last approach is a bit too much, since the user of your code can no longer supply a “Number” of his own kind. Say he has a class, that behaves just like a number, he would want that to work with your gem as well.

Thanks much, Ohm, for your thoughtful reply.

I had overlooked the possibility you suggest in your last paragraph, and will give that careful thought.

I think I may end up doing some very limited explicit type-checking. I build test automation, so in particular, if I’m looking for test.kind_of?(Minitest::Test) to be true, I really, really want that to be so.

I use contracts in my work project too
But I never use it in my gems since gem user cannot opt out from contracts

When writing gems, I always try to use opt-in instead of opt-out in usage
(no implicit change on install by default)

To ensure “correct” usage of gems, I prefer writing clear documents (in doc form and/or code comment form)
And if someone reports issues due to unexpected input, I will point them to the document.
Sometimes the unexpected usage is reasonable to support, then I will add support for that

Many thanks, PikachuEXE. That confirms my strategy.