Is there a commonly (or rarely) used pattern for a "confirming you want to do this" message when calling a function from a library?
I have a API that exposes some operations that are potentially dangerous if misused (would cause unwanted changes to the database). I would like to pass a warning back to the caller to double check that this is on purpose. This is both to guard against other programmers in the organization misusing the API and to prevent an end-user from accidentally executing this command from a form without thinking about it.
There are really three use cases for this API function:
- Execute it against legit data. Should succeed with no warnings.
- Execute it against bad data. Should fail with an exception.
- Execute it against questionable data. The validate logic sees that it is a non-standard case, but maybe the end user knows what they are doing and is doing this on purpose.
I have been trying to think of a way to put case 3 into my API.
One way I have thought of revolves around a "confirmation token"
Sub DoRiskyOperation(thisData As String, Optional confirmationToken As ConfirmationToken)
If Not Validate(thisData) Then
Throw New ArgumentOutOfRangeException("thisData", $"Cannot perform this operation on {thisData}.")
End If
If Not confirmationToken.ItsOK Then
If Not TotallySafe(thisData) Then
Throw New Warning("thisData", $"Are you sure you want to do this?", _
New ConfirmationToken(AreYouSure))
End If
End If
'perform risky operation
End Sub
Another way I was considering is more of an "ask first" which is sometimes frowned upon:
Enum PredictedSuccess
WillSucceed
WillFail
WillSucceedButIsRisky
End Enum
Private LastDataAskedAbout As String
Function IsOperationRisky(thisData As String) As PredictedSuccess
LastDataAskedAbout = thisData
If Not Validate(thisData) Then Return PredictedSuccess.WillFail
If TotallySafe(thisData) Then
Return PredictedSuccess.WillSucceed
Else
Return PredictedSuccess.WillSucceedButIsRisky
End If
End Function
Sub DoRiskyOperation(thisData As String)
If Not Validate(thisData) Then Throw New ArgumentOutOfRangeException("thisData", $"Cannot perform this operation on {thisData}.")
If Not TotallySafe(thisData) AndAlso LastDataAskedAbout <> thisData Then
Throw New InvalidOperationException($"Hey, you were supposed to check before you try doing something this dangerous to {thisData}!")
End If
'perform risky operation
End Sub
Is there another way to encode the concept of this "confirmation handshake" into an API that I am not thinking of?
In case anyone is interested, the specific use - case is updating standard cost while there is inventory on hand. Accountants are picky about these kind of things.