Picture of stu

Static Typing and Readable Code

  • Posted By Stuart Halloway on May 12, 2007

Neal's post Static Typing is Communist Bureaucracy has drawn out the usual arguments on both sides of dynamic vs. static typing debate. I fielded many of the same kinds of questions at my Rails for Java Developers talk at Java University.

One of the most common questions asked by people moving from static to dynamic languages is "How can I tell what the code does without the type information?" This is a good point! Static typing makes code readable, just like training wheels make a bicycle ridable. But eventually you want more than not-falling. You want elegance and speed.

Here is a specific example from R4JD. Consider the following (old school) Struts+Spring code from a simple CRUD app.

  public ActionForward edit(ActionMapping mapping, ActionForm form,
                            HttpServletRequest request,
                            HttpServletResponse response)
      throws Exception {
    PersonForm personForm = (PersonForm) form;
    if (personForm.getId() != null) {
      PersonManager mgr = (PersonManager) getBean("personManager");
      Person person = mgr.getPerson(personForm.getId());
      personForm = (PersonForm) convert(person);
      updateFormBean(mapping, request, personForm);
    }
    return mapping.findForward("edit");
  }

There are nine static types in play here: one return type, four arguments, one exception type, and three local variables. An experienced Java developer should have no trouble reading this code. Here is the equivalent Ruby on Rails code:

  def edit
    @person = Person.find(params[:id])
  end

There are only two dynamic types in play here: the params and the @person. A novice Rails programmer should have no trouble reading this code.

Why are the two examples so different?

  1. The Struts example uses four typed arguments where the Rails example uses none (equivalent objects are available as fields on the controller instance, but they are out of sight unless you need them).
  2. The Struts example introduces two types (Exception and PersonForm) for no other reason than to make the compiler happy. This is the obvious example of Neal's Communist Bureuacracy argument.
  3. The Struts example uses two different objects to represent the same person: personForm and person. In the Java world this approach is a good thing, and called separation of concerns. Compared to a more flexible language, this is another form of the Communist Bureaucracy. Because Java classes are closed at compile time, you must get the separation of concerns right at design time. In a language with open classes (Ruby, Groovy, Smalltalk, et al) you can separate the concerns only when and if they need to be separated.
  4. The Struts example introduces a manager layer. More Communist Bureaucracy. The manager layer anticipates a future that may or may not happen. Because the language is inflexible, future-proofing is often done during initial development.

Languages do not write readable code, programmers do. Trying to bake readability into a programming language is like trying to bake poetry into grammar. A better idea is to create a flexible language and let human creativity flow.

