Wednesday, July 4, 2007

Opinions about Ruby

I have been reluctantly been forced to admit that some of the stuff you can do with Ruby is pretty damn cool. Now that I have had to try to debug a non-trivial (to me at least) application, I feel I can have an opinion on Ruby, and do this based on experience rather than prejudice.

First of all, documentation is poor for many libs. This is something that was raised at one of the general sessions at RailsConf 2007 in Portland, and got a very loud applause. I'm not just talking about tutorials or examples, many of them lack even minimal rubydocs. Many of them also do very little logging.

Secondly, I like checked exceptions. There, I've said it. This particular application failed silently somewhere, and from the few things I could get from the logs it seemed like a problem with SSL. After messing around for days trying to get this to work, I noticed something odd. At one place in the code, I had this:
@@services[wsdl_class].wiredump_dev = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
@@services[wsdl_class].options['protocol.http.ssl_config.verify_mode'] = OPENSSL::SSL::VERIFY_NONE

Now, if you switch around those lines, you get something funny, the wiredump logs aren't written. In fact, you could change it to
@@services[wsdl_class].options['protocol.http.ssl_config.verify_mode'] = blahblahblah
for the same effect. This is what finally clued me in to what was going on. In a completely different place in the codebase, the "model" code that fetches the SOAP object does a begin/rescue, assuming that any exceptions that occur are network related. I think that this was a valid assumption when the code was written, but later on some code had been refactored and some meta-programming magic goes on in a sub-lib to generate convenient helper classes and methods, and if you have a bug there, the generated exception is also silently swallowed and discarded. And this was application code by a very experienced programmer. Once other less experienced Ruby programmers (like me!) starts to mess up the code it quickly gets very difficult to understand what is going on.

True, you can sprinkle your code with
try {
} catch (Exception x}
{//Ignore}
in Java as well, but I believe this is rarer or mainly done by beginner programmers. Some very good frameworks to it too, but generally wrap the exception in their own layer appropriate exception and passes it on. Knowing that introducing a new checked exception breaks client code does make Java code less malleable, but on the other hand it might make the lib developers more careful about how they structure the code, and reminds them when they have to handle exceptions that sub-libraries might throw themselves, and when they can wrap the the exception in another (layer appropriate) exception and pass it on. I might be wrong though, we'll see if my opinion changes as I learn more of Ruby and other languages.

No comments: