-1

Does the following (anti?)pattern have a name?

  • every function returns an instance of a result class (or structure, or associative array) that has at least these two public variables:
    • success: a true/false value to hold if the action completed successfully
    • result: a variable that holds the result of the function or nothing if the function is void.
  • if success is false an error variable may hold information (exception/stack trace/debug) about the error
  • a message variable holding an user friendly message might be defined if error is not empty
  • only the result of the operation is encapsulated. Inputs are passed normally.

I've seen this used both in .Net and PHP (on server and in a script invoked by JavaScript/Ajax requests). Is it best practice? Is this an anti-pattern?

beppe9000
  • 1,056
  • 1
  • 13
  • 28
  • fixed title. i don't know if this is an anti-pattern – beppe9000 Jan 21 '17 at 00:23
  • 1
    Not really the pattern, just an easy representation of your http responce in array/object form as most of developers have no clue on how to use statuse codes of http – E_p Jan 21 '17 at 00:23
  • Sounds like you're talking about some kind of API controller class – M. Eriksson Jan 21 '17 at 00:23
  • Does this go together: _every function returns an instance of a result class _ and _I've seen this used both in .Net and PHP_. Not all .NET function do this. In fact I wonder which you mean.. – TaW Jan 21 '17 at 00:29
  • @TaW I mean user code! – beppe9000 Jan 21 '17 at 00:33
  • Might be a [monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)) if I'm understanding the description. – zzzzBov Jan 21 '17 at 16:37
  • @zzzzBov it might be badly implemented monads or something different because I saw no 'chainability' and the functions take 'naked values' as inputs. Anonymous down-voters please express yourselves. – beppe9000 Jan 24 '17 at 13:00

1 Answers1

1

This is a common way to handle a procedure call that can return both failure or success and a value. As noted in the comments, it is fairly common when calling APIs. Alternatives include: a) combining the return value with the success/failure so it has to be known and checked externally in the calling code, b) using an out parameter to return the desired value on success, or c) throwing exceptions to indicate failure, which is expensive and silly, so I will not discuss further.

a) Combining the return value with Success/Failure

This requires the calling code to know what represents failure in the return value instead of being explicitly told it failed.

public string GetSomeString(int id)
{
    //return a value on success or null on failure
}

So the calling code has to know that a null or empty string is failure and check accordingly...

var result = obj.GetSomeString(2);
if(string.IsNullOrEmpty(result))
{
    //ooops, failed
}

And this, of course, isn't an option if null is a legitimate return value.

Similarly for an int call...

public int GetSomeInt(string someArg, bool someOtherArg)
{
    //return a value or a -1 for failure
}

So the calling code has to know again what is bad and assume everything else it OK...

 var result = obj.GetSomeInt("blah", true);
    if(result == -1)
    {
        //ooops, failed
    }

And again, doesn't work if your "error" value is legitimate in some cases (or worse becomes legitimate at a later time).

b) Using an out parameter to pass back a value on success

An other option is to return success or failure from the method and use an out parameter to return the value if successful.

public bool GetSomeString(int id, out string someString)
{
    //if fail return false
    //otherwise set someString = value and return true
}

So the calling code looks like this...

string goodString = null;
if(!obj.GetSomeString(2, out goodString))
{
   //ooops, something bad happened
}

This offers the advantage of separating the success/failure of a call from the value it returns. It works, but it's a klutzy syntax and if you need to return more than value, you'll end up adding more out parameters or creating an object to return in the out anyway. It also can't tell you why it failed. Which brings us back to you to the subject of your question...

Using a Result object

This gives you the advantage of b) in that success/failure is unambiguously evident and does not require the calling code to have any knowledge of what return value might indicate failure. It feels cleaner because it doesn't require using the out syntax. It also provides the additional benefit of allowing you to indicate the reason for failure by passing it back along in the message property of the result object.

dbugger
  • 15,868
  • 9
  • 31
  • 33