DEV Community

Discussion on: Java vs Go: Impressive solutions for invented problems

Collapse
 
leob profile image
leob

Haha brilliant, I completely agree that in the Java world "we" tend to horribly overcomplicate things, and the "declarative" approach is one of the biggest culprits.

To give an example of this other than JUnit:

I once worked on a project where the backend part was a REST API made with Spring. I didn't develop that part myself, but I had to read the code and make a few small changes to it.

What I noticed is that more than half of the code of that REST API was not Java code but Spring annotations (so the '@' stuff). What I observed was that the Java code was extremely trivial, but the annotations horribly complicated and opaque.

The biggest problem is when something goes wrong (doesn't work as expected), because how on earth are you then going to debug this stuff?

Suffice to say that I hated this style of coding. There is of course no reason why it has to be like this, Java does not mandate this style of coding, but it's become a bit of a "tradition" in the Java world (probably influenced by both JavaEE and Spring).

Collapse
 
siy profile image
Sergiy Yevtushenko

Spring is a great example how Java should not be used.

Collapse
 
jawher profile image
Jawher Moussa

What I noticed is that more than half of the code of that REST API was not Java code but Spring annotations (so the '@' stuff). What I observed was that the Java code was extremely trivial, but the annotations horribly complicated and opaque.

Which reminds me of annotatiomania.com/ :D

The biggest problem is when something goes wrong (doesn't work as expected), because how on earth are you then going to debug this stuff?

Exactly: you end up starting at a multi-hundred line stacktrace with layer after layer of Tomcat stuff, Spring security stuff, Spring MVC stuff, various proxies around your own code, ....

Collapse
 
190245 profile image
Dave

There is of course no reason why it has to be like this, Java does not mandate this style of coding, but it's become a bit of a "tradition" in the Java world (probably influenced by both JavaEE and Spring).

This is a very salient point.

I think the problem is the opinionated frameworks in the Java ecosystem. Spring, for example, does away with a lot of "boilerplate" code... but in doing so, you have to do things the "Spring way" - unless you spend the inordinate amount of time learning what's happening under the hood, and then optimising your code.

In a business environment, no Project Manager on the planet will care about Spring optimisations, because there is no direct business benefit (vs simply choosing a less opinionated approach).

Most experienced Java developers (that I've spoken to) passionately hate JavaEE. Some senior developers are slowly realising that Spring is a bit of a bell curve. In the early days, you don't understand Spring enough to see the benefits... in the middle, you love it... and towards the end, you realise just how much it gets in your way.

As with everything else in our world, it's the appropriate tool for the job, at the appropriate time. Unfortunately, deciding what's appropriate up front is a lot more difficult than with hindsight.

Collapse
 
jawher profile image
Jawher Moussa

In the early days, you don't understand Spring enough to see the benefits... in the middle, you love it... and towards the end, you realise just how much it gets in your way.

I couldn't have put it better 👍
This is exactly it.

Once you've learned the ropes with Spring:

  • You start a new project
  • You're glad to have Spring Boot to quickly bootstrap your app: the embedded tomcat server, the magic auto-discovery of your various config classes and beans, the transparent transaction handling, security, ...
  • Then you start a slow and never-ending cycle of fighting with the framework
  • You get a bug report: if I call the endpoint GET /tax/{code} with something with a dot in it, e.g. vat.20, I get a 500 error No serializer configured for the "20" media type
  • Furiously Google for the magic bean to override to tell Spring not to infer the response type from the extension in the path
  • Don't even get me started on the Spring Security mess: a supposedly extensible setup with dozens and dozens of beans, but good luck understanding the intricate inter-bean relations, which ones to override, how to )safely) override them, ... (I have so many horror stories wrt. the JWT part for example)
Thread Thread
 
190245 profile image
Dave

Spring Security

I'm yet to find a valid reason to include Spring Security in any corporate project. It's simply not maintainable enough for our use-case(s).

Thread Thread
 
jawher profile image
Jawher Moussa

the fear factor: "Are you really sure you want to reimplement your own security stack instead of going of the industry standardm battle-proven 15 year old Acegi/Spring Security stack ?" ¯_(ツ)_/¯

Thread Thread
 
190245 profile image
Dave

Re-inventing the wheel is not a good thing. There's options that aren't Spring Security. For example, for those that for some reason like XML, there's Shiro.

Our model though is that Front End applications implement security properly, and the middleware/backend treats the front end as a trusted component with very basic security requirements. This way, the Front End gets penetration tested and we don't have duplicated code/effort in the security layer. We don't have any Front End applications in Spring, and very few in Java.

Collapse
 
siy profile image
Sergiy Yevtushenko • Edited

I've used Spring since circa 2008 and better I knew it then more I disliked it. It poorly designed and even worse implemented. I really impressed how Spring guys were able to screw up every single idea they've implemented. They implemented slowest possible DI container (about 10x times slower than reflection-based class istantiation!). They made using string constants as a code and exceptions in business logic a everyday norm - which is just insane. Moreover, classic "business exceptions" (let's keep aside for the moment that this concept should not even exist) assumes that "business exceptions" are checked ones and present in method prototypes. Spring uses "technical exceptions" derived from RuntimeException in the place of "business exceptions" and hides remaining signs of business error handling. In other words, they were able to screw up even the idea which is already screwed up. I'm really, really impressed.

Thread Thread
 
leob profile image
leob • Edited

Haha totally agree, Spring is vastly overrated ... the point is of course that back then J2EE was so horrible that Spring felt like an improvement :-) but that doesn't say much, it only proves what an incredibly low bar was set by J2EE.

Maybe it could even be argued that Spring was quite okay in the beginning, but over the years it became more and more bloated and overcomplicated.

And at some point J2EE was improved and simplified so much that it was probably better and simpler (more "lightweight" even) than Spring ... but by then Spring had become totally dominant as the new "incumbent" and J2EE didn't stand a chance anymore.

But even years ago there were already Java frameworks which were much, much better than both J2EE and Spring ... Play (playframework.com) is an example, it does away with all the Servlets and container baggage and is much simpler and easier than either Spring or J2EE.

Thread Thread
 
siy profile image
Sergiy Yevtushenko

Well, I understand how Spring achieved it's popularity. I just realize that there are rarely any justification to use it in new projects. For those who can't imagine their project without Spring "magic" there is a modern alternative (Micronaut) which solves significant amount of Spring issues and shifts huge part of run time reflection to compile time.

There are a lot of Java Web frameworks which are better than Spring - Spark, Jooby, Vert.x, etc. Vert.x, for example usually one of the top performers in Techempower benchmarks.

In my spare time I'm working on similar framework which is based on Promise-based asynchronous processing model and asynchronous I/O API present in recent Linux kernels - io_uring. I hope it will be extremely fast while easy to use.