Jun 02 2007


Ruby vs. Java Myth #1: Project Size

This week, I abruptly switched gears from working on a green-field Ruby project to pitching in on a well-established Java project. Revisiting Java provided a good chance for me to set down in words how we at Relevance think about platform choice. This week I will be posting a series of five myths that often misinform platform choices for new projects.

Myth #1: Ruby is suitable for small projects, and Java is better for large, complex projects.

This is exactly backwards. In fact, Java is more suitable for small, well-defined projects, while Ruby is better for large, complex, open-ended projects. There are several reasons Java wins for small projects:

  • On small projects, finding the right open-source library often means you have nothing to do. Java has more libraries than anyone. Advantage: Java.
  • The budget for a small project can be blown by a few gotchas that require unexpected development effort. Java is much better known and documented than Ruby. Advantage: Java.
  • On small projects, teams don't have time or budget to acquire new skills. Most teams already know Java. Advantage: Java.

On a large project, all the factors above get reversed:

  • There is a lot of new work to be done, so language productivity matters more than having libraries to choose from. Advantage: Ruby.
  • Large projects are sure to have many gotchas, so you need maximum flexibility in responding to change. Advantage: Ruby.
  • On a large project, retraining pays for itself. Companies grossly underestimate this. A five-week(!) training course on a technology that makes a developer 10% more productive would pay for itself in about a year. Advantage: Ruby.

If the myth is so backwards, why does anybody believe it? Ruby is, at present, exceptionally good at one specific kind of small project: database-backed web applications. Ruby on Rails counteracts all of Ruby's small-project disadvantages:

  • Rails is the library you need.
  • Rails eliminates the gotchas (for small projects!)
  • Rails has a great out-of-box experience, so web developers need little retraining (for small projects!)

For web applications, Advantage: Rails.

People see the success of Rails and draw exactly the wrong conclusions. There are lots of visible, successful, small Ruby on Rails projects. There are lots of visible, successful, large Java projects. Look at these facts without broader context, and you get Myth #1.

Jun 01 2007


Object Models: Not What, But Who

The important thing about an object model is not "what is in it," but "who can change it." Charles Nutter provides a nice demonstration of this with his field-initializing new method. Open classes empower library writers, and make it easier to keep code DRY.

When languages are tightly controlled at the expense of library developers, you end up with the bad side of design patterns.

May 23 2007


Recontexting and Hygienic Code

When building software, we are often faced with a choice: Should we build just what we need now, or should we do extra work now to make things easier in the future? Consider this simple example:

  // 1. Simple
  GasGrill grill = new GasGrill();
  Hamburger h = new Hamburger();
  grill.cook(h, 375, 8);

This is great, but what if I want a charcoal grill? One alternative would be use a factory:

  // 2. Factory
  Grill grill = GrillFactory.newInstance();
  Hamburger h = new Hamburger();
  grill.cook(h, 375, 8);

