The "Yes is No" Problem 12
login: pdcawley
password: *****
Yes is no and no is yes.
Do you want to delete all your files? [y]: _
Rereading What’s wrong with Ruby, I realised that the meat of Matthew Huntbach’s worry about dynamic classes boils down to the ‘yes is no’ problem. Given just the source code of a Ruby program, it can be tricky to work out what the eventual program ‘looks like’.
Ruby source can be thought of as a program that you run on the Ruby kernel which creates a bunch of classes, objects and relationships between them. In static languages, once a class has been created, that’s it, the only way to change it is to recompile and restart the program. In dynamic languages, no class is every really ‘finished’, it can be modified at any time.
Done right, that can be a great thing. It’s instructive to look at the way ActiveRecord’s behaviour gets built up in Ruby. ActiveRecord::Base doesn’t really do all that much, it concerns itself with the nuts and bolts of marshalling data to and from the database and building the basic accessors and support methods needed to do that. Its implementations of basic methods like #create, #update and #save are positively naïve. New behaviours are then layered on by including other modules. Modules like ActiveRecord::Locking::Optimistic, ActiveRecord::Validations, ActiveRecord::Callbacks and others all layer behaviour on top of these methods, usually by renaming the old method, so #update becomes #update_without_lock and ActiveRecord::Locking::Optimistic#update_with_lock becomes the new #update, at least until ActiveRecord::Timestamp changes its name to #update_without_timestamps and installs the behaviour that it needs.
It can make the code harder to understand though. Say you’re looking at ActiveRecord::Timestamp#update_with_timestamps and you want to look at how #update_without_timestamps 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.
What’s needed (or at least desirable) is a way of understanding what the state of the program and its classes will be at runtime. It’s easy in static languages, it’ll look like the source code says it looks. It looks like the source code says it will look in Ruby too, but Ruby source code can get a good deal more twisty. Even attr_accessor has the potential to blow minds…
Would you believe it’s a solved problem? It’s been solved for years too. Heck, the solution is older than David Heinemeier Hansson.
Counsel of Perfection
I’m thinking of Smalltalk, but I’m pretty sure that the Lisp Machine folks had similar tools at their disposal. 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 been admiring Smalltalk from afar for a long time now, but until recently it wasn’t a language I spent any time programming in. I was more likely to think “How does Smalltalk do that?”, then fire up my local Squeak image and do a little fossicking about until I had a grasp on how things worked. Then I’d close it down and do something similar (or curse because I couldn’t) in Perl or Ruby. You can learn a great deal just doing that; if nothing else I’ve learned that I like Smalltalk’s message selector syntax a great deal.
Then, a few weeks ago, I watched a couple of screencasts of experienced Smalltalk developers doing their thing and… wow. I’ve always known that Smalltalkers rave about the environment, but I’d not really seen it in full flow.
So, I’ve been doing a few Code Katas in Squeak and starting to get a feel for working in the environment. It’s really, really lovely. Watch this space for more ‘coo er gosh’ type posts. Who know, maybe even an embarrassing screencast – if nothing else but so I can get some feedback from experienced Smalltalkers on what I’m doing wrong.
What about Ruby?
Short of someone coming up with a Smalltalk style interactive development environment for Ruby in the next half hour, this isn’t an immediately useful solution to the problem in Ruby.
But is it really a problem?
Having taken the time to explain why dynamic modification of classes can be a problem, I should point out that I don’t think it’s really a problem in practice. Sure, you can do Very Bad Things with it, but so what? You can do the same bad things (and more) in Smalltalk, if you couldn’t, it would be (nearly?) impossible to implement the Smalltalk environment in the first place. In the absence of an interactive programming environment, you need to take more care with structuring and organizing your code. Impose some standards on yourself – in Rails for instance, the various ActiveFoo classes are structured similarly: first there’s the ‘active_foo.rb’ file, which is responsible for loading up all the packages that define the class (generally found in the ‘active_foo’ sub directory) and includeing them in ActiveFoo::Base in the correct order. This convention helps comprehension. About the only thing I’d like to see further is some documentation in each module describing the behaviour they expect of any class they’re included in – behaviour like that of ActiveRecord::Validations is just too useful not to be pinched for other classes.
As always with these things, it boils down to the good taste and skill of the programmer. Write code that communicates your intent clearly to your fellow programmers – mere compilation is the least of your worries.
Updates
In the comments, Phil Toland has come up with links to some Smaltalk screencasts and a long presentation from Avi Bryant that includes some interaction with a Squeak image.
NB: For ‘ruby’, you can read ‘pretty much every dynamic OO language ever’. Except Matthew Huntbach didn’t write an article called “What’s wrong with pretty much every dynamic OO language ever”.

