Skip to main content

Chapter 7: Ruby on Rails

9 replies [Last post]
invalidname
Offline
Joined: 2003-06-09
Points: 0

Chapter 7 looks at Ruby on Rails in detail, considering it as an alternative to the usual combination of enterprise frameworks (e.g., Spring + Hibernate, or EJB) used in Java web applications. To justify this coverage, Tate recalls his first experiences with RoR:

"As I've said, I worked with a company that builds safety software for a manufacturing plant. We effectively build a web user interface to manage a complex domain model. We decided to build this application with a lightweight Java stack of Spring, Hibernate, and Web Work. We moved pretty quickly, and were pleased with our progress. We were proud of our accomplishments, because we'd rewritten a one-year Microsoft application in four months with Java. Naturally, as we accumulated a bigger code base, coding began to take longer.

Over time, Dave's arguments nagged at my subconscious. Dave and my business partner had the same conversations. As luck would have it, over the same week, we tried building a part of the application in Rails. I banged out the model and scaffolding in a couple of days. With his stronger HTML experience, Justin got further than I did. He actually implemented the whole application in Rails in four nights. The Rails version shocked us in another way--it was actually faster!"

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Anonymous

This reminds me of an excellent article about using the C# properties feature in C++. The gist of it is, is that yes it's faster, but more difficult to maintain over the lifecycle of the app. Now if you are just whacking out apps for clients, speed is of the essence. But obviously there is much more to software development than cranking out lines of code. One of the issues with 4GLs (remember all the xBASE or Access apps?) is that people mistake RAD for quality development - not so.

That is why I think Sun should work harder to carefully add language changes, rather than 'hey in my C# programming class I see they added properties to C#, we really need that in Java...'. For example, I like 'assert', but agree with the rest of the posters that we should leave the syntactic sugar out. So far from the Ruby I haven't seen anything spectacular - I can more easily build a HashMap? Write a for - loop faster?

As far as ActiveRecord beating Hibernate - so what? With Java, I have many, many persistence options, I choose what works best for the requirements. Java relies on XML too much? Well, that was because everybody thought XML was the greatest thing since sliced bread, even saying XML would replace Java, and started using XML for things it shouldn't be used for. But that's a reflection on tools like Hibernate and Spring, not Java.

Don't get me wrong, I use other languages such as Perl, C++, VB, Python, even Javascript, as necessary. But will Ruby replace Java? Hardly. That's what everybody said about XML, Python, Groovy, C#. Like C#, Ruby simply isn't that much different (and personal pet peeve, I can't stand the perl-like reserved characters like using the @ sign, like perl's $ sign, symbols should never be used like that in my book).

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1615.pdf

olsonje
Offline
Joined: 2005-08-10
Points: 0

> It took less time to go from from one version to the
> other since the whole logic of the application is
> well understood. The new version can fully use the
> broad knowledge and does not have to go around
> kludges that where introduced. Basically you have a
> clean and fully working design.
>
> Quite often in a "four nights" work you come up with a
> skeleton, I mean, unless the application is truly
> trivial (the the real issue is really on the plan) you
> have to have icons, you have to have labels, you got to
> do cross browser testing... etc. etc. I can build an
> application in one night if it fits the model of the
> framework that I normally use but it will still be a
> skeleton since it misses testing, gui details, customer
> changes..
>
>So, basically, what you do is take a clean design,
>implement a skeleton and declare a winner. Hmmm, this is
>just a biased comparison to me, much better would be to
>start from scratch (including defining the spec) build
>prototype, change it, mess it, clean it, test it, all
>the usual mess that comes out of a project and has
>nothing to do with the language.

This actually was talked about in the chapter 1 discussion, I'll post Mr Tates response to my question regarding this exact debate.

[i]
[b]bruce tate Re: Chapter 1: Owls and Ostriches Posted: Nov 7, 2005 9:42 AM[/b]

