> More seriously, what are you missing in Go that is well-done in Java?
1. Generics. And yea, I know Go is getting generics "Real Soon Now" (tm), but it is incredibly annoying to write the same collection code over and over and there's some third-party libs that would really benefit from generics (looking at you Azure Go SDK).
2. Error handling... with the big caveat that I actually like Go's error handling mechanism at small scale but wish there was a good way to chain several operations together and return an error to the top if any failed... I find myself writing a lot of `err != nil` checks in sequence and I've found baking my own abstractions around this to be leaky or difficult to grow as the program requirements change.
3. Diverse collections API.
4. Iterators.
5. Not Java-the-language but the JVM has amazing monitoring tools.
> I assume verbosity of the code is still the defining characteristic of Java?
Pound for pound... I think Go and Java have about the same verbosity. I'm honestly never quite sure what people mean by "verbosity" in Java. Generally I interpret this as "frameworks" but I predicated my OP on the idea that legacy framework bloat is where most of people's frustration with Java lies... not the language itself.
> I'm honestly never quite sure what people mean by "verbosity" in Java.
Java improved with "var" keyword (use with caution!) and introduction of records. These are not the only code-shortening features (there are e.g. interface methods, diamond operator, lambdas, convenience "of(...)" methods, even "fluid style"), but they, used well, can really reduce verbosity.
Also, a lot of verbosity in Java came from people going off the rails with design patterns to hide crap multiple levels deep in a file with 5+ words in the class name.
Much of the verbosity came from the false presumption that every field in every class needs a public getter and setter. (I cannot express in words how terrible this is.) Some can come from the framework, mostly poorly-designed ones.
I think Java 11 and higher are reasonably terse/expressive without being overly dense.
Remind me, why doesn’t Java have object-properties yet?
So far the only reason I’ve concluded is Java’s language designers’ egos were so damaged by C#, Swift, Kotlin, TypeScript, etc that after dogmatically denying the developer-productivity benefits of properties for the past 20 years that to concede now would mark the end of Java as a language entirely.
...I kid, but seriously I haven’t heard any compelling argument from the Java camp yet for refusing to add this feature. Object-properties are easily the lowest-hanging-fruit with the biggest productivity-gains.
Heck, even some of the most popular C++ compilers support object-properties as proprietary extensions.
It's so crazy - with all the huge and radical features they've added this would surely have been so simple by comparison and yet added more value than about 80% of the things they've done. It's about half the reason I still use Groovy now since Java has solved most of the rest over time. But I just cannot go back to writing getters and setters!
Couldn’t agree more, the madness of idiomatically adding setters and getters to every field was something I ended up putting an end to in my last gig, and my life improved immeasurably as a result.
I think I'm going to convince my team to get to 16 (with records) before I can convince them to stop adding getters and setters everywhere, but just out of curiosity... how did you manage to make this happen?
Well - I was the boss :) so that helped. But I’d also taken over a fairly unhappy and unproductive team that was ready to try new stuff. I’d been out of the game for a few years and had some fresh perspectives too.
So I did some small standalone projects and demonstrated how much easier life was with this and other (more significant) changes. For example, we had loads of operational problems with dependency injection - the usual cognitive and debugging issues - so I threw all of that out too, along with the frameworks that implemented them. Things started booting in a few seconds instead of minutes and I’d say the lack of setters/getters was mostly done because I built trust in my team that I was making their lives better so they just followed me.
Probably not the answer you were looking for but there was friction from the devs and in the end I just showed them how much nicer life could be...
I agree with your points here, but just want to add that, while Java's generics are better than the non-existent generics in Go, I still find Java's type system to be really subpar for today's era.
The type system is not strong or expressive enough to do full type erasure, but then we're stuck with type-erased generics, so it's just incredibly frustrating.
Sorry that I find it necessary for yet another answer to your verbosity question, but: The real verbosity is in the standard libraries. What would be a one-liner in any other language is usually at least 2, often 3, and sometimes enough that you end up writing your own wrapper function or library. Especially noticeable is the agony of Lists & Maps, which are first-class citizens in most languages (classic job interview question: what is the difference between ArrayList and LinkedList? Real answer: Nobody actually uses LinkedList).
The stdlib often seems to be written by people who had no intention of using it. I guess maybe this applies to C++ as well, so for some folks it seems normal.
About verbosity: you needed to define classes for so many things. Eg you want others to hook into processing in certain places. So you create a listener interface with some methods. And the provider needed to work with those, and the consumer also needs to work with them.
In modern Java maybe you can make do with functional interfaces and lambda, but it doesn’t always work I think.
And in emacs: the provider does run-hooks, and the consumer defines a function and says add-hook. Done. Very little ceremony.
Now we've got Spring, which in my, admittedly limited, experience does a great job of transforming what could have been compile-time errors into run-time errors.
Spring native is a game changer for so many organizations using containers for startup times. There are other spring related issues you still have to deal with
Well said :) . Spring looks so much as to show how useful ideas can be misapplied with catastrophic results. For example, liberate encouraging of dependency injections leads to multitude of interfaces which are only ever implemented once by a production code class, and maybe one more time by a test class, even though Java has all methods virtual and testing could be done without requiring the interface.
It's reasonable to provide a single implementation of an interface, if the goal is to facilitate dependency injection for that component. The problem I find with Spring is that it is designed for dependency injection at all levels of its architecture, leading it to be one of the ultimate examples of Ravioli Code.
DI is a powerful concept, but Spring projects rely on DI in such a generic way that it often doesn't even make sense for your application. You have to gain intimate knowledge of the abstractions, and inject a bunch of code in a bunch of places just to make it do the very-straightforward thing you were trying to do.
> It's reasonable to provide a single implementation of an interface, if the goal is to facilitate dependency injection for that component.
You don't really need dependency injection if there is only single choice of what to inject. You can just refer in code to the only possible component.
>> Java has all methods virtual and testing could be done without requiring the interface.
Not sure what you mean by that. I thought that interface/implementation divide is the way to implement virtual calls. Unless you want testing frameworks to do bytecode instrumentation.
If your interface is going to be implemented by just one class, I'd offer to skip interface - it reduces amount of code. If you still need to pass, as a parameter, a class A in order to test a class B, you can instead pass class C inherited from A, with all necessary methods overloaded.
If you just create a class A in java, no interfaces involved, class A will have its methods virtual. I'm not sure what do you mean by interface/implementation divide.
Running ‘mvn install’ on even a simple Spring project with default dependencies is scary to watch on the console. So many things happen and it’s not even the verbose mode.
Running ‘dotnet build’ is much more saner and one can reasonably understand what happens.
> More seriously, what are you missing in Go that is well-done in Java?
As cliche as it is to say, Go missing generics (for the time being) does hold it back in many ways relative to Java. I like and use both languages regularly, and as I thought about my answer to this question I realized that essentially all of my complaints stem from the lack of generics - things like streams, a rich collection framework, and non-channel concurrency features (java.util.concurrent among them) don't exist in go because you can build them as generically as needed for them to be useful.
You might have said "well-done" as a way of excluding generics in Java since many people like to suggest they're not well done; of course most developers would like more, but they already enable an enormous amount of stuff not possible in Go.
The java ecosystem is very nice. Not necessarily the language itself, but everything else. The jvm, the tools, the libraries are all very mature and good.
Skipping java and instead using Kotlin allows one to reuse all that knowledge in a great language as well.
I guess it depends upon what you mean by ecosystem.
Java the language is ok. The culture (which is part of the ecosystem) and how you're pushed to write code is the biggest problem with Java. The wide array of tooling, frameworks, and libraries within the ecosystem is nice.
But the way you have to use them tends to be shit due to the culture surrounding the language. At least it seems to be shifting to something more sane.
Good language ought to discourage (enough) the bad practices. Culture forms slowly, and it's Java fault that the culture managed to produce such excessities as proverbial FactoryFactoryFactory.
Edit: I still think Java is a good language, especially later versions, and both original goals and recent advances are quite noble.
I somewhat agree, but Java grew up in a different era when communication about these things wasn't as easy. It's hard to change the direction of something as large and widely deployed as Java. It's happening but it will take time and its always going to dealing with its legacy as there just so much of it out there.
Huh, one needs to see first party Java libraries from earlier times. It is pretty clear engineers at Sun also believed that AbstractFactoryFactory everything will be the way world need to be rebuilt.
Of course one can show empathy and understand justifications for things they like and simply laugh out "LOL Go No Generics' when they don't.
I at the same time laughed and got nauseated just by looking at that FizzBuzzEnterprise code LOL. I'm a minimalistic programmer myself, so the thing I hate the most in coding is over engineered code. Yes , it's a joke, but a joke based on real life haha.
This, and the FizzBuzz, Enterprise Edition: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
More seriously, what are you missing in Go that is well-done in Java? I assume verbosity of the code is still the defining characteristic of Java?