Do you have a link to those screencasts you can email me? I’m curious what all the fuss has been about as well. Even having done some SmallTalk, I never did see the magic. Thanks!
-Vince
Can I ask which smalltalk screencasts you found impressive?
Welcome to SmallTalk :)
Once you enter…
Why do you need this ability? Is it impossible to pick the real algorythm to be used at design time?
Johnathan: It’s not impossible to tell. ActiveRecord needs them all, but the various different behaviours can be thought of as layers on top of some basic functionality. If your language supports them, you could use Traits (Smalltalk) or Roles (Perl 6) to layer the behaviour, but Ruby doesn’t have that, so Mixins it is.
Layering the behaviour in this way also enables reuse in a way that having one big hunk o’ code doesn’t; I can (and do) write classes in such a way that I can layer ActiveRecord::Validations on top (it’s often useful to do this for objects that are going to end up serialized inside an ActiveRecord based object, especially if you’re generating them from form data and want to give feedback on entered data).
Everyone else: If I could remember which ones and their URLs I’d’ve added them to the body of the post. I shall hunt through my browser history at some point.
“Having taken the time to explain why dynamic modification of classes can be a problem, I should point out that I don’t think it’s really a problem in practice. Sure, you can do Very Bad Things with it, but so what?”
You really, really need to look at a big codebase that does this and has done so over many years. One example is Zope2.
Zope2 also has a shell/codebrowse environment, but try running dir() on a Plone page object inside it. Watch the screen scroll through many hundreds of methods, over a thousand in some cases. It’s food and drink to the “scripting languages don’t scale” crowd.
I’ve always said that the worst case scenario for Rails is that it evolves in something like Zope, because at Zope’s core is an object web publisher, which did 8 years ago what Rails does today.
Given enough time, dynamic modification and class monkey patching are entropic, or rather, beg serious questions about sustainability. All languages present tradeoffs.
I don’t know if these are the screencasts you mentioned, but here are a few that I have recently watched:
Bill: About the only thing I’d disagree with in your discussion of Zope as a system whose codebase got bad is your implication that it was ever anything but bad. It’s a framework I’ve disliked since I first saw it.
And bear in mind that I’m praising Smalltalk – when I check in my local Squeak image, I see that ‘Object’ has around 500 methods sorted into something like 60 message protocols. And that’s not counting class methods or anything inherited from the ProtoObject class. It could probably stand to be slimmed down some (there’s quite a bit of cruft kicking around in Squeak), but it’s still manageable.
It’s not about method counts, it’s about care and clarity. I have issues with Rails in some areas, but profusion of methods isn’t one of them. I’d like to see the way mixins are layered to build the core classes documented more clearly, but within any module it’s usually clear what’s going on – methods tend to be named well and each mixin concentrates on doing one thing, so it tends to be understandable on its own terms.
Phil: Ah… thanks for those links. I’d not seen Avi’s last one, but the rest are all familiar.
Would something like the ‘use’ module solve your issue? I based it somewhat on Curtis Poe’s traits module:
http://rubyforge.org/frs/download.php/8825/use-1.2.0.tar.gz
Frankly, I don’t think it is an issue; it’s a capability. I was trying to explain why some people think it’s a problem.
You can also see screencasts and videos on Smalltalk at the Cincom Smalltalk site: