Hello guys, I basically want to do the following: ...
# announcements
p
Hello guys, I basically want to do the following:
Copy code
class Dto(val name: String, val age: Int, val somethingElse: String) {
    var signedKey = ""

    fun encrypt(shaSign: String): String {
        /*do something with all constructor fields*/
        return "encryptedString"
    }
}
the function
encrypt(shaSign: String)
returns an encrypted string by hashing the fields
name
,
age
and
somethingElse
. I basically just want to set the field
signedKey
with the output of that operation.
Copy code
val dto = Dto("John", 36, "something else")
dto.signedKey = dto.encrypt("someShaKey")
Ofc I could do it like that, but that is really not a good way. I thought a bout a distinct setter which takes a parameter (some sign), executes
encrypt
and places the returned value as
signedKey
. How could I achieve that? Thanks ahead!
a
p
Yeah I thought about that too. But the parameter (the key which signs it) has to be somehow part of the object, right? Not a problem for me, just exploring all possibilities. Thanks!
a
Oh yeah, I missed that argument. Is it going to change? Is it known when the object is initialized?
p
Yeah, it basically changes by project scope. There's a different key for the test environment and for the prod env. Making the key a field of the object wouldn't be a problem.
a
the other way is to have a property getter an index operator with some form of memoization (e.g., with a private field)
p
Could you show that as code? I can't really follow there, sorry.
Ah, I missed that the delegate is of course not working with Jackson (I'm building an xml string from the object), so I guess that solution doesn't work.
a
well, I spoke too quickly and thought of something that does not work 😅
a
I would have done something like this
Copy code
data class Dto(
  val name:String,
  val age:Int,
  val somethingElse:String,
  val signedKey:String?=null
)

fun Dto.encrypt(shaSign: String) :Dto {
  // do something will all constructor fields except signedKey
  return copy(signedKey="encryptedString")
}

val signedKey = Dto("John",38,"something else").encrypt("someShaKey").signedKey
💯 1
p
That's a nice approach! Thanks!
m
I think that exposing mutable state like your
signedKey
is bad for many known reasons (increased space state and complexity, not being thread-safe, not referentially transparent, etc.). The simplest solution would be to eliminate the field and just let the client decide what to do with
encrypt()
output. Otherwise, if you really want to make the signature part of the Dto, this is the most OO and testable way I can think of:
Copy code
interface DtoSignature {
    val key: String
    fun encrypt(dto: Dto): String {
        return "some hashing using key and dto fields"
    }
}
// for test environment
object TestSignature : DtoSignature {
    override val key = "test-key"
}
// for prod environment
object ProdSignature : DtoSignature {
    override val key = "prod-key"
}

class Dto(
    val name: String, 
    val age: Int, 
    val somethingElse: String, 
    private val signature: DtoSignature
) {
    val signedKey:String by lazy { signature.encrypt(this) }
}

// usage
var dto = Dto("John", 45, "something", TestSignature)
dto.signedKey // -248748363
 
dto = Dto("John", 45, "something", ProdSignature)
dto.signedKey. // 909103134
👍 1