Lenses: what they are and why you may want to use them ;)

This is my first post here, and I hope you will enjoy it.
I was trying to figure out which topic I can talk about and I came up with one I encounter in the last few weeks.

I am a backend software engineer in N26, Barcelona office. In N26 we use kotlin…


This content originally appeared on DEV Community and was authored by Paolo Sciarra

This is my first post here, and I hope you will enjoy it.
I was trying to figure out which topic I can talk about and I came up with one I encounter in the last few weeks.

I am a backend software engineer in N26, Barcelona office. In N26 we use kotlin and we build microservices, as you can imagine, to run the digital bank.

We were working on a backoffice microservice, that somehow handled some data about our customers and exposed some endpoints to change them (like a CRUD but not exactly).

So I cannot tell the problem using the same data because those are privileged, but I can explain the same problem using a simpler example.

Suppose you have a model in your application to store information about a Person:

data class Person(
 val name: String, 
 val address: Address
)

data class Address(
 val streetName: String, 
 val number: String, 
 val city: String
) 

Now imagine you have an endpoint and so a domain service to update information about the person, let's pretend you have an interface like:

interface UpdateAddressService {

 fun updateStreetName(
   person: Person, 
   newStreetName: String
 ): Person
}

Now if you try to implement such an interface using just kotlin language you can end up with a class like this:

class SimpleUpdateAddressService: UpdateAddressService {

 fun updateStreetName(
   person: Person, 
   newStreetName: String
 ): Person {
  val newAddress = 
    person.address.copy(streetName = newStreetName)
  val updatedPerson = 
    person.copy(address = newAddress)
  return updatedPerson
 }
}

Now you can imagine that things can easily become cumbersome, imagine for example if the streetName was another value object, something like:

data class StreetName(
 val streetType: String,
 val name: String
) 

then you would end up with something like:

class SimpleUpdateAddressService: UpdateAddressService {

 fun updateStreetName(
   person: Person, 
   newStreetName: String
 ): Person {
  val updatedStreetName = 
    person.address.streetName.copy(name = newStreetName)
  val newAddress = 
    person.address.copy(streetName = updatedStreetName)
  val updatedPerson = 
    person.copy(address = newAddress)
  return updatedPerson
 }
}

As you can see, as soon as your model starts to become nested the longer you will take to do the simple update you were required to.

There is a simple concept in functional programming, called Lens. A lens is a very simple interface that lets you get something from a source, let's call it a target, and let you also set a new target given a source value.

interface Lens<S, T> {

  fun get(s: S): T
  fun set(s: S, newT: T): S
}

Now the real power as often happens in functional programming is that this structure supports what is called a Semigroup, meaning you can define an operation that takes two lenses and combines them, and also this operation is associative.

So for example you can define this combine method in the Lens interface like this:

interface Lens<S, T> {

  fun get(s: S): T
  fun set(newT: T, s: S): S

  fun <A> combine(l2: Lens<T, A>): Lens<S, A> {
    val self = this
    return object : Lens<S, A> {

      override fun get(s: S): A {
        val function: (s: S) -> A = self::get andThen l2::get
        return function(s)
      }

      override fun set(newT: A, s: S): S {
        val newT1 = l2.set(newT, self.get(s))
        return self.set(newT1, s)
      }
    }
  }
}

This is basically what arrow-kt provides to you without the need of having to define the Lens interface and all your needed lenses by yourself.

Arrow 1.0 uses kapt kotlin annotation processor, and using the @optics annotation you will be able to leverage the generated code at compile time using kapt like this:

@optics
data class Person(
 val name:String, 
 val address: Address
) {
 companion object
}

@optics
data class Address(
 val streetName: String, 
 val number: String, 
 val city: String
) {
 companion object
}

And so with these newly defined data classes we can implement the previous interface in a different way:

class ArrowUpdateAddressService: UpdateAddressService {
 private val lens = Person.address.streetname
 fun updateStreetName(
   person: Person, 
   newStreetName: String
 ): Person {
    return lens.set(source = person, focus = newStreetName)
 }
}

and in case we had the StreetName value object, we just need to change the lens:

class ArrowUpdateAddressService: UpdateAddressService {
 private val lens = Person.address.streetname.name
 // unchanged code

So you can see how powerful and clean this structure is.

I hope you enjoyed this article.

See you!

References

The image in the cover is taken from Wikimedia


This content originally appeared on DEV Community and was authored by Paolo Sciarra


Print Share Comment Cite Upload Translate Updates
APA

Paolo Sciarra | Sciencx (2021-11-25T19:34:52+00:00) Lenses: what they are and why you may want to use them ;). Retrieved from https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/

MLA
" » Lenses: what they are and why you may want to use them ;)." Paolo Sciarra | Sciencx - Thursday November 25, 2021, https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/
HARVARD
Paolo Sciarra | Sciencx Thursday November 25, 2021 » Lenses: what they are and why you may want to use them ;)., viewed ,<https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/>
VANCOUVER
Paolo Sciarra | Sciencx - » Lenses: what they are and why you may want to use them ;). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/
CHICAGO
" » Lenses: what they are and why you may want to use them ;)." Paolo Sciarra | Sciencx - Accessed . https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/
IEEE
" » Lenses: what they are and why you may want to use them ;)." Paolo Sciarra | Sciencx [Online]. Available: https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/. [Accessed: ]
rf:citation
» Lenses: what they are and why you may want to use them ;) | Paolo Sciarra | Sciencx | https://www.scien.cx/2021/11/25/lenses-what-they-are-and-why-you-may-want-to-use-them/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.