What do you guys think about this kind of naming? ...
# announcements
e
What do you guys think about this kind of naming?
Copy code
typealias SessionId = String
typealias TopicName = String
fun unsubscribe(who: SessionId, from: TopicName) {..}
fun subscribe(to: TopicName, handler: (Topic) -> Unit)
๐Ÿ‘Ž 3
๐Ÿ‘ 1
l
if you want to be really strict about it, you could also create a simple extra type for SessionId, such that you are unable to accidentally provide any other string. you could give it a private constructor and only create it at the place you retrieve your sessionId, such that you know that if you have a sessionId instance, it is valid
g
isn't it where inline classes shine?
โž• 1
๐Ÿ’ฏ 5
d
I don't think this is bad - it adds useful intent to your code and means it's easy to 'upgrade' the type later on in case you need to add meta-data. As others have said though, an inline class may give you these benefits and more with no runtime cost.
a
Nah, this is a good example of where not to use
typealias
. It gives no additional type safety but obscures the actual type and associated information from people reading the signature. It increases both complexity and ambiguity. You would gain the benefits from giving better names to the function parameters, e.g.
Copy code
fun unsubscribe(sessionId: String, topicName: String)
without losing the type information and making the reader go look at the definition of the unfamiliar types.
inline classes can be better but they're not a clear win here either for similar reasons.
v
I'm not 100% sure but I think I saw examples of how to deal with similar kinds of situations in this talk:

https://youtu.be/t3DBzaeid74โ–พ

๐Ÿ‘ 1
g
I was waiting for somebody to post it ๐Ÿ™‚. Please, take it with a grain of salt. Many times such "best practices" are based on a debatable premise that this extreme strictness is good, removes ambiguity and even more โ€” comes at no cost. But half of those "bad" examples can be improved with just a better argument names. And the cost is there. With every new type you lose flexibility and stray further away from the actual data. In terms of
Accelerate
metrics (highly recommend this book) it increases your lead time for changes. Simply: extra "wrapping" code brings complexity and coupling which increases cognitive load and slows you down because changes take longer.
โž• 1
l
On the other Hand, making impossible things actually impossible is always good. The whole idea behind Elm does also apply to kotlin to some extent. For things like ids the cost of opaque types is neligible, as youll never have to Do any calculations on the actual data behind it, just Use it in specific places
n
Inline classes seemed like the right path until I tried to deal with them and serializations like JSON or databases... kaboom. Type aliases help with code readability but don't yield type safety.
l
Yea, theire usefulness is limited currently. Theyll have a popular usecase once it's possible to have sealed class Variants be inline
v
@ghedeon he addressed the Cost question starting at

https://youtu.be/t3DBzaeid74?t=1532โ–พ

That's basically can be summed up as: 1. Allocations on JVM are very cheap: allocating space in TLAB is often just a pointer bump. 2. The compiler might even inline the whole class: allocation elimination with escape analysis
@ghedeon what book were you referring to when you said
highly recommend this book
?
g
@vsosnin I'm talking about human cost of processing/changing "extra code", not the allocations. As stated famous stand-up comedian Chat Haase: "more code โ€” more bugs!". The book is about more abstract topics than we discuss here, it's called "Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations", they highlight 4 metrics that make your organization a top performer. One is lead time for changes. And I'm afraid excessive bulking your code with primitive wrappers is a ceremony that is damaging this metric. As always, it depends on the case, just don't throw the practically out with the bath water ๐Ÿ™‚.