Why we picked Java
blog.picnic.nl
blog.picnic.nl
I focused on front-end for 10 years. Starting with motools and IE6, jQuery, into React + Redux. I moved on exclusively to backend development after a few years of the latter.
You couldn't pay me enough to maintain a highly available/scalable system that wasn't written in a "verbose," strongly typed and compiled language. I'm done with that pain. If you're going to pick Node, I hope you're using TypeScript. Python, no thanks.
Refactoring and implementing new features in Java with IntelliJ feels like cheating, in comparison.
Even Go, which I actually really like, starts to lose specificity at large scale due to its intentional terseness. I deeply dislike implied interfaces, and the error handling in a large codebase is really noisy (one of Java's main complaints), without much net benefit.
There definitely was a learning curve with Java. To the untrained eye it looks very noisy and magical, but once you learn to visually parse it and understand what all the annotations do you can move very quickly with low risk.
Your mileage may vary. If you can move fast without breaking things using some other technology, go for it. But I hope you're prepared for success, when 30+ devs are contributing code to your house of cards. You'll want all the natural protections you can get from your choice of stack.
This shines especially in large monoliths. Refactoring microservice interfaces is hell (which means it's rarely done and they rot), refactoring module interfaces in a Java monolith is a breeze.
Very few projects benefit from microservice architecture.
I think the pendulum will swing in the other direction, as it usually does. The previous (NoSQL) hype burned out in about ten years, hopefully this one will go out a bit quicker.
Also the problem with microservices in my mind is the tooling. Right now microservices are deployed with k8s in docker containers which is still heavyweight for what they're supposed to be. It could be that a language (maybe go) introduces features to allow for tooling to make easier refactoring.
They're hell for new developers coming on to a project too, since they can't just follow IDE links to trace execution paths, and too few projects implement full REST call request/response type safety for endpoints.
If you must use Python, turn on mypy with the `--strict` flag, and do it early in your project's lifecycle. Do NOT make exceptions or allow for "gradual" typing, it's monumentally more difficult to add typing after the fact than early on. Type hint as much as you can, including tests. Pytest's fixtures can be type hinted both at the `def` and with their results as function args.
Scripting language, dynamic typing, microservices and a message queue is shockingly effective.
There is no way to compete with that if you are using traditional development techniques.
It's why we watch videos online on Youtube and not Google videos. The Google developers got beaten up by the much smaller group of Youtube Python developers.
To be honest, I find it shocking that the average user on hacker news doesn't know that software development using dynamic typing is considerably faster than software development using static typing.
Most modern languages are pretty close in productivity, architecture and the way a company is organized have much more impact on productivity.
In big enterprises every small change requires 3 meetings, in a startup you can just make the change.
Youtube did the dynamic typing thing in Python with 20 developers and Google did the static typing thing with several hundred developers in C++ for their Google Videos.
Who do you think won?
https://books.google.co.uk/books?id=eulODwAAQBAJ&lpg=PA136&d...
How about this: Python is only ~1.5 times more popular than Java, and Ruby is way below Java, and yet if you look top successful YC startups, Python has 17% of valuation, Ruby has 52% and Java is merely 1%. You can, of course, choose to interpret it in a multitude of ways, but at least one of them is that if you pick Java for your startup, you are unlikely to be successful (or, alternatively, people who are unlikely to build a successful startup are more likely to choose Java).
https://charliereese.ca/y-combinator-top-50-software-startup...
Nowadays, the speed of development for statically typed languages is much faster, thanks to improvements in tooling. Going further, if you choose a modern language that supports type inference, static typing becomes a pure win, and in my opinion, there's no longer any good reason to use something like Python on the back end. If I had to pick a language for the situation you're describing, I might pick something like Kotlin.
My background for context: in 2000-2009 or so I wrote a lot of C++ and often wrote Python bindings using Boost::Python because of how much quicker and more convenient Python was for scripting and exploratory work. I also wrote a lot of Java in that era, and Java was indeed incredibly verbose and ugly. Like C++, it imposed heavy costs for the benefits it gave you. After 2010 I worked mostly in Scala, and for a year now I've been working primarily in Python. The simplicity of working in Python still feels liberating, and doing Pandas work in Jupyter is great fun, but in most ways it feels like a relic to me now, because I can write code that looks almost as simple and reads just as easily in Scala as Python. (Sadly, I wouldn't recommend picking Scala for a tech stack in a business, because it's hard to find Scala developers who want to write stupid simple code.)
What you static camp guys don't seem to understand is that tooling is not that important, it's just a minor multiplicator that caps out pretty fast. You can't turn nurse into a surgeon by giving her a sharper scalpel.
Most engineers that had Java background I interacted with had a tendency to over-engineer. It's not because they had bad tools, it's because Java has a culture of over-engineering, which they soaked in and embraced. Tools & language are getting better - that's great. But that does not automatically fix the culture, which might take another decade or two.
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
At this point, Java is like BASIC. You can fix the language all you want, but you also need to fix the culture. It's not going to happen while most people won't even admit there is a problem.
There's a reason Zen of Java is a joke: https://medium.com/@ratherabstract/the-zen-of-java-edd99991f...
Starting with needing a level of testing that would make even the most paranoid static-language devs spit their coffee out. If you have any untested code and need to make changes that affect it, you are incredibly screwed. I can make sure my own code has the necessary level of testing, but when I'm at the mercy of other people's test coverage, I'd rather have the help of a compiler.
The performance of tools and tests is noticeable every day. Unit tests and linting are palpable interruptions. One thing I notice constantly is the delay when asking my IDE to add imports. With Scala, I can get it done almost as fast as my eyes and brain can work. With Python, it takes a few seconds before it can offer me the right import.
Speaking of performance, we were excited to discover ruff on HN a few days ago, which advertises a >100x speedup over flake8 -- it's written in Rust, flake8 is written in Python.
Writing C++ and Scala, the attention paid to performance in 95%+ of the code we wrote amounted to using efficient algorithms and not making stupid mistakes. Computers are amazing these days, and if you write straightforward code with good data structures and algorithms, code on the JVM runs incredibly fast, almost always much faster than you need it to. With Python, sometimes you use the right representation and the right algorithm and the result is still disappointing, because in the absence of a JIT, good Pythonic code is a huge multiple slower than it needs to be.
In many cases where performance has been disappointing, we've decided to live with the slowness, because making it faster would mean departing from the straightforward Pythonic style that gives us easy-to-read, easy-to-test code.
> At this point, Java is like BASIC. You can fix the language all you want, but you also need to fix the culture. It's not going to happen while most people won't even admit there is a problem.
This is one thing I agree with. Java and Scala development both have culture problems. The Java world has a disproportionate number of programmers who believe that the imperative, mutable-everything, deep inheritance hierarchies OO style of the 1990s and early 2000s is an eternal truth of software development, and programmers are either virtuous and enlightened OOP warrior-monks, or benighted stray sheep. Apparently most people who don't believe that have jumped ship to other languages, making the problem worse than ever. Scala's cultural problems have been adequately discussed here, so I won't repeat them. In my experience, the best Java code, and the best Scala code, is written by people who are deeply suspicious of the culture associated with both languages.
But you aren't. If your software isn't landing airplanes, you shouldn't treat all bugs as critical. Build safety nets, not guard rails.
Python might have 10% more non-critical bugs, but also allows you to ship 5x faster. That's a great tradeoff for vast majority of projects.
> Unit tests and linting are palpable interruptions.
I do believe some teams have this problem, but mine never had. To me it's a signal of many tangential issues (bloated codebases, obsession with unit testing). I don't believe it's a language-specific problem. Also, you should just lint-on-save anyway, slow linting in CI is a minor nuisance.
> Speaking of performance, we were excited to discover ruff on HN a few days ago, which advertises a >100x speedup over flake8 -- it's written in Rust, flake8 is written in Python.
In order to create a better flake8, you have to create flake8 first. The reason flake8 exists in the first place might be that it was easier to create in Python. First succeed, then optimize, not vise versa. Also flake8 is a CPU-intensive command line tool, not your typical environment for Python.
> Apparently most people who don't believe that have jumped ship to other languages, making the problem worse than ever
> In my experience, the best Java code, and the best Scala code, is written by people who are deeply suspicious of the culture associated with both languages.
I believe that. I think culture will simply push good engineers out of those communities. If you have to fight both language and community, why would you stick around?
It should also be noted that statically typed doesn't necessarily imply verbose. Many statically typed languages support type inference which more or less gives you the best of both worlds.
I find java mentally exhausting. I have only ever worked with java once, and it was long ago when I just began my career over 6 years ago.
Since then I mostly work with typescript and go on backend, and the languages are quite simple and strange code can be understood quickly without having to dive too much into documentation and navigating a million folders/layers of OO abstraction.
I've tried getting back into java and each time I just get exhausted looking at the code.
I was the happiest with when Python grew, not having to deal with things like 300 classes just to make a ping to some REST end point was a welcome thing.
By the time you work around this you are lost in the forest of classes.
Idk, I have written Java EE (and Jakarta EE) projects, and I found everything to be so much worse than e.g. Next.js + TypeScript. It feels like everything is broken in the Java web-dev ecosystem, except spring. I had plenty of struggles with the JPA, where some SQLite JDBC wasn't straight up working or MySQL8 was not supported. This was just to get the project running.
Then, JSPs have like 300 different ways and 300 different opinions on how to do stuff. Should you do routing via XML? Should you put your routes in annotations? Or do implicit navigation in the JSPs? Managing sessions is a pain too.
Setting up and deploying Java application servers in prod is way too complicated compared to Node, Deno, Python, Ruby, Whatever.
> Starting with motools and IE6, jQuery, into React + Redux
Anyway, I hope you didn't have to write pure react without any framework on top of it. I mean, the library is fine, and the React patterns mostly stay the same, but React.js is missing a lot. Personally, I wouldn't touch pure react, unless I have to write my own framework on top of it, but that hasn't been the case yet.
P.S. I also had to work on JavaFX applications in the past. I used IntelliJ too, and the tooling of JavaFX is broken to the point, where you can't even use place controls in your great FXML. Which just made me think about another thing I dislike: Java's XML fetish. I don't hate the format, but knowing what XML namespace is the correct one is often beyond me.
Writing new Java is probably fine, but older Java codebases are the often PITA. :(
"Except Spring?" Spring IS the modern Java web-dev ecosystem. You can't write it off as a small exception. With Spring Boot it is very easy to get something working quickly.
It sounds like you may be suffering from the Paradox of Choice when it comes to the broad Java ecosystem(s). For new projects, just pretend nothing exists except Spring Boot and use annotation/java config for dependency management.
There's obviously a lot of legacy Java out there, but it's so massively popular that there's an immense amount of greenfield development going on as well. Don't take jobs working on Java EE stuff unless nowhere else will hire you and/or they are paying you a massive amount of money to do it.
Spring Boot is passable, as long as what you are trying to do fits within what you're allowed to do and you don't have to dig into the internals too much. Regular Spring is painful, attempting to migrate a project that's been around for close to a decade from Spring to Spring Boot without a rewrite is even worse, especially if it is stuck on an older version of Spring, even worse if you need to go from JDK 8 to JDK 11+.
The complexity of Spring and Spring Boot itself is pretty considerable. I wouldn't scoff at anyone using something like Dropwizard for comparatively smaller projects, as I did recently: https://blog.kronis.dev/tutorials/2-4-pidgeot-a-system-for-m...
In a limited set of circumstances it can be useful to opt for something simpler, that's built on a bunch of other boring, mostly "standard" or at least idiomatic packages. Some might advocate for Quarkus, others for the likes of Vert.X - both are interesting and pretty usable, but perhaps it's a bit too early for either of those. For those interested, ktor might also be worth an exploratory look in non-prod projects (if you like Kotlin too).
There is something to also be said about the likes of Ruby and Ruby on Rails, or PHP and Laravel, or .NET and ASP.NET, or maybe Python and Django - sometimes having fewer options can also make you more productive, especially if a lot of ecosystem is grown around those "main" solutions. Perhaps that's an argument in the favor of Spring Boot.
Nine times out of ten, that's the whole story.
Once again, it must be said that almost no app will ever be twitter scale. Time to market is more important than needing to do some architecture in the future. Twitter was also early in both Rails and doing globally distributed web apps, a lot of lessons have been learned since and rails itself is much better, it's been almost 12 years after all.
It seems like this article could have stopped with, most Dutch developers already write Java professionally.
And like that, there are other crazy things that make me glad I don't have to write Java anymore (I worked 4 years with it in total in the early 2000s).
[1] (VB6, VB.net, C#, Java, PHP, ActionScript3, C++, JavaScript, TypeScript Python, Ruby, 8086 asm, top of my head).
[2] https://stackoverflow.com/questions/6622974/convert-string-t... StringUtils or TextUtils
Is it possible for java developers to entangle their work through poor choices such that development becomes slow? Absolutely; the java ecosystem has accumulated a number of such tar pits. Competent java developers avoid these.
Unfortunately incompetent java developers abound. The world is full of java developers that haven't learned anything new since Java 6 appeared 16 years ago.
The above argument is also used by C++ advocates; C++ is great if you know what you're doing and apply the solutions provided in modern iterations. Ironic since java was Sun's 'fix' for C++. Given the rapid rise of competitors to C++ I believe that argument isn't working terribly well.
There is definitely a higher barrier to entry with Java, and starting new projects involves a bit more setup, but that is never the bottleneck. You start a project once. You work on it every day after that. The time it takes to set up the build system is a drop in the bucket compared to the rest of the work. Maybe it will take your company a few more hours to get to market because of that? Big deal.
Sure, you'll want to check your settings before pushing your first code to prod, but the same is very much true for any other "default" deployment.
The same is very much true for other "boring" platforms as well, such as dotnet these days. Getting started is quick and easy.
Java will have a significantly longer setup process if you decide to throw out all the work that's been done for you and implement your own boutique web server and routing system, but that's not a realistic scenario for most companies.
I imagine most of the Java horror stories people recall come from the days where there were no good Java libraries and everyone was reinventing the wheel. Sometimes there are weird dependencies that stop being maintained and rather than fix the problem, companies opt to stick to ancient versions of Java and the JVM, but that's not really a Java problem either, that's a supply chain issue.
I don't understand what the higher barrier to entry is supposed to be like in practice. If you know the basics of backend development in any language, you can get started. Learning to place annotations on top of endpoints is a five minute tutorial process, not dissimilar from how setting up routes in any other language takes reading a page or two to get right.
The only barrier to entry I can think of is that you probably want the full version of IDEA which costs money, though you can use all of its features for free by sticking to the EAP release if you're tight on money.
My memory of java is from about 2007 and I had a pretty negative memory of it. I recently joined a company that primarily does java development and it's amazing what 15 years of progress can do. It's night and day. Using IntelliJ instead of eclipse alone is a big jump.
The thing is, as a C#/.NET dev, those tools weren't that great 15 years ago, either. But I'd been keeping up with the progress in that ecosystem, using it day to day, so it's easy to forget.
This is what is missing from the conversation. Most of us Java fans have been doing Java for a while. I started in '96. We know the JVM. We grew up with Java and were exposed to various aspects of this platform for over 2+ decades. Java the language is not that hard to pick up, but the platform in its total glory is formidable to those new to the language.
I myself never realized this until a few years ago when in course of quizzing a very vocal anti-Java front-end dev in a startup, he blurted "it intimidates me".
And I think this is really the issue.
There are certainly valid arguments against everything I just said, but quite often they are not the true motivation.
Some of us, like me and possibly you, are more comfortable with conceptual complexity but abhor operational complexity. This [division] mirrors the society at large, imo, but was masked during the early days a couple+ of decades ago when software geeks were truly geeks. That subset of demographics never was upset by complexity per se, only un-necessary complexity was a cause for getting upset. The general demographics is bothered by complexity, period.
Companion theory partly based on this opinion is that as the community grew by orders of magnitude from say late '80s to '10, it began to more closely resemble the general population. So the degeneration of keep it simple, stupid (KISS) to mean keep it stupid and simple is an economic and social phenomena.
We are workers in a field with an arts and craft mentality on the production side and global industrial demand on the consumer side. The factory worker plugin iPhones together is not asked to think conceptually. The factory worker making software widgets in some IT department however has to come up with an ad-hoc 'assembly-line' with his or her teammates. Of course they are going to poo poo conceptual complexity. What does it bring to the table for them or the production line?
In contrast, learning (or copy/pasting) n chants for m different infra-beasts to get your widget online seems far more reasonable and far more bangs for mental bucks.
May be you are the one refusing to leave the comfort zone. Fairly large chunks of programming ecosystem has moved to Golang, Rust and even other JVM languages like Kotlin for a reason. Most Python programmers today are Java refugees too.
Its just that the overall culture of Java is loaded with programmers who like to use senseless abuse of design patterns as some 'smartness signalling' mechanism. Endless layers and indirections to achieve even simplest of the tasks.
Using something like Golang and Python feels instantly less stressful and liberating when you go from Java to these languages.
Really, really doubt this. 100%. Not blaming the developer, surely, but even modern java is more complicated than running something in node.js
> The time it takes to set up the build system is a drop in the bucket compared to the rest of the work
It's not just a one-off, Maven will make your development slower every day of the week. Every build, every unit test run, etc
It takes 2.5x time to develop a program in Java rather than Python. It's been measured.
So you will reach market in 2.5 years instead of 1 year. Bit of a difference to say the least.
People use scripting languages like Python due to faster development times. They certainly don't use them for resulting code performance :p
Youtube vs Google Videos: https://books.google.co.uk/books?id=eulODwAAQBAJ&lpg=PA136&d...
Youtube's 20 developers using Python were able to out compete Google's several hundred developers using a more traditional language.
Here's a study for you: https://games.greggman.com/game/dynamic-typing-static-typing...
And productivity to me is not how fast I can bang out a solution to a small problem. I can do that in many languages no problem. Productivity to me is being able to effectively maintain very large (million+ lines) code bases. Not having types is a productivity killer in that scenario. And Python being a slow languages (when not calling C libraries) makes it even worse.
But hey if you feel more productive using Python that’s great! More power to you.
For why Python is more productive:
Dictionaries (maps), sets, (generic) lists, tuples are first class citizens of the language with simple syntax.
Typing is dynamic, which means generics, abstract base classes, interfaces and tons of typical boilerplate code, which you would use in Java, are simply speaking omitted entirely.
Extensive library, which is easy to access by pip.
It would be very weird indeed for a developer not to be more productive in Python than say Java.
It should be fairly obvious why the hundreds of Google engineers were run into the ground by a small team of Python developers.
And if you think that typing a few fewer characters will make you more productive then we clearly don’t agree on what it means to be productive. Programming is not about typing fast :)
And pick any two random developers using the same programming language and you will probably find that they vary dramatically in productivity.
And please don’t worship Google developers like they are made of magic fairy dust. I have worked with people who ended up joining Google and they were OK but not great developers.
So no it is very far from being obvious.
I'm pretty sure that developing with scripting languages is significantly faster than regular programming languages :p
Are you actually trying to argue against that?
Not sure why you think I was worshipping them? Several hundred developers being knocked out by 20 developers is an impressive feat.
You do know that Java has had those for decades, right?
I thought it is 2.54 times faster. Python to Java is inch to cm.
A fast horse is not slower than a fast car.
Languages and ecosystems shape how people think. For example, you will find that Java and Python programmers have very different values and principles. Given same options, they will make extremely different choices. Clearly this is going to have at least some effect on time to market.
I found Java to be a land of overengineering, verbosity, and anti-patterns. The infamous "Hammer Factories" [1] post screams Java to me.
[1] https://www.danstroot.com/posts/2018-10-03-hammer-factories
Co-routines have been in Kotlin for a while, got added to Java (Project loom) recently. Same for startup time. Native image support in Project Leyden
Downsides are that highly dynamic and reflection-happy Java code bases/libs won't run OOTB, that using profile-guided optimization (for achieving or surpassing HotSpot perfornance levels) requires a commercial EE license from Oracle (about 300-400 bucks per seat last I checked, not required for mere development until used in prod or at customer sites, and bundled with commercial JRE/JDK subscription since about a year), that even with EE your garbage collector choices are limited, and the somewhat overwhelming number of optimization flags to pass to native-image, not unlike earlier JVM runtime arg excesses.
Super light frameworks, more http focused, Kotor and Javelin
Spring itself had a major overhaul recently
What matters most for maintaining large codebases that a lot of people work on is the type system and the tooling. A large ecosystem of good tooling exists for working with Java, and it is empowered by the static type system to do some very impressive things. Some of the .net stuff is probably close to that with Visual Studio and the ecosystem around it. Everything else is pretty far behind, including Python and Ruby and Go.
I know people who work on a massive Java codebase that is almost 20 years old and has over 1000 people currently working on it -- and thousands more have passed through that codebase in prior years. It's not a lot of fun. But if it was a Python codebase, it would actually be impossible.
But on the whole Java is not bad. I think it’s perfectly OK. I am more afraid of Java culture.
I've worked on a lot of codebases that appeared to be put together by developers who took that as a challenge - IME Java developers LOVE global variables (but they call them "public static" to make themselves forget they're using global variables).
Edit : Python. The point remains the same.
Search for the memo where Twitter migrated to the JVM. That one actually did happen.
Link :
The source :
https://twitter.com/TechEmails/status/1433837480449613839/ph...
Discussed on HN, 2021
"We're constrained on UI/Java development resources", "we have 1.5 engineers working on UI things and that is slowing us down" and "I think if we had one more good Java/UI engineer we'd be kicking butt vs YouTube".
So the problem was a lack of people ("resources") assigned to the UI side, i.e. too much of their headcount is being consumed by the C++ infrastructure leaving very little time for UI-centric work like social features. Google Video's problem is stated here to be too little Java development, not too much.
As someone who was there at the time and who read the internal post-mortem written by the Video team, Google Video vs YouTube wasn't primarily about implementation language. It was pretty much as the emails you cite say:
"They're cranking interesting features a lot faster than we are, but don't likely have a backend that will scale or a plan to make money. We, otoh, have these"
The YouTube guys did the now classic VC play of focusing on growth hacking without any idea of how to pay for it all beyond being acquired. At the time Google bought them the site was close to total collapse; the project to stop it running out of bandwidth was literally called BandAid. The Google Video team was also small but focused more on stable and scalable infrastructure, and product-wise they'd been chasing professional content as they couldn't see any obvious path to monetizing hobbyist produced video. In turn that pushed them away from the Flash plugin towards a more HD video oriented custom plugin, which hurt adoption. These were the wrong calls clearly, but, YouTube didn't really have a plan either. In the end both sides needed each other. One of the first things that was done after the acquisition was start moving core YT functions like video and thumbnail serving off Python and onto the Google C++/Java infrastructure. The web server UI on the other hand remained in Python for a long time so their (social) feature throughput wouldn't be disrupted. I think that codebase did eventually stop scaling and got rewritten, but my memory starts to fail there and I can't quite recall what the state was back when I left.
> Before Google acquired Youtube, the majority of the code was initially written in PHP, but there were many restrictions and clutters in PHP at the time, so after acquiring Youtube by Google, they moved to Python as one of the core parts of its backend programming.
Python started after google's acquisition. It's not that youtube was "never written in PHP".
https://ourtechroom.com/tech/technologies-programming-langua...
Had to stand-up a server in Java recently.
At some point I realized I was doing more programming via XML files and Spring decorators than via actual Java code. Mostly because Java itself isn't a great abstraction for a CRUD server.
I haven't touched XML for nearly a decade as a full-time Java developer.
BUT I have to say, every project using gradle as alternative so far has receded into bizarre ad-hoc deployment scripting. Maybe that's just because gradle can do stuff that was hidden away in jenkins build files, but still ...
Predictably, the team therefore used both.
I usually enjoy Spark[1] for bootstrapping a simple REST-like interface. There are other options, but in general, you don't really need glue-languages at all if you stray away from old-fashioned EE-style frameworks.
It's just that with Spring, I can go to an extremely well-written user manual, or to StackOverflow and get my questions answered. With the Python/Flask codebase, I had to splunk my way through all the layers of random libraries the original developers slapped together, in an attempt to reproduce something resembling out-of-the-box Spring.
I suspect that those original developers had fun making all of those custom choices back in the beginning. I don't know for sure though, since of course they've all left the company since then. The company chose to migrate because it wasn't maintainable once that tribal knowledge left.
I'm sure there are Flask style frameworks in Java land too. And there was a port of Spring for Python a while back too :)
Both of those put a strong emphasis on types, but only one of those (it's Java) is the sort of language that really attracts developers that love types like AbstractWidgetBoundaryFactoryWrapperFactory.
I can definitely understand the "Citizen Kane" effect of looking at a modern Java framework and going "yeah looks just like any other language, except with types and IDE support". Java didn't get there from nowhere. It got there after 20 years of being overly verbose and frustrating to work with.
Honestly, I think the only reason C# is winning at all right now is because MS controls Windows and can silently keep .NET infrastructure up to date all the time. There must surely be a parallel universe where Oracle created their own OS where they enjoy the same benefits as MS.
Thanks to verbosity, Java creates the very problem that it tries to help with.
Did you need to have that many programmers and that much code? Who knows. But once you have it, continuing with Java makes sense.
If you've never worked on a small team, the productivity difference from staying small may not sink in. But they are real and large. And companies should not lightly cross that threshold.
I agree with you that, on a large team and in a large organization, terseness and dynamic typing are bad. But I don't agree that verbosity is not a problem. It absolutely is. It makes you have to go to large teams sooner.
In all the time since I keep hearing "modern Java this" and "modern Java that". But every time I venture into some Java, well, my limited experiences haven't fit what I was told about "modern Java".
Maybe I just haven't encountered modern Java?
As for the API+3rd party support argument, the productivity of third party libraries has been used as an argument for ages. I remember when it was being made about Perl with CPAN. My experience of it has always been that libraries make a great start to the extent you have a common problem. Which is wonderful for demos. But once you're in the weeds, you still have to write lots of code. Maybe there isn't a library for your unique needs. Maybe the standard library has bugs. Maybe you wrote code because there wasn't a library but now there is.
No matter how it comes about, you wind up writing code.
even modern Java 18 codebases with exclusive use of records instead of classes, and with enabled enhanced support for instance pattern-matching instead of old-school conditional blocks and switches, are still significantly more verbose than Scala codebases, especially if the latter use `cats` or `scalaz` for all traversal/mapping/folding logic. Java developers would just manually encode all these patterns into series of nested loops by hand by default every time, because the required tooling as well as the compiler help to aid that tooling is not available in the language.
But that's not the code that takes time to write or read. In that department Java isn't more verbose in a significant amount. If you're the type of person that gets upset that every line ends with a semicolon or that we need to repeat the word public for many methods. Then sure. Java is verbose.
Looking at the body of a Java method I don't see something I can significantly cut down with TypeScript or Python.
Also, I really have a hard time believing that java would be significantly longer than any other mainstream language, it is at most longer by a small constant amount.
It is, all the time. For some random examples:
https://news.ycombinator.com/item?id=27175184
https://news.ycombinator.com/item?id=8893204
The "Triple Crown" of Java frameworks, namely Spring Boot, Quarkus, and Micronaut, but also with the influence of smaller contenders (Dropwizard, Javalin, SparkJava, and a few others) have helped developers focus on business code rather 'design patterns' because these frameworks have embedded a lot of the "over-engineered" concepts into their 'opinionated' approaches.
Developers are no longer thinking too much about layers, and just writing components by following the guidelines and best practices of these frameworks. The final result is pretty similar among all of them, especially for microservices.
A mundane version of this problem is dependency management: every Spring app I know is constantly patching CVEs, almost always in optional code for features they aren’t even using, and sometimes upgrades are not trivial because you have to push around a lot of framework code. Node is similar but at least the tools are better.
None of that is specific to Spring, and I’m sure someone will pop up to say that’s doing it wrong but it’s been 100% of the work I’ve seen from multiple contractor teams so perhaps the way to characterize it is that the community doesn’t have enough culture of pushing back against support burden or complexity.
Spring is the fucking devil though.
What's wrong with maintaining large Java code bases? Say what you want, but the language is built for that.
The worst code-bases I've seen tend to come from dynamic languages. Try to maintain hundreds of thousands of lines of python or ruby code over several years, and see how fun that is.
>From a non-engineer view though, let's be real : nobody ever got fired for picking java.
No. That's not a correct framing. Java is one of the few languages that able to strike a great balance between performance, development productivity, 'debuggability", cross-platform support (i.e. works just as well under Windows as Linux), language safety, and library and framework ecosystem. Honestly, it's hard to come up with a use-case where Java isn't a natural right answer.
Maintaining a larga Java code base is very easy (I think much easier than e.g. Python). The tooling is awesome, there are countless libraries, last but not least Java is the easiest to hire for.
Only because it's almost impossible to quantify and is so contextual. However there is a good reason why Java is getting many extra language features from functional programming, e.g. streams, records, "sealed classes", pattern matching. Yes, productivity. Personally I am far more productive in OCaml, Haskell and Rust than Java; and that's after spending many years getting a lot of Java experience. But these are not necessarily good choices for the risk averse, which really comes down to the real reason why you chose Java.
Also, Java deliberately move slowly, it is a huge benefit for the platform as it can better avoid potentially vain features that would have to be maintained forever even if they are not popular. Algebraic datatypes debuted many many decades ago, yet they only become sort of mainstream in the last couple of years.
> Another important factor is that the team of engineers building the first version of Picnic’s platform already had ample experience using Java and the JVM.
And the author of the blog post is a book author on the language and Java Champion, so uhh, yeah, it would be very weird not to go with Java in this case.
If your product or service is a success you can completely rewrite your app and change your entire stack.
That's exactly what they did.
> Go make your thing already.
This article is about a company founded in 2015 that now has a 300-person technical team. They already made their thing and this post is a retrospective looking back at that experience.
https://news.ycombinator.com/newsguidelines.html
Also, my comment that is about making their thing is not about this article specifically, but in general as this type of article is very common, but I removed it to clarify my main point.
That's fair. I've updated my comment to remove that bit.
Unless you're writing things in C or brainfuck, you shouldn't "hire for" language experience.
It's boring and unsurprising to a fault, which is a great selling point if you want to build something of nontrivial size and scope.
Another strength is that it has a large well rounded standard library and a large set of mature libraries you can pull in when needs must. Not quite as batteries included as python, but not far off.
The tooling is best in class, the available IDEs are great, debuggers and profilers are ridiculously powerful even at face value, and that's not going into the iceberg of weird shit you can do, like you can attach a debugger to live production process like no big deal.
There are pitfalls when it comes to frameworks. Like both Spring and Spring Boot are quagmires that tank your performance. Like whatever velocity you gain from starting off with those is lost waiting 90 seconds for the planets to align every time you want to run your unit tests.
There is also a lot of magic going on in JVM e.g. there is one optimization that causes stack trace to be omitted if the exception is thrown from a given place a lot of times. Beginners then see an exception without a stack trace and are stuck. SO rel: https://stackoverflow.com/a/3010106/1779504
Spring can be a source of confusing problems when defining beans (especially when you have to use Qualifier's). Most of the juniors that I had a change to work with had very hard time getting used to Spring bean model. And I am not mentioning here strange Spring Proxy behaviour that can defy even programmers with 10+ years of exp
That said, I did once sorta port a somewhat tortured definition of Haskell's parser monads to Java's type system for an event at work, mostly as a joke. Like it's doable. Wouldn't want to maintain that code, but it's doable.
In general I don't think "does it confuse beginners" is a great metric for what makes a good programming language. You'll be able to find a beginner who is confused by almost anything. Beginners are hopefully not the same people who will write or maintain the code.
I have yet to be bitten by this stack trace behavior, thanks for the heads up, but I think every platform has its idiosyncrasies. I would still not change it for UBs everywhere :D
And I really don’t think that the spring model is all that difficult, we just have plenty of bad developers and not enough focus on proper education of juniors (often done by “senior”, bad devs)
There is some admittedly unintuitive behavior when it comes to type conversions, especially in bitwise operations. Like this is just nasty:
long f(int a, byte b) {
long ret = 0;
ret |= b;
ret |= (long) a << 8;
return ret;
}
System.out.println(Long.toHexString(f(100, (byte) 64))); // 0x6440
System.out.println(Long.toHexString(f(100, (byte) 129))); // 0xffffffffffffff81
// you need to do
long f(int a, byte b) {
long ret = 0;
ret |= Byte.toUnsignedLong(b);
ret |= Integer.toUnsignedLong(a) << 8;
return ret;
}This doesn't sound like a thorough assessment of Java alternatives one would normally expect from an engineering team. There's hardly any technical reason to choose Java in favour of Scala3 today, except one: the team's lack of Functional Programming expertise. Otherwise, choosing Scala for JVM would almost certainly result in better quality software in terms of safety and internal components design suited for long-term maintenance.
I disagree about your premise at multiple points, but I want to focus on just one point - In my experience, Functional Programming is a large enough of a technical reason to not choose Scala in a company of a reasonable size. It's actually such a big reason that it deserves more than as an afterthought as you have it written.
I worked in Scala for 10 years. Not only was it difficult finding seasoned Scala devs, but also we often had to compromise by hiring Java devs and training them on Scala. Time and time again, functional programming was always the most difficult hump for them to grasp and it took experienced devs forever to learn the language and a new paradigm at the same time. Sure, you could hire someone who knew functional programming already and came from a background writing Haskell, but they were rare and usually commanded exorbitant salaries that made sure they were never in the equation to begin with.
Not to mention, you better have a disciplined team with strict linting rules and styleguides, otherwise your devs will go off the rails using Scala in ways that the team isn't prepared to learn. Or if you have Java-trained-Scala devs, they might revert to their old OOP ways.
Because of that, it actually causes more problems, resulting in worse quality software and worse deliveries overall.
It's too much of a risk, really. Especially when Java is not really a terrible choice in a large enough organization - same huge JVM ecosystem, large pool of devs, mature toolset, etc..
You say you disagree with my premise, yet you seem to be confirming the point I made. Your arguments revolve around difficulties with finding devs for a team and with training them to actually understand FP at a level that would allow them to untangle their algorithmic thinking from OOP. It's exactly what I said about the only proper reason to choose Java over Scala: team's lack of FP expertise. Other than that, my point still holds: type algebra and explicit nulls opt-in bring better quality software overall. And it does require FP expertise, not just awareness or vague familiarity with.
> otherwise your devs will go off the rails using Scala in ways that the team isn't prepared to learn
This also contributes to my initial point. But I'd like to know what are your examples of off-the-rails, as I've been to situations where a couple of folded traversals had been called similarly "too much" in a Scala codebase, but for someone writing Haskell it was just a regular application of a familiar pattern.
> Sure, you could hire someone who knew functional programming already and came from a background writing Haskell, but they were rare and usually commanded exorbitant salaries that made sure they were never in the equation to begin with.
This is a specific argument that could be made within your organisation. I don't know your budgets and the requested salaries by respective candidates, and you didn't clarify the level of expertise your teams were looking for, so I can't make an informed judgement about the merits of this argument and to what extent it could be applied onto the tech stack in general. I've been doing FP for a meaningful amount of time, mostly in Haskell, and the common theme over all these years has always been a visible shortage of FP positions compared to the number of capable candidates willing to compromise on their salary in exchange for an opportunity to use Haskell at their workplace. Many of them were instead compromising on Haskell in exchange for a regular Java-grade salary for writing Scala. And I've never heard of people commanding better salaries just for the fact of being able to write Scala instead of Java. Usually it was due to additional set of skills, like strong algorithmic training or extra years of business domain expertise, and these traits bring additional value to organisations, if they are able to utilize them within their teams.
> Especially when Java is not really a terrible choice in a large enough organization
It certainly isn't terrible, but it also is neither safer nor more productive. For a developer who has a good command of both paradigms, Scala would be a better choice on JVM.
good call. that's where it belongs.
Java is a very backward language, at my current job we use Lombok to generate boilerplate code. Lombok itself is a compiler hack, I don't like it. Why is that Java 17 records does not have supports for builders or for "withers" (point.withX(3)), C# & Scala offer both of those things. This makes records unusable for most of my use cases.
The other hard miss is lack of named parameters. This either makes code very verbose or less readable.
And my last complain is about lack of support around Futures/async/await. Yes there will be project loom, maybe even in next JVM release but currently we don't have it and a lot of libraries will need at least a year to support it. So instead of await's I have to manually compose CompletableFutures into spaghetti like code. I really hate this. We propose to our architect to use Project Reactor but the idea was discarded (after all Reactive Programming is not very popular among "commodity" programmers).
If I had to start a company now I would probably also pick Java (or Go), my main points would be: - Free compiler and IDE - Good library support for wide range of use cases - Programmers available on the market (Java) or willing to learn (Go) - Good build system, static analysis tools, best practices, learning materials & stack overflow - Language is battle tested (sorry Haskell, Ocaml & Lisp)
Yeah this reduces it to Java for JVM, C# for .NET, Go if you are adventurous. If someone pick something more ambitious like Scala 3 or Rust I would gladly join that company, but if it was my own I would not risk it.
do you mean battle-tested by yourself? Otherwise it's kind of FUD opinion, as Haskell is battle-tested across industries in quality-demanding domains[1], and I'm sure the other two have similar lists of industrial application.
[1] https://www.reddit.com/r/haskell/comments/6p2x0p/list_of_com...
Spoken like its 2002!
Java does "have it," as in Java has streams. It's pretty crappy compared to Linq due to language limitations but it's a lot better than nothing.
I think that's unfair to the Streams API. It wasn't intended to solve the same problem as Linq and the problem it does solve it does very well. Streams transform collections. Streams API statements are usually elegant and the party piece of Streams is concurrency with parallelStream(), which will distribute stream operations across threads safely and transparently.
Perhaps java should have a Linq equivalent, but the fact that the Streams API isn't that isn't actually a knock on Streams. In the meantime there is JOOQ and others that deliver elegant query syntax with compile time type safety.
If you think Streams API statements are elegant compared to LINQ, I again don't think you are familiar with LINQ. C# has language features Java does not have which usually makes LINQ much more succinct. For example, imagine a list of order items where each item has a double "Price" property. If you want to sum the price of all the items, here's how you'd do it in C# vs Java:
C#: double sum = items.Sum(item => item.Price);
Java: double sum = items.stream().mapToDouble(Item::getPrice).sum();
Java lacks extension methods, so stream() must first be called to get at any stream methods. Worse, Java has generic type erasure, so I have to to call "mapToDouble" to get this hacky concoction called a "DoubleStream" which actually has the sum method.
Not the end of the world, for sure, but definitely crappy compared to LINQ. There are lots of other irritating problems, such as Stream itself not being enumerable and the need for calling collect with a Collector.
Java has a massive community and a community that shares knowledge. This is what makes Java the greatest tool for any business.
I mean, it's perfectly fine to pick language you're most familiar with, but maybe let's not pretend you're not biased? I wouldn't want to work for a leader that is full of BS.
The article unquestionably leaves the impression that you were there when the choice was made.
And then everything in Spring and stuff you can plug from the ecosystem.