This is a pattern I've run into a few time while working with Kotlin.

I have a DynamoDB tables with some required fields, and some that get filled out later on in the user workflow. In my case, I register the user which saves details in DDB, and then I let the user pick a phone number to buy through twilio, storing the choice in DynamoDB.

The lateinit var

There are two different ways forward that I can see. None of them let me use an immutable reference, so if you can think of a way to do it that way I'd love to hear about it.

lateinit @DynamoDBAttribute(attributeName = "phone") var phone: String

This means that the variable will be late initialized and throw an UninitializedPropertyAccessException if it is accessed before it has been initialized.

The other option is to use

@DynamoDBAttribute(attributeName = "phone") var phone: String? = null

Note: lateinit does not work on Nullable variables - and with good reason. If null is a valid state then it can be initalized to null.

The solution

I decided to use a nullable string variable for this purpose. There were a few things that helped me decide:

  1. I didn't want to use exceptions for flow control. I could try to read the phone number property and then catch the UninitializedPropertyAccessException and redirect the user to choose their phone number, but that is using exceptions as flow control.
  2. Sticking with a nullable variable allows me to do if (phone.isNullOrBlank()) - which allows me to redirect the user if they need to choose a phone number.

Conclusion

In order to avoid using exceptions for flow control, I opted for a nullable variable. Null is a valid state for some properties, and doesn't need to be avoided in Kotlin if you can't help using it.