> The cost of the C# approach is that existing classes could not be gradually migrated to be generic; existing
collections had to be effectively deprecated and replaced, or a "flag
day" had to be declared where all the code (library and client) changes
simultaneously. These are not options for us. At the risk of being
obnoxious, C# was able to get away with it because at the time, they had
a very small base of existing users and code and were not yet successful
enough to have to worry about compatibility.
The reason C# was able to do it is not because they had so few users that a "flag day" was acceptable, it was because they went with the first option and rewrote all their collections. C# did genetics right the first time, and didn't end up in this bizarre type-erasing, half-ass world that Java find itself in today.
Site note: I liked how both authors took pains to be respectful in their tones, keeps the focus on the issues at hand and avoids people getting irritated with one another.
Agreed. Gavin's post didn't seem to acknowledge that this was a proposal and seemed to belittle the work put into it...but I found Brian's overly defensive (though I agree with his conclusion).
Having seen Brian's stewardship talk at ClojureConj, and now this, it seems clear that he feels the need to be defensive against the non-Java JVM languages out there.
I vote for not making the language more complicated than it already is in Java 7. Oh but we have Java 8 with closures and stuff, well OK how about no more complicated than Java 8. Please? Instead maybe introduce useful things that make programmers more productive. How about implicit generics. Where this whole mess of T and Any and <: extendsT< gobbldygook> melts away. Notice how a new class extends Object automatically? It always has. Why do I have to muck about with all the fancy and overly complex syntax. Give me the features of all of that but abstract it away so I can just write what I need to and it works implicitly. Either that or just leave the dang language alone and go make some cool libraries.
I am really rather tired of the appeal to simplicity that is often made in language design. Simplicity is not a virtue in a programming language. Consistency is a virtue, but not simplicity.
Simplicity is a tradeoff that takes away power and control from the programmer and gives it to the computer. Computers don't need to be more powerful, programmers do. The tradeoff is a poor one and rarely worth the little gained.
In this case, what do we gain by not adding primitive value types in Java? The fact that you sleep better at night because the language is more "clean"? Why should we want that? Sleep is definitely important, but the idea that a language can be too complex is silly.
It does matter that new additions do remain consistent with the overall architecture, but there is no reason to advocate less features simply because you find the idea of learning something new disconcerting.
Agreed. I feel like a C# Stan in here at the moment, given how often I'm speaking glowingly of it lately--I use it to make games but my day job is Ruby and Scala!--but you can look at C# to see what moderately progressive (not even "aggressive") iteration on a language to add more and more powerful features in a smart, clean way would look like. Nobody's complaining about C# having too many bells and whistles, honest.
I really agree with you as well, but I can think of a few reasons to want simplicity.
First, including features that you expect others (beginners) not to use is problematic. You can't really claim to know a language if you can't read other people's code when they are using standard language features. So you have to learn all those features whether you intend to use them or not. And learning them means knowing when and why they are used. Usually, this kind of stuff is just deferred to libraries and language extensions. (Haskell-style Langauge extensions and Python's future imports are a wonderful idea, I think.)
Second, people like to get comfortable in their languages. If the C language designers just said "Hey, er..., you know all these curly b's are unnecessary, let's drop 'em in the next standard," people wouldn't care for it. More features + more power + backwards compatibility can only carry you so far before it becomes downright unwieldy.
I don't think people learn very well that they should just forget everything they know every 5 years and start on mastering something completely new. The problem is not in the language being too complex (like you said,) but in our culture and habits. People don't like complexity. That's why we work so hard to make it go away.
I rather like closures and streams quite a bit! Please do continue to improve the language, especially generics! Generics as they currently are are just so much more limited than they could be. I hope they end up fixing them and getting things moving forward again with respect to generics!
I appreciate the link, but this information is not terribly encouraging. Steve Yegge somewhat famously pointed out how painful Java's lack of object literals is back in 2006, and some mailing list discussion is all the progress that the Java community has made toward that feature in the 8 years since. http://steve-yegge.blogspot.com/2006/09/bloggers-block-4-rub...
The response by Brian Goetz[1] is kind of unpleasant and combative. Moreover, the ideas in it kind of encapsulate why I'm growing more and more uncomfortable with relying on the JVM to keep up with my needs in the future.
> The cost of the C# approach is that existing
classes could not be gradually migrated to be generic; existing collections had to be effectively deprecated and replaced, or a "flag day" had to be declared where all the code (library and client) changes simultaneously. These are not options for us.
This is why, despite doing it in my day job, I'm not high on the JVM's future as it stands right now. Compatibility uber alles is not a virtue, even Microsoft gets that these days. Saying "on 1 Jan 2017 we're pushing Java 10, and you will need to recompile your dependencies to upgrade" is not a bad thing. No, many people won't upgrade immediately. That's true. But they already don't! It takes years for consumers to catch up with the newest version of Java (for reasons that do not reflect well on those consumers). Why should I, as a consumer, care about them? Why should I, as a consumer, continue to use your product when you would care about laggards more than me? I mean, Oracle's welcome to, it's their business, but why would I respond positively to that?
But he says that a flag day means they "hate their users." No, it would mean they are going to firewall off the damage laggards can do to their environment and ecosystem. And for the sake of a healthy platform for the next decade I would think they should do exactly that, because those laggards don't make the ecosystem and the environment better.
And then, at the very end:
> And, feel free to prove us wrong! Try implementing the changes you are envisioning in the JVM, and show how they can get us to the goal!
Why should I, guy-who-works-for-Oracle? I'm not drawing a paycheck from Oracle, who owns Java so utterly and wants to attack and damage related tools and platforms (hi, Android), and guess what? I really don't need Oracle to fix this because in 2015 I am going to have options. Microsoft is releasing an open-source CLR for OS X and Linux and it's effectively substitutable for just about anything I care to use (and, if I had to be honest, a combination of C# and F# are probably better than even Scala for what I do). This is Oracle's problem and Oracle's ground to lose, not mine.
Two-thirds of my Github are C# and Ruby at this point, anyway, and I don't even use C# for work.
It sounds like you do hate Java's users. You dismiss the difficulty of upgrading existing apps, which is an enormous amount of work, without even making a rough estimate of how hard it would be. They are just "laggards" to you. At least consider that others may have different values than you and actually care about these people.
Sacrificing backward compatibility means adding pain for existing users in the hope that the world will be better for new users. Splitting the community on purpose has a cost; just look at python 3 for how painful this is.
Whether this makes sense depends very much on the size of your existing user base and on the potential for growth. The users you gain by making a language somewhat more elegant may not be worth the loss from the disruption.
A flag day on a bytecode format is "hating users"? It's a Python 3 split? Come on now. Heck, I can't come up with anything (and I've been thinking about this a lot for a few weeks, as I spend more personal time in C# and getting stuff done quickly that's kind of a pain in Java) that'd prevent automatic translation of pre-flag bytecode to an equivalent matching the old code's intent. If a jar has a pre-flag bytecode format, then rewrite to treat those parameters at runtime as T => Object and transparently box value types that are supplied for T. The pre-flag jar still contains the necessary information for the compiler to throw a rod if generic constraints are violated. (You could even experiment with more restrictive runtime constraints, but I haven't thought through the implications thereof.)
But you know? If it takes laggards three years instead of the usual two to jump from Java 9 to Java 10, I don't care. I shouldn't care, because I'm not them. Oracle might. They can do that. But Oracle doesn't want my business if they do to my detriment, and the more time I spend outside the JVM the more annoyed I am by their self-imposed limitations. Microsoft seems like they wouldn't mind my business, though, which is faintly astonishing. I'm happy giving it to them if they're going to provide a better product. (I'm reserving judgment until we see their Linux and OS X ports of their CLR, but I'm high on it.)
And if you're seriously going to get riled up about "laggards", I hope you never take an economics class, because they think words mean things and I do too.
Yes, you're probably right that they don't care about your business. Oracle's actual customers are large businesses running hundreds of millions of lines of code and they probably don't understand all of it. They probably care a lot about preserving their existing investment. If they decide to put off upgrading to the latest VM, Oracle can't sell them stuff.
The point here is to have some empathy. There are other people in the world with different priorities. You can't say whether a technical decision is good or bad without understanding what they're trying to do.
>Yes, you're probably right that they don't care about your business. Oracle's actual customers are large businesses running hundreds of millions of lines of code and they probably don't understand all of it.
That was true for SGI, HP, DEC, SUN etc at some point too. See how the ended when they didn't adapt?
SUN could still be alive and be pioneering all this cloud and web programming in 2014...
They could have created something like Heroku (or lower level like AWS), they could have added some flexible Rubu/Python Django/Rails like option for the JVM (instead relying on third party ho-hum small attempts). They could have pioneered the big data space.
Instead the insisted on Java for everything, and kept it as stale as they could. This is were it got them...
They did try. Sun had all sorts of innovative projects that didn't work out (such as JavaFX), but they've been forgotten. Java on the server is what remains. It may not be flashy, but it's a survivor (still around even after Sun is dead) and it's likely to last as long as Fortran and COBOL.
It's only in the early adopter community that survival doesn't seem to count for anything.
I'm stating what I want in my tools. I've been very clear that, while I am entirely convinced that they are wrong and will suffer for it, they can do whatever the hell they want and I'll respond in kind. Where is the lack of empathy here?
And, as coldtea notes, lashing themselves to boat anchors hasn't done Java, or Java's owners, much good throughout its history.
There's nothing wrong with saying what you want in your tools. But it's rather weird (though a common sort of move on the Internet) to follow that up by saying that the Java maintainers are making the wrong decision and therefore they are courting disaster. Why draw that conclusion? I'm assuming you're not so much of an egotist to think your desires are that important?
A more reasonable conclusion would be that what I want, or what you want, and what's good for Java have little to do with each other. You should use another language that fits better (since you're fortunate to be free to switch), and Java will probably be fine.
Because the history of tech and business is "stagnation kills"? I cannot envision a mindset where "we exist because we can't be excised from decades-old businesses" is a desirable place for Java and the JVM to be. If Oracle thinks they can grow the JVM off of stagnant customers who can't afford to move, they're nuts. If they think forward-looking customers are going to settle when competitors are getting better, faster around them, they're also nuts.
I want healthy competition, and so yeah, my jimmies are rustled when they're making bad decisions because even if I exit the JVM ecosystem for my own purposes, one of the major players being too afraid of their own customers to fix a central rot of their product is bad for us all.
The issue is whether it's actually "central rot" or not. That's not an objective statement. It depends on your point of view. If you're putting your customers first, you have to look at if from their point of view.
Startup thinking is that you never have enough users, so you have to appeal to a lot of new users or you die. Companies selling consumer products are similar - you have to convince a lot of new customers every year. But that's not where Java is. It's going to last as long as COBOL and Fortran and C++. Making small, careful changes and paying attention to migration costs so you don't leave people behind will work fine.
For a business with many large, satisfied, long term customers, the software can survive as long as they're willing to pay maintenance. The userbase may slowly fade, but the customers they have aren't going to be too quick to move if things are working. If anything, disruptive changes will make them move away faster since they're forced to do something, so why not do a rewrite that's bigger impact?
Making migration easy is not "stagnant", it's good customer service, allowing old code to be modernized a bit. If you know the real cost of upgrades, a more dramatic change may not be worth it.
And for those of us doing new projects, well, there are a lot of other shiny toys to play with. We don't have to disrupt everything.
While the conclusions are correct the comments about C# are wrong. C# started with a unified type system -- all types both scalar and classes inherit from a single root class called System.Object. Ot had value types and reference type from the start. And it's byte-code format to handle that situation from the start.
Also there was no "flag day" for the C# when generics were added. The situation between C# and Java when generics were added to both languages was exactly the same. The only difference is, due to the unified type system, C# supported scalar generic type parameters from the start.
System.ValueType was in .NET 1.0? Interesting, I didn't know that. (There are no docs on MSDN for 1.0, and I came in at .NET 2.0, so that's before me.)
In MDSN, you use the drop-down to change the version of framework you're looking at for documentation. Here is the ValueType class documentation for .NET 1.1:
Believe me, I spend plenty of time up in there to make sure this library I wrote will be cool with .NET 3.5 or whatever. =) I wasn't sure if that had been wedged in with .NET 1.1. I've never seen even 1.1 in the wild.
I don't know if it's quite a "flag day", but Microsoft is definitely going to make some breaking changes soon in .Net 5.0.
The particular one I'm watching for is lambda closures. Currently it's close-on-reference rather than close-on-value, even on value-type objects. This leads to some really counterintuitive behavior in certain situations.
Breaking changes are perfectly fine as long as you keep supporting legacy runtimes. That's why we have major framework versions (eg Java 7/8, .Net 4.5/5.0, etc).
Flag Day means your project is now stuck on the version of the legacy runtime of your slowest dependency to upgrade. If you have a dependency that is no longer being maintained, migrating away from it is then required.
This kind of flag days is why you still see some Java 1.4 around for some projects 8 years after it went into it EOL period! Projects on java 1.5 are relatively rare because they where easier to upgrade to later versions. (Java 1.5 introduced enum as a keyword, 1.4 assert) Java 1.6 and later did not introduce flag days like that for code. I think that the Java team has learned that flag days are very very painful for the wider ecosystem.
Something, I am personally very happy with. Because by going slower I think they have started to go faster for us end users ;) The accepted Lambda syntax and implementation was much better than the first proposals and lost nothing in expressive power. Sure it added 1.5 years before we got them, but when we got them we could actually use them right away.
In my experience code is kept longer than runtimes. The project I have worked on for the last 7 years was started on Java 1.4 and is moving in production to 1.8 next month. If we had to rewrite a significant part of the code each time a new version came out we would still be stuck on 1.5 today!
Sure Java is paying the price of decisions made 18 years ago, but that is the nature of technical debt ;) at least most of this debt was used as an investment instead of wasted.
PS. .Net is significantly younger than Java being a late 90's language instead of a early 90's one.
PS. These new keywords in java 1.4 and 1.5 did impact real world code, in one project we moved code from 1.4 to 1.5 and had to rename a package from something.enum to something.enums. Then we ended up with a crippling bug because some incompetent had used reflection to select a class on the basis of information stored in the Database, a class that enum in its name :( So a trivial change using refactor in JDeveloper let to a huge bill in emergency fixes roll backs and SLAs being missed.
Being compatible with existing code, while still evolving to the future is of real value!
The reason C# was able to do it is not because they had so few users that a "flag day" was acceptable, it was because they went with the first option and rewrote all their collections. C# did genetics right the first time, and didn't end up in this bizarre type-erasing, half-ass world that Java find itself in today.