Grass is greener


Hello. My name is Cliff and I think it’s time to should throw away the Java editor and jump on the Ruby bandwagon. Ruby is so much more “way cool” than the burdensome Java stoopid stuff that I write everyday. Java is now dumb because I can’t use closures. Objects (nouns) are first class citizens and there’s no clever way to process a list of items without a bunch of ugly curly brace code. I won’t use it anymore because it lacks the little “?” operator that prevents messages from being sent to null references. (“prevents messages from being sent to null references” is Hindu for “calling methods on null variables”…) I feel it is time to forget about my JAXP/TRaX craziness and break out REXML. I’m tired of breaking out the commons libraries and every other third party component under the sun just to post to my form upload servlet over the network. Ruby is just plain easier to extend.

Time To Convert!
So now I sit in front of my monitor glaring holes in the screen while I study the new laws of the land. Forget about java.util.* and java.io.* and no longer will I ref the Javadocs for JDBC. There’s a new way! I just gotta stop being so comfortable with the facilities provided by my JVM and do things different, do everything different, down to the packaging and deployment of my app. There is no more CLASSPATH, instead there are Ruby Gems. This is a great idea right? Let’s see.

What if we didn’t have to?
What if there was a way to have our cake and eat it too. I mean, c’mon, the Java platform isn’t bad right? There is a lot of maturity there. There’s a huge wealth of tools, frameworks and goodness that can be had merely by having a JVM loaded. I’m sure Ruby has a lot of goodness too but what if we didn’t have to learn a whole new API, a whole new way of packaging and deploying, a whole new way of writing web apps, a whole new technology set on day one when all we really wanted was a cleaner way to write:

Mushroom mushroom = null;
for(Vegetable veggie : plate.getVegetables()) if(veggie instanceof Mushroom) mushroom = veggie;
if(null==mushroom) throw new RuntimeException("You ate all of your mushrooms! Start eating your chicken!");

What if we could look for mushrooms on our plate and still talk to the javax.servlet.http.Request object that was asking for them? There’s JRuby, which is a hell of a project. A great initiative started by some very brilliant people but that’s not quite scratching my itch. You see I don’t want to be thrown into a whole new syntax, API, or new way of doing things. Call me conservative but I still don’t see that many problems with my current way. (Sure there’s the Java API bloat from release to release, the deprecated method calls that sometimes get reprocated, the missing convenience methods on a variety of APIs that would make my life easier, the confusion of wether I need to look in javax.xml, javax.xml, transform.sax, or org.xml.sax for an object that can respond to/delegate SAX events, and also the silly HTTP authenticator API that I can never get to reckognize different credentials, and don’t get me started on the many parrellel AWT/Swing classes that jump in the middle of my code from the auto-complete window making me feel like I’m losing my mind in many debugging sessions when I swear I want a JComponent but really need an awt.Component, but aside from that it’s not that bad right?) What if I could just bend the rules a little as I need to and make life sweet and dandy? What if I could pretend that Java did the same things as Ruby?

Get to the damned point!
If you’ve been to my site once or twice then you probably already know what I’m hinting at. “Spit it out already and stop futzin’ around!” However if you’re a new vistor responding from a trackback ping I’ll continue to confuse you a little more just like I’ve seen many people confuse the Java community pretending that there is only black and white with no shades of grey. There’s more to life than just one or two languages. Each language excels in different areas and is suited for different tasks. I’ve seens a lot of articles that appear to promote Ruby over Java as if they were trying to do a service for the average Java Joe. The fact is that Ruby is an interpreted scripting (or dynamic though I don’t want to debate) language. It is a different language, with a different technology stack. That makes for a huge jump similar to jumping from C to Java, though the argument for a C migration would not be based solely on syntatic convenience.

Getting to my point, what if we could bend the rules in Java? With Beanshell you can take advantage of closures and duck typing. Beanshell also closely resembles Java and feeds off of the same API stack so transition is near transparent for a typical Java Sam. Beanshell also supports dynamic method dispatch allowing “meta programming” style method interceptors to be implemented creating what is commonly referred to as a DSL. (That last sentence was complete techno-jargon that translates roughly to “my brain is actually 3 times bigger than yours so stop trying to decipher it and concede to my superiority!”) Let me give an example beanshell session to prove my superiority… err… my point:

BeanShell 2.0b4 - by Pat Niemeyer (pat@pat.net)
bsh % java.util.HashMap words = new java.util.HashMap();
bsh % public static void invoke( String methodName, Object [] arguments ) {
if(methodName.startsWith("define"))
words.put(methodName.substring("define".length()), arguments[0]);
else if(methodName.startsWith("show"))
print( words.get(methodName.substring("show".length())) );
else if(methodName.startsWith("remove"))
print( words.remove(methodName.substring("remove".length())) + " removed!" );
}
bsh % defineDog("a four legged animal");
bsh % showDog();
a four legged animal
bsh %

Still there’s other things that Ruby exploits that we can’t take advantage of even with a language like Beanshell. For example, I had a problem getting the above script to work within the context of an object instance. Then there’s the matter of operator overloading, mixins, and other niceties that I’m not sure if Beanshell supports. Enter a language titled Groovy, my current favourite. (…until something better comes along, sorry Groovy but you know how it is! I’m a player baby! Don’t be a hater!) Groovy boasts a feature set equivalent to that of Ruby including the popular Rails framework which has been implemented by the Grails project. (While I have mixed feelings about a framework that ties code so closely to a DB schema it’s a popular feature and well worth a mention.) It also boasts a feature that Ruby cannot fully exploit, a dramatically reduced learning curve for Mr. Java Jenkins. With Groovy you can begin with code like this:

public class Airport {
   ArrayList flights = new ArrayList();

   public Airport(List flights) { this.flights.addAll(flights); }

   public List findFlightsToOntario() {
      ArrayList result = new ArrayList();
      int idx = 0;
      while( idx < flights.size() )  {
         if( ((Flight)flights.get(idx)).getDestination().equals("Ontario") ) result.add(flights.get(idx));
         idx++;
      }

      return result;
   }
}

And incrementally make it Groovier:

public class Airport {
   //types and semis are optional
   def flights = new ArrayList()

   //public keyword is optional
   Airport(List flights) { this.flights.addAll(flights) }

   List findFlightsToOntario() {
      //type declaration cleaned up
      def result = new ArrayList()
      int idx = 0
      while( idx < flights.size() )  {
         //unecessary casting removed
         if( flights.get(idx).getDestination().equals("Ontario") ) result.add(flights.get(idx))
         idx++
      }

      return result
   }
}

Becomes:

public class Airport {
   def flights = new ArrayList()

   public Airport(List flights) { this.flights.addAll(flights) }

   public List findFlightsToOntario() {
      def result = new ArrayList()
      int idx = 0
      while( idx < flights.size() )  {
         //use superpowered subscript notation and direct property access
         if( flights[idx].destination.equals("Ontario") ) result.add(flights.get(idx))
         idx++
      }

      return result
   }
}

and then:

public class Airport {
   def flights = [] //groovy list syntax []

   public Airport(List flights) { this.flights.addAll(flights) }

   public List findFlightsToOntario() {
      def result = []
      //don't need indexed access at all, 
      //instead pass a closure to the each method from the GDK
      flights.each  { 
         //"it" is the implicit variable representing each element for the closure
         if( it.destination.equals("Ontario") ) 
            //use overloaded left shift operator to append to a list
            result << it
      }

      result //return is optional
   }
}

…even better:

public class Airport {
   def flights = [] //groovy list syntax []

   public Airport(List flights) { this.flights.addAll(flights) }

   public List findFlightsToOntario() {
      return flights.findAll  { it.destination.equals("Ontario") }
   }
}

Try refactoring that in Ruby syntax without an “alls yuh haff tuh do…” Holla…

8 thoughts on “Grass is greener

  1. Nice progression, this is the best way to learn Groovy, port directly, and then stare at the code until you see a simple Groovy way.
    One more little thing, the == operator invokes the equals method.

    public List findFlightsToOntario() {
    return flights.findAll { it.destination == "Ontario" }
    }

    Now it’s 100% Groovy🙂

  2. You know you can call Java classes directly from JRuby, right? I understand not wanting to learn a new syntax (even if it’s a gloriously beautiful syntax like Ruby), but the point of JRuby is to bring Ruby the language to Java the *platform*. That means you don’t have to stop using all the libraries you use today; indeed, you don’t even have to use the Ruby libraries if you don’t want to.

    And I think it’s fair to show the Ruby version of your code too🙂


    class Airport
    def initialize(flights); @flights = flights.dup; end

    def find_flights_to_ontario
    @flights.select { |f| f.destination == "Ontario" }
    end
    end

    But diversity is important. Some folks won’t want to stray far from Java and will want to use Groovy. Some will want what Ruby has to offer.

  3. and of course this:
    public Airport(List flights) { this.flights.addAll(flights) }

    can be:
    public Airport(List flights) { this.flights += flights }

    just a tad shorter

  4. Yes, I’m aware that you can call Java APIs directly from JRuby. I’ve also heard of the impedence mismatch with that approach: http://www.tbray.org/ongoing/When/200x/2006/08/22/Ruby-Java-Glue
    I also know little if any Ruby syntax so I am unable to provide a Ruby/JRuby equivalent. The point of my post was to illustrate how easy it is for a typical Java Joe to pick up and use Groovy as it is similar to Java in many ways. Though to be fair I should point out some gotchas when porting existing Java code to Groovy.

  5. You can remove quite a lot more of the Java noise:

    class Airport {
    def flights = [] //groovy list syntax []

    Airport(flights) {this.flights += flights}

    def findFlightsToOntario() {flights.findAll{it.destination == “Ontario”}}
    }

    and of course you could always use invokeMethod to catch all the calls of the form findFlightsToXXX and return the flights to “XXX”

  6. Since there is JavaScript support in Java 6 you should also consider JavaScript as a very easy and powerful scripting language. I to add features to my satellite data processing server. Also pay attention to the development of AJAX and JSON. IMHO you can do everything in JavaScript that you can do with Ruby, etc. But there are many things you can do only with JavaScript. For instance think of the Google Gadget’s or look at js-kit.com, to name a few.

  7. Alex,

    You make a good point. Rhinoscript (a.k.a. JavaScript for the JVM) is a very powerful alternative too. It’s also a little closer to std. Java syntax than Ruby, which would make it easier for Java developers to adopt. Also, many Java developers have either been exposed or have direct experience with it in some shape or form. I’m not quite sure how it would stack up feature for feature against Ruby/Groovy but I gether it would be an interesting comparison. Definitely food for thought.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s