I've got a validation function something like this (pseudo-code):
public function validate(Thing thing) {
if (thing.a != "a") {
return false; // most of the time
}
if (thing.b != "b") {
return false; // most of the time
}
return true;
}
This function is in a domain service class. It's called from lots of controller classes. 90% of the time, all I want is a boolean answer to "is thing valid?" But 10% of the time, I want to display a message on the UI as to why it's invalid, if so. So instead of false
when thing.a != "a"
occurs, I want a string that says "thing's a is not a"
or whatever.
I can think of several ways to manage this, but none of them make me particularly happy.
- Just return the string all the time and in the
true
case just returnok
or something similar, but that feels fragile. It also makes the calling code have to do a string compare everywhere. - Return an enumerated type, and have a helper method available to translate the enum into the string for when it's needed, but that feels like I've just hidden the problem. And the calling code has to check a constant -- better than 1, but not by much.
- Store the last message in a class property, to be obtained via a getter after a call to
validate
returns afalse
. That makes most of my calling code much cleaner since it only deals with boolean results except when it needs to know the cause. But is this fragile? It's a web app, so it's single threaded per request, so race conditions shouldn't be a problem.
I feel like this is a common enough problem that there should be an elegant design pattern for it, but I've been unable to find it.
validate(Thing thing, Func onError)
, where onError is an error handler with the signatureonError(error)
oronError(thing, error)
. This lets you de-emphasize (or separate out) the error path in client code. Alternatively, you could dovalidate(onOK, onError)
, but depending on the language, this might be somewhat clunky. Another option is to return a response object as suggested in the answer below.