Monday, March 20, 2006

Enterprise Sour Grapes

Recently a post by James McGovern on Why Ruby Isn't Enterprise Ready floated my way. I felt it necessary to offer up a response. My disclaimers: I am not familiar with McGovern's past work, I am not (yet) using Ruby in the "enterprise", and I am far from a Ruby or Rails expert. I am, however, trying to bring Ruby the capabilities of Enterprise Java using JRuby, and I've done a bit of Enterprise work during my ten years as a Java developer.

Point-by-Point Responses

McGovern's points are not all bad, but most of them are either poorly realized or amount to chicken-and-egg arguments: Ruby isn't in the enterprise now, so it's not ready for the enterprise. I'll try to blaze through the nonsense and tackle the substantive issues more directly.

Point 1: Books for Ruby Suck and are too introductory
Nonsense. Ruby as we know it today is young and has only garnered attention over the past few years. Books are written to be sold, and since almost everyone doing Ruby work has started very recently, the market for introductory books is largest. There are, however, more and more people interested in enterprise Ruby, and so the books are starting to follow. It will take time, just as it did for Java, but it doesn't mean Ruby isn't ready to make the jump to "enterprise" software.

Point 2: Huh? (i.e. poorly-written nonsense)
I couldn't really glean out any specific point being made here. I'm not familiar with "insulting" firms, though perhaps that's a crude attempt at humor. Assuming he means "consulting" firms, he's only partially right; obviously if an organization already has an "enterprise" plan, they won't be told how to rewrite it. However, any consulting firm worth its mettle will try to follow the same best practices when building out a new architecture or conforming to an existing one, and those practices aren't specific to any language or platform. This has nothing to do with Ruby.

Point 3: Ruby isn't enterprise ready because consulting firms aren't doing it
Nonsense. Consulting firms have a vested interest in keeping their technology portfolio tailored to the demands of clients. They also have an interest in telling clients what they actually want, so those demands continue to fit their portfolio--just like Enterprise Thought Leaders have a vested interest in convincing others their platform of choice is the best solution. Regardless, Java has a huge presence in the enterprise space, and has become the perfect vehicle for consulting...a well-understood, boring, accepted platform. .NET is well on its way to "boring" as well. Ruby will have work to do to "break into" this world, but its absence there says nothing about its viability as an enterprise platform. It's a small fish in a big pond...but fish grow.

Point 4: Magazines read by enterprise architects don't cover Ruby
Nonsense. This doesn't even make sense, since I doubt McGovern can speak for all "enterprise architects". If he means "enterprise architects that only use Java or .NET or don't read about languages", then he may be right. Otherwise he's making a blanket statement that's obviously impossible to prove and is at best totally wrong.

Point 5: Fortune 500 company-employed architects don't blog about Ruby
If this is true, then they are at risk of being passed up by others that do read and blog about Ruby. However this is another statement that says nothing about Ruby's enterprise capability. It only continues to say that "Ruby isn't enterprise now, so it's not ready for the enterprise."

Point 6: Large enterprises like big vendors (i.e. the same old Open Source FUD)
Ruby is garnering more and more attention from the "big vendors", but they're naturally cautious about leaping into a new language that may or may not be the right way to go. However, this argument could have been said for languages like Python, which now sees extensive use in enterprise apps and for which Microsoft has been funding IronPython for their CLR. Ruby is simply a tool; the eventual platform we will use to build enterprise applications is being built and will be built upon that tool, and it will in many cases be "big vendor"-driven.

Point 7: Big vendors can't make money off Ruby
Sun does not make a lot of money off Java, if they make any at all. Microsoft does not make a lot of money off the .NET languages. In either case, what little income they gain is offset by the massive research and development staff making those platforms possible. They make their money by selling products related to those platforms, such as toolsets and server software and hardware. Nobody is making money "selling Java" or "selling C#", just like nobody makes money "selling C" or "selling Ruby". As in the real world, the market for tools pales in comparison to the products of using and deploying those tools effectively. And again, this says nothing about Ruby's technical merits.

Point 8: Legal transparency is more important than software development productivity
This has nothing to do with Ruby or anything else, except to say that "so what if there's productivity gains to be made...I'm too busy dealing with the lawyers". Certainly, the cost of answering a subpoena may offset productivity gains elsewhere in an organization. However, McGovern does nothing to demonstrate any causal relationship between the two. I'm not entirely sure that he's demonstrated anything at all.

Point 9: People, then process, then tools
If tools matter least of all, then whether the tool is Ruby or some other language is entirely irrelevant. This point basically states that all his other concerns about Ruby in the enterprise are moot. Huzzah!

