This is a bit pedantic maybe, but I was hoping peo...
# arrow
b
This is a bit pedantic maybe, but I was hoping people could share their opinion on how they name function parameters and types in a way where you don't unnecessarily repeat (or leave out) information.
For example, let's take this as a basis:
Copy code
import java.io.File

data class Profile()
Here's one way to do it (1):
Copy code
fun readProfile(file: File) : Profile = TODO()
Here
file
nor
File
says nothing about what kind of file. So, you could improve this as follows (2a):
Copy code
typealias ProfileFile = File

fun readProfile(file: ProfileFile) : Profile = TODO()
or
Copy code
fun readProfile(profileFile: File) : Profile = TODO()
This example may not be great, but I hope the question is clear. It's hard to encode the contextual meaning in your data without duplication. Could someone share his experience with how to deal with this?
r
Hi @Bart Kleijngeld, in this case I would use
Copy code
fun ProfileFile.read(): Profile
👍 1
b
That seems a nice way to do it here. Although if I understand correctly, if
ProfileFile
is a type alias of
File
, you will extend the
File
with this function, right? (Which would be undesirable)
r
yes, if you don’t want to extend File you need to wrap it.
Copy code
@JvmInline
value class FileProfile(val file: File) {
  fun read(): Profile = TODO()
}
otherwise typealiases are just aliases and don’t really hide the type you are decorating
b
Okay, thanks 🙂. And considering my question more generally, I would expect having the types be descriptive and meaningful is probably the first priority, parameters second? Curious how you feel about that
r
no problem! I have no strong opinions on names but I tend to follow the same kind of approach as in your example plus more concise on the operation names which are the ones used the most in syntax and calls. I plan on heavily abusing extension receivers when they are available in main kotlin to make things more concise and better separate data types from their behaviors.
1
t
Descriptive types are also useful to display (architecture?) intent. If you have a FileProfile your function can now ask for a file: ProfileFile, which means you are modelling possible state changes and the compiler will guarantee some things for you there
b
@Ties Could you elaborate "you are modelling possible state changes" a little? I'm not sure I follow that one in the context of suggesting
FileProfile
as a type
t
It was a bad wording in this particular case. The better example would for example if you have a Contract that could be signed it is better (imo) to have a Contract class and a SignedContract class instead of a Contract(signed : String?) . Now you can ask for a fun blah(contract : SignedContract) in your function signature, and therefor your code will not compile if you try to put a Contract (without signature) in that method because the compiler will now allow you to. So instead of nullable fields you model the state change (contract -> signedcontract) as different classes and you now have compiler protection that a method will not be called when the contract is not yet in a valid state. In your case there was not really a statechange but you will still display intent (you will not accept any file, you want to have a FileProfile, which means the person calling your method will be forced to make a consious decision)
❤️ 2
🙌 1
b
That's a really nice advantage indeed!
t
So that would be the big difference between parameter name and type 🙂
b
This really helps sharpening my intuitions, thanks 🙂
t
But im also curious whatt @raulraja thinks about this 😛 cause he is a lot more clever than I am
👀 1
r
not at all @Ties, agreed 100% descriptive and restrictive types are key to correct domain modeling in general regardless of FP. To me the purpose of a type is to constrain the amount of values it holds. If you have a type for example
String
to model an ID that has certain constrains but does not accept all strings then it’s open for trouble. In some cases though you don’t bother because performance may matter or unpacking repacking the types becomes annoying. I wish Kotlin had the notion of opaque types because value classes still have considerable overhead and ergonomic issues. Opaque types are like type aliases but hide the API of what they are aliasing so you can selectively expose what you want. https://docs.scala-lang.org/scala3/book/types-opaque-types.html
❤️ 1
1