Now, the details of grilling are hidden behind the GrillFactory, and we can choose another grill without modifying code. Or, I could avoid the dependency on factories with POJOs and dependency injection:

  // 3. Dependency Injection
  public class InjectionGrillAction {
    private Hamburger h;
    private Grill g;
    public Hamburger invoke() {
      g.cook(h, 375, 10);
      return h;

Agile practice argues "You Ain't Gonna Need It (YAGNI)." So we could build the simple, concrete implementation, and switch to factories or DI only when and if necessary.

Modifying code to be more flexible or general is one form of refactoring. Refactoring is a Good Idea, but in this case there is a Better Idea. What if we could recontext? Instead of changing the code, we change the context in which the code runs. Consider this example:

  # 4. Hygienic: grill_main.rb
  h =
  g =
  g.cook(h, 375, 8)

Is this an example of the Simple, Factory, or Dependency Injection approach? You can't tell, without context. Depending on what other code runs first, the Hygienic code might exemplify any of these approaches, or none. I can run the code in a Simple context:

  ruby -rsimple_context grill_main.rb
  => Hamburger is medium_rare and has a totally generic flavor

Or, I can run the code in an Injection context:

  ruby -rinjection_context grill_main.rb
  Hamburger is medium_rare and has a generic outdoor flavor

The injection framework I am using here supports injection through system properties, so we can inject a charcoal grill:

  export Grill=CharcoalGrill
  ruby -rinjection_context grill_main.rb
  => Hamburger is medium_rare and has a delicious charcoal flavor

The Hygienic approach is as simple as the Simple approach, and more powerful than the Dependency Injection approach. How is this possible? All of the other approaches commit to too much. Rather than simply solving the task at hand, the Simple, Factory, and DI approaches all embed presumptions about future needs. They either do not plan for the future at all (Simple), or they complicate the code with concerns peripheral to the task at hand (Factory, DI).

Hygienic code cleanly commits to solving the task at hand, and avoids committing to anything else. This is a simple idea, but look what it does to some sacred cows:

  • Factories (and most other design patterns) are code smells.
  • Refactoring IDEs may have done more harm than good. How often are you refactoring code that should be recontexted?
  • POJOs are a necessary evil. In more hygienic languages, the notion of a POJO is almost meaningless.
  • Domain-Specific Languages (DSLs) are a Good Thing. They naturally tend to be hygienic.

If you are interested in learning more about hygienic code, we are integrating this approach into our curriculum. Or, come to North Carolina and work with us.

May 22 2007


The Business of Rails

At RailsConf, I had the distinct pleasure of serving on a panel called "The Business of Rails". Nathaniel Talbott organized it, and asked Joe O'Brien, Robby Russell, Andre Lewis, Geoffrey Grosenbach, and myself to participate.

First of all, thanks to Nathaniel for getting this on the schedule. The number of people in the room, and the subset of those people that were thinking of starting a business based around Ruby and Rails, was awesome to behold. If only the most excellent Extra Action Marching Band had held off for a few more minutes, we'd have had a complete success. As it is, we lost part of the crowd to this. Such is life.

Also, since the panel was such a success, and so many people wanted to continue the conversation, Robby set up a Google Group for anyone who wants to keep the discussion going. So, drop by the Ruby on Rails meets the business world group and be part of the revolution!

May 21 2007


Language Matters

My Design Patterns are Code Smells post has been picked up by It is interesting to read through the comments. One side exchange about Test-Driven Development includes this observation:

I think the point of the TDD comment is that TDD forces you to consider using interfaces to reduce coupling between classes.

Yes, near 100% of my data access interfaces have exactly one implementation. But I never create these interfaces because, gosh, I may want to change from Oracle to Some-New-Cool-Database in the future.

This is a terrific example of how implementation languages color your thinking. Notice how easy it is to switch between concept and implementation details:

  • "TDD forces you to consider..." (conceptual)
  • "...using interfaces to..." (language-specific)
  • "...reduce coupling..." (conceptual)
  • "...between classes." (language-specific)

There is nothing wrong with this level-jumping; it is often more concise than speaking at a single level could be. Just make sure that you understand what level you are playing at, and why. Otherwise you might conclude that

  • "If only I had an interface ..." (language-specific)
  • "...then I could mock my data access layer..." (conceptual)

which says more about your platform choice than it does about the problem at hand.

May 21 2007


Domain Driven Design

In Design Patterns are Code Smells I argued that Design Patterns are heavily influenced by implementation language. This should not be surprising, since design patterns are often translated directly into code. What about higher design abstractions? Surely as you get more distant from the code, the language dependency goes down. You wouldn't expect to see UML, or Domain-Driven Design, or Model Driven Architecture, totally colored by implementation language, would you?

In fact, you should. I have been reading a lot of software design and architecture books lately, and have come to two conclusions:

  1. No matter how far you get from code, design and architecture is inevitably colored by the designer's knowledge of programming languages.
  2. The design literature unintentionally creates a vicious lock-in around programming languages, as follows: Design books tend (even more than programming books) to fixate on the most popular programming language at the time they are written. Call it Language X. Enterprise developers need "lots of design", because they are writing "serious" code. Q.E.D., enterprise software must be written using X, because the design books (implicitly) say so. But this is not the designers' intent! Designers are not making proactive language recommendations. They are making reactive, lowest common-denominator choices in order to reach a broad audience.

I will be expanding on this topic at the Rails Edge in Chicago, August 23-25. In "Domain-Driven Design in Ruby," I will revisit the concepts in Eric Evans' excellent book, but with Ruby-colored glasses, and maybe even a bit of a Lisp. You can find the abstract here (scroll down).

May 18 2007


Nice review of R4JD

Rafi Jacoby says this about R4JD:

This is probably one of the best programming books I’ve read. It was a quick and easy read, and really hooked in well with my background. All scenarios are laid out as “here’s how you’d do it in a Java stack, and here’s how Rails does it.”
Thanks Rafi!

May 17 2007


Design Patterns are Code Smells

In the original GoF book, the authors made it clear that when you are doing design patterns, implementation language matters:

The choice of programming language is important because it influences one's point of view. Our patterns assume Smalltalk/C++ language-level features, and that choice determines what can and cannot be implemented easily. (Design Patterns, p.4)

Unfortunately, this message has generally been lost, and programmers all too often use patterns as recipes. Martin Fowler explains the difference:

Recipes tend to be more particular, usually tied to a particular programming language and platform. Even when patterns are tied to a platform, they try to describe more general concepts.
If you have seen a Java or C# application that looks like a C++ recipe collection, you know the damage that conflating these two concepts can cause.

Regardless of how you distinguish patterns from recipes, the programming language that you think in will be the programming language you design for. This is one reason why the Prags encourage everyone to learn one new language a year. You will still design for the union of the languages you know, but at least you will not be hopelessly provincial.

Language advances kill patterns-as-recipes. Back in 1998, Peter Norvig argued that most of the original GOF patterns were invisible or simpler in Dylan or Lisp. Since then, Greg Sullivan has made the same point for Scheme. Jan Hannemann demonstrated the same for Java+AspectJ. Design patterns do not perform well as recipes. They are seasonal at best.

At code level, most design patterns are code smells. When programmers see a design pattern in a code review, they slip into somnolent familiarity. Wake up! Is that a design pattern, or a stale recipe from a moldy language?

May 16 2007


Microsoft Licensing Apology

In my post about Silverlight, I described the Microsoft Permissive License as the "Nixon-mask" of open source licensing. I was confusing the MsPL with the Microsoft Limited Permissive License, which restricts usage of the code to Windows-only boxes. My apologies, the MsPL really seems like a fine (if redundant) addition to the OS Licensing space.

May 16 2007


Groovy and Grails: Three Worries

Yesterday I blogged ten pleasant surprises with Groovy and Grails. Let me reiterate that overall, I am impressed. But there are a still a few issues that make JRuby a more promising alternative at present.

  1. Groovy classes are not open. I understand the reasons for this decision, but I want the productivity boost possible in a language where this is legal:
      class Person { 
        def firstName; 
      p = new Person();
      class Person {
        def lastName;
      p.lastName = 'Halloway'
    My example here is trivial, but the concept isn't. For more on both sides see here and here.
  2. Grails is not written in Groovy! (For the most part.) I went looking for the implementation of the chain method, and it was a whole Java class to itself. I am hoping that the Java bias is legacy, and that the Grails team is now more comfortable eating Groovy dog food.
  3. The "optional static typing" argument is a red herring, until somebody produces some compelling examples. Groovy advocates point out that they have the best of both worlds--dynamic typing with static typing available on request where needed. This sounds good, and it may be good, but show me some significant examples. Better yet, articulate some rules of thumb for when to use dynamic typing, and when to use static typing, within a single Groovy project. This is a serious request, not flamebait. Instead of debating "static typing--yes or no?", let's debate "static typing--when?" in a language with a clean syntax for both.

Popular Tags