Point 10: Do not talk about Fight Club.
There is no point 10 in McGovern's post. I'm not sure if this is intentional or due to carelessness but judging by the rest of the post I'd expect the latter.

Point 11: More ranting about productivity
The absurd productivity gains claimed by some in the Ruby community are a concern, but these same sorts of numbers have been used for every Next Big Thing. Undoubtedly, Ruby will have an effect on productivity, and I believe it will have a strong positive effect, but this point has nothing to do with Ruby in specific.

Point 12: More ranting about books
Complaints about a particular magazine's method of giving out "awards" or publisher's use of those "awards" to market books has nothing to do with Ruby. There's plenty of SD Magazine "award-winning" books in the Java and .NET worlds too.

Point 13: Productivity gains are outweighed by increased contract negotiation time
Clients are interested in getting the best value for their dollar, but are also interested in tried-and-true technologies. As mentioned earlier, Ruby is still young, but its youth says nothing about its capability in the enterprise. I remember plenty of companies that shunned Java early on for the same reasons...if I'd followed their advice I'd be looking for COM+ and Microsoft DNA work. It's just another chicken-and-egg argument that has affected every other language and platform since there have been such things.

Point 14: Agile methodologies should emphasize code generation and the agile community doesn't get it
Other than a brief mention of Ruby, this doesn't seem to have anything to do with the core thrust of his post. It's worth mentioning that the poster child for Agile development, Rails, generates a large amount of its code before and during deployment.

Why Respond to such Drivel?

I've heard many folks ask this question about responses to such misguided "thought leaders" as Mcgovern. Why respond to nonsense? Why give air to FUD?

There's probably a few good answers.

First off, not responding implies to many that there are no counterpoints to be argued. Responding to a well-written and well-thought-out post is probably less important than responding to FUD, since the latter is generally filled with lies and vitriol. This is the case with McGovern's post; the points are not valid and generally say nothing about Ruby, but the title and thrust of the posting implies such. Other "enterprise architects" that skim through such a posting may use it to solidify their own prejudice and bias toward specific tools and platforms, which only hurts the evolution of software and software development. It is for this reason that I choose to respond and choose to publicly call out such bogus claims as well as I am able.

Second, such posting make us folks actively working on Enterprise Ruby more than a little pissed off, because the content is so weak and the facts are so twisted. Consider this post my outlet for such frustration. Edmund Burke said it best: "The only thing necessary for the triumph [of evil] is for good men to do nothing." Perhaps McGovern is not evil, and perhaps I am not good, but I will not stand by and do nothing. If roles are in actuality reversed, I would expect the same from McGovern.

Third, we like to talk. This is certainly true, but does not necessary imply any malice. I like to sue me.

Rails' Generators Are Working

I considered making a post last week, to keep up my at-least-one-posting-per-week schedule. However, I had dug myself deep into Rails' generator script and the built-in generators and resolved myself to finally get them running. There were a number of more complicated issues to solve, but it felt like I was very close to having it working. Any of you all-night hacker types know the feeling; success is just around the corner...maybe this is the last bug...maybe this run will complete without errors.

I can now announce that as of this evening, all the built-in Rails generators appear to be running and generating correctly using JRuby.

This has certainly been a hard-fought battle, and the last week had some big fixes:

  1. As mentioned in Pickaxe, Object does not actually define any instance methods; instead, it mixes them all in from Kernel. However, the original design of JRuby had followed Pickaxe in form rather than substance, defining those methods on Object. While this did not typically affect the functioning of normal Ruby code, it did break one library in particular: delegate. DelegateClass, in delegate, uses Kernel's list of public instance methods to select which methods on the target class are to be delegated. Rails uses it internally for, among other things, delegating some behavior for generator commands to a generator base class. Fixing the issue meant redefining the Object instance methods as Kernel module methods...a fairly major change, but one that does not appear to have caused any other regressions.
  2. My recent addition of binding support had a small flaw. The current chain of method calls in JRuby to do an eval is long and winding (much longer than I would like), and one link in that chain I did not inspect caused two issues: evaluating with a binding did not correctly set "self", and completion of that eval did not correctly reset it. In lieu of cleaning up the eval chain (which I commit myself to eventually do), I made a few modifications so "self" would work correctly.
  3. Enumerable#collect should work without a block; this is not documented in Pickaxe and finding this issue from deep within the bowels of 'generate' was a painful chore. This is a perfect example of a miniscule bug that causes massive trouble; the fix was less than a line of code, but the bug prevented 'generate' from correctly mapping and executing any actions. And why would you want to collect without a block? Answer: if you only have "each" defined and wish to turn your Enumerable into a simple array.
  4. JRuby's Module code inexplicably defined a singleton "new" method. This prevented Module subclasses from defining their own initializers that call "super". I'm still not sure why this was there, but it has been removed.
  5. Module#ancestors failed to include singleton classes.
  6. Java does not support the concept of a process-wide "current directory" as Ruby does. In order to fake this behavior, JRuby originally modified the system property "user.dir" to point at JRuby's new current directory. This was not only a dangerous thing to do, but was also not sufficient to make current directories work correctly. It also would drastically affect all other code running in the same JVM that depended on "user.dir" being correct. My modification was to introduce into JRuby a runtime-wide "current directory". In addition, I fixed a problem in Dir.chdir where failures in the provided block prevented chdir from resetting the dir back to its original location.
  7. Dir.mkdir dir not handle multiple levels of dir creation. The simple fix was to use Java's File#mkdirs instead of File#mkdir. How easy bug.
  8. IO#read returned nil at EOF, instead of the correct "".
  9. File#join did not clean up multiple dir separators in a row, resulting in invalid paths like "app//models".
