Monday, 31 March 2008

Lost a Safety Net

I've just finished working through Chapter 9 of Pickaxe - Modules - and to be honest, it sacred me a little. Now I'm not religiously tied to static languages and can see the benefits something dynamic like Ruby can bring to me but there was something about Modules and name spaces which had me yearning for good 'ole Duke.

Here's the scoop. Mixins (using Modules as a way to provide multiple inheritance) allow you to provide instance variables. If I create an @myString instance variable in my mixin, and then in my class which includes it I also have an instance variable with the same name it can all go horribly wrong.

But here's the pain. In nice statically checked land, the compiler (best chum o' mine) will flag my goof. In Ruby-land, there is no compiler. Things might even work for a while. Worse still they miht break without my knowing it. Then finding the problem would be pretty nasty and debug-steppy.

Now I know I should have created a nice set of unit tests to avoid this, but in a complex application I can see things like this falling between the cracks; horrible nasty cracks with spikes and stuff at the bottom. Yurgh!

Or am I just being over sensitive?

Before I close, there are a few other confusions this deceptively short chapter threw up:
  1. I thought everything in Ruby was a class. Even objects. How come then Pickaxe states "a module isn't a class" (page 119). Hmmm.
  2. include / require / load / aaaaarhg! I like Java's "import" better and despite the problems, classpaths sheild the rest from me in 90% of situations (though heaven forbid when I have to debug a classloader problem, or worst still, implement one of my own...)


Travis Whitton said...

I agree this is annoying. The manual says:

For the most part, mixin modules don't try to carry their own instance data around---they use accessors to retrieve data from the client object. But if you need to create a mixin that has to have its own state, ensure that the instance variables have unique names to distinguish them from any other mixins in the system (perhaps by using the module's name as part of the variable name).

Like certain other interpreted languages, Ruby gives you the tools to shoot yourself in the foot and assumes you'll have the wisdom not to. This is less of an issue if you're only using modules that you've defined, but if you're loading 3rd party modules, it might be worth giving them a once-over to make sure nothing is going to clash.

Roger Pack said...

Does this merit a comment to core "throw a warning if you mixin something that overrides previously defined variables?"