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

After years of Python and TypeScript, I've started using Java as my default for everything. It's just so much more productive. The ancient developer memes that Java is slow and clunky don't apply anymore.

Postgres also had a long-held reputation for being slow and difficult, but it made incremental improvements for decades and now it's the default choice for databases.

I see Java in the exact same position, as the Postgres of languages.



The problem with Java since Java 8 has never been Java. It's been about the appalling ecosystem that infected it with reflection frameworks. It was bonkers that "POJO" was ever a thing that had to be defined.

It feels like these frameworks are now just falling away, which is great. I'm not even hearing about Spring anymore, and if there is any reason to not use it, it would be this cringe "how do you do fellow kids?" blurb I just saw on their front page:

> Level up your Java™ code

> With Spring Boot in your app, just a few lines of code is all you need to start building services like a boss.

I personally would reach for Go by default, but I have no ill-will to Java.


Spring boot is itself also very different than Spring, so depending on what was your last experience with these frameworks, you might be surprised.

Given, they are still quite reflection-heavy and full of POJOs and annotations, it supports compile-time resolution for many things now.

Also, you would be hard-pressed to find a more productive developer than a well-versed Spring boot guru for typical backend jobs. You might dislike the framework, but credit where it's due, it is a workhorse and the amount of time someone makes a POC, you can make it with spring properly, in a way that you can build your prod app on top. Like, it's easily as productive as RoR and similar.


Serious question - what could Spring Boot give me for POC/prototyping that Javalin or Micronaut couldn't? I really struggle to understand why most of Java shops out there have set themselves on the Boot path. Is it technology-based decision or politics?


Boot has an "app" (err, lib) for everything. It's fully featured, and highly opinionated.

Pretty much any modern computing problem you have, Boot has you covered[1].

So while you may not have ever used a Streaming library before, if you know Boot, then the Spring Boot Streaming library will already be familiar.

[1] https://spring.io/projects/spring-boot


I’m not familiar with either of those frameworks so can’t comment on them specifically, but 10+ years ago not using spring/boot entailed glueing together a lot of disparate libraries to do things spring boot had built in. Spring boot includes pretty much everything. Plus reliability, battle tested, easy to hire people with experience using it.


Spring Data can be ridiculously productive. It is definitely in the magic category, but you can just have an interface with methods named in a specific way, and then just call that from a controller class, and you have a REST API that calls into your DB for any of the usual CRUD queries immediately. And it's not even just a hack that works on the easy case, you can annotate it with complex hand-written SQL (both db-independent, but feel free to use native queries), and easily extend them with real implementations if you need more control.


I choose Spring Boot anytime I have to create a service, just for that reason.

The eco system is a huge force multiplier, and is constantly evolving. Spring Boot simplifies that a lot by simplifying the setup to the point where you often only have to add a single dependency, and everything is configured with default configurations (which you can change if necessary of course)

Just look at all the different projects under the Spring banner: https://spring.io/projects

One example is the new Spring AI, where they have abstracted a lot of functionality and you can change providers (OpenAI, Mistral, AWS, Azure, Google) easily.


The ecosystem factor is real. I was looking at implementing the SCIM protocol [0] in our user management app, and if we were on Spring I could have just added an Apache boot-starter dependency and been done in a few days. However my company uses the Play framework and it’s going to take me weeks to implement it by hand.

[0] https://scim.cloud


If I ever found a startup I will mandate that we use Spring Boot (java/kotlin) until we grow big enough to afford the extra overhead with other frameworks. Spring Boot is truly a Get Stuff Done framework

It would be hard to convince some people of this, because "everyone knows Spring is enterprise". Unfortunately many only have experience with legacy companies, bad code or through reading old blog articles, and base their opinions on that.

It's actually something you need to have experienced yourself to recognize the possibilities.

It may sound strange, but I enjoy going through the long list of projects in the Spring web site. I almost always find something cool and is surprised at how much they can simplify complex functionality

The learning threshold is also relatively low, because they tend to use common best practices in the framework.


I’ve spoken about this before but choosingg Play and not Spring has been my companies biggest mistake. It has lead us down so many half documented custom solutions that would have just worked out of the box if we had chosen the more popular stack.

