Hacker News new | ask | show | jobs
by EnderMB 2372 days ago
As someone that used to write a lot of C#, I find that the language is changing so often that it's hard to know what's new and what's been around for years.

In contrast, Java hasn't changed all that much over the years, and I wonder if an approach of taking the more useful features from C# and ignoring some of the others would be a good approach.

I often wonder how Java developers feel when they look over at C#, and see a language that has exploded in functionality over the last decade, all while Java has mainly optimised the JVM and slowly added features.

5 comments

It's not taking some features and ignoring others. It's taking features than have shown good cost/benefit, and not taking those that haven't. The choice here is about which features not to adopt, just as much as it is about which features to adopt. Java's philosophy is still innovation in the VM while keeping the language conservative. It's just that conservative is a relative term, here. If some language feature seems to have a good cost/benefit ratio and it's become mainstream enough, Java will adopt it.

BTW, Java has also "exploded in functionality over the last decade", it just hasn't translated to language changes. Even the project I work on, adding lightweight concurrency, will not change the language at all, while in C# it took the form of a huge language change (async/await). Nevertheless, in Java the added functionality will be at least the same as it's been in .NET.

> It's taking features than have shown good cost/benefit, and not taking those that haven't.

I actually wonder if it's more taking features that have proven sexy, and ignoring the rest. I still think that the single biggest source of verbosity - and design damage in some of the newer APIs such as streams - is that Java hasn't implemented extension methods. That costs me time and money on a regular basis. By comparison, the cost of fall through by default in switch statements is that I have to use a linter. Which I already have to do for a fistful of other reasons, anyway, so, while this -> operator certainly scratches an itch I've had, it doesn't move the needle much in terms of productivity or code quality.

edit: Should add, in C#'s defense - .NET's lightweight concurrency was initially implemented as a library. C#'s async/await came later, and is just syntactic sugar as far as I've ever been able to tell.

First, no language feature has been shown to move the needle much in terms of productivity or code quality. We are unable to detect differences between (reasonable) language choices, let alone individual features, so it's mostly about ergonomics. I'd be extremely surprised if you could show that any feature or lack thereof actually costs you money, but if you could, that would be quite a discovery. As to extension methods, they're not ignored. The language team is just unconvinced it's a good feature, which doesn't mean there aren't people who like it. As to switch statements, the language team had actually analyzed many hundreds of millions of lines of code before committing to the feature.
> First, no language feature has been shown to move the needle much in terms of productivity or code quality.

Absolutely true. When I've looked at that research, I was really quite impressed by how little has gone into looking into it, considering how interesting the subject is to so many people. My guess would be that it's because it's prohibitively expensive to study. That said, there was one result that I believe was shown to be fairly robust, and independent of language: that bug rate and cost are both generally proportional to lines of code written.

To that extent that that may be true, while I certainly don't have a $500,000 study by a team of professors at Stanford to back me, there's at least a plausible basis for my own perception of doing better work in object-oriented languages that do or do not have some sort of mixin mechanism: I find that using them often lets me get the same job done in less code. (Without that, I admit I have to retreat to pointing out that absence of evidence is not evidence of absence.)

There's also the design damage thing. Some developers on my team are quite resistant to using streams instead of loops in Java, and it's precisely because of the poor ergonomics. If you need to do an operation that isn't built into the Java API, you have some sub-par options: You can implement a collector, which is justifiably criticized as being a hassle (6 methods to implement) that yields code that scans poorly (every other verb is "collect"). Or you can implement a function, but using that function requires breaking the flow of the stream code by creating a bunch of intermediate variables, or, worse, constructing a pyramid of doom. By contrast, when we're working in Kotlin, you can just write a function and deploy it the same way you'd deploy any other method in its equivalent APIs. It's less effort, it's less code (read: stuff to get wrong), and, perhaps critically, it's a lot less annoying.

What operation that isn't in the stream API would you say you need most often?
> I'd be extremely surprised if you could show that any feature or lack thereof actually costs you money,

Bad language design and semantics definitely costs money in the long term. For example, Tony Hoare refers to Null References as his "billion dollar" mistake. The verbosity of Java before sophisticated IDEs would also have cost significant time and money. Java is improving significantly (and arguably was never as bad as say JavaScript or PHP), but there are some legacy decisions that will be very hard to change; and so improvement can only ever be incremental.

> and so improvement can only ever be small and incremental.

You seem to hint that some hypothetical non-small improvement can be made differently (in some other language). Perhaps it could, but it doesn't seem anyone has done it yet. We do not observe large differences between and in companies based on language choice. I think some of the reason is that developers overestimate the cost of coding in the entire software development process.

> We do not observe large differences between and in companies based on language choice.

Hmm, I think it's pretty clear that most folks are far more productive in Python than say C++. But yes, I agree that there's no silver bullet, programming is hard.

> I often wonder how Java developers feel when they look over at C#, and see a language that has exploded in functionality over the last decade, all while Java has mainly optimised the JVM and slowly added features.

I am a long time Java programmer that has mostly programmed C# lately.

I'm getting more conservative by the years but I still found myself liking modern C#.

The thing I miss from Java is the ecosystem:

- three top notch IDEs

- more mature ecosystem

- maven

Use Rider and Nuget and you shouldn't miss much.
I like C# more than Java because it is improved more often. Conservatively of course, but each version adds some new good stuff to play around with. Java felt like it stayed the same for so long.
I find it to be the opposite. In recent years C# has had modest language changes while Java has introduced streams, optionals, lambdas, function pointers...a whole lot of catch up and IMO arguably in an uglier but ultimately quite similar way to C#. Now I get to relive another couple years of devs learning, unlearned, and then properly learning when to use Linq/streams.

Optionals and the new IO libraries are causing far more churn in my Java code and the libs I use than any recent C# changes.

The Java language doesn't feel conservative to me. It just feels slow. What was worth the wait? What does Java do better than C#? The only thing I miss while in C# is Java's take on enums.

All that said, I don't begrudge Java as a whole. The JVM and other priorities add a lot of value and I'm glad their adherence to bytecode compatibility remains strong. The language is the trade off but that doesn't mean I need to pretend its better.

Java has changed a lot too. Its a real problem in an old code base as there are different generations of developers writing in different styles making the whole thing inconsistent and confusing.