> I haven't recieved my copy of the book yet, so I
> can't answer this for myself, but does he take into
> account the time previously spent on understanding
> the project domain & any other issues in the inital
> creation of the java version and factered/considered
> that into the RoR time?

Let me go into the experience in a little more detail. Justin had been writing the code, and I'd been working as an analyst, and done some data modelling (and written some hibernate code for the app). I played with RoR after a couple of conversations with Dave Thomas. My goal was just to satisfy a nagging doubt...what if I'm wrong, and there's a better answer for my customer? I did just the Active Record model in just 2 days. I called Justin to brag, and suggest that RoR was in fact pretty clean and real (MVC; partials; templates; etc), and he'd started to play with it for the same reasons and had completed the app in 4 nights, blogged about it, and run performance tests. Selling to the customer was easy.

I've got no problems with people who say a job should be faster the second time...but that much faster??? I mean, we were doing CRUD with an existing data model. Not rocket science. Working against us was this: neither of us had ever written a line of Ruby in our lives.

So saying "it's much faster the second time" is kind of like saying "Yeah, but it's a dry heat" in a 120 degree Phoenix. I mean, give us a little credit. We've developed software before, and all great programmers have rewritten code. This was a much different experience.

But thanks for the question...and thanks for asking instead of jumping to conclusions.

[/i]

murphee
Offline
Joined: 2003-06-10
Points: 0

> Java gives up launch speed to portability (JVM),

Launch speed doesn't stem from using a virtual machine, but from some design decisions in Java. For instance, the bytecode verifier (which takes time for application classes; this will be changed in Java 6 to use the .NET and J2ME approach of perverified classes).
Another problem is the fact that the class is the basic code unit, so each class has to be loaded, handled and linked seperately (unlike loading DLLs .NET assemblies which are simply mapped into memory and include large chunks of code or classes. I'm not whether this could be improved, although the Java 5 CDS changes had improved this).

> gives up code simplicity in favor of code check at
> compilation time (instead of runtime crash),

See... this is a property that has been disappearing more and more in the past years. Java libraries rely on Reflection more and more... and just look towards all IOC containers & friends... all of that happens dynamically without and compile time checking doesn't help because all the compiler ever sees is java.lang.Object or Strings that hold class names, method names, etc.
Not to mention the various Design Patterns prevalent in Java designs, where you handle Commands, Interpreters (the pattern), Hooks, Proxies, ... all of these further reduce the helpfulness of the static type checking.
And you're suddenly in the realm of UnknownMethodException, ClassCastException, ... etc.

So... Java is moving more and more dynamic constructs where static type checking doesn't or can't help... actually, I slowly see it as a distraction in many situations where I have to basically re-implement feature subsets of a dynamic language because I want the dynamicity, but can't have it easily.

Oh... and on the matter of "Static Checking prevents runtime Errors"... ... so you've never seen these exception in the wild?:
- ClassCastException
- UnknownMethodException
- IllegalArgumentException
- NullPointerException
- IndexOutOfBoundsException
- ClassNotFounException
- ConcurrentModificationException (Iterators throw them)

... OH... and *my* personal favourite:
- UnsupportedOperationException (which undermine the whole static checking business completely; a class that implements an interface but doesn't want to support one operation then implements that method BUT throws a RUNTIME Exception. So the class says it supports the method... except that it doesn't. You won't find that one without unit tests... or not at all). Just look at the Collections API to see that this Exception is recommended there.

I'm a Java dev, and I also like some of the benefits of static typed languages... but ... as I said: even in Java code, there are less and less places where it *really* helps. Whether we continue using Java or switch to purely dynamic languages, developers will need to know/learn how to deal with both.
And repeating the mantra of "Static typing catches bugs early" is silly, because it's just plain wrong. "Static typing catches typos early" is right, but anyone who seriously believes that logic errors are caught by static typing or the compiler... well... I happen to have a nice bridge to sell to those folks...

> it gives
> up simple hacking into calling 'c' in favour of
> security,

JNI?

> gives up gotos and basic syntax like in
> favour of OO approach, how's Ruby ?

Static typechecking and the fact that it's harder to know what a method expects or returns just by looking at it's signature. There are coding standards to get around that (parameter names should include a hint as to which types are wanted etc), but I don't think there's something for return types.

bonefry
Offline
Joined: 2005-05-12
Points: 0

> See... this is a property that has been disappearing
> more and more in the past years. Java libraries rely
> on Reflection more and more... and just look towards
> all IOC containers & friends... all of that happens
> dynamically without and compile time checking doesn't
> help because all the compiler ever sees is
> java.lang.Object or Strings that hold class names,
> method names, etc.

Oh yeah, let us forget completely about static type checking. Really my friend, if Java (a static typed language) is allowing dynamic behaviour, I would call that a Good Thing TM.

> Not to mention the various Design Patterns prevalent
> in Java designs, where you handle Commands,
> Interpreters (the pattern), Hooks, Proxies, ... all
> of these further reduce the helpfulness of the static
> type checking.

What do design patterns have to do with everything ?
Does anyone force you to use a specific design pattern ?
Too bad.

> So... Java is moving more and more dynamic constructs
> where static type checking doesn't or can't help...

Again, because in Java you can do it, that's a Good Thing, not a sign of weakness ;)

> actually, I slowly see it as a distraction in many
> situations where I have to basically re-implement
> feature subsets of a dynamic language because I want
> the dynamicity, but can't have it easily.

Yes, but the problem is with Ruby you cannot have static type checking whenever you want ;)
And that's a Bad Thing.
I would rather stick with Java, a static and strongly typed language, and have dynamic behaviour whenever I want to than dismiss static type checking because I am too lazy to implement dynamic constructs a little harder that I would in Ruby.

> Oh... and on the matter of "Static Checking prevents
> runtime Errors"... ... so you've never seen these
> exception in the wild?:
> - ClassCastException
> - UnknownMethodException
> - IllegalArgumentException
> - NullPointerException
> - IndexOutOfBoundsException
> - ClassNotFounException

Not as often as I see compilation errors ;)
Also, NoSuchMethodException is a checked exception (the most important of the whole lot, which you misspeled btw)

