Simple Communications ctd…

Or, “how to force others to assume failure.”

Frequently when writing code that calls out to other services, the calls fail. For all kinds of reasons:

  • time outs
  • network outage
  • power outage at the host
  • bad parameters
  • bad credentials
  • no permissions

… and myriad other reasons. The point is, when you’re communicating across a network, lots can go wrong.

The unfortunate part is that, it often goes just fine, and that’s the problem. You end up with code that usually works, certainly in a developer’s environment, and you don’t end up with code that is required to be resilient to failures.

This is why, when I write service objects, I construct the methods such that they take callbacks for failure modes. This is my little contribution to attempt to push people into a pit of success.

It looks like this:

public class MyService : IMyService  
{
private RestServiceClient client;
public MyService()
{
client = new RestServiceClient();
}
public void GetData(
Guid id,
Action<Data> onSuccess,
Action<NetworkError> onFailure)
{
var request = RequestBuilder.GET($"/v1/employee/{id}")
.Build();

client.Execute<DataResponse>(
request,
response => { onSuccess(new Data(response)) },
onFailure);
}
}

At first, this might seem weird, or superfluous. Certainly the RequestBuilder makes this function seem simple, and then we just call out to the ResetServiceClient which looks like this:

public class RestServiceClient 
{
protected RestClient Client { get; set; }

public void Execute<T>(
IRestRequest request,
Action<T> onSuccess,
Action<NetworkError> onFailure)
where T : new()
{
ExecuteAsync<T>(request, onSuccess, onFailure);
}

private async Task ExecuteAsync<T>(
IRestRequest request,
Action<T> onSuccess,
Action<NetworkError> onFailure)
where T : new()
{
if (!CheckConnectivity())
{
onFailure(NetworkError.NoConnectivity());
}

try
{
var response = await Client.ExecuteTaskAsync<T>(request);
if (IsSuccessfulStatusCode(response.StatusCode))
{
onSuccess(response.Data);
}
else
{
onFailure(NetworkError.From(response.StatusCode));
}
}
catch (Exception exception)
{
onFailure(NetworkError.From(exception));
}
}

protected bool IsSuccessfulStatusCode(HttpStatusCode code)
{
return (int)code >= 200 && (int)code <= 299;
}
}

Here we have a simple function that calls out to an async function immediately, so that it can execute independently and call back to the onSuccess or onFailure functions when the call succeeds or fails.

So that’s a bit of code, and it’s the inclusion of the requirement to take an onFailure callback that helps force developers into a pit of success, or forces them to write code that is resilient to failures. Calling code now must look like this:

var service = new MyService();
service.GetData(guid,
onSuccess: data => {
// do what you want with the data, update the UI, etc.
},
onFailure: networkError => {
// do what you want with the error, try again, update the UI, etc.
});

So, no every call to a function on a service object that goes over the network, is required to pass a function that handles the failure scenario.

Using this, which becomes a fairly simple pattern to use, I’ve had a number of mobile apps and native apps that have had excellent and reliable behavior communicating over unreliable network connections.

Hope it helps!

Simple Communications

Here’s a set of patterns that I’ve seen in other projects and used a number of times myself, with success. I’d like to share them with you. They revolve around communication over a network.

The first is more of a convenience than anything else, but I’ve enjoyed it so much, for such a long time now, that I think you might as well. It’s a fluent builder for constructing REST requests. As you probably deciphered, it’s a combination of the fluent interface pattern and a builder pattern, and it looks like this:

public class RequestBuilder
{
    private IRestRequest request;

    private static RequestBuilder Init(string resourceUri, Method method)
    {
        var resource = resourceUri.StartsWith("/", StringComparison.CurrentCultureIgnoreCase) 
            ? resourceUri.Substring(1) 
            : resourceUri;
        var builder = new RequestBuilder { request = new RestRequest($"api/{resource}", method) };
        builder.request.AddHeader(C.Headers.Accept, C.Headers.Json);

        return builder;
    }

    #region Static Constructors

    public static RequestBuilder POST(string resourceUri)
    {
        return Init(resourceUri, Method.POST);
    }

    #endregion
}
  1. The point here is that the entry point to this class is no-longer the constructor. It’s one of the static constructors, each representing an http verb (I’ve omitted the other http verbs for brevity, but you can check the gist for a fuller version).
  2. I’m using RestSharp here to build the rest request, but I’ve used multiple different libraries in other projects just the same for making requests (RestSharpPortable, and plain HttpClient being two others).

This isn’t very interesting yet, but it becomes so when you start adding the fluent builder methods that build up the request. Those look like this:

public RequestBuilder WithHeader(string key, string value)
{
    if (!string.IsNullOrEmpty(value))
    {
        this.request.AddHeader(key, value);
    }

    return this;
}

public RequestBuilder WithParameter(string key, string value)
{
    this.request.AddParameter(key, value);

    return this;
}

public RequestBuilder WithQueryStringParameter(string key, string value)
{
    this.request.AddQueryParameter(key, value);

    return this;
}

… which are all very simple, in and of themselves, but they lead to being able to write code that looks like this:

var request = RequestBuilder.GET($"v1/emeployee/{id}")
    .WithHeader(C.Headers.ContentType, C.Headers.Json)
    .WithHeader(C.Headers.Authorization, $"Bearer {auth.AccessToken}")
    .WithQueryStringParameter("key", "value")
    .Build();

Which, to my eyes, is very readable and really nice to work with (and code completion tools work really well with this as well).

I’m sure you are seeing the Build function and have a good idea what that might be… it’s here:

public IRestRequest Build()
{
    return this.request;
}

Simple and effective. I hope you use it and enjoy writing code with it.

Next post, I will show the next pattern, which often results on rock solid communication over a network.

Hope it helps!