Debate: Should the Java language stop adding new features?
Recently, there has been a lot of debate over the future of the Java platform, with some arguing for more features to compete with languages such as C# and Ruby, and others saying that Java should become a more stable language lest it become too complicated to use. Bruce Eckel started a new round of debates by stating that Java should stop adding new features entirely.
In his blog post, Bruce Eckel said that Java needed to stop evolving if it is to stay in the mainstream, and that it is already "too noisy" as a language, with code being unnecessarily verbose (e.g.
System.out.println()). Eckel identified Java generics as an area in which the complexity added has caused concern, and also described what he sees as a key problem with Java:
The only control we have over complexity is abstraction: hide the parts that don't matter ("divide and conquer" is a variation). The paradox of of Java is that a critical aspect of the complexity problem was ignored; code readability was not considered an important issue. It seems that if the IDE writes the code for you, then it doesn't matter if that code is needlessly complex.
[Joshua Bloch] took this idea of complexity one step further. He said that it's not just the complexity of a particular feature in isolation, where it can often seem fairly straightforward. It's the combinatorial complexity that you get when you combine a new feature in every possible way with the other language features. When you shoehorn a feature into an existing language rather than carefully designing it in from the beginning, you cannot control how that feature combines with other existing features. The combinatorial complexity can produce horrifying surprises, typically after the feature is added when it's too late to do anything about it. Over breakfast Josh noted that this kind of complexity makes for a bountiful supply of Java puzzlers; entertaining for him but not good for the community as a whole.
Eckel identified himself as a "feature junkie" who had always thought of language evolution in terms of new features, but now questions whether a feature should be skipped if it can't be implemented correctly (as with Java's generics). Eckel noted that both C and C++ are very stable, and mentioned that Java should stabilize as well rather than chasing after new language features or otherwise trying to follow every market impulse. The idea of breaking backwards compatibility was also raised, with the opinion that those who want the old features can stay with the old version and not upgrade to the new Java. Eckel also warned against the perils of maintaining backwards compatibility at all costs:
If we can't insert features correctly because of backward incompatibility, we are straightjacketed when it comes to language changes; we are in the same position as C++. C++ is often criticized because of its design, but I was on the standards committee for 8 years starting at its inception, and I saw all the debate around each language feature. These were not made capriciously, but very carefully and thoughtfully. What produced the complexity and difficulty of the resulting language was one thing: backwards compatibility with C. Once you bind yourself to backwards compatibility with anything, you must be prepared for your language to be corrupted as you add features. If Java is unwilling to break backwards compatibility, then it is inevitable that it will acquire both unproductive complexity and incomplete implementation of new features.
Eckel described new languages as the correct place for fundamental new features, and said that Scala was "the current best exit strategy for Java". He also stated that Java's only salvation would be to become a workhorse like C and that only cleanup and fleshing out of incomplete libraries should be done in the future, with major language changes like closures being left to other languages rather than being bolted onto Java.
Kevin Dangoor agreed with Eckel, saying that adding new features to a language which requires backwards compatibility will be clumsy at best, and pointing out that ECMAScript has the same problems as Java has in this realm. Dangoor also questioned the criticism that developers are always looking for new, shiny features to help with projects:
Software is the stuff of thoughts. It’s very malleable and new ideas can be tested out fairly cheaply. With the internet, new ideas and code can spread far and wide quickly. This is all a good thing. For me, creating software today is tremendously better than it was 5, 10, 15, 20 years ago. I watch many of the shiny things go flying by, but I don’t actually use them. But I consider the shiny things to be very important. There are all kinds of ideas wrapped up in there that can be applied in different contexts and with different tools. Some of the implementations that come out of those ideas will make it into the mainstream.
Generally speaking, people don’t switch to all of the shiny things that fly by. Some people will give them an honest try and will either be rewarded for being a successful early adopter or will suffer some pain and head back to other solutions. If enough people like the idea and follow through, it will become mainstream. Rails was the shiny new thing in 2004. There were undoubtedly people who felt the pain of being early adopters, but many more were far more productive than people using other tools that were common back in those days. Regardless of how many people ultimately adopt Rails, the fact is that many of the ideas presented there have had a significant influence on work that has happened since.
Cay Horstmann also chimed in, saying that there needs to be less focus on the syntax of Java, and more focus on the pain points. Horstmann also referred to C++ and said that Java addressed the two major pain points it had, which were memory management and GUI/database access. However, Java now has it's own pain points which need to be addressed:
- Boilerplate code - getters and setters, event listeners written as anonymous classes, and long type declarations which could be inferred by the compiler
- Web application development - this is difficult, and developing web applications with complex and underpowered technologies like JSP and JSF "is like eating soup with a fork"
- Concurrency - "I am not smart enough to write a nontrivial concurrent program where I can say with confidence that it won't ever deadlock and that it won't have any race conditions. Just like I was not smart enough to write a nontrivial C++ program where I could say with confidence that it won't ever leak or corrupt memory"
Some other opinions:
- Phillip Calçado agreed that Java should be fixed rather than expanded, but disagreed that Java is inherently difficult to read saying that Java was more readable than languages which existed when it was created like C++
- Richard Relos said that most Java code doesn't use new language features anyways, and that adding more new features just dilutes developer attention and logic formulation
- Ian Cooper saw parallels with C#, and questioned whether it too is reaching the point of diminishing returns while agreeing that the place for major new features was a new language
- Giovani Salvador voiced concern that if features are no longer added to Java that it will become obsolete, and that Java developers will become "dinosaurs"
What do you think?
Java feature set
In my opinion, Microsoft did the right thing when designing .NET 2.0 - abandon backwards compatibility in favor of implementing new features completely and correctly. They were consistent enough to "drill out" the type system and runtime. Consequently, C# generics just work the way you would expect them to. C# 2.0 just feels very natural.
In constrast, Java generics are basically useless - for all but the most trivial cases, you're stuck with compiler warnings, lots of artificial casts, or you simply can't do things the way you wanted to. Generics are a great thing if you can actually use them. In C#, you can. In Java, you can't.
I don't understand why Java generics have been implemented that naively. Everybody should have realized that type erasure won't do the job. So I don't take the argument that in order to "not let a disaster like generics happen again, we won't add any new features to Java".
I would strongly advocate adding some missing features to Java, and implementing others (i.e., generics) correctly. Java is a rather primitive programming language. Yet I fear that Sun won't ever take that route.
More missing features
In Java, you can't directly assign an Integer to a Long, which is what you would naturally expect to work. Integer and Long derive from Number, but there's no way of smooth conversion between numbers (aside from the artificial intValue/longValue).
In C#, you have conversion operators (and operator overloading in general, which Java doesn't offer), and the compiler can convert between number types in a very natural way.
Re: Java feature set
The JVM can support meta-programming on existing byte-code and duck typing, see Groovy.
There's probably an opportunity to create a version of Java that breaks backward compatibility on the byte-code level (for example, adding methods to java.util.Collection) but this will be a language separate from Java.
Since we already have those - Groovy, Scala - it seems that those that limit themselves to the Java language will have to accepts its idiosyncrasies. However, those same people can combine Java with other languages on the JVM: Groovy, JRuby, Scala, ...
Maybe it's time to give up this fetish with the Java language and embrace the richness of the Java Platform.
Re: Other languages
Maybe it's time to give up this fetish with the Java language and embrace the richness of the Java Platform.
Very well said. The JVM has a lot of future, but I'm unsure about the Java language. There are far expressive languages today, that can be ported to the JVM. I would suggest to everyone to have a look at the Io programming language - it's very, very promissing. www.iolanguage.com
IT's Centre of Gravity has Moved to XML; Java Needs Native XML Support
With increased SOA thinking (whether SOAP or REST), there is more emphasis on XML as a language to abstract and represent the interface to encapsulated domains, more emphasis on XML as a data interchange language between such autonomous domains. Java has now hunkered down to be more of an implementation language _within_ a domain, and in a SOA world, it needs to be able to handle its interactions with other domains better, i.e., it needs to handle XML much more elegantly and naturally.
Contrast the elegance of this E4X example (which "mashes up" two XML documents) with anything currently possible in Java, and you'll see what I mean:
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Mashup Demo (Pure content aggregation)</title>
Grocery list with items and quantities only (e.g., my shopping list)
var gList = new XML();
<line-item prodid="tomato" qty="4"/>
<line-item prodid="potato" qty="3"/>
<line-item prodid="onion" qty="6"/>
<line-item prodid="chilli" qty="40"/>
alert ( "Raw shopping list\n\n" + gList );
Grocery unit prices (e.g., supermarket prices)
var gPrices = new XML();
<prod id="potato" unit-price="10.00"/>
<prod id="tomato" unit-price="20.00"/>
<prod id="onion" unit-price="30.00"/>
<prod id="beans" unit-price="40.00"/>
<prod id="chilli" unit-price="0.50"/>
alert ( "Grocery prices\n\n" + gPrices );
Mash up the two pieces of content to produce an augmented grocery list with
individual costs and total cost
var total = 0.0;
for each ( i in gList.descendants("line-item") )
i.@amount = i.@qty * gPrices..prod.(@id==i.@prodid)["@unit-price"];
total += Number( i.@amount );
gList..list["total-amt"] = total;
Display the mashed-up list
alert( "Mashed-up shopping list\n\n" + gList );
Copy and paste this example into an HTML file and view it in your browser. You'll see what Java needs to become.
I've blogged about this here and here. Sure, Java can stop adding features, but not before it supports XML natively.
My two cents.
Re: IT's Centre of Gravity has Moved to XML; Java Needs Native XML Support
Power to Weight ratio
There is no need to freeze Java's features. Nor is there need to stuff the entire kitchen sink into it.
Clean up the house!
Very good points.
1) Backward compatibility serves Microsoft well enough for them to suffer (or is it inflict upon it's users?) the inevitable problems which come with it for one very good reason. They are currently a virtual monopoly in the desktop OS and productivity suites market - and if they break backwards compatibility and are forced to compete with themselves they will open the market to other competitors. Is that the case for Sun? No, they are competing in a very aggressive market again (at least) DotNet and RoR (if not LAMP and others). I think that Sun is insane to place such a high premium on backwards compatibility in such a competitive market when the other options will start to look better and better over time. This is why MSoft is so happy to forgo backwards compatibility with DotNet but not with Windows or Office.
2) Clearly generics are a disgrace. I have made it a point to use them correctly as best as I can understand them and am continually surprised by them. I remember the STL in the 0.2, 0.3 days and it reminds me of that (but with much better error messages!). Still people are missing a point about it. It wasn't backwards compatibility with the Java language that limited the design, it was backwards compatibility with the JVM itself, which is a whole other kettle of fish! Would it have been worth it? Maybe. Msoft seems to version the DotNet runtime separately from the language and it doesn't seem to bother them. But generics (unlike closures but similar to continuations) are a much bigger change than any other as the whole platform needs to evolve.
3) I fear that Scala is just too complex for the masses (due to it's functional programming roots). Although I understand what I see with Scala, I just can't think of solutions to problems in a way which leverages it's power - a problem which simple closures in Ruby and Groovy do not suffer from. I think Scala should be officially 'adopted' by Sun like JRuby (same with Groovy actually), but I think it's a mistake to push something so advanced as the mainstream approach.
4) Having said that, of all the changes ever proposed for Java - a full closure proposal - one which would allow creation of new 'control statements' would be for me the single best change that could be made. Closures are a HUGE way to improve the quality of the coding. With a single change - although closures themselves may be hard to write (like generic classes) the senior developers on projects can make such plain abstractions for the access to the resources that the others need that code will be free of the badly handled exception/finally and synchronized blocks. It's HUGE! I don't care if it is in Java 7 (or lets say Java 1.7) or a new and shiny Java 2.0 - but I want it!
Re: Java feature set
Add the features
The only reason to "stabilize" a language is if it is so hopelessly foregone that new essential features cannot be added in an intelligent way to the language. There is nothing inherently difficult about the Java syntax that would prevent new features from being added.
Re: Java feature set
C# did NOT break any backward compatibility when they introduced generics in C#2.0. You can run your old bytecode written on .Net1.0(and 1.1) DIRECTLY on .net2.0 without any recompiling or any modification. Microsoft solved this backward compatiblity issue by keeping both their generics and non-generics versions of all the classes in their SDK (i.e. they have both Dictionary and Dictionary<T,Y>). So the new .Net2.0 framework will still be able to run all your old non-generics .net1.0 libraries just fine.
When Java talked about "backward" compatibility, they were actually talking about "forward" compatibility. They were talking about guaranteeing that the old Java4 will be able to run the newer applications written on Java5. Silly. Silly silly goal. Even sillier, considering that in practice you normally won't be able to run your new java5-targetting-applications on java4 anyway.</t,y>