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

i am by no means a java expert, but i would have thought that the fact that most objects in java are shipped between functions as references makes purity more difficult to effect and to diagnose than in c++ where everything is by default shipped as a value - of course c++ allows you to change this , java less so?


While you're not wrong RE: object references, Java does have the `final` keyword that you can apply to fields, local variables, method arguments, etc. This prevents the value from being re-assigned short of going out of your way to do reflection hacks and such. You can also apply it to classes themselves and prevent them from being inherited and modified that way.

The only real 'gotcha' there is that, while it prevents whatever it is applied to from being reassigned, if the value is a mutable object of some sort (e.g., an array, mutable collection, etc), it, of course, does not prevent you from modifying the contents of the array, etc. However, Guava provides nice immutable collections to mitigate that issue [1].

It's been a while since I've written modern Java, but I want to say JDK 14? also brought records, which I believe are basically the equivalent of having `final` and `public` on everything as well as overriding the equality and hashcode functions on everything by default so that comparisons are done based on the contents of the object rather than the reference.

And while I am sure many people are scared of the bytecode manipulation that it performs, Lombok [2] provides a lot of little utilities that make using immutable objects totally painless - e.g., applying `@Value` to the class generates all of the necessary boilerplate at compile time, or my favorite, `@With`, which generates methods for copying an immutable object with one of the fields changed (e.g., `val newUser = olduser.withName("Nayeon");`)

Lombok also offers Kotlin-style extension methods [3] which can be nice too for this kind of thing. Though, in my experience, it is the only feature in it that has bitten me at times.

[1]: <https://github.com/google/guava/wiki/ImmutableCollectionsExp...>

[2]: <https://projectlombok.org>

[3]: <https://projectlombok.org/features/experimental/ExtensionMet...>


At that point, why not just use Scala? Get all the immutability, implicits, etc without bolting these things on? I’m asking more rhetorically and there are organizational constraints from doing so, but it seems like if you’re looking for more FP, better solutions still exist on the JVM.


This is definitely true in theory, but in my opinion isn’t so much of a problem in practice. If you expose APIs on your objects that don’t expose mutable methods (I.e. like the normalised method on Vec3 in the article) then you limit exposure massively and in the places that remain exposed (ie standard library methods), it goes against the grain and tends to be avoided. Much as null safety is theoretically a huge issue in Java but, at least in my limited experience Null Pointer Exceptions are relatively uncommon in our microservices.

Obviously process isn’t a good replacement for a proper syntax to prove these don’t occur, but in terms of shipping maintainable, readable software, these pragmatic approaches applied to a mutable, multi-threaded language have largely proved sufficient.

Also, as mentioned in other comments in this threads, Java 17 Records go some way to mitigating mutability concerns too - although mutable APIs are still everywhere in common frameworks and standard libraries. That said, most mutability in a microservice can be scoped to either boot time or locally to a function though, with the latter being invisible to the caller, i.e. constructing a map with the mutable `put` calls, all within the scope of a single method.


(edit: sorry, reply does not really match your post, might have been better a level up? The bar connection to the "java vs c++" that I can come up with is that the pass by reference is not much of an issue when the general mindset is mutation-averse)

Java has come a long way since the "OOP is the bee's knees" days when people fully bought into OOP's out of sight, out of mind promise about mutable state. This started long before language features like records gave post-OOP the official blessing. Along the way have been a few odd intermediate stages like the bean craze that was all about exposing state and pretending that it's still OOP somehow, and the AOP adventures that explored ways to get along with all that mutability.


In my experience this is mostly solved using the “lombok” library for older versions of Java, and by using the records feature in newer versions of Java. Both of these allow you to create data classes with immutable fields.


Java 17 adds records, which are a more blunt tool than using const on method, you have to choose if a class is mutable or not, and not if a method is mutable or not.

For microservices, where you deals with data, it's quite effective because it works like typed JSON.




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

Search: