You are currently viewing Having fun with Kotlin types

Having fun with Kotlin types

Metacontext: I’m new to Kotlin and I’m learning/experimenting stuff.

Context: A backend’s UserService package. A user can change it’s password if they provide their old password.


sealed class AuthenticatedUser private data class PrivateAuthUser(val user : ORM.User, val password : String) : AuthenticatedUser()

The abstract class is exposed (sealed classes are abstract classes) but not any of its variants. From other files, you cannot construct an AuthenticatedUser.


class UserService { fun authenticate(val username: String, val password: String): AuthenticatedUser? { val user = // Perform ORM-y stuff return PrivateAuthUser(user, password) } fun changePassword(val user: AuthenticatedUser) { // cast user to PrivateAuthUser and access it's properties. } }

This design enforces:

  1. Security: You cannot construct a “fake”
    AuthenticatedUser

    outside of this package. This enforces that a user can change it’s password only if they have proven their identity.

  2. Safety: To change your password you need to provide your old password. This requirement now is enforced by the compiler. You don’t need tests.
  3. Self-documenting: Whoever wants to call the function
    changePassword

    will see it requires and

    AuthenticatedUser

    and then see that they need to provide the old password. The code teaches about the requirement. It is like free documentation.

This can be taken further. For example, creating a

ValidPassword

and

PrivateValidPassword

to ensure that the new given password is valid.

Basically, what I’d want to do is to make a public class with an “internal” constructor (only available inside the package). There’s probably a better way to do it (please comment), I guess I got tired of fighting the compiler.

submitted by /u/mauroc8
[link] [comments]