Mar 9 2007

JRuby can save Swing - Follow up

madlep

My recent post "JRuby Can Save Swing" generated a bit of discussion around the blogosphere. A few blogs replied, and a lot of good points were made. I was a little disappointed that most of the rebuttal I got was in regard to Joshua Marinachi’s original 2003 post and his list of why Swing sucks, and not to the points I raised about the potential that a new framework based in JRuby could provide. I guess that is blogging-101 - put your payload at the front and minimize the lead up. ;)

From the original post, my dream list for a higher level GUI framework for Swing are

  • Structured application layout
  • Proper decoupling of model from view
  • Automatic binding of model to view without glue code
  • View logic code separated from layout markup
  • Application lifecycle support
  • Minimize the amount of code
  • Minimize complexity
  • Testable
  • Make the Right way of doing things the path of least resistance

JRuby cannot save Swing

pinderkent replied with the idea that Swing is beyond saving, and nothing JRuby or anything else can do can save it. I don’t think Swing is at that point. I think in the last few years Swing has turned a corner an is improving with each release (5 was great, 6 is good as well). My initial article title was intentionally a little inflammatory. I don’t actually think Swing “needs” saving. All the same I think there are some areas that can be helped out.

Swing is slow?

Pinderkent then trots out the tired “Swing is slow argument”. This may have been the case… on a Pentium 2 back in 1998. This has not been true for a long time. Swing itself is more efficient, and CPUs are faster. It just isn’t an issue anymore. The pinderkent says they haven’t actually done any profiling. Nuff said.

Danno Ferrin responded to pinderkent and makes the point in another follow up:

"The stock answer to this is always true: "bad programmers abuse the Event Dispatch Thread." Seriously, whenever anyone wants to start programming Swing someone else needs to get a stick and beat them until they write in blood the oath "I will not do data processing in the Event Dispatch Thread." "

Which is exactly my experience. It is possible to create snappy, responsive Swing apps - but the moment anyone does some heavy processing, or a database call, or file operation from a listener - you’re wading through mud. Maybe that’s an extra point for my framework wish list: "Makes using worker threads instead of the EDT the path of least resistance for heavy operations."

Groovy Can Save Swing

Danno Ferrin’s main point is that Groovy would be a more suitable layer for Swing than JRuby.

The argument is that Groovy is closer to Java and it would mean developers wouldn’t have to learn all of Ruby’s weird syntax and "ugly PERLisms". Maybe. I have to admit I haven’t had any exposure to Groovy. Ruby isn’t difficult to pick up though, and the syntax arguments are really just a matter of opinion. What I believe makes Ruby ideal as a DSL/wrapper API layer is the level of meta-programming Ruby affords to achieve things that are impossible in Java. I’m talking about things like stupidly easy model-view binding. In ruby you can do something like

model = Person.new('Julian Doherty', 'julian@example.com')

name_label = JLabel.new
name_label.bind_to model, :name

email_field = JTextField.new
email_field.bind_to model, :email

And have the text label and field bound to the model so changes on either side are automatically replicated to each other - all without a single line of event listener glue code. I’ve got some sample code showing this working, and will write something about it soonish. I’ve already written about Transparent Property Change Listeners for Ruby bean-type classes, which shows part of the solution.

I don’t know if Groovy gives you that or not. If it does, great. If not, then that’s a reason to consider JRuby over Groovy.

Homework for me: grok Groovy so I’m better informed on this :)

Does Swing Need Saving?

Daniel Spiewak posted a rebuttal of Joshua Marinachi’s original “why Swing Sucks posts” that I reposted.

It’s a good post and A lot of his points were on the money (which I won’t discuss much except to say I agree): his discussion of layout managers (GroupLayout etc); native feature integration; and Swing’s bad perception from a troubled past.

A few didn’t quite stack up with me though.

Ruby is the same amount of work as Java?

In arguing that Swing GUIs are just as easy to construct in Java as JRuby, Daniel Spiewak provides an overly simple UI consisting of a label and three buttons - implemented both in JRuby and then Java. The two versions are almost identical, and there is no difference in code complexity or length (how surprising!). Problem is, the examples didn’t have anything done in the real world: no advanced layout, no event handling, no model/view interaction, no validation. It’s a weak straw man argument that really doesn’t tell us anything.

A more interesting example would be to compare a straight Java implementation of a reasonably complex application (including any cool 3rd party libraries) and a JRuby framework based implementation (using all the Ruby black magic possible). My guess is that the JRuby version would come out ahead.

Swing isn’t slow to build?

