Piers Cawley writes about Ruby’s dynamic nature:
Say you’re looking at ActiveRecord::Timestamp#updatewithtimestamps and you want to look at how #updatewithouttimestamps does its thing. If you simply grep for def update in the source code, you’ll find the implementation in ActiveRecord::Base and miss out on the alterations introduced by the locking module. You can’t simply look at the source code, you have to look at the order in which it was executed, and that can be a headache. Once you understand that you need to look at load order, and you find where that is defined, things get much easier, but things can get seriously scary when plugins come into play too.
I agree that this is both Ruby’s blessing and its curse — Ruby enables some extremely powerful features, but at the cost of creating a powerful mess if these aren’t used properly. Piers points to Smalltalk as an example of where these problems are addressed properly:
In a Smalltalk image, you can browse the source code at any time, and it always reflects the current specification of the system. In a Smalltalk implementation of ActiveRecord, as soon as you rename #update to #updateWithouLocking that’s what it’s called. When, later you’re looking at the definition of #update and you want to know what #updateWithoutLocking looks like, you can browse straight too it. The knowledge that #updateWithoutLocking used to be called #update hasn’t been lost, you’ll find it in your changes, but it’s irrelevant to how the system behaves now.
I’ve spent some time (though not nearly enough) with Lisp and Scheme, but I’ve never managed to do the same with Smalltalk. Yet another thing I’d love to do if I had the time …