I like Kotlin, but the lack of checked exceptions really kills it for me. Exception safety is a bigger thing for me than null safety.


It‘s established patterns. Javelin or Micronaut are probably great, but not a lot of people understands how to build a real project with them. With Spring Boot you don’t even think about it.


> The problem with Java since Java 8

I agree with the sentiment, but I'd move up to a version with type inference at least. I have nothing against static types and in fact in a vacuum I prefer them, but the particular brand of OO and "weak" generics that Java and C# have feels like filling forms in triplicate. "var" alleviates that significantly.


Any competent Java IDE automatically generates you a variable declaration from the expression you want to assign to it. It’s actually less keystrokes than having to type “var”. Unless you only use a simple editor that doesn’t perform static analysis, less typing is not a good excuse for using “var”.

Conversely, in Java you often use the diamond operator like in:

    List<String> items = new ArrayList<>();
(Half of which, again, is code completion in your IDE.)

That doesn’t work with “var”. You’d have to write:

    var items = new ArrayList<String>();
while losing the ability to constrain your variable to a narrower type.

The loss of directly seeing the type information in statements of the form

    var foo = bar(x, y);
should meet a very high bar, IMO.


I've found var preferable when reading code.

I've wrought my hands over this and eventually came to the conclusion that developers in every language that started with local type inference have embraced it. So I've mostly ignored my concerns and gone with "var for everything".

If you have trouble with a type then rename the function or variable (AKA your "foo" and "bar" example. The names are bad, fix them. Context matters, we have none here. No one has an editor that displays a single line of code at a time.). But in general we haven't had issues on our projects.

Beyond that, my IDE (Intellij) makes it easy to uncover the inferred type if I really need to be 100.00% sure what it is. In general I don't, because in general I don't care, and even before 'var' I was generally ignoring the type anyways.


I think there is a tasteful way to selectively use var where it makes sense.

Even in your example, narrowing the variable doesn't make much sense - you are in a local scope, you control everything. Narrowing is more meaningful in fields, where var won't work by design.

Locally a well-named variable is often significantly more important than some long, somewhat useless type signature, especially when the right hand side makes it clear.


Generics in Java and C# are _vastly_ different.

.NET has true generics with full type information and struct type parameter monomorphization which works the same way generics do in Rust.

Edit: C# does have type inference for generics, just not the full HM one. It is also quite more capable for lambdas which is a bit frustrating because it does not resolve nested generics otherwise. I miss it - F# does it the way it always should have been.

There are many other differences small and big that arise from the way Java does generics and the fact that primitives can't participate - you will never see `IntStream` kind of workarounds in C#. Some libraries abuse and misuse generics for no profit (looking at you Azure SDK), but it's not as widespread. Shallow generic types are always inferred from arguments.


> you will never see `IntStream` kind of workarounds in C#.

You may not see that in Java in the future either. Java will have value objects from the Valhalla project, and part of the plan is to replace Integer with a value object. Then there will be less of a reason to use raw int primitives, because the JVM can treat value objects much more efficiently than normal objects.


The difference is that C# has been designed with proper generics since version 2 (pushed by F# research group with Don Syme) and is now on version 13. At the same time, structs have been present since version 1.

All APIs and collection types build on this foundation, with standard library leveraging generic monomorhpization for zero-cost abstractions. Code that would have needed C++ implementation in the past is naturally expressed in pure C#. Generics are fully integrated into the type system at IL level, avoiding special-cased types or bespoke compiler handling (besides monomorphization).

This enables numerous zero-cost features: tuples (unnamed/named), structs with controlled mutability and record structs, pattern matching, stack buffers that do not rely on escape analysis, structs with byref pointers for slice types (Span<T> and friends) which a good two thirds of the standard library accepts. Numeric and vector primitives are used in a simple way without setup requirements like Panama Vectors.

While project Valhalla will get Java's foot in the door in some domains, it will remain a less optimal choice than C#, C++, Rust, etc. Java's evolution primarily serves its ecosystem's needs, whereas C# benefits from being a newer language that learned from both Java and C++ and got influenced by F# and other research projects inside MS. This makes C# more idiomatic and terse. The historical drawbacks - platform lock-in, being closed-source, and having relatively weak compiler - have been resolved over the past ~9 years.


