[HN Gopher] Making Lenses Practical in Java
       ___________________________________________________________________
        
       Making Lenses Practical in Java
        
       Author : goostavos
       Score  : 33 points
       Date   : 2023-01-15 20:19 UTC (2 hours ago)
        
 (HTM) web link (chriskiehl.com)
 (TXT) w3m dump (chriskiehl.com)
        
       | javaunsafe2019 wrote:
       | I just use Kotlin. Never looked back.
        
         | Garlef wrote:
         | Sure. But what does that have to do with lenses?
        
       | tsimionescu wrote:
       | 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();
       | copy.getApproval()             .getConfirmation()
       | .setUpdatedOn(LocalDateTime.now()));          return copy;
       | }        )
       | 
       | (of course, we could also get rid of the getters and setters and
       | replace them with direct field access, if we take the data class
       | concept seriously)
        
         | ImprobableTruth wrote:
         | 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.
        
           | ivan_gammel wrote:
           | 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())
        
             | kitd wrote:
             | 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.
        
               | ivan_gammel wrote:
               | 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).
        
       | fedeb95 wrote:
       | 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.
        
         | marginalia_nu wrote:
         | Record classes arguably do a lot of the same thing without the
         | drawbacks.
        
           | wtetzner wrote:
           | The biggest thing missing from records that Lombok provides
           | is withers.
        
       | gardenfelder wrote:
       | https://github.com/chriskiehl/Deoplice
        
         | Twisol wrote:
         | For want of context, this is the library described in the
         | article.
        
       | [deleted]
        
       | _old_dude_ wrote:
       | I believe this is a case where a named tuple of functions, a
       | record, is better than an interface.                   public
       | record Lens<A, B>(Function<A, B> get, BiFunction<A, B, A> with) {
       | public <C> Lens<A, C> compose(Lens<B, C> inner) {
       | return new Lens<>(               inner.get.compose(get),
       | (a, c) -> with.apply(a, inner.with.apply(get.apply(a), c)));
       | }         }              Lens<Confirmation, LocalDateTime>
       | $updatedOn =           new Lens<>(Confirmation::updateOn,
       | Confirmation::updateOn);
        
       | ploppyploppy wrote:
       | Jesus just use Kotlin.
        
       ___________________________________________________________________
       (page generated 2023-01-15 23:00 UTC)