A bit delayed but here.
So we both agree it is bad for overwrite function to reject null values and update function to accept them, but I would prefer both functions to accept them and you want both functions to reject them.
Here are the reason I think it is better to accept them:
- I think it is generally bad practice to accept nullable values and then handle them with runtime errors. If you want to write API’s that don’t accept null values I think you should use non-nullable types.
- I think in this specific case, there is no reason these APIs should not accept null values. Ihe purpose of the update function is to be able to atomically read and update settings. But there is no function to atomically read and delete settings and this should be a completely valid use-case for situations where you want to safely reset settings without clobbering concurrently set values. We can easily support it by just not going out of the way to add unnecessary restrictions.
I am fine with existence of deleteRwSetting as a more convenient & readable wrapper around overwriteRwSetting and updateRwSetting, the same way overwriteRwSetting is a convenient and readable wrapper around updateRwSetting. But existence of deleteRwSetting should not be an excuse for crippling the behavior of the other functions and making them less safe to call. Ability to atomically read and delete settings is useful, and trying to deal with null values at runtime rather than compile time is a bad practice that should be a last not first resort.
Yeah ok, thread-safety wise, fully agree. The read+update atomic function for deletion is also needed, deleteRwSetting
does not fulfills that purpose for now, unless we turn it into an update
wrapper. And also agree about treating null values at compile time rather than during runtime whenever possible.
I think the only thing that “bothers” me a bit about the nullable class is the different meanings it could have, which require additional clarifications at the API level. E.g. “store key with no value”, “disable feature temporarily with no storage, so it can be restored at the next startup” or “delete this item”.
It seems we could achieve the behavior by turning the SettingsAction
into a bit flag, returning something like REMOVE_ITEM | WRITE_TO_DISK
or UPDATE_ITEM | WRITE_TO_DISK
and using optionals instead.
That said, it’s not a strong concern at all. I agree that null values should be treated at compile time and don’t think we want to change the API to move away from UniValue
. So, all good.