yes, this is true. I was talking more about the UX of how to use them, which in both cases is quite painful without type inference.


Ahhhhh, yes. Java itself isn't bad and has been getting better. The frameworks made me want to scream.


which ones specifically? I like Spring Boot tbh


Hibernate mostly. Spring too, but it has been a while. Mostly I just find the abstraction isn't worth it .


I find pretty much every ORM in any language is problematic. The best you can hope for is a certain amount of internal design consistency, so that even if you can't do what you want it's at least clear what you are doing.


The way you write this makes be think you rawdog'd Hibernate and Spring Framework. Don't do that... you will hate yourself.

Boot is something entirely different. You write very little code and get a ton done. The trade off is you are firmly now a "Boot" codebase, but once you learn how Boot works it's not a big deal.


I've had to maintain a couple Spring Boot apps and I absolutely cannot stand them: they pull in a whole pile of random dependencies and do weird things to your build with little explanation. Then, all the functionality involves a ton of classpath scanning and annotation-based DI that makes it hard to figure out how all the things fit together.


I mean, have you learnt the framework before attempting to do that?

Frameworks are frameworks, not libraries. You can't just start writing/understanding them - frameworks are different from libraries precisely because they call your code, not the reverse.


Yes, the problem is exactly that the framework calls your code instead of being called by you code.


That's how all frameworks work though. This is not a criticism of Spring Boot. You are criticizing the use of a framework at all.

Some people hate to write the same basic things over and over. That's where a framework excels. Write only the glue/logic you need to make your app work.

The way you have described your experience with Spring Boot seems to imply you did not take the time to learn it at all, and therefore its' unsurprising to us you had a hard time of it.


Not writing the same thing over and over again is a feature of abstraction. A framework is a user-hostile way to abstract because it makes the source code opaque to developers. There's no reason why a library-based approach has to be more repetitive than frameworks.


Right, so you cobble together 48 different libraries, wrangle all of their configurations and stitch them all together yourself.

You do this 18 times because you have 18 different apps with similar requirements but deal with different data/endpoints/whatever.

On your 19th app you decide to standardize how you cobble together all of these libraries so that you don't have to start at ground zero every single time.

Now you've invented a framework.


CRUD backends have well-understood requirements, in a way, a significant part of the work is done for you. You are there to customize certain parts only.

How else would you architect with this in mind? Given that literally every other framework is quite similar (RoR, PHP's solutions, etc).

There is another niche, the HTTP server libraries, but they are much more low level.


That's a great explanation. Thanks for that.


I was working with legacy code bases where the original Devs loved frameworks. Massive performance problems and nobody could understand how it all fit together at runtime.

Hibernate eventually got entirely nuked, Spring we couldn't entirely unwind easily; it had caused a whole bunch of crappy architectural issues and was too much effort to rewrite from scratch.

Although the code looked simpler using the frameworks and annotations, it was actually a huge rotten mess that didn't work well at all, with workarounds for all kinds of weird things in it.


Since I had the "joy" to use TypeORM (node.js stuff), I really value Hibernate, although there are some little corner cases I'd like to be better. But ORMs solve a really hard problem and I haven't seen anything better than Hibernate so far (and don't come up with JOOQ or MyBatis!).


First time I hear those claims about Postgres. Was that the sentiment 30 years ago?


If say it was only about 15 years ago that the Postgres is slow stuff started dying off. Right around 2010.


It was definitely initially seen as big and cumbersome compared to MySQL, but sentiment shifted.


MySQL was kind of a fast toy database in the early days, but it was good enough to power simple PHP based websites.


14 years or less. Any version of Postgres before 9.0 was a nightmare to administer as a real production transactional dbms, at least the off the shelf version without a whole lot of tweaking without a (then very rare) pg expert.


I don't remember that. But I remember having basic DB features like transactions while MySQL didn't.


what parts do you enjoy now ?

I do agree that new ecosystems (js for instance) makes you miss some of the old big languages development feel. less churn




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

Search: