Python code that follows traditional Python paradigms is called "Pythonic".
Java code that follows Java paradigms is called "awful".
To be fully transparent, I've never written Java professionally, only for a couple small hobby projects 10 years ago, plus some while in school, so my opinion isn't worth the pixels you're reading it on, but I look at most Java code with abject horror.
Endless levels of abstraction. The apparent inability to write a simple function and instead creating a "ThingDoer" class with a single function called "doThing". Run-time introspection and reflection EVERYWHERE. Stack traces that are just an endless stack of calls to functions like ".invoke" and ".run".
I've been under the impression that all of that is a by-product of Java's strict type system, but someone please correct me. Why do Java paradigms seem so awful?
One reason Java codebases feel more abstract is that they're attempting to solve problems that the scripting worlds tend to just punt on, or handle in ways that don't scale well. And because Java's type system is nominal, solutions to those problems require names.
For example, a lot of the abstraction in Java codebases is to make things deeply testable. That's what drives dependency injection, which is where a lot of BeanFactory stuff comes from. What's the Python solution to that problem? Often they just hardly have tests by the standard of Java developers! This is why Python is big in ML research where codebases are often small disposable experiments, and why after a brief era where Django was popular it sort of died off in the wider server / big data space.
Another source of complexity and abstraction is a focus on pluggable ecosystems. Databases are abstracted by JDBC, and then again by an ORM, which then might be abstracted again by Micronaut or Spring, and at each layer there are multiple competing implementations available which implement standard APIs. This kind of thing happens much less in the scripting world. The downside is that scripting codebases are far more locked-in to their choice of libraries. Porting a Java codebase from one database or ORM to another is hugely easier, because the core APIs are all standardized.
On the other hand, how universal is the problem of migrating from one ORM to another? Not all problems Java I has been leveraged to solve are relevant today. This is the extra baggage we have to carry forward.
https://github.com/plantuml/plantuml/blob/master/src/main/ja...
Is there a full library ecosystem of stuff written like the json parser you shared, which is as complete as the enterprisey library ecosystem? Similarly, SO answers? LLM output? Tutorials? YouTube videos?
I think the answer is no.
It's the same problem with C#. Just adding alternate paradigms means nothing. The only thing that matters is how a majority of code in the ecosystem is structured. In java, that's enterprisey code. Most code is glue code, so you're forced into the majority pattern, lest you want to write endless wrappers...
On the other hand, while typescript supports a lot of the enterprisey nonsense similar to C#, the majority of the ecosystem is written with simple functions, callbacks and options objects. Not in an enterprisey way. I don't need to use decorators to use zod.
People that eschew enterprisey code and prefer simple code can't switch to java or c# until the whole culture changes, regardless of the kitchen sink of features either language adds.
Going back to culture, who makes up the Typescript community? While C# devs are attracted to it there are many multiples more devs coming from a JavaScript background. This has a big impact on how the culture developed.
Taking a step back. C# devs often need to do frontend work. They could go with what the industry has settled on, React, or go another way. The bulk go with react and some perhaps lament still have to switch their brain to another mode for that work. Frontend is obviously more fragmented, but the scale prevents C# devs from influencing patterns to the extent that they do on the backend.
I'd argue similar for Java devs when it comes to frontend. In the case of Blazor, I think C# patterns are a much smaller factor in decision-making. In fact, lots of C# adherents would default to React given it's the industry standard.
C# is still much better because it has a lot of useful DX improvements: from object initializers to IEnumerable everywhere. It keeps the tower of abstractions lower, and makes working with the tower a better experience.
Though I've only worked on microservices written in C# in .net core
As for the language itself, a lot of verbosity has been culled in later language versions, with diamond operators, lambda expressions, local variable type inference, etc.
In either case, code is read more than it is written, so if a bit of verbosity makes code easier to read, I'm okay with it.
1. Lack of first class functions till Java 8 is one reason old APIs are horrible with inheritance and reflection everywhere. You had to extend class and override methods even for simplest of tasks.
After Java 11 the code is much more succinct and functional style. But old libraries remain.
There are places where the overextensibility these libraries provide is useful. But those are few.
2. the annotation processors were late to the game - so many libraries which need to inspect object structure (such as serialization) were written with heavy use of reflection.
I will give you an example of how frameworks designed for "modern" Java look like.
Micronaut has something called Micronaut data JDBC - in which you just declare methods with few annotations eg `List<Book> queryTop10BooksByYear(int year)` and it will auto generate the JDBC + SQL code and handle injecting it into your service. The returned object can be a POJO without all the Proxy object circus ORMs come with. I haven't seen something as easy in Python yet. And all this happens in compile time with an annotation processor.
Eh, I don't think Java type system is strict, nor is it the root cause of this cargo cult mess. It's probably due to many enterprise programmers who think design patterns are the building blocks of everything rather than an invisible, emergent structure.