The Operation Result Pattern — A Simple Guide

Isaac Cummings
4 min readSep 21, 2018

--

“red fire wallpaper” by Andy Watkins on Unsplash

The Operation Result Pattern is not really an official pattern (as in, i haven’t seen it show up in books yet). But its still legitimate and i would like to write a 5 minute guide. The purpose of the Operation Result Pattern, is to Identify the possibility of failures in the contract of a function. I like to categorize results in 3 buckets: Success, Failure, and Exception. The difference between failure and exception being that a failure is more along the lines of a business validation, and an exception more of a technical problem. If your not sure if something should be an exception or a failure you could ask yourself “Would the user understand what to do with this failure message?” Typically a user doesn’t know what to do with exception messages, they are intended for a technical person to do a more in depth troubleshooting of the problem. Business failure messages however, could be interpreted by a person and they should be able to act on them.

Consider the following class:

public class OperationResult
{
protected OperationResult()
{
this.Success = true;
}
protected OperationResult(string message)
{
this.Success = false;
this.FailureMessage = message;
}
protected OperationResult(Exception ex)
{
this.Success = false;
this.Exception = ex;
}
public bool Success { get; protected set; }
public string FailureMessage { get; protected set; }
public Exception Exception { get; protected set; }
public static OperationResult SuccessResult()
{
return new OperationResult();
}
public static OperationResult FailureResult(string message)
{
return new OperationResult(message);
}
public static OperationResult ExceptionResult(Exception ex)
{
return new OperationResult(ex);
}
public bool IsException()
{
return this.Exception != null;
}
}

This is a solid base for Operation Results, of course, as you develop your own way of handling failures, you may want to add functionality. For example, the Operation Result makes a GREAT monad (I might write about this in more detail later). The idea here is pretty simple, we are just holding a structure that can be either a success, a failure, or an exception.

Consider the function:

public OperationResult DoSomeStuff(...) { ... }

The user of this function could take the result and pass it back up the chain having confidence of the intention. If the intention is a validation error of some kind, this gives us a clear path towards making sure that validation error is clearly presented to the user (or in the case of web services, passed back with the appropriate error code).

A Side Note About TRY-CATCH: If you are returning an operation result from your function, you should never, ever, ever throw an exception. One of the main purposes of this pattern is to provide a clear interface into the operation that is being performed and the possible results. If you are going to return an operation result, you should catch any exceptions in your function, and return an ExceptionResult(...)

Suppose though, that your function needs to return a value of some kind upon completion. You could easily create a class that inherits from OperationResult but uses a generic type parameter. Of course the result would only be passed in upon successful completion. So, now your SuccessResult function would accept a parameter of the generic type.

public OperationResult<MyModel> GetMyModel(...) { ... }

Good practice would be making sure that the operation result is successful before unpacking the model.

Once you get to this point, it’s all about the extensions. I usually end up adding functions like:

public static OperationResult<TModel> FromFailureResult<TOtherModel>(OperationResult<TOtherModel> result)

So that if i’m in a function that returns OperationResult<TModel> but i’m calling a function that returns OperationResult<TOtherModel> and the function returns a failure, i can just call OperationResult<TModel>.FromFailureResult(otherResult);

When To Use It: It might be obvious at this point that your code could easily become ‘OperationResult Infected’. As in, once you have a function that returns an Operation Result, any functions that call that function could also return an operation result, and so on. These are some cases where operation results could be very useful.

  • Functions that perform long running calculations or operations
  • Functions that run business rules or validations
  • Functions that call out to unpredictable 3rd parties, like data access or IO

Some cases where you might NOT want to use operation results:

  • Functions that are operating on the UI
  • Code that does logging, or error reporting

When deciding whether to use Operation Results consider the following question, is it legitimate to report an error in this instance? For example, if my logging function fails, would reporting an error even be helpful? And what would the caller do with this information? (if logging failed, there isn’t anywhere to log the error). Or in a somewhat extreme example, suppose you are opening a dialog to alert the user of a failure, and the dialog throws an exception. In cases like these, maybe using more standard exception handling methods are the way to go.

--

--

Isaac Cummings

I’m a software developer, architect and otherwise average guy. I believe we learn the most through writing, and teaching.