Prototyping Java-Processing in Ruby-Processing

Justin Marney, Former Viget

Article Category: #Code

Posted on

It's no secret that I spend copious amounts of free time trying to create art with my laptop. Not too long ago I gave a talk on using Lily and the Monome to generate algorithmic music. More recently, I've been obsessed with learning Processing, an animation and interaction programming language. It has the capability to generate both algorithmic music and visualizations and it runs on the JVM so it's quite fast and portable. The language itself provides a huge library of functions that serve as abstractions to the intricate and tedious world of graphics programming in Java. That said, it isn't really its own language per se. At the end of the day, coding in Processing is coding in Java. Fortunately, Jeremy Ashkenas has created a JRuby interface to the Processing API called ruby-processing. I've been using both, together, at the same time to help improve both my Ruby code and my Java code.

The Concept

The Java based version of Processing runs faster than ruby-processing and this is no surprise as there is an inherent performance cost when translating Ruby to Java. On the other hand, I can code faster in Ruby. I've been combining these two forces and prototyping my Processing applications in ruby-processing and then porting them to Processing. Along the way I've realized that this technique is a powerful aid in understanding object-oriented fundamentals. It has also increased my appreciation of Ruby as it demonstrates how features of the language map to Java code structures with surprisingly less syntax and greater flexibility.

Examples

Here's an example based on a Processing simulation I've been working on. My simulation is based on this video, by Robert Hodgin who blogs at flight404. We'll look at a small subset of the app for demonstration purposes.

Modules and Base Classes

?module Movable def move; end end class Magnetism attr_accessor :particles def act; end end class Gravity include Movable attr_accessor :particles def act; end end class Particle include Movable end 

A little explanation is in order here. Magnetism takes a collection of Movables and applies a magnetic field equation in Magnetism#act. Gravity does the same thing except it uses a gravitational equation. Here we see that instances of Particle and Gravity are both Movables. I wanted to be able to have a bunch of small magnetized particles influenced by gravity, as well as a handful of gravitational objects that were magnetized with respect to each other. Watch the flight404 video if that isn't totally clear.

My Java solution is essentially the opposite of what I talked about in an older blog post, Inheritance is Unlikely. I created a Movable base class that Gravity and Particle inherit from. Inside Magnetism#act I cast the objects in the particle collection to the type Movable.

Duck Typing and Interfaces

?class Particles def display particles.each do |p| p.display end end def move particles.each do |p| p.move end end end 

While Particle and Gravity instances get their movement behavior from the Movable module, they both implement different display behavior. Particles, which is the particle collection class, contains an array of instances that respond to both #display and #move messages. My goal was to use this as a collection for both Particle and Gravity instances. In Ruby, this happens automatically. As long as the instance p passed into the #each block responds to #move or #act I should be able to use these delegation methods without any trouble.

interface IDisplayable { void display(); } class Gravity extends Movable implements IDisplayable { void display() { } } class Particle extends Movable implements IDisplayable { void display() { } } class Particles { void display() { for(int i = 0; i < particles.size(); i++) { IDisplayable p = (IDisplayable)particles.get(i); p.display(); } } } 

In Java, the solution is a bit more tricky, at least for a Java novice such as myself. I created an IDisplayable interface that defined the display method signature and made Gravity and Particle implement that interface. This particular approach helps concretize the idea that adding public methods to a Ruby object implicitly builds an interface. The duck typed nature of Ruby somewhat hides this aspect but in porting to Java the concept of interfaces becomes explicit.

Lessons

Clearly, these two examples aren't groundbreaking but the value of this approach is in the actual practice. Looking at your Ruby code and thinking about what various interfaces your objects conform to will help you model more flexible and reusable classes. In the event your end goal is flexible Java code, prototyping a class hierarchy in Ruby can help you build in the flexibility of Ruby without having to mess with explicit interfaces until everything is working the way you want. Processing itself is a great environment to try out something like this as the boiler-plate overhead of creating a running Java application is well hidden within the Processing internals.

Related Articles