3 ms·
While there are things I wish it did better for the sort of stuff I use it for (foreign memory API can't arrive fast enough), Java is a pretty solid pick. It's
by marginalia_nu 4y ago
While there are things I wish it did better for the sort of stuff I use it for (foreign memory API can't arrive fast enough), Java is a pretty solid pick.
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.
- 0xmarcin 4y agoHave you got a chance to read "Java Puzzlers: Traps, Pitfalls, and Corner Cases"? Java is a very surprising language with a lot of strange corner cases (a lot of them related to reified generics and wrapper types). 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 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
- marginalia_nu 4y agoYeah. Generics is arguably Java's weakest point. They're an afterthought in the language's design and should in general probably be avoided in all but the most trivial cases. A lot of problems go away if you stop trying to make Java into Haskell or C++ and just avoid the feature unless absolutely necessary, which you rarely do. 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.
- kaba0 4y agoWhile it is surely an afterthought, it is imo very well executed knowing that — while you can’t have proper Monads, quite a lot can be accomplished, just have a look at some FP libs written in Java.
- kaba0 4y agoI have read that book, and while it is a great read, it rarely employs realistic code you would run into (will you really cast some number literal multiple times and try to guess the resulting value in actual prod code? And things like that) 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)
- marginalia_nu 4y ago> I have read that book, and while it is a great read, it rarely employs realistic code you would run into (will you really cast some number literal multiple times and try to guess the resulting value in actual prod code? And things like that) 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; }
- 0xmarcin 4y agoThe problem is that in Java byte is _signed_ type. So `(byte) 129` is the actual source of the problem, the number is simply out of range (-128 to 127). Since there is no byte literal and numbers by default are integers you always have to cast when calling a function with byte parameter. There is simply no distinction between safe and unsafe cast...