Search code examples
springkotlinbackenddto

How to make an optimal DTO mapping in Kotlin backend?


My approach is something like I have my entity class let's say:

data class User(
  private val name: String,
  private val age: Int
)

And I have a DTO:

data class UserDto(
  val name: String,
  val age: Int
)

And the mapper function is an extension function of User (inside my class file):

User.mapToDto(UserDto u) {
  this.name = u.name
  this.age = u.age
}

My doubt is if this approach it is the best, because my DTO doesn't have private modifiers thinking it is a val attribute (so it will not be changed). Or there is a best way to do this, respecting concepts like encapsulation and all that clean code other stuff.

I already tried to make a mapper (in another file) but does not work because my entity class has private access, so it makes necessary to do it inside my class User.


Solution

  • I have a take on this question. First, the common approach that I commonly use is to have an extension function that maps an entity to its DTO.The approach is

    data class User(
        private val name: String,
        private val age: Int
    )
    
    data class UserDto(
        val name: String,
        val age: Int
    )
    
    fun User.mapToDto(): UserDto {
        return UserDto(name, age)
    }
    

    This approach makes sure that our code is aligned with the immutability principle.But in your case you have a private properties in your data class and if I use my first approach then I violate the encapsualtion principle. So to resolve this issue we have a second approach that is

    data class User(
        private val name: String,
        private val age: Int
    ) {
        fun getName(): String = name
        fun getAge(): Int = age
    }
    
    data class UserDto(
        val name: String,
        val age: Int
    )
    
    fun User.mapToDto(): UserDto {
        return UserDto(getName(), getAge())
    }
    

    So now our second approach allows better control over the internal affairs on our codebase and alligining with encapsulation principal