Comments
  1. Norman RichardsMay 12, 2007 @ 06:32 PM

    I think your problem comes from poor choice of framework and design patterns than from any typing required by Java. You could compare this to something like Seam which would not require any of that mess. In fact, if you use the built-in framework classes, you wouldn’t even need the edit method at all. The id parameter could be bound to personManager.id (for, example), and then then you could refer personManager.instance in your view. That would be a single annotation on your framework subclass (which is mostly empty – think active record) or one line in the pages.xml if you prefer.

    The type of complexity you are referring to is not at all necessary in Java.

  2. MasklinnMay 12, 2007 @ 07:03 PM

    Java having a god-awful static type system and no type inference doesn’t mean every statically typed language is like that you know…

  3. Cale GibbardMay 12, 2007 @ 08:42 PM

    Doesn’t this confuse static typing with the lack of type inference?

  4. Slava PestovMay 12, 2007 @ 11:50 PM

    Comparing a Ruby one-liner with some cruddy Java framework proves nothing. Have you ever used Haskell, Ocaml, Clean, or some other language with a serious static type system?

  5. Kabir SooryaMay 13, 2007 @ 12:30 AM

    Your point about the bureaucratic nature of common statically typed languages is valid. But from the title you seem to want to make the assumption that it’s true of all static type systems, which isn’t true as soon as you come up against type inference. For example, static typing and type inference in languages like Haskell and OCaml actually lead to extremely robust, expressive, & readable code.

    ~K

  6. oceanMay 13, 2007 @ 05:00 AM

    Well the example is very outdated which makes the argument difficult to take seriously. (I also wonder about all these programmers who are suddenly experts on Communist Bureaucracies? Hello?) Nobody writes code like that anymore except for poor schmucks trapped in Struts legacy code. In real world Java (check out Seam and the like) IoC and annotations (nobody writes form classes anymore!) would reduce the method to a single line of code equivalent to the RoR example: find the person with this id and stick it in the request. But ignoring this, I don’t see how this is an argument against static typing as it’s really an argument about api design.

  7. RubyhornMay 13, 2007 @ 03:08 PM

    Dear Java-basher Ruby-lover,

    I would be thankful if you keep hating Java. I’ll be thankful if you never use JRuby in the near and far future, because it is built on top of Java, Carls Marx Edition ;-) Keep on being creative with your powerful Ruby language and RoR framework that, oops, should rely on cron, jeez, Windows Task Scheduler, to run code periodically!

  8. RobertMay 13, 2007 @ 09:33 PM

    sigh What you’re comparing here are programming idioms, not languages. There is nothing in Java which says you couldn’t do “person = Person.find(persondId)” as a one-liner – nor is there anything that forces you to go down this path. I used to do Struts work where 95% of the usual boiler plate code was abolished, simply because we used conventions and wrote code to take advantage of those conventions – just like Smalltalk (and, for that matter, Ruby On Rails)

  9. Bob LeeMay 14, 2007 @ 12:47 AM

    Give me a break. You’ve just compared Rails to a seven year old web framework. It has nothing to do with static vs. dynamic typing. You can certainly write more concise code with a more modern framework.

    The way I see it, to make Ruby code readable and maintainable, you need to document the API you expect your parameters to fulfill and the API your return types implement. Otherwise, I have to trace through your code to figure out what you expect. This might not be that difficult if the parameter value never escapes your method, but it can get tricky if your store that value off in a field or pass it to another method—I have to find everyone who accesses that field and trace their usages of it, and I have to trace all possible implementations of the method you delegate to. If you have to document the API anyway, you might as well have a type system, as you’ll almost always end up with less duplication and fewer errors. Am I missing something?

    Though I’d love support for optional types, I’ll take mandatory static type checking over none at all. I’ll stick with Java, thanks.

  10. Christian RomneyMay 14, 2007 @ 02:13 AM

    Nobody writes code like that anymore except for poor schmucks trapped in Struts legacy code.

    That argument doesn’t carry much weight if you’re one of those poor schmucks. I’m consulting with a team of really smart people and we’re all knee-deep in a 3-year old project that was built on precisely the sort of code you see above.

    Having spent the last 2 years writing mostly Ruby code on Rails applications I can’t begin to describe how painful it is to deal with Struts.

    It’s not just the “extra typing (on the keyboard)” that’s an issue. It’s the rigidity of the language that slows you down.

    Incidentally, it’s not just a symptom of Java code, nor is Ruby a panacea. All other things being equal, however I’d much rather write code in Ruby, Python, Perl, or Lisp than C/C#/C++, Java or VB.NET.

  11. Hani SuleimanMay 14, 2007 @ 05:30 AM

    It’s examples like this that undermine all the smart useful ruby people out there. Idiotic comparisons of apples and oranges that show total ignorance of how to write java code.

    I could equally prove that ANYTHING is better than Java, just by showing some struts code. Not surprising mind you that you’re on Neal’s side, the same idiot who at JavaOne proclaimed that all developers have unit tests with 100% coverage.

  12. Stephan SchmidtMay 14, 2007 @ 09:31 PM

    @Bob: You’re totally right. Imagine refactoring and debugging a 1.5M LOC dynamic typed application which is 10 years old and still running.

    And am I the only one who is seeing more and more Ruby and Javascript frameworks with type declarations in their ‘JavaDoc” comments?

  13. Curt HibbsMay 15, 2007 @ 07:03 PM

    I beg to differ from most of the comments posted here. The Java example posted above is stereotypical of the type of Java code I have to deal with everyday. Sure its a bit extreme, sure it could be done a little simpler in other Java frameworks, but that doesn’t diminish the point.

    What would really be illustrative would be for someone to take this example and recode it in 15 or 20 different web frameworks so we could see the differences in many real-life scenarios.