6 ms·
I program in Java for more than 15 years now. I can resonate with people hating the language from it's early days due to the experience with all the enterprisy
by ludovicianul 7mo ago
I program in Java for more than 15 years now. I can resonate with people hating the language from it's early days due to the experience with all the enterprisy features and over abstractions. Or confunding Java with the Spring ecosystem. But Java came a long way over the years. It's now what many would call a "modern" language. It's less verbose, has many of the features people find appealing in Scala and Kotlin and it can even compile to native binaries using GraalVM. This made building CLIs in Java feasible. Or lambdas.
- zadikian 7mo agoLack of virtual threads was its biggest remaining problem because this made the common ways of doing cooperative multitasking very ugly. Go's big thing was having that from the start. Maybe now that Java has it too, it's set? Though JS will still have the least boilerplate because of the way it handles types.
- deepsun 7mo agoIMO, Kotlin coroutines are better of Go's goroutines, although they are a little different beasts to compare honestly (apples and oranges). Go inits goroutines on stack, but min size is 4KiB, so it's not trivial to grow them. Also you need to watch over and destruct goroutines manually to prevent memory leaks (using var wg = sync.WaitGroup defer wg.wait() wg.Add(1) go func() { defer wg.Done() } ) And create a separate channel to return errors from a goroutine. Definitely more work.
- zadikian 7mo agoIt is, but your typical backend code isn't dealing with that most of the time. You can just use blocking I/O in handlers.
- Ternari 7mo ago>you need to watch over and destruct goroutines manually to prevent memory leaks No, you don’t. Any stack-allocated resources are freed when the function returns. WaitGroup is just there for synchronization.
- HendrikHensen 7mo agoKotlin coroutines don't really exist. They're a (very neat) programming trick to support coroutine-like behavior on the JVM which doesn't support coroutines. If you look at the bytecode it produces, it honestly is a mess. And it colours your functions too: now you have be ever careful that if your function is running in a coroutine, there are certain things you should absolutely avoid doing in that function, or any function called by that function (like spinning the CPU on loop without yielding). In Go, you don't have to worry about any of this because the concurrency is built-in from the start. Also I don't understand "it's not trivial to grow them". It is trivial to grow them, and that's why Go went this way. Maybe only 0.1% or fewer of use-cases will ever find any issues with the resizing stack (in fact probably the majority of uses are fine within the default starting stack size).
- gf000 7mo ago> Kotlin coroutines don't really exist. They're a (very neat) programming trick to support coroutine-like behavior on the JVM Well, guess how coroutines are implemented in Rust/C++/everywhere else! Nonetheless, I do think that java virtual threads are superior for the vast majority of use cases and they are a good default to reach for for "async" like code.
- HendrikHensen 7mo agoI think there is something to say for compiling to native code, having binaries in the ~25 MiB range, being able to run in distroless containers, being able to run a web application with less than 100MiB of memory and startup times measured in milliseconds rather than seconds (sometimes dozens of seconds). Don't get me wrong, I like Java and don't very much like the Go language. But Java has a lot to improve upon still.
- gf000 7mo agoSmall java programs start up well in the milliseconds. I don't really think it's fair to compare some old jboss monstrosity doing the job of a whole kubernetes cluster to a dumb hello world server written in go. Sure, java startup time is and will probably always be worse than putting everything into a single binary - but it is way overblown in many discussions. I have a bunch of Quarkus services on my home server and they start up immediately.
- ludovicianul 7mo agoWith Quarkus (and other new frameworks) you can have webapps with less than 100MiB. Startup times in a couple of miliseconds. CLI apps, with limited number of third party libraries are under 40-50MiBs.
- lenkite 7mo agoYou can have a <20MiB Graal-compiled binary for a Java project if you use a lean framework like Micronaut. Memory footprint is 5–40 MB RSS.
- deepsun 7mo agoI recently worked on a Go project and my task was to make it more configurable at build time and start time (add plugins / addons, make it possible to reuse from other libraries and tools). Turned I had to create *Factory and *Providers, even though I did not want to. It's easy to avoid "AbstractFactoryProviderBuilder" if everything is hardcoded. Try to make it reusable and extensible, and I bet you write one yourself.
- troad 7mo ago> It's easy to avoid "AbstractFactoryProviderBuilder" if everything is hardcoded. Try to make it reusable and extensible, and I bet you write one yourself. The first domino is opting for OOP. AbstractFactoryProviderBuilders are just the inevitable downstream consequence of that initial choice. No need for factories if you don't traffic in objects in the first place. Objects. Just say no.
- pjc50 7mo agoBit of an extreme position, no? Languages without OO tend to end up reinventing it. Like the Linux kernel style of "big C structure with function pointers": that's just a vtable which you have to maintain by hand. Or, god help you, trying to do COM in C. What's a good codebase that is very large but without either OO or pseudo-OO?
- troad 7mo agoI totally agree one ought not use a non-OOP language for OOP. Right tools for the job and all that. I work on large (but private, so I cannot share, sadly) FP-style codebases. The code style is stateless functions grouped in modules that operate on data-only structs in a factory line manner. Typed boundaries for correctness, short and maintainable functions for clarity. No member functions, so no vtables. I've never seen such code need or use OOP design patterns. I'm just very gently pushing back against the idea all code devolves into OOP spaghetti in due course. It doesn't! There are better ways. :)
- deepsun 7mo ago