Daniel Spiewak then says that a reasonably complex UI could be coded in a few hours by a himself, and half that by Romain Guy.

So what?

It’s a pretty arbitrary metric which still doesn’t say anything. What would be interesting again is the difference between Java and a JRuby framework implementation. Maybe JRuby only takes one hour or maybe it takes five? I don’t know. My guess though is that again it would take far less code, would be easier to test, and would be finished quicker in JRuby by the same developer.

Separate markup layout of view is bad?

Daniel Spiewak also questioned whether using XML to store the GUI config is a good idea. I AGREE! XML is horrible and is abused in Java land (I actually said to use YAML in the original post as it is a bit more human friendly). I wasn’t advocating to use XML/YAML to create the whole GUI - just as a mark up to separate the layout from the component instantiation and move layout out of the view code.

My opinion is that code is good for expressing view logic, but not visual layout. That would be better served by some separate markup.

Swing apps are hard to maintain because of bad developers?

One of the main beefs I’ve got with Java/Swing and one that Daniel Spiewak’s touched on, is the difficulty maintainability of Swing apps. He says that main problem with bad Swing apps is that bad developers don’t do a good job - which I totally agree with! It is definitely possible to structure a good Swing app and develop it in a nice clean way, but to do things the right way is a lot of work. The path of least resistance is to take short cuts and just get it done (especially when deadlines are pressing). Yes, Swing has a nice MVC architecture, and best practice says you should build apps that way - but it’s just too much work to use properly in the real world.

I liked a quote from one of Danno Ferrin’s other related blog posts “Groovy, Verbosity, and Swing:

“I think that the greatest problem with the swing APIs are not that they are too complex or too poorly explained. The biggest problem I see is that to do simple things the correct way, it can get quite verbose. Kind of like reliable file I/O, but you get far fewer urgent-1 bug in the GUI than in core I/O routines. Perhaps the best thing isn’t to change the Swing APIs, but to add more syntactic sugar.”

Which is exactly what I was trying to get at with my original post. Swing is a great low level API, and provides the developer with a lot of power to do things. Problem is, the path of least resistance is to produce ugly crud that barely works. Where as something like Rails provides a path of least resistance that results in elegant and well structured code.

Every API acts like a multiplier for developer productivity, and has a response curve of varying slope. Some frameworks make good developers amazing while making mediocre developers passable (Rails springs to mind).

Swing seems to do the opposite though. It makes amazing developer’s work merely good, and mediocre developer’s work unacceptable.

Comments on the original post

Why not Eclipse/NetBeans RCP? What about JSR-296 application framework?

Steve said…

I agree with the sentiment, but not to craft yet another solution.

Why don’t we just call this Eclipse or NetBeans RCP?

Really these things have been done, what we lack is people understanding and using them.

There is a JSR on the table for a Swing framework too - JSR-296, this will help quite a bit.

Good points. I have to plead ignorance on exactly what the Eclipse and NetBeans RCPs provide (more homework for me!). However one of the benefits of JRuby is all the meta-programming that is either impossible or overly verbose in Java. They also both smack of the whole Big Java philosophy (XML configuration and all!) which a lot of developers are getting disillusioned with. As for JSR-296 - it’s definitely a good thing, and any framework should build on top of it, not replace it.

Groovy SwingBuilder?

Anonymous said…

Groovy already has a SwingBuilder, which I suppose you could duplicate in Ruby… but most of these are done arleady.

Good point, but layout is just a small piece of the puzzle. My understanding is that SwingBuilder just helps you with the layout and still leaves everything else (binding, application structure etc) to you to implement

So… now what?

I’m keen to experiment with some of my original ideas from JRuby Can Save Swing. I’m trying to pick a small/medium, low-risk project to roll a basic JRuby Swing framework for and see how it goes. So far I’ve been doing a few little demos that show off some of the basic concepts (will post some examples soon!). It’s definitely promising, but it’s hard to tell from anything that small.

Stay tuned :)


Feb 15 2007

JRuby can save Swing

madlep

Swing is hard. Needlessly so. With the advent of scripting support on the JVM, why not wrap a light and elegant Ruby layer around Swing? Why keep coding Swing at it’s lowest API level using a heavy-weight language like Java?

I’ve always maintained Swing is a nice framework. It’s just that it’s too low level and Java is a lousy language for programming it in. It’s already possible to code Swing in Ruby by using JRuby. You get some of the Ruby niceness (such as easier method calls, some dynamic typing, and blocks), but you still end up fighting against listeners, layout managers, look-and-feels, event-threads etc before long. Suns trademark API over-engineering casts a long shadow, even into Ruby land.

The Swing API itself is very flexible and powerful, but at a low level. It’s powerful in the same way that a coil of wire and a bunch of tools is a flexible and powerful way to configure the electricals in your house. It’s just that sometimes you only want to plug a few things in and flick a switch to watch a DVD.

So what specifically are the problems?

Swing’s issues

Joshua Marinacci’s blog post Swing has failed. What can we do? from 2003 covers this issue nicely. Joshua points out these flaws which I’d agree with 100%. Nothing much has changed in the years since, except maybe that Swing looks somewhat better now and resembles native apps much more closely.

  • "Swing apps are slow to build."
  • "Swing layout managers suck."
  • "Swing apps are hard to maintain."
  • "Swing is too powerful."
  • "No native features."
  • "Swing apps have a bad history."

What needs to be done?

Joshua’s ideas on what needs to be done to fix Swing are interesting.

(there are more points he makes, but I’m just including the relevant ones)

  • "A structured way of building Swing apps. Something like Struts where each concern (aspect?) has it’s own special place to be stored and manipulated. How do you organize your layout, workflow, validation, intz’ed text, and hooks to the BL? Should you subclass to make frames or use factory code? We need a set of best practices and then a framework to implement them."
  • "A standard cross-tool representation of a GUI that is not Java code. Something that can be moved in and out of different IDEs and build tools. Probably an XML representation or maybe serialized Swing objects."
  • "An intermediate API. Maybe we need a simpler API on top of Swing? A new set of wrapper components which hide a lot of the complexity. Hell, half of the work could be done by just conditionally hiding 3/4 of the API from the Javadocs."

I particularly like the idea of a structured way of building Swing apps. At the moment it’s a free-for-all. Some developers have come up with nice individual patterns for maintaining order, others implement spaghetti, most start out well, but degrade into entropy. This even applies individual screens in some apps! - I’ve seen 6000 line long, single-class monstrosities for a single window! One of Rails main strengths is it’s “Convention over Configuration” approach for separating out and structuring an application. There is no reason why this can’t apply to a Rich Client.

My Ideal Swing/Ruby framework features

So… what would this look like?

  • Structured application layout. Works for Rails. Nuff said.
  • Proper decoupling of model from view. Probably using Martin Fowler’s Presentation Model pattern, or similar.
  • Automatic binding of model to view without glue code. (this makes the last point much easier to implement.) Ruby is perfect for this. You should be able to write something like name_field.bind_to song, :title and be done with it. Ruby should do it’s thing and set up listeners automatically - Even if the model class wasn’t designed with listeners when it was coded.
  • View logic code separated from layout markup. View components and interaction (enable this button with this tooltip etc) should be coded in Ruby. Layout should be stored in a YAML file or similar (please no more XML…). Layout via coding is far too hard for most people to use effectively. Minimize the pain and let the framework take care of the grunt work. We definitely DO NOT want anymore GridBag boilerplate code…
  • Application lifecycle support. Related to having a structured application layout. Provide session support, long lived models etc, and handle startup/shutdown.
  • Minimize the amount of code. You already get this for free by using Ruby, but removing the fluff from Swing is a must. Too much code to achieve too little. It should be possible to scaffold something basic like Rails does, then tweak it if it needs to do more. DRY is part of this, but that just seems like basic common sense for any kind of development in any language.
  • Minimize complexity. Related to minimizing code. Making it easy to use a proper pattern like Presentation Model and removing a lot of the spaghetti listener code by using bindings will help a lot.
  • Testable. It’s really hard to write automated tests for GUIs. Libraries like JFC Unit make it easier, but it’s still pretty heavy going. I don’t know the answer to this one. GUIs always need at least some manual intervention to check the visual layout (a computer can’t tell if it doesn’t “flow” right). Maybe the framework could help by making it easy to substitue mock objects for testing the presentation model code.
  • Make the Right way of doing things the path of least resistance.. This one is important, and I think it is one of Swing’s big weaknesses. This is related to having a good structure, but it goes from there all the way down to how easy the APIs are to use. Rails makes it easy to create good designs and stick to them. Swing makes it hard - as evidenced by the plague of badly thought out Autonomous Views espoused by Sun’s Swing tutorials

Even a few of these points would make Swing much more productive and fun. I’ve made a few posts recently that are leading up to this. Over the next few posts I’ll start to experiment with a few more of the pieces to see how it all hangs together. Who knows, maybe I’ll actually get something usable at the end :)