Patrick Peak had some thoughts on a Rails presentation at the Denver Java Users Group (why is there no Ruby User Group to talk about this?). Namely, he comes to the conclusion that the main benefit Ruby brings to the table over Java is that the development workflow is simply code, alt-tab, reload browser. In Java, it is typically code, compile, package, deploy, alt-tab, reload browser. Dave didn’t really like Patrick’s thoughts, but I think this is just a case of someone being overly protective (I know I have been in the past with WebWork).
This is very true and, in my opinion, is the heart of the Rails vs J2EE/Java/WebWork/Whatever argument. The key thing is, in fact, not Rails, but Ruby. And that’s OK.
Rails benefits…
Before I get in to the different development workflows, I want to mention some of the cool things I’ve seen from Rails. I’ve been playing with Rails for the last couple of days (hands on, this time), and it does some excellent things:
- I was worried about configuring Apache with Rails, as I am far from an expert. Much to my surprise, simply invoking scripts/server booted up a mini server ready to develop with. This is comparable to WebWork shipping with Jetty, and ready to run sans external Servlet container. I like it. A lot.
- Gems is just like CPAN and made installing Rails extremely easy. Java needs something like this… that isn’t Maven. Ivy could be it… though the usage patterns are slightly different.
- I liked the idea that the rails command creates a fully working environment for you, complete with a makefile (Rakefile), unit tests, and customized scripts to generate more views, models, controllers, and other scaffolding. This is very similar to AppFuse, though much lighter weight and more focused (only one technology stack to serve).
Is it a revolution?
However, nothing in Rails floored me, or otherwise indicated a revolution was taking place in front of me. The design principals are very similar to Struts and WebWork and most other web frameworks. While it is true that it does more implicit configuration, that isn’t the key benefit. The key benefit, while partly that, is bigger: the development workflow is several orders of magnitude faster. This, combined with a fairly modern web framework, is the true winning combo. As such, I suppose some might call this pairing a revolution. I would call it an evolution.
Software maintenance
Now, development workflow isn’t everything. Code maintenance is by far more important, and Ruby really falls down here, mostly due to the fact that there just aren’t excellent tools out there similar to those found in Java. Say what you will about various programming methodologies (test first, etc… remember, I did write a book on TDD), but tools like IDEA make any methodology easier, test-first, test-after, or no-test, it doesn’t matter. Some on Slashdot have claimed that there is no need for advanced tools (especially when paired with Extreme Programming or TDD), and that they are simply crutches. While some may be (Xdoclet comes to mind), I really can’t see how one could say such things about IDEA.
It’s the tools, stupid!
Could someone make a Ruby-enabled IDEA? Sure. If they do, and there are good libraries available (such as Rails), I have no problem using it for my projects. However, I find browsing existing code, quickly seeing the API docs inline, code completion, refactoring support, etc all make the code maintenance much easier in Java. Ruby already has some of those tools (namely, libraries like Rails). But given that I spend most of my time writing code and not doing framework plumbing (as is touted heavily by the Rails crew, and rightfully so), I need my IDE to be of the highest standard. And I need all my coworkers, support engineers, and services engineers who work on the same code to also be using these excellent tools.
Can Java compete?
So the question is: is an IDEA-like IDE for Ruby the only thing keeping it back from conquering the software world? Maybe. But Java isn’t as far away as some might think. Sure, Java wasn’t developed like Ruby and SmallTalk: dynamically changing class, method, and field signatures isn’t currently possible in Java (though HotSwap is close, it isn’t good enough). This means that Java currently can’t compete with the simplified developer workflow that Ruby offers.
What can the Java tools do?
But that doesn’t mean Java is out of the game. Not by a long shot. First and foremost, Sun should recognize the fact that this extended developer workflow is unnecessary and a waste of time. They can fix this by offering a “development mode” in the JVM where full class replacement is possible, even to objects already initialized. Smart defaults, just as Ruby and SmallTalk have, would revitalized a slowing Java community.
Tools like IDEA are doing an excellent job and continue to innovate. IDEA supports HotSwap, meaning I can inject method-level changes (though not method signature changes) at run-time. This has been a huge productivity boost for support and development. Just remember: Ruby has this and more.
While IDEA is doing great, the specifications like J2EE are not keeping pace, and as such the vendors implementing those specs are not keeping up either. Tomcat and Resin, while fast, still take several seconds to start up. Until the JVM allows for full class replacement, quick startup times are critically important.
What can the Java frameworks do?
And speaking of startup times, the app servers aren’t the only ones to blame. WebWork takes about 1 to 2 seconds to reload its configuration — we could shrink this down. Worse, anyone who has used Hibernate can attest to its abysmal startup times. These things must be fixed, regardless of the direction of Sun and other JVM vendors take in the future.
On top of startup times, most frameworks in the Java land should begin to get out of the mindset that code is “deployed” and state can be set up once. If possible, frameworks should embrace a “just in time” execution policy. WebWork did this when Struts did not: Actions are created on every new request rather than being re-used.
Is there anyone we can do NOW?
Lastly, there are things that are happening right now that might make this whole discussion a moot point. With projects like BeanShell and Groovy close to supporting 100% Java syntax, there is potential for Java programmers to have all the development workflow benefits Ruby has while still keeping the excellent tools close to them.
Specifically, I’ve been playing with teaming BeanShell up with Jetty and configuring BeanShell’s classloader to be used as the webapp classloader for Jetty. The result: I can change my code, alt-tab, and refresh the browser. Viola! Changes are there, no compile, no packaging, no nothing. Right now, the changes are only available for objects initialized after the changes, meaning the class-level signature changes don’t get injected in to existing objects. However, I’m told by the BeanShell guys that this is possible to do, so there is a lot of excitement to get a working prototype of this.
Remember: as long as BeanShell supports 100% of the Java syntax, you could still use IDEA, refactor all you want, and develop quickly. Then in production, just like in Rails, you’d compile, package, and deploy, locking the release down.
Anything less scary on the menu?
Of course, this is a scary alternative and may take years to get working perfectly. BeanShell surely has bugs it it’s implementation that are not in the real JVM. And with dynamic class replacement, more problems could arise. And don’t even start to think about all the scary classloading that might happen. Fortunately, there are other options you can use today.
Shockingly, many Java developers (and maybe Rails “fanboys”, who are ex-Java developers now) painfully build and test their Java web apps by creating a war and deploying it. If you’re doing that: stop, there are better ways. In the simplest form, you can structure your source to essentially be an expanded war, letting you at least edit JSPs on the fly. Most people know about this.
Beyond that, use your debugger and use HotSwap. It is sad that it is such as little known feature. It effectively breaks down some development to at least code, compile, alt-tab, refresh.
On top of that, IDEs like IDEA know how to take your source control that isn’t structured like a webapp and copy the files in to an exploded war directory very quickly. The end result is a quick make which breaks down the “compile, package, deploy” steps to simply “make”.
Finally, if you’re not using an advanced IDE (you should!) and your code isn’t in the form of a webapp, there are still options. Namely, Resin and Jetty allow for very advanced configuration of webapps, allowing you to specify JSPs/resources, classes, and libraries from all over the place. Resin even has a very little known feature where you can map two directories to a single webapp path using a “merge:” directive, which is great if you ever extend existing webapps, such as we do in Jive Software’s professional services department almost daily.
What’s the point?
This definitely has to be one of my longest posts I’ve ever done. And it should be: this is something I’m very passionate about. Developer productivity is not to be dismissed lightly. Ruby has a leg up on Java right now because it is inherently a better language. But it is far from a better platform right now, which is unfortunate. So the question is: Which will happen first? Will Ruby get the tools, or will Java get its act together and catch up to Ruby? One, if not both, are bound to happen soon, and no matter what the developers will win.
PS: For full disclosure, I’ve said what some might view as negative comments towards Rails in the past (here and here). Feel free to read them and take them in to context with this article. I hope that I have explained myself even better this time, but my underlying message remains the same: “it’s the tools, stupid!”
on Jul 15th, 2005 at 4:07 am
Interesting article.
Just one quick comment: Have you actually tried to use hot swapping?
I’ve only used it with Suns JDK 5.0 JVM but man it sucks! It can’t handle any schema changes to a class which essentially means that if you change any signature, reorder any methods or fields or anything else than doing very small changes to the body of a method then you’re screwed and have to restart anyway. I’ve been trying to run in debug mode in IDEA on my current project and I’ve yet managed to get one single successful hot swap. Unfortunately the overhead of running in debug mode is just too big so I’ve stopped doing that too.
That Rails can do it is a testament to Ruby and the “Shared Nothing”-principle. In Ruby if you want to “refresh” something you just use the “load” method instead of the “require” method and it will reload it every time. “require” only loads once which means it’s a lot faster. In Rails “require” is used in the test and production environment, “load” is used in the development environment. The “Shared Nothing” principle means that nothing is kept around in between requests, so there are no objects (in sessions or caches or whatever) lying around that needs to be upgraded when the code changes.
on Jul 15th, 2005 at 4:55 am
Since Rails’ Action Pack concepts map pretty well to WebWork, I was thinking whether it would make sense to code a “translator” that would take the controllers from a Rails app and generate WebWork actions from them. Granted, translating Ruby to Java is probably rather difficult, but the WebWork action skeletons could be generated quite easily given the naming conventions used in the Rails controllers. Methods in Rails controllers map to methods in WW actions, Rails filters can be easily mapped as WW interceptors, etc.
This would make sense if you start your work on the interface first, refine it as a Rails app then generate the WebWork skeleton and continue working in Java implementing the business services. Essentially Rails would be used as a quick prototyping tool.
Any comments on this?
on Jul 15th, 2005 at 10:09 am
Well said. As much as I like the speed with which I can develop in rails, I still get a warm fuzzy feeling whenever I see that Eclipse refactor menu. There’s a lot to be said for great tools. Unfortunately, I can’t afford IDEA, but Eclipse 3.1 is wonderful. And groovy? The eclipse plugin sucks, but it’s become my favorite way to work with XML. For you ruby folks, it has closures and builders! Very cool. There’s a lot of great stuff going on in the Java open-source community, and I don’t think we have to worry much about Java’s future.
on Jul 15th, 2005 at 11:35 am
Jon,
I use HotSwap every day. Yes, it is limited for sure, but IDEA will tell you when things can be hot-swapped in. Also, it is all the more reason to write your interfaces early and then fill in the blanks at run time
Also, running in debug mode has never been any slower for me than running without debugging turned on, at least for day to day development (not load tests).
I do this on Java 1.4 and 5.0
Patrick
on Jul 15th, 2005 at 1:05 pm
HotSwap is mostly useful when you’re doing algorithm changes. It’s especially useful when you find a bug, break the execution in the problem method, fix the code, rebuild-and-swap, and then continue execution from the start of the method to check that it works better now.
It is much less useful when your (static) code structures are still in flux.
Essentially, the further you are in a project, the more useful it becomes. So don’t try using it at the start of a project, but switch it on once your interfaces and object structures have settled down a little.
Maarten
on Jul 15th, 2005 at 6:48 pm
It’s great to see that you’re warming up to the importance of productivity, Patrick. I think HotSwap sounds like an interesting approximation, but I’d be pretty frustrated and disencouraged whenever I wanted to change interfaces. I don’t at all work in a specify-all-upfront, then program-it-all-afterwards mode.
Anyway, I agree that good tools are nice. I liked IDEA a lot when I was doing some Java work. I obviously enjoy pushing productivity into the core tools (the language, the framework) rather than layering it on top. BUT, I’d certainly like to have IDEA for Rails.
Good tools are important. Java is blessed to have IDEA and Eclipse.
on Jul 16th, 2005 at 2:48 am
Maybe this just means that rubyeclipse.sourceforge.net project could attract more development?
In freeride.rubyforge.org:s newest version 0.9.4. experimental refactoring support is deactivated because it doesn’t work too well.
And, there is no Windows or Linux version for x86 of TextMate, so I’m kind of lost what editor to use on Windows or Linux to code RoR.
on Jul 16th, 2005 at 8:20 pm
Hi all.
I have to disagree.
The language shapes and fundamentally defines what kind of tool support you can have.
Creating a refactoring tool like Idea for Ruby (or any other pure dynamic language) is impossible because you are severely limited on what you can statically reason about.
You will be left with tools that are little more than search and replace macros – loosing the “semantic preserving” guarantee that is what refactoring is all about.
Static typing has its strengths and weaknesses. It is more verbose and it can worsen the impedance mismatch between RM and OO.
But tool support: refactoring, UML-diagramming etc. is where it shines.
on Jul 16th, 2005 at 11:20 pm
There is nothing in the Java language that makes it as heavy as the some of the so-called best practices make it. It’s proven to be as light weight as any scripting language such as beanshell — in my mind Java is just a strong typed scripting language that can be pre-compiled. Ruby has done a great job of showing the Java community that there is an easier, more efficient and more enjoyable way to write code.
The problem seems to be somewhere between a grotesque fascination with XML configuration files and the market-purported need for heavy application servers. Java isn’t heavy; it’s how people use it that makes it seem heavy.
Thank you for pointing out that there is a better way to develop then to deploy an app before running it. In the development team I work in we use a combination of Tomcat, Eclipse 3.1 and a project laid out like an expanded WAR to get all the benefits of so called code/alt-tab/refresh aka CAR (why not another TLA?) development. When Tomcat can’t handle a hotswap of the code the JVM terminates and restarts — with moderately fast machine this restart is not noticeable.
Here’s the rest of the environment for the heck of it. All in-container unit tests are done with Jetty/http-lib, Hibernate/x-doclet is used for O/R mapping and a stripped down struts+velocity setup for the web framework.
on Jul 17th, 2005 at 11:07 am
Christian: You do realize the first refactoring IDE is the Smalltalk Refactoring Browser, right? The fact that the first refactoring tool support was created for a dynamic language kind of destroys your claim.
on Jul 17th, 2005 at 7:09 pm
Hi,
I’m from a C/C++ background, and whilst C/Unix was great in its’ day, I think we’ve got a bit stuck on the C legacy and need to see beyond C derived languages. As an advocate of Agile development, I agree that productivity is significant, and dynamic languages are just more productive (and fun).
Also static languages don’t really fully support OO semantics (IMHO). For full OO semantics I think that late binding of messages to methods at runtime is crucial (something overlooked in C++). The nearest Java gets to this is interfaces.
So ruby is a step in the right direction, but if people could just let go of the C like syntax the options increase.
Dynamic, pure 00, with a great class library and a great IDE? Sounds like Smalltalk!
I just do not understand why this obvious choice (to me at least) is so often overlooked.
on Jul 18th, 2005 at 5:31 pm
Heya Mike.
I wasn’t trying to be controversial – static typing helps intelligent IDEs. It is a fact. Heck. Even Fowler says so in his famous blurp on dynamic typing:
Another area where static typing is useful is that it allows programming environments to be much more helpful. The revelation here (as in so many things) was IntelliJ. With an IDE like this I really felt the type system was helping me. Even simple things like auto-completion are greatly helped by static types, and leading IDEs can do much more than that.
(From http://martinfowler.com/bliki/DynamicTyping.html)
on Jul 19th, 2005 at 2:17 am
Hi Christian,
Have you ever tried a dynamic language with a good supporting IDE (e.g. VW Smalltalk)? Try it and see what you think. Before Intelij can use your type system to help, you need to type in a hell of a lot of extra information first. Also there is a lot of stuff that a static language stops you doing, hence the need for patterns like factory, null object etc.
I know of no one who has tried both and feels that static languages are more productive (even using intelij).
on Aug 15th, 2005 at 1:01 am
Zsolt, you can try starting with Rails, then convert it and change to Java. Maybe it would work. But after some real experiments, you will fall in love with Ruby and Rails, and converting to Java will not be neccesarry. I know it, because I wanted to do it with Perl.