Sunday, 14 December 2008

JDK 7 language changes - Devoxx votes!

Once again, the great Devoxx conference allowed ordinary developers to express an opinion on the future of the Java language. This time, the focus was on prioritising which changes should happen.

The figures given below are of course indicative only. They are based on those Devoxx attendees who actually participated on the whiteboards. Also, the figures are as recorded at the end of Thursday (Friday scores not included). The whiteboard photos are available which provide additional information. Bear in mind that my figures may disagree with the photos in some small way based on when I counted the results relative to when the photos were taken.

Given eight language changes, rank them according to priority

This year, rather than simple "do you like this yes/no" questions, we posed something tougher. Prompted by Alex Buckley, we asked participants to rank eight language change proposals. Voters had to mark the number one against their highest priority, two against their next highest and so on until they had no more priorities. Attendees could also vote against a proposal by marking an 'X'.

The voting system was not the simplest, and we know a few people didn't vote correctly. However, we do believe that the vast majority did vote according to the rules making these results valid. The total number of voters was around 220, so the results have good validity.

Feature Properties Multi catch Null handling List/Map syntax Extension meths Method pointers Multiline Strs Infer generics
1 33 47 70 10 6 8 9 61
2 21 56 38 16 8 10 12 49
3 30 35 27 35 10 15 21 35
4 25 26 15 42 17 13 28 19
5 10 20 15 29 13 25 29 19
6 14 15 8 17 23 21 27 15
7 14 9 2 18 24 25 24 11
8 26 19 2 9 19 23 32 8
X 29 1 12 8 28 24 15 0
 
Total Votes 202 228 189 184 148 164 197 217
Total votes
(excluding X)
173 227 177 176 120 140 182 217
Weighted average 4.08 3.41 2.49 4.32 5.36 5.25 5.16 3.07

Here are the first preference votes:

Adding the second preference votes:

Adding the third preference votes:

Adding the fourth preference votes:

Adding the remaining votes:

So, what do these results tell us?

Well, they are in fact amazingly clear. Null-handling was the first preference favourite by a small margin, ahead of Infering RHS generics and Multi-catch of exceptions. However, if particpants had been given just three votes, then these three would have scored almost exactly equal (135/145/138) and over double that of List/Map access (61).

Next in line (ignoring properties) was List/Map access using [], which can be seen by the big jump in third and fourth preference votes. Fifth was Mult-line strings, which developers seem to not be that fussed about.

Finally, extension methods and method pointers (method references) performed poorly in the vote.

Properties was shown to be the most divisive, with both a large number of votes for and against, and fewer in the middle preferences. For example, notice the high number of first preferences, but dropping back when adding second and third preferences. In addition, properties has a high number of low preferences and votes against (coloured black). Since properties isn't going to be included in JDK 7, the properties column is really just an interesting comparison data point.

Obviously in a free vote like this without any explanations, it is easy for people to not vote for items they don't understand. This could explain some the lower scores for Extension methods and Method references (see the total number of votes cast to confirm this). However, even taking this into account, these two don't seem to have as much support as the big three of Null-handling, Infering RHS generics and Multi-catch exceptions

It should also be noted that the graphs and the weighted averages are in line with one another.

Other language changes

In addition to the ranking above, there were some other votes.

The vote on closures was split 50/50:

Yes41
No41

The vote on abstract enums showed a majority in favour:

Yes24
No18

The vote on ARM (resource management) showed a large majority in favour:

Yes64
No11

The vote on some form of delegation showed a majority in favour:

Yes36
No9

The vote on for each over a string showed a majority in favour:

Yes34
No21

Summary

Firstly, a big thank you to the Devoxx voters, and to Stephan and the Devoxx organisers. I think this exercise was a huge success in participation. I'm certainly not in favour of language design by democracy, but I am very much in favour of gathering large scale information on what really causes developers pain. Clearly, handling nulls, RHS generics and catching exceptions are three big issues.

I hope to repeat the exercise again soon. And if any JUG (public or company internal) wants to do the same (maybe with different proposals) then I'd recommend it (and I've even got an Open Office presentation if you want some material - just drop me a line).

Any feedback or thoughts are welcome!

24 comments:

  1. Interesting. Why didn't you talk about another -small- feature that mind be interesting for Java7: improved "foreach" loops (where you can also get hold of the iterator inside the loop).

    There are several situations this construct would be valuable: how many times have you started a foreach loop to discover a bit later that you need to access the iterator or even an index (eg to check if this is the first/last item).

    ReplyDelete
  2. Stephen Colebourne14 December 2008 at 23:25

    Jean-Francois: This blog is simply about what was discussed at Devoxx. I hope to cover the enhanced for-each loop again soon.

    ReplyDelete
  3. I'm quite surprised that properties are such a divisive issue. It seems quite plain to me that *not* having property support as a language feature is a real pain in the proverbial.

    If done right, it costs nothing, makes code briefer and more transparent (since you can see in one place the type of property - r/o, r/w, w/o, whether it supports firing a property change event) without having to look through the mostly-redundant getters and setters (which are just source-code-bloat). Where's the issue?

    ReplyDelete
  4. I'm surprised that improved "foreach" isn't in the list because it was on the Devoxx board at some point. In fact, I remember Josh Bloch having a longer debate about it with a few of us standing around. The original comment was about a foreach that supports more types (all chars in a String for instance).

    Thanks for putting this together, it was fun.

    ReplyDelete
  5. The idea of another magic foreach behavior for Strings bothers me. The problem is deciding what to "each" over. Lines? Characters? Paragraphs (double newline)? Everyone has their own desire.

    Given that fact, I'm entirely unclear why having a magic foreach for String would be any better than just doing:

    for (String str : src.split("\n")) {

    It's obvious what you're eaching over, and we don't wire a specific preference into the language.

    ReplyDelete
  6. I'll also weigh in and say I think the null-handling call syntax is just asking for trouble. Not only will it lead to a proliferation of nulls throughout the system, it's also incompatible with primitive types. For example, if you have this code and one of the null-guards fires, what gets assigned?

    int i = foo()?.bar()?.baz()

    If it returns some magic integer value, we're destroying a perfectly valid result to make room for that value. If it raises NPE because it can't assign a null to int, we have a case where the code behaves differently depending on the return value of the final call. Bad idea, run screaming away.

    ReplyDelete
  7. +1 to what Charlie said about null-dereference. This feature needs an extra twist to make it handle edge cases and not spread nulls throughout the system.

    I am thinking of a "default" value to formally indicate "Yes, one of the expressions tested really was null, and we know how to proceed". E.g.

    int i = foo()?.bar() default -1;

    ReplyDelete
  8. Most of these small language changes seem like a horribly bad idea: They add more language complexity and confusion for very small gains.

    IMO, Multiline strings are the big exception where the gains really exceed the complexity growth.

    ReplyDelete
  9. My feeling is totally identical to that of Massimo's.

    The geek crowd seems to be very eager to turn Java into a C++-ish intellectual mind game.

    Down in the trenches we are still decorating our 300-lines SQL queries with 300 '+ "...\n"' beauties, making everybody else (Perl, Python, Groovy etc.) rolling on the floor, laughing. Only JavaFX is empathically padding our aching shoulders.

    ReplyDelete
  10. Stephen Colebourne15 December 2008 at 22:12

    Rhys: It is my impression that most developers are pretty comfortable with the idea of properties and the value they bring. I think the problem comes with integrating them into the syntactic monster of Java. Adding them in now would bring new NPEs where previously there couldn't be, and an overload of one of the most fundamental language features - field access. That doesn't necessarily mean that we shouldn't do it, its just that its very hard, and perhaps best left to newer languages.

    Hamlet: The for-each over characters in a string was included - see the last pie chart. In addition, I hope to have more data-points on for-each enhancements late this week.

    Charles: So how do you loop over each character in a string? The for-each loop can't handle that efficiently using a library (it gets boxed).

    Charles/Alex: I agree some more thinking is needed with primitives in the null-safe dereference. Bear in mind that the official vote was for both ?. and ?: from groovy, which I believe gives:

    int i = foo()?.bar() ?: -1;

    Massimo: I'm interested that you should choose multi-line strings, where many at Devoxx didn't. As with all these votes and collective input, no one person or group is wrong, nor are they right. Its just another data-point.

    ReplyDelete
  11. Why didn't you propose "reified generics" as a possible Java7 feature ?

    Realy we do need reified generics urgently in Java. What is the use of a genericity that you can not use using reflection API to introspect its type and perform automatic job on it ?

    ReplyDelete
  12. Why didn't you asked about "reified generics" support ?

    This is a must do feature, top 1 priority IMHO. Without reified it remove lots of genericity usage scenarios.

    ReplyDelete
  13. What i would really want to have is an operator for equals() with null management.

    Something like
    a =?= b
    translates internally to a == null ? b == null : a.equals(b)

    I think this would be much more usefull than the ?. operator (but it could be a nice improvement too)

    ReplyDelete
  14. Most important: don't mess up the grammar.
    Better to be conservative than sorry. See the problems introduced by autoboxing.

    ReplyDelete
  15. @Stephen: We can add property support without overloading field access. We just need a short but different syntax, i think there has been many proposal for this.
    E.g
    a.prop := value (for setter a.setProp(value)
    or
    a.:prop = value (this one can be used for setters and getters: value = a.:prop)
    The thing is we need to keep the grammar clean and the langague coherent.

    ReplyDelete
  16. Hi Stephen

    Good to meet you at Devoxx again.
    We should touch base about you coming up to London again, in 2009, and talking to JAVAWUG on either FAN or JDK 7 Small changes (or even both).

    Let's do this!

    ReplyDelete
  17. @testman: Alex Buckley commented on the issue of reified generics during a BOF session at Devoxx. Basically, the question he asked was: What do they really bring you apart from being able to reflect over the type at runtime? You'd still be not able to call "new T()" in Java. That's inherently not possible without introducing structural types. See one of Alex's blog posts on that matter.

    Furthermore, you would complicate the use of libraries because you'd have old code without generics, new code with erased generics and on top of that new code with reified generics. Sounds like an awful mess... to me at least.

    Well, I'm not 100% satisfied with generics as well, but I think they're good enough for what most people want to do. Reflecting over types at runtime would be nice, no doubt about that, but you can work your way around that with erasure to a certain extent...

    ReplyDelete
  18. Well – it’s sad that closures won’t make it in. I’m afraid that when people at Sun and Language gurus like Josh advise people to use a different language on the VM they might just do that – only it might NOT be on the VM but on a competing platform.

    Small changes that would be great for me are (in no order)
    1.) multiline string
    2.) resource block (because closures won’t ever get in with the politics)
    3.) multi catch block
    4.) type inference
    5.) null deferencing
    6.) [] syntax for lists
    7.) Method references
    8.) fix generics mess

    ReplyDelete
  19. Well – it’s sad that closures won’t make it in. I’m afraid that when people at Sun and Language gurus like Josh advise people to use a different language on the VM they might just do that – only it might NOT be on the VM but on a competing platform.

    Small changes that would be great for me are (in no order)
    1.) multiline string
    2.) resource block (because closures won’t ever get in with the politics)
    3.) multi catch block
    4.) type inference
    5.) null deferencing
    6.) [] syntax for lists
    7.) Method references

    ReplyDelete
  20. I used to be about sql strings in code, but after TRYING to maintain nightmarish scripting applications that concatenate sql strings every possible place in an app, I realized we shouldn't have multiline strings in the language for a reason. People don't generate Javascript/Html in Servlets anymore, why haven't backend programmers made that leap?

    What I wouldn't mind though is maybe an annotation that can load a file as a String. Then when you annotate method, it could be populated automatically for you. But then, why do you need that even if a StringLoader.load("/hereismysql"); static method would work fine...

    Yeah I don't agree with Strings in Java. not sure why the community is so into it.

    ReplyDelete
  21. re: "So how do you loop over each character in a string?"

    I would write a for loop. But perhaps I'm not the target market? foreach over collections, which have a lot of noise (especially in the case of generics) I understand. foreach over a primitive array, I'm not convinced is worthwhile.

    Re: foo()?.bar() ?: -1;

    If we ignore for the moment the fact that it looks totally heinous, are you actually saying that in order to handle primitive values as the terminal call on a series of null-handling dereferences you would *need* to use ?: or risk it returning a value you might normally expect to be valid? That sounds even worse to me. I don't see a way to reconcile ?. with non-nullable types without a lot of nasty, nasty edge cases. It works in Groovy because everything's nullable. It does not work in Java.

    ReplyDelete
  22. No comments wrt/ "Infer Generics." Stephen, what do you envision for this?

    Thanks,

    Dave

    ReplyDelete
  23. Stephen Colebourne21 December 2008 at 09:52

    Charles: See the next blog post for more votes wrt null handling. It may be tricky, but we should try to get something woking.

    Dave: Infer Generics means using <> on the RHS of a variable declaration to avoid duplicating the generic parameters.

    Reified generics: I personally don't believe this will ever happen in Java - its too complex.

    ReplyDelete
  24. @testman

    As Martin has said, there are ways to get (partial) type information using reflection.

    Unfortunately it's harder than it should be due to the "interesting" type hierarchy that has been implemented in java.lang.reflect, but it is (usually) doable.

    (Shamless plug)
    The orthodox library attempts to make it easier to work with the Java type system using reflection, if that's something you need.
    http://adjective.sourceforge.net/orthodox/

    ReplyDelete