Busy, busy, busy. On top of these fixes I also helped resolve a few regressions discovered by a hardcore JRuby user (who also happens to be a team member). If only I had another eight hours a day to work on this stuff. But, I digress.

At any rate, you're here to read about the generators.

Rails Generators

Part of what makes Rails so agile and powerful is its beautifully simplistic code generation capability. By using the "generate" script, you can generate perhaps 90% of a working web application. With the 1.0 release, there are generators built in to create models, controllers, mailers, plugins, web services, and database and session migration code. There are also third-party generators for quickly generating other bits and pieces of a typical web app.

The generator code is fairly extensive, but unsurprisingly it does not exercise all of Rails' code. It does, however, represent the typical "first step" into the Rails world, and so I set out to get it running in JRuby. After many tests and fixes, documented in my other blog entries and immortalized in CVS, generators now work.

A few test runs to demonstrate:

C:\rails>jruby script\generate scaffold "myapp/Account" open close balance
create app/controllers/
create app/helpers/
create app/views/open
create test/functional/
dependency model
create app/models/
create test/unit/
create test/fixtures/
create app/models/account.rb
create test/unit/account_test.rb
create test/fixtures/accounts.yml

C:\rails>jruby script\generate web_service User add edit list remove
create app/apis/
exists app/controllers/
exists test/functional/
create app/apis/user_api.rb
create app/controllers/user_controller.rb
create test/functional/user_api_test.rb

C:\rails>jruby script\generate plugin SiteMinderAuthentication
create vendor/plugins/site_minder_authentication/lib
create vendor/plugins/site_minder_authentication/tasks
create vendor/plugins/site_minder_authentication/test
create vendor/plugins/site_minder_authentication/README
create vendor/plugins/site_minder_authentication/Rakefile
create vendor/plugins/site_minder_authentication/init.rb
create vendor/plugins/site_minder_authentication/lib/site_minder_authentication.rb
create vendor/plugins/site_minder_authentication/tasks/site_minder_authentication_tasks.rake
create vendor/plugins/site_minder_authentication/test/site_minder_authentication_test.rb

And so on. It's a pretty big milestone to finally have these generators working, and it means that one more step in the Rails development process now works under JRuby. I'm very pleased.

There are a few caveats (of course), but all told they're fairly minor. Rest assured they'll be remedied forthwith:
  1. Among other block arg tricks, specifying an index into an array or hash as a block arg is still nonfunctional. This will require interpreter work and possible parser changes.
  2. There are a couple warnings that display while running 'generator', but they are safely ignored. I believe they are overzealous warnings within the parser, left over from Ruby 1.6.
  3. I can neither confirm nor deny that the generated code and content is correct; however, it looks correct to my untrained eye.
  4. Not all the above fixes are committed; not all fixes committed are guaranteed not to cause regressions.
  5. I'm no Rails expert, despite swimming in the deepest parts of its ocean. I will be putting my Pragmatic 'Rails' book to heavier and heavier use now that we're finally putting JRuby on Rails.
The next big step will be continuing on to get Rails proper running with JRuby. The fixes I've contributed should help speed that process along, and Tom is already well into it. After wrapping up those last minor issues, I will endeavor to help him.

So there you have it. Great progress has been and is being made, and I'm having fun making it happen. Hopefully Rails actually running is coming very soon...stay tuned.