5 ms·
In terms of applying this to languages other than C++, as someone who’s relatively new (4 years) to Java I expected to see a lot more side effects in the Java I
by RichieAHB 4y ago
In terms of applying this to languages other than C++, as someone who’s relatively new (4 years) to Java I expected to see a lot more side effects in the Java I’ve worked with in that time. In fact, the opposite has been true, and much of the points discussed in this article seems to have been adhered to; even going back to some of the older codebases. That said, we mainly have stateless microservices running on k8s, so naturally that leads to a very different mental model than long-lived stateful applications.
The thing that really strikes me from the article is the tone in which it’s couched. The pragmatism on display makes it so much easier to read than it could be. Coming from another few years writing Scala and thinking I was a functional programmer (writing hobby projects in Haskell, Elm etc.), I’ve realised I prefer programming in Java in a team (or at least my current workplace’s flavour of Java, and we’re on Java 17); a realisation that still surprises me now. In reality, there’s only so much purity needed to ship even a relatively complex microservice, and Java does that very well with some functional patterns thrown at it.
- zabzonk 4y agoi 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?
- _old_dude_ 4y agoJava 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.
- bspammer 4y agoIn 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.
- OmarAssadi 4y agoWhile 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/ImmutableCollectionsExplained https://github.com/google/guava/wiki/ImmutableCollectionsExp...> [2]: <https://projectlombok.org https://projectlombok.org> [3]: <https://projectlombok.org/features/experimental/ExtensionMethod https://projectlombok.org/features/experimental/ExtensionMet...>
- japanman425 4y ago[dead]
- halfmatthalfcat 4y agoAt 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.
- RichieAHB 4y agoThis 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.
- usrusr 4y ago(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.
- pron 4y agoNow that Java has algebraic data types and pattern matching, it explicitly espouses a programming style long associated with FP, especially when programming in the small. See Brian Goetz's (Java's chief language architect) article: https://www.infoq.com/articles/data-oriented-programming-java/ https://www.infoq.com/articles/data-oriented-programming-jav...