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:
- 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. - 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.