anyone else sometimes feeling the urge do wrap str...
# announcements
l
anyone else sometimes feeling the urge do wrap strings with value classes so that e.g. in a
UserProfile
class
email
and
about_me
are different types ? I know its overkill but i cant help it
a
Me too
d
Not necessarily overkill at all. Being able to do
userProfile.email.isValid
can certainly have value.
l
ok im gonna ask the other way round: in which scenarios should i not wrap primitives in value classes ?
c
Arrow Meta (an experimental Kotlin compiler plugin, #CJ699L62W) has a thing to do exactly that, with automated compile-time checks For example you can create an ‘email' value class, and check at compile-time that instances are valid:

https://youtu.be/lK80dPcsNUg

Tbf, you say it's overkill but it's a oneliner and it's not going to impact performance in any measurable way, so... Having the type safety is pretty good
a
When you have no reason to add a method or property to it When you don't need to disambiguate arguments Then you don't need to wrap a primitive
a
That reminds me of a talk in Kotlin conf 2019 :

https://youtu.be/t3DBzaeid74?list=PLQ176FUIyIUY6SKGl3Cj9yeYibBuRr3Hl

l
When you have no reason to add a method or property to it
i actually use functions or additional properties in value classes quite rarely. my main use case is just disambiguation. eg im working with an api of a video game trading website and there's
UserId
ItemId
OrderId
ChatId
TransactionId
ect... in total 15 kinds of ids that all have the same format (16 digit random generated hex string) so i wrapped them all in different value classes with no additional members just to make sure that you dont accidently try to use an id in the wrong context
it's a oneliner and it's not going to impact performance in any measurable way
i was more thinking about how annoying it would be if you constantly had to do
.value
everywhere. but then again i now realize that you don't always need things as their underlying type... maybe i should just try it and see how it goes
p
one trick for the id situation you describe that i’ve used once or twice in the past is having the entity type as a parameter of a generic
Id<T>
class. That might save you a bit of redundancy while still ensuring that you can write method signatures like
fun fetchUser(id: Id<User>): User
, so that someone might not accidentally pass in an order id there instead.
l
oh thats a really cool idea, ty
c
I often use
typealias
for the IDs, but that's only so it's easy to read the documentation, you can't use it for verification
l
yeah to me value classes are most something like "enforced" typealiases
e
as type wrapper for safety or convenience, (inline) value classes should be a great fit
a
that kotlin conf talk was gold