Question

One of the things that I have never been happy with on any project I have worked on over the years and have really not been able to resolve myself is exactly at what tier in an application should human readable error information be retrieved for display to a user.

A common approach that has worked well has been to return strongly typed/concrete "result objects" from the methods on the public surface of the business tier/API. A method on the interface may be:

public ClearUserAccountsResult ClearUserAccounts(ClearUserAccountsParam param);

And the result class implementation:

public class ClearUserAccountsResult : IResult
{
    public readonly List<Account> ClearedAccounts{get; set;}

    public readonly bool Success {get; set;}    // Implements IResult
    public readonly string Message{get; set;}   // Implements IResult, human readable

    // Constructor implemented here to set readonly properties...
}

This works great when the API needs to be exposed over WCF as the result object can be serialized. Again this is only done on the public surface of the API/business tier. The error message can also be looked up from the database, which means it can be changed and localized.

However, it has always been suspect to me, this idea of returning human readable information from the business tier like this, partly because what constitutes the public surface of the API may change over time...and it may be the case that the API will need to be reused by other API components in the future that do not need the human readable string messages (and looking them up from a database would be an expensive waste).

I am thinking a better approach is to keep the business objects free from such result objects and keep them simple and then retrieve human readable error strings somewhere closer to the UI layer or only in the UI itself, but I have two problems here:

1) The UI may be a remote client (Winforms/WPF/Silverlight) or an ASP.NET web application hosted on another server. In these cases the UI will have to fetch the error strings from the server.

2) Often there are multiple legitimate modes of failure. If the business tier becomes so vague and generic in the way it returns errors there may not be enough information exposed publicly to tell what the error actually was: i.e: if a method has 3 modes of legitimate failure but returns a boolean to indicate failure, you cannot work out what the appropriate message to display to the user should be.

I have thought about using failure enums as a substitute, they can indicate a specific error that can be tested for and coded against. This is sometimes useful within the business tier itself as a way of passing via method returns the specifics of a failure rather than just a boolean, but it is not so good for serialization scenarios.

Is there a well worn pattern for this? What do people think?

Thanks.

Was it helpful?

Solution

I would suggest that you build a well defined API with clearly defined set of error results for each exposed method for the following concerns:

  • an API should not be designed around the consumer. It should define clear behavior and clear failure codes. Your caller could be a UI, a service or another API. The caller should decide what to do about the failure and whether any presentation is even needed.
  • The consumer might need more or less "message" depending on its own scenario. Pushing the presentation back to the consumer allows maximum flexibility in presentation.
  • Any localization or language concerns should be addressed by the consumer not the API.

OTHER TIPS

A common approach that has worked well has been to return strongly typed/concrete "result objects" from the methods on the public surface of the business tier/API.

That tightly couples your views to your data models. Causing the client to break when those objects are changed. You should treat your clients as an engine to render templates, and send only data for those templates to the client. That data should be as generic as possible to meet the needs of the templates.

This works great when the API needs to be exposed over WCF as the result object can be serialized.

Serialized yes, but think of it not as a response object but as data values for your view template. The view should be a logic-less rendering of that data. How logic-less the views are depends on how connected you want the clients to the backend, but the less logic the better.

1) The UI may be a remote client (Winforms/WPF/Silverlight) or an ASP.NET web application hosted on another server. In these cases the UI will have to fetch the error strings from the server.

I would send the message along with the response from the server to the client. Why send a response code and then have the client query what the code means? That is not the job of the client. The client should do as little work as possible to render the view for the user.

2) Often there are multiple legitimate modes of failure. If the business tier becomes so vague and generic in the way it returns errors there may not be enough information exposed publicly to tell what the error actually was: i.e: if a method has 3 modes of legitimate failure but returns a boolean to indicate failure, you cannot work out what the appropriate message to display to the user should be.

You are missing something here. There should be a middle piece between the data models and the client view. Often referred to as the controller. That middle piece will query the data models to do work, receive back a response code, take that code and look up a human readable message and then push that to the client for viewing.

Is there a well worn pattern for this?

It's called Model View Controller (MVC) pattern.

http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

http://msdn.microsoft.com/en-us/library/ff649643.aspx

There is also something called MVVM (Model View ViewModel).

http://en.wikipedia.org/wiki/Model_View_ViewModel

I've found that you sometimes have to implement MVC on the server, and MVVM on a client.

Licensed under: CC-BY-SA with attribution
scroll top