> - ConcurrentModificationException (Iterators throw
> w them)

Well, that's when one doesn't know how to implement thread safe iterators, and really, what connection does this exception has with static typing ?

> ... OH... and *my* personal favourite:
> - UnsupportedOperationException (which undermine the
> e whole static checking business completely; a class
> that implements an interface but doesn't want to
> support one operation then implements that method BUT
> throws a RUNTIME Exception. So the class says it
> supports the method... except that it doesn't. You
> won't find that one without unit tests... or not at
> all). Just look at the Collections API to see that
> this Exception is recommended there.

Aha, and how many times have you bumped into this one ?

Also, unit testing is recomended on all platforms, static or dynamic, and nobody said static typing saves us from unit testing.

> I'm a Java dev, and I also like some of the benefits
> of static typed languages...

No, the way I see it you are here to brag about your new toy.

> but ... as I said: even
> in Java code, there are less and less places where it
> *really* helps.

Guess you are the expert.

> Whether we continue using Java or
> switch to purely dynamic languages, developers will
> need to know/learn how to deal with both.

Because you are the one thinking in terms of one language rules all. I work with Java, Ruby and PHP almost on a daily basis. Ruby is better for some tasks indeed.

> And repeating the mantra of "Static typing catches
> bugs early" is silly, because it's just plain wrong.
> "Static typing catches typos early" is right, but
> anyone who seriously believes that logic errors are
> caught by static typing or the compiler... well... I
> happen to have a nice bridge to sell to those
> folks...

Ha, ha, ha, and ha ... this is where you realy blew it. No, experienced developers never claim static typing catches logic errors.
But if you fail to see the benefits of static typing I hope no friend of mine will ever be your customer.

> > it gives
> > up simple hacking into calling 'c' in favour of
> > security,
>
> JNI?

You are wrong here, as no other platform was kept more pure than Java. Although JNI is heavily used, at least it's used when no pure Java alternatives can be used.

But in Ruby you can't even have a pure XML DOM parser that doesn't suck without dropping to C code ;)
It makes me wonder, if I have to drop to C code (that's hardly multi-platform btw) for every bottleneck I have, were is that productivity ?

And you know what ?
Bruce Tate is really low in my eyes right now.
4 days vs 4 months ? What a dumb statement.
What sane developer could ever believe this ?
Of course, as always dumb managers who couldn't tell the difference between a potato and a keyboard.

And yeah, just to be clear about it, my company does have a PHP team that just started out learning Ruby and they all love it because their productivity was really boosted.
I love it too as I have a really complex deployment script written in Ruby, plus a couple of pet projects already.
But Ruby will never replace Java, no matter how much you geeks want it.

murphee
Offline
Joined: 2003-06-10
Points: 0

> > java.lang.Object or Strings that hold class names,
> > method names, etc.
> Oh yeah, let us forget completely about static type
> checking.

Where did I say that? My point is that it gets more common to use dynamic typed constructs in Java. Wherever you use these, you won't get help from static typing, so the argument that static typing catches bugs early is wrong.

> Really my friend, if Java (a static typed
> language) is allowing dynamic behaviour, I would call
> that a Good Thing TM.

It is good... but if Java developers are using these dynamic constructs then they'll have to consider that they won't get benefits the from static typing in that code.

> What do design patterns have to do with everything ?
> Does anyone force you to use a specific design
> pattern ?
> Too bad.

Sigh... if you program, then you'll use solutions described in Design Patterns. Not because someone tells you to, but because the DesignPatterns book was an analytical description of code patterns in the real world. Interpreter, Subscribe/Publish, MVC, etc are concepts to get things done... any many of them also allow more dynamic behaviour.

> > the dynamicity, but can't have it easily.
> Yes, but the problem is with Ruby you cannot have
> static type checking whenever you want ;)

I'm aware of that. But there's a solution: JRuby, Jython, Javascript (with Rhino), etc.
Use the dynamic language and concepts when you need the freedom and dynamicity, use static typing when you really need to.

Not to mention that reasearch in these areas is going on and will only be increased due to increased popularity of languages like Ruby.
Gilad Bracha (Sun 'Compuational Theologist" I think) has a paper on that, where he talks about Pluggable Type systems. A link and my own thougths on that can be found here:
http://jroller.com/page/murphee/20051103

> want to than dismiss static type checking because I
> am too lazy to implement dynamic constructs a little
> harder that I would in Ruby.

It's not that it's "a little harder"; it's a matter of
*re*implementing stuff in Java that are available in Ruby... stuff that isn't even listed as a feature because it's just the normal way it is.
Not to mention that the extensibility of modern languages allows to do more *inside* the language without messing with the language itself. Just watch all the effort going into AspectJ and friends... a new language (or Superset of Java, if you like)... just for a bit of crosscutting and other concerns? That's possible in dynamic languages with a few lines of code...no mention of changing the language spec, having to update all tools, educating developers, etc.

> > - ConcurrentModificationException (Iterators throw
> > w them)
> Well, that's when one doesn't know how to implement
> thread safe iterators, and really, what connection
> does this exception has with static typing ?

It's not about concurrency issues; ConcurrentModificationException is thrown if you modify a Collection while an iterator is iterating over its contents.
How can this happen? Just try writing a fireEvent method that iterates over the listeners. If you use an iterator, you can get the CME if a listener unregisters in the event handling code.

If you don't believe me, see the SwingHacks book, where this is actually a seperate "Hack" or tip.

> > ... OH... and *my* personal favourite:
> > - UnsupportedOperationException (which undermine
> Aha, and how many times have you bumped into this one
> ?

Try removing something from a List that has come out of Collections.unmodifiable* Methods.

Not to mention that I've seen this when using some PGP crypto library ... which decided that it didn't want to support some methods in the JCE and just threw Runtime Exceptions (can't remember if it was this Exception or a custom one).
This made the API about as usable for programming as a minefield for a bit of tapdance...

> Also, unit testing is recomended on all platforms,
> static or dynamic, and nobody said static typing
> saves us from unit testing.

Well... then why does the argument "Static typing catches bugs early" always appear in discussions such as this? (see the BeyondJava forums, listen to the JavaPosse where I've heard it several times, etc).
This seems to be a believe that's out there and it's wrong.

You're right, UnitTesting will solve this problems... but if you already have a complete UnitTestSuite for you product that calls every method and shakes out problems... then how is that worse than static typing?
You'd catch typos, and other type errors with your UnitTests anyways...

> > I'm a Java dev, and I also like some of the
> benefits of static typed languages...
> No, the way I see it you are here to brag about your
> new toy.

I'm here to discuss the benefits that dynamic languages have and how they can benefit development.
You said yourself, that it's a GoodThing that Java supports dynamic features (Reflection et al).
But let's remember that these features were an improvement over languages like C++, where dynamic classloading is much more difficult than in Java (where it's a nonissue... because it's the normal way).
Add in Reflection & co, which were taken from dynamic languages when Java was designed in 1995.

Now it's 10 years later, the Java features are accepted and added to programmers toolboxes... now it's time to steal some more from the dynamic language area...

> language rules all. I work with Java, Ruby and PHP
> almost on a daily basis. Ruby is better for some
> tasks indeed.

So... what exactly are we arguing about?

> 4 days vs 4 months ? What a dumb statement.
> What sane developer could ever believe this ?

If you read his statement you'll see that he had already developed the app in Java before, and thus had already solved all design issues and problems. From what I see, he simply reimplemented it in Ruby/Rails.

In that case, it's easy to claim 4 months vs 4 days.
Developing an app from scratch is something different.
If you simply look at the ration of 4 months vs. 4 days it's of course unrealistic... but then it's not managers pushing Rails but geeks and many Java devs among them

> But Ruby will never replace Java, no matter how much
> you geeks want it.

Why should I want to replace the Java platform? I'm earning my money with it and it's a huge platform that contains everything that one can need (libraries, tools, etc).
But: it does not mean that Java (the language) is the last word in language design. Only Scott McNealy sunk as low as to say that everyone should port *everything* to Java... but I doubt he'd say that again nowadays.
Not to mention that I'm slowly losing trust in the Java language development team, after such nonsense as static imports added to the language (I won't discuss Generics).
With all the mad talk about adding direct XML to the language & all, I'm looking for possible(!) exit strategies from the Java language that will allow me to keep on using the Java platform.

I don't believe the hype... but that doesn't mean that it can't be used to get things changed and maybe even improved... just look at the changes in the Java space that have trickled in over the past 4-5 years. Hibernate, Spring, etc. as simpler alternatives to the heavyset EJB2.x. If you believe that software will write itself just because you're using Spring, Hibernate, etc... well... good luck. But these API have still managed to get EJB3 to be created, which shares their concepts.

Rails is just another step ... and an effective one... just look how it got developers of web frameworks for all languages to copy it's design (Sails, Trails, Grails; various efforts for doing something like it in PHP; for Pythong, etc) and look for ways to make work easier.

leouser

As someone who develops an application in Jython and Java, if I had my pick Id choose Java. In terms of productivity, Im not sure if Im really that more productive in Jython then Java. Im starting to think after working with dynamic languages that they may be actually more complex as an implementation than say Java is. To get at what Im saying, is that you have to consider that your dynamic language code is only a snapshot, its structure is inheriently more unstable than say Javas is. I guess an example from real life that was a bugger was when I ran across some Python code that I was converting to Jython/Java that altered the type of a variable at some juncture during its running. It went from being a List to a Set. Why? I guess it was a blunder on the developers part. How did it escape the test harness? You got me, you can't test everything away. Even if you had a unit test for this particular case, nothing stops some other piece of code from altering it. This particular problem would not have happened in Java, our friend the compiler would stop it.

Readability wise, I find the productivity boosting conciseness of the dynamic languages, cut against it. Usually from perusing some Java code you can figure out what the heck it is after doing a good read. You know who the players are, the addresses variable is a List. With Python, you can get, hmmm there's an iteration here but what does self.addresses refer to... its not in the __init__ or set in this method? Let me see if the find function of this editor can get at it.. not in this file. Let me try the project search... hmmm... its in the AddressGiver class, that's odd.

With that said, I like working in Jython/Python. It's fun. But as I said in the beginning, I still like working in Java better.

leouser

Tired

I'm already tired with all this Ruby stuff. Is this java.net or ruby.net. Why this java forum has topics starting with Ruby. We have java you have ruby. However this site is, and should stay about java. Good bye.

dbolla
Offline
Joined: 2003-06-17
Points: 0

I say that the plan is the hell and the detail is the devil..

It took less time to go from from one version to the other since the whole logic of the application is well understood. The new version can fully use the broad knowledge and does not have to go around kludges that where introduced. Basically you have a clean and fully working design.

Quite often in a "four nights" work you come up with a skeleton, I mean, unless the application is truly trivial (the the real issue is really on the plan) you have to have icons, you have to have labels, you got to do cross browser testing... etc. etc. I can build an application in one night if it fits the model of the framework that I normally use but it will still be a skeleton since it misses testing, gui details, customer changes..

So, basically, what you do is take a clean design, implement a skeleton and declare a winner. Hmmm, this is just a biased comparison to me, much better would be to start from scratch (including defining the spec) build prototype, change it, mess it, clean it, test it, all the usual mess that comes out of a project and has nothing to do with the language.

What my reasoning is that you cannot lower entropy forever, if you do this you will end up writing a program using only one byte, so, someone please tell me what Ruby gives up in favor for what it has.

Java gives up launch speed to portability (JVM), gives up code simplicity in favor of code check at compilation time (instead of runtime crash), it gives up simple hacking into calling 'c' in favour of security, gives up gotos and basic syntax like in favour of OO approach, how's Ruby ?

Cannot be all and only good, can it ? :-;

archangel
Offline
Joined: 2003-07-01
Points: 0

> I say that the plan is the hell and the detail is the
> devil..
>
> It took less time to go from from one version to the
> other since the whole logic of the application is
> well understood. The new version can fully use the
> broad knowledge and does not have to go around
> kludges that where introduced. Basically you have a
> clean and fully working design.
>
> Quite often in a "four nights" work you come up with
> a skeleton, I mean, unless the application is truly
> trivial (the the real issue is really on the plan)
> you have to have icons, you have to have labels, you
> got to do cross browser testing... etc. etc. I can
> build an application in one night if it fits the
> model of the framework that I normally use but it
> will still be a skeleton since it misses testing, gui
> details, customer changes..
>
> So, basically, what you do is take a clean design,
> implement a skeleton and declare a winner. Hmmm, this
> is just a biased comparison to me, much better would
> be to start from scratch (including defining the
> spec) build prototype, change it, mess it, clean it,
> test it, all the usual mess that comes out of a
> project and has nothing to do with the language.

I agree with many of your points, but there is still a difference in the order of magnitude in development - four months to four days. I doubt the rewrite could have been done in Java that quickly.

With regards to the sacrificies made in Ruby, like Java, they're acceptable depending on your point of view. The biggy is less static checking of code - this means that the compiler will save you less (but you've written unit tests right?), but you get a more flexible programming model. There are many others (syntax, code blocks, portability etc.). It depends on your point of view.