Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Java has a culture of over-engineering, to the point where even a logging library contains a string interpolator capable of executing remote code. Go successfully jettisoned this culture, even if the language itself repeated many of the same old mistakes that Java originally did.


> Java has a culture of over-engineering [which] Go successfully jettisoned

[looks at the code bases of several recent jobs] [shakes head in violent disagreement]

If I'm having to open 6-8 different files just to follow what a HTTP handler does because it calls into an interface which calls into an interface which calls into an interface (and there's no possibility that any of these will ever have a different implementation) ... I think we're firmly into over-engineering territory.

(Anecdata, obviously)


Java is a beautiful and capable language. I have written ORMs in both Java and Go, and the former was much easier to implement. Java has a culture problem though where developers seem to somehow enjoy discovering new ways to complicate their codebases. Beans are injected into codebases in waves like artillery at the Somme. Errors become inscrutable requiring breakpoints in an IDE to determine origin. What you describe with debugging a HTTP handler in your Go project is the norm in every commercial Java project I have ever contributed to. It's a real shame that you are seeing these same kinds of issues in Go codebases.


But don't those exist primarily for unit testing? That was my understanding of why interfaces were there.

If you wanted a mock, you needed an interface, even if there would ever only be one implementation of it in production.


> But don't those exist primarily for unit testing?

I believe that's why people insert them everywhere, yes, but in the codebases I'm talking about, many (I'd say the majority, to be honest) of the interfaces aren't used for testing because they've just been cargo-culted rather than actually considered.

(Obviously this is with hindsight - they may well have been considered at the time but the end result doesn't reflect that.)


I hate this pattern. Needless indirection for insignificant benefit.


It's indeed horrible when debugging. OTOH, there's merit to the idea that better testing means less overall time spent (on either testing or debugging), so design choices that make testing easier provide a gain -- provided that good tests are actually implemented.


Golang "punishes" you for wanting to write a unit test around code.

You need to refactor it to use an interface just to unit test it.


No, you don’t, unless you’re of the opinion that actual data structures with test data should not be used in a unit test.


I think you're missing the point here.

Duck typing with python (e.g.) makes it easy to mock a class. One can subclass a Java class to make a mock, etc.

One can't do that in golang unless it's through an interface which then decouples tightly coupled code because [golang reasons].


Agree. Open source OAuth go libraries have this too. It's like working with C++ code from the bad old days when everyone thought inheritance was the primary abstraction tool to use.


I stand corrected!


Why would those require 6 separate files?


They don't; you could put it all in one file but people tend to separate interfaces from implementation from types from ...


Interface, actual implementation, Factory, FactoryImpl, you get the idea.

Java lends itself to over-engineering more than most languages. Especially since it seems that every project has that one committer who must be getting paid per line and creates the most complex structures for stuff that should've been a single static function.


I asked Rob why he didn't like Java (Gosling was standing nearby) and he said "public static void main"


Nice. My reply would have been something like: it combines the performance of Lisp with the productivity of C++. These days Java the language is much better though, thanks to Brian Goetz.


The performance of the JVM was definitely a fair criticism in it's early years, and still is when writing performance-critical applications like databases, but it's still possibly the fastest managed runtime around, and is often only a margin slower than native code on hot paths. It seems the reputation has stuck though, to the point that I've seen young programmers make stock jokes about Java being slow when their proposed alternative is Python


Just for an example: on the recent 1billion rows challenge, the top java contender takes only 2x as much time as a SIMD-optimized C one.


Yes it's possible to write Java without any boxing of primitives or garbage collection, but one can't use any of the standard libraries and it's not really Java one is writing but a very restricted subset. I don't think these benchmark are particularly indicative of real world performance. But of course Java is still hundreds (thousands?) of times faster than Python.


It’s okay to do some allocations - it can be stack replaced, and even if it’s not, the cost is very negligible. The problem is mindless allocation, not allocation itself.


> it combines the performance of Lisp with the productivity of C++

Is that supposed to be a jab? Because IME SBCL Lisp is in the same ballpark as Go (albeit offering a fully interactive development environment), and C++ is far from being the worst choice when it comes down to productivity.


Hopefully you agree Lisp is more productive than C++? Lisp is however not quite fast or efficient enough to displace C++ completely, mainly because, like Java and Go, it has a garbage collector. C++ was very much the language in Java's crosshairs. Java made programming a bit safer, nulls and threads not withstanding, but was certainly not as productive as Lisp. Meanwhile Lisp evolved into Haskell and OCaml, two very productive languages which thankfully are inspiring everyone else to improve. Phil Wadler (from the original Haskell committee) has even been helping the Go team.


Common Lisp, is also among the GC based languages that offer mechanisms to do GC free allocations and has value types.

The only reason is the AI winter, and companies moving away from Lisp.


I agree; my point is simply that C++ is still OK-ish w.r.t. productivity, and Lisp is OK when it comes down to performances.


Well, that's taken care of: https://openjdk.org/jeps/463 (well you need `void main`)


still better than case deciding visibility


i love this feature to be honest


I consider that a bad practice, because it doesn't make things obvious. I guess it works so well in Go, because the language itself is small, so that you don't have to remember much of these "syntax tricks". Making things explicit, but not too verbose, is the best way in my opinion. JetBrains has done amazing work in this area with Kotlin.

    for (item in collection) {
        ...
    }

    list.map { it + 1 }

    fun printAll(vararg strings: String)

    constructor(...)

    companion object
I like the `for..in` which reads like plain English. Or `vararg` is pretty clear - compare that to "*" and the like in other languages. Or `constructor` can not be more explicit, there is no need to teach anyone that the name must be the same as the class name (and changed accordingly). Same is true for companion object (compare with Scala).


I've always found it eye rolling how often this is given as some sort of "mic drop" against Java. Yeah it's a little weird having to have plain functions actually be "static methods", but it's a very minor detail. And I really hope people aren't evaluating their long-term use of a language based on how tersely you can write Hello World


At least he knows something about a single other language! Honestly, I wasn’t sure about given the stupidity of go, and the warts it has.


Go code is equally over-engineered when taken into the hands enterprise architects.

You just happen to be looking at the wrong spot, see Kubernetes, YAML spaghetti, and plenty of stuff originated from Go in the enterprise space.


It seems the goal of Java is to have one executable line of code per file.

Thus, the Java exception trace in the log file is almost like an interactive debug trace.

Whether that is a bug or a feature is an exercise for the reader.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: