Friday, December 01, 2006

JRuby and RSpec Leftovers

I took a few minutes to interview Charles Nutter, Michael Studman, and Aslak Hellesoy for an article I wrote for InfoQ. I tend to ask a lot more questions than I'll have space to print in an article like that, and I hate to throw stuff like this away, so here's the whole interview. Enjoy!


Why do you think RSpec on JRuby is a big deal?

Michael: I think this development is important from a couple of perspectives. Firstly RSpec working on JRuby is proof, visible to the wider Ruby community, that JRuby is a solid Ruby interpreter and a viable alternative to MRI. It's rapidly approaching the point where big, complex, important apps and frameworks like RSpec just work. The fact that we're almost there with RSpec speaks volumes about how good JRuby's implementation is today - this is a cause for celebration!

Secondly, it's important because it opens up the possibility of BDD to Java developers in a way that's largely been denied to them in the Java language: a simple, clean, natural means of expressing intent. Many developers in the enterprise will, for a long time to come, be denied the ability to develop the production code in Ruby (JRuby or not). I'm personally encountering this at the moment and the myopia mistaken for common sense and risk avoidance is really frustrating. This means for many there's no chance of taking advantage of the substantial benefits Rails, Camping and the like give you. Where I've found more wriggle room (again in the enterprise) is in areas like BDD and unit testing - the prejudice against dynlangs isn't as strong here. So I think many Java developers can at least make use of the substantial benefits of tools like RSpec today while delivering a 100% Java product. In this way I hope tools like RSpec running on JRuby become Trojan horses for Ruby in the enterprise.

Charles: Behavior-driven development, using a tool like RSpec, is important for two reasons: It's a higher level of abstraction than is typically found in standard unit-testing frameworks, and it's closer to how we think about such problems. When using RSpec, we also benefit from using Ruby with all its capabilities. And of course RSpec under JRuby ties everything together: behavior-driven development, agile and elegant Ruby code, and access to all available Java libraries. It's the best of all worlds, and a pretty exciting new way to test applications on the Java platform.

Aslak: I think there are several big deals here.

First, it will help bring Ruby (the language) to the Java world (see below).

Second, having RSpec running on JRuby is a big step for JRuby itself. RSpec is used to spec itself and it pushes Ruby to its limits by using some fairly exotic metaprogramming in the internals. If JRuby is able to run RSpec's spec suite this is a very good indication that JRuby is on par with standard Ruby.

Third, RSpec is the de facto library for BDD in Ruby. Being able to use it on JRuby is a big deal because more people will be able to get familiar with BDD and realize the benefits of writing executable documentation. This is actually more of a big deal to the BDD cult than to RSpec or JRuby. These tools are just vehicles for a grand plan to take over the world >:)

What were the hardest bits in making it happen?

Michael: Frankly I think the hardest bits were all done by other people — the many JRuby developers over the years and particularly the current three committers. It's a testament to their efforts that RSpec just mostly works right now and that getting even further along this path is not proving a substantial effort. I guess the only hard bit for me was sneaking development in between work, sleep and life!

Charles: Hmm, I dunno, downloading JRuby? When I tried out RSpec a couple months ago, everything I tested worked fine. Aslak (or someone) also discovered that all the sample specs in the RSpec distribution ran fine. RSpec's own tests showed a number of errors, but Michael and I managed to resolve the vast majority of them with a simple method-visibility fix. I think we're down to only a couple remaining failures out of hundreds of tests, so official 100% compatibility is probably days away. JRuby's mature enough now that most pure-Ruby apps like RSpec "just work", so we'll see more and more such apps "officially" supported.

Aslak: When I first started to run RSpec's own suite of specs with JRuby there were somewhere around 50 errors. I submitted a couple of bug reports and within a few days they had been fixed. It turned out that most of the errors were caused by Kernel.raise having wrong (private) visibility. So within days the number of failing specs were down to about a dozen.

I figured that the main reason the remaining bugs had been allowed to survive this long was that they would only surface under very rare conditions. And since I was sitting on the code that could pry them out I decided to dig into the JRuby internals and submit patches. I'm really impressed by the JRuby team's responsiveness. The patches usually make it into trunk in less than 24 hours!

For me the hardest part was to become familiar with the JRuby internals, but the code is really well tested (good tests are great documentation) so I managed to get to the bugs much quicker than I had anticipated. I've made an extra effort to include tests along with my patches - to prove that something is wrong until the patch gets applied. There is no better way to get a patch in quickly.

How does doing things like this help JRuby in general?

Charles: Without a complete testing kit for Ruby (though the RubyTests project is starting to make progress in that area), we tend to use applications' own test suites to measure Ruby compatibility. RSpec represents another set of tests we can use to ensure we don't regress, and once it's 100% Aslak has offered to start running future tests against JRuby as well as MRI. That will help us all ensure RSpec continues to run in future releases...and ensure we don't break anything.

Michael: I agree. It also helps JRuby because it builds confidence in the wider Ruby community that JRuby is ready for the big time. The more of these big applications and frameworks we can say "JRuby's 100% compatibility with that" frees people to choose to use it for the reasons that should matter: because it's fast (coming soon!), because it has a native threading model that can give your app greater throughput, because it seamlessly integrates Rails with the 4 million lines of backend Java code you've spent the last 5 years developing.

Aslak: Cooperation between JRuby developers and developers of other Ruby projects helps JRuby become more compatible with the standard Ruby runtime. I hope more Ruby developers will join the effort. I'm sure they will.

What affect do you see RSpec on JRuby having on the wider Java world?

Charles: I think it's certain that dynlang-based testing frameworks — especially RSpec — are going to make TDD and BDD far easier on the Java platform than anything of the Java-based tools available today. There's no doubt in my mind.

Aslak: You can use RSpec running on JRuby to write executable specifications for standard Java code! Consider this example:


require 'java'
include_class 'java.net.ServerSocket'

context "ServerSocket" do
 specify "should know its own port" do
   server_socket = ServerSocket.new(5678)
   server_socket.localPort.should == 5678
 end
end
(Of course, you'd expect the JDK classes to be sort of stable, so in real life you'd use it to write specs for *your* code, not SUN's).

RSpec is a powerful alternative to JUnit and other similar tools. Being able to generate documentation that expresses the code's intent is really, really powerful. I'd almost go as far as saying it's a paradigm shift in programming. For example, running the spec above with the --format specdoc option would produce:


ServerSocket
- should know its own port

Another impact of RSpec on JRuby is general adoption of Ruby in the Java community. People are usually less sceptical to introduce new tools in the build environment than in the production environment. Since RSpec fits in the java build environment (you can call it from Ant) it's going to be easier to try out for people who just want to get a feel for what Ruby is - without having to deal with as much red tape as they'd typically have to deal with if they were to introduce it in the production environment.

This way people on Java projects can use RSpec on JRuby to get familiar with the Ruby language in a relatively risk-free context. This is an important step towards more widespread understanding of the powers of Ruby and its general adoption. I think this will make more people willing to take the next step - develop full-scale applications in Ruby and run it on JRuby (or on classic Ruby for that matter).

Michael: RSpec is a beautiful example of what's possible in Ruby: a natural, logical, consistent & delightful API. I hope that RSpec on JRuby, besides becoming the de-facto way to develop BDD for the Java platform, also causes more Java developers to sit up and notice Ruby as a language with incredible potential for all manner of problems. The 10 minute 'build a blog in Rails' videos have been a useful draw card but what better way to convey Ruby's power to Java developers than to have them experience it themselves by putting JRuby and RSpec to work in a current project?

Anything else you'd like to add?

Charles: I hope other Ruby developers will start looking at JRuby as well. The reality now is that JRuby is very close to full Ruby 1.8 compatibility, and more and more folks are going to be using it. Ruby app and framework developers should embrace that fact and start designing their apps with implementation-independence in mind. We promise to help however we can.

Aslak: Both SUN and Microsoft have started to take dynamic languages seriously. I recently attended Microsoft's TechEd conference in Barcelona, and there was a lot of buzz about Python on the CLR. We're seeing the same kind of buzz around Ruby on the JVM. When the big ones embrace dynamic languages, the developers sitting on the fence will follow suit. Ruby and Python are coming out of the closet now.

The past 2-3 years have seen a big drift towards "lightweight" java web and persistence frameworks - away from the complex J2EE stack touted by SUN's design-by-committee enterprise architects.

Today it's possible to write much simpler Java applications than 3 years ago. I think JRuby will push this trend even further. Ruby's language features will to some extent obsolete the need for separate AOP libraries, dependency injection and other "glue" features provided by lightweight frameworks that Java people (me included) have invented in order to simplify things.

Less infrastructure means more focus on code delivering business value. Ruby/JRuby makes it easier to write loosely coupled code - and less code. Couple this with increased adoption of automated testing (where RSpec plays a role) and you have a bright future for outcome-focused programmers and people who are willing to hire them.

Michael: I'd like to put a thought out there and hope someone runs with it.

Charles mentioned the work being done by RubyTests in creating a testing kit for Ruby implementations. He's also the creator of the RubySpec wiki — a community effort to document what Ruby is. Matz has also made positive noises about RubySpec and seems to approve of the movement towards specification. I see tremendous potential synergy between the two efforts.

My fear with something like RubySpec is that if it's really successful and has hundreds of pages documenting Ruby, its core and standard library etc, that this may become difficult to maintain over time. On its own it will require constant revision to ensure it stays accurate. Ideally I'd like to see the output of RubyTests drive a large part of the content in RubySpec but I know that standard unit tests don't provide the right abstractions for this - this is where RSpec comes in. What if a large part of the effort to document 'what is Ruby' was driven by RSpec specifications? We'd have an executable set of specifications we could point at any Ruby implementation to determine how well they stand up. We could also extract human friendly prose from such specifications and publish those to the wiki along with reports indicating which implementations fall down and where they do so.

Granted, there are aspects of 'what is Ruby' you simply can't express in a specification language built on top of the language you're trying to specify - and you need to write that in prose or in the language of maths. On the other hand there are plenty of things that could do well with RSpec-style specification - the core and standard libraries are prime candidates.

A trivial example is TCPSocket.new(remote_host, remote_port). Remote_port can be specified as a fixnum _or_ as a string so long as the string can be converted to a fixnum or is a well-known service name. Where is that specified? It's not in the rdoc and its support could change between any given release of MRI or JRuby or RubyCLR or Ruby on Symbian.

No comments: