ribesg
11/25/2021, 8:58 AMvalue class? I just always name it value and I wonder if there is another way that would make more senseMarko Novakovic
11/25/2021, 9:00 AMCompose when am defining routes as value class I name property route.
for example:
@JvmInline
value class Route(val route: String) {
companion object {
val Main = Route("main")
val Dialog = Route("dialog")
}
}Joffrey
11/25/2021, 9:00 AMDuration value class, you could choose to represent the inner value in many ways. For instance, it could be milliseconds: Long or nanoseconds: Double - and you'd better give a clear name here because value would be quite uninformative. Same goes for an Angle value class, that could store degrees or radians. Basically any unitless class that needs to use a unit to store a value should specify the unit. That's just one example though.Marko Novakovic
11/25/2021, 9:00 AMJoffrey
11/25/2021, 9:04 AMvalue is ok of course, when there is no more information to bring. For instance, value class Password(val value: String). But even here we could argue that Password(val clearText: String) would be nicer.ribesg
11/25/2021, 9:05 AMidribesg
11/25/2021, 9:07 AMvalue everywhere for the wrong reason, like âI know itâs a value class so I know I need to call value on it to get the actual valueâ, but you shouldnât really care that itâs a value class when using it I think. Just like if it was a typealias, but with type checkJoffrey
11/25/2021, 9:09 AMbut you shouldnât really care that itâs aÂExactly. That's precisely why I think it's nice to choose a property name that makes sense when you read it. when using it I thinkvalue class
password.clearText is nice, password.value is OK (slightly more ambiguous, but I think everyone gets it).
But it's always on a case-by-case basis for me: userId.value may actually be less weird than userId.id when using it, so maybe value is not that bad here.
Even worse, imagine you have data class User(val id: UserId). I would hate to read user.id.id so IMO in this case user.id.value is better.ribesg
11/25/2021, 9:14 AMeventId.idMichael de Kaste
11/25/2021, 2:38 PMJoffrey
11/25/2021, 2:48 PMInt or Long to avoid messing up what can be combined with what. It also prevents passing a distance to method that expects a duration. This is the type safety benefit.
And if you're hardcore you can even define extension functions like
operator fun Length.times(other: Length): SurfaceArea
operator fun Speed.times(time: Duration): Distance
operator fun Distance.div(time: Duration): Speed
And you never get lost about the dimensions you're working with. It's really interesting as opposed to using regular primitive types.
Another example could be using a Password class instead of a String to avoid mixing passwords with other sorts of texts.
However, wrapping all of those into data class Password(val value: Int) might have a non-negligible cost at runtime due to the boxing of primitives into objects. Value classes are a way to tell the compiler that you don't care about the identity of your objects (just equality of the value inside), and thus the compiler can optimize the boxes away in many cases.Michael de Kaste
11/25/2021, 2:56 PMgildor
11/26/2021, 3:13 AMI would hate to readÂI think itâs a less a problem if you unwrap your value classes only when you need an actual value and most of business logic works with value class itselfuser.id.id
ribesg
11/26/2021, 9:13 AMid.id still triggers me đgildor
11/26/2021, 9:17 AM!! đribesg
11/26/2021, 9:37 AMid.value, still donât like it, so it works anyway đDaniel
11/27/2021, 9:03 PMUserId(val rawId: String)Daniel
11/27/2021, 9:05 PM