Live data from Hacker News

Making Lenses Practical in Java

chriskiehl.com

11–20 of 108 posts

Re: Making Lenses Practical in Java

#11

The problem this is trying to resolve is creating copies of a complex immutable class with some deep fields changed. I do have to wonder for a case like this if using a mutable object with a deep copy function wouldn't be a better solution, rather than adding extra magic to do it more easily as possible... Edit: The code in the article would become something like pendingOrders.map(order -> { copy = order.DeepCopy();…

The issue is that this potentially copies a lot of unnecessary information. Also, if you depend on object identities (reference equality), deep copying will recreate objects even if they aren't supposed to change. Furthermore, if you want to chain two update functions, you'll deep copy parts of the object twice times. Lenses are "smart" in the sense that they only copy what's necessary.

A business method on order would do the same without any unnecessary overhead and ensuring proper encapsulation and consistency of the state that cannot be achieved with getters and setters.

   pendingOrders.map(order -> order.approvalConfirmationUpdated(now())

Re: Making Lenses Practical in Java

#12
post #9

I don't agree on the fact that lombok has brought us out of the dark ages. We used to use it, but it has some drawbacks. One of them, it's an additional dependency. This, for a simple thing such as pojo, seems a bit overkill to me. The additional amount of time used to write some cose isn't worth the risk of additional bugs hidden in having one more dependency.

Record classes arguably do a lot of the same thing without the drawbacks.

The biggest thing missing from records that Lombok provides is withers.

Re: Making Lenses Practical in Java

#14

Earlier quoted context omitted.

The issue is that this potentially copies a lot of unnecessary information. Also, if you depend on object identities (reference equality), deep copying will recreate objects even if they aren't supposed to change. Furthermore, if you want to chain two update functions, you'll deep copy parts of the object twice times. Lenses are "smart" in the sense that they only copy what's necessary.

A business method on order would do the same without any unnecessary overhead and ensuring proper encapsulation and consistency of the state that cannot be achieved with getters and setters. pendingOrders.map(order -> order.approvalConfirmationUpdated(now())

I believe the intention is to allow operations on multilayered business objects to be composable. So your approvalConfirmationUpdated() method may actually be made up of a sequence of smaller operations, each of which I might want to use elsewhere in the application. Lenses allow this to happen succinctly, and works better with eg the Java streams API.

Re: Making Lenses Practical in Java

#15
post #14

Earlier quoted context omitted.

A business method on order would do the same without any unnecessary overhead and ensuring proper encapsulation and consistency of the state that cannot be achieved with getters and setters. pendingOrders.map(order -> order.approvalConfirmationUpdated(now())

I believe the intention is to allow operations on multilayered business objects to be composable. So your approvalConfirmationUpdated() method may actually be made up of a sequence of smaller operations, each of which I might want to use elsewhere in the application. Lenses allow this to happen succinctly, and works better with eg the Java streams API.

I got that, my point is that such composability is rarely better than good old OOP with encapsulation. Enumerating all possible state transitions on object interface leads to better design than procedural programming (and composable operations are procedural programming).

Re: Making Lenses Practical in Java

#17
post #9

I don't agree on the fact that lombok has brought us out of the dark ages. We used to use it, but it has some drawbacks. One of them, it's an additional dependency. This, for a simple thing such as pojo, seems a bit overkill to me. The additional amount of time used to write some cose isn't worth the risk of additional bugs hidden in having one more dependency.

Record classes arguably do a lot of the same thing without the drawbacks.

[deleted]

Re: Making Lenses Practical in Java

#18

Earlier quoted context omitted.

The issue is that this potentially copies a lot of unnecessary information. Also, if you depend on object identities (reference equality), deep copying will recreate objects even if they aren't supposed to change. Furthermore, if you want to chain two update functions, you'll deep copy parts of the object twice times. Lenses are "smart" in the sense that they only copy what's necessary.

A business method on order would do the same without any unnecessary overhead and ensuring proper encapsulation and consistency of the state that cannot be achieved with getters and setters. pendingOrders.map(order -> order.approvalConfirmationUpdated(now())

I don't think I understand. We're talking about how to implement this. That method will still have to use deep copying + mutation, lenses or something else internally.

Re: Making Lenses Practical in Java

#19
Lenses are cool, but they make me wonder: how many different paths of a deep immutable data hierarchy are transformed in an application to make this abstraction worthwhile, as opposed to replicating the entire traversal at each location? If the number is small then, however cool, this abstraction may be more trouble than it's worth. Just because you can reify some concept in an elegant composable construct doesn't mean that you should in the sense that it saves you a significant amount of effort.

One way the number of paths could be (arbitrarily) large is if the transformations originate in user input, and the user can choose to arbitrarily transform any node in the structure. But then that input isn't typechecked (because it's not part of the program code), and requires interpretation and validation, so you might as well do the process of interpretation, validation, and transformation in one go using reflection. You don't lose the typechecking that you don't have in the first place, and the result is even more general.

Now if you don't have reflection, lenses could make the interpretation of an input path much simpler (a switch of one level at a time), but Java does have reflection. So lenses solve a problem, but the question is: how big of a problem is it (especially in a language with reflection)?

Post reply on HN