Mike Nichols - Son of Nun Technology

Messages From Domain Layer Up To Presentation Layer - Notification Patterns and Exceptions

One of the frustrating things with Domain Driven Design principles (for me) is some of the unanswered questions and lack of good .NET examples implementing solutions to real-world problems. A few days ago I posted a proposition that (kind of) attempts to propose a way of dealing with all the little messages we want to send up the pipeline but without throwing exceptions all over the place. I really wanted to keep from including every call to my Service layer from my Presentation layer in a try...catch block. I realize that it is common to do this when crossing boundaries but I wanted to have a consistent way of dealing with all the messages. More on that later. First, some elementary foundational stuff...At first it might seem like I am reinventing wheels, but hopefully after I am completely done it will make sense.

On one hand, we are told exceptions  are expensive and should not be used for program flow purposes, but on the other hand the fact remains that you only get to return one result from a method (out and ref notwithstanding). Now, some think events such as bad data being passed from the user is a reason to throw an exception, but I just don't think that is exceptional...that is something I EXPECTED. Hmmm...are we getting our "cepts" crossed with our "pects" ? :)

DDD has lots to say about how to create a rich domain but very little in regard to how this works in relation to all the other application stuff like infrastructure or presentation. We are told to protect the Domain Layer at all costs, but then I find myself dying on the hill of complexity to do so. Sending messages from the Domain layer up to the presentation is one of these I think. So over the next few posts I am implementing how I am solving this problem in my project, ending up wiht the final Notifier implementation I blogged about a couple of weeks ago and has since evolved into something I really like.

First, let's give ourselves some flexibility. As I see it an exception is something you didn't see coming or perhaps something that is unusual in an application and should interrupt application flow. In some ways, though, an exception is just a message and can be used like a Notification pattern. So to get some consistency, I implemented an INotification interface: 

    public interface INotification

    {

        IList<INotificationItem> Items { get;}

        bool HasItems { get;}

        bool HasErrors { get;}

        void AddItem(INotificationItem item);

        void Clear();

        IEnumerable<INotificationItem> GetBySeverity(params NotificationSeverity[] severity);

 

    }

The INotificationItem this INotification contains are this:

    public interface INotificationItem

    {

        string Message { get;}

        NotificationSeverity Severity { get;}

 

    }

Now, I'll create an application exception to be used across my app :

    [Serializable]

    public class AppException : ApplicationException, INotificationItem,INotification

    {

        private int _errorCode;

        private NotificationSeverity _severity;

        private string _message;

 

        private INotification _innerNotification= new Notification();

Notice I am implementing both the INotification and INotificationItem interfaces on this. I realize Exception has InnerException for doing this same thing but I wanted to give some more information about the exceptions including error codes.  This gives me some flexibility to have nested Items as things go up the pipe to the Presentation layer. All of these sit in an assembly such as a Common library that is visible to my Domain, Services, Presentation, and Web assemblies.

Let's assume that I have a Service layer which is actually consuming my Domain Entities.

public class DomainService

{

    public void AddPhoneToContact()

    {

        try

        {

            Contact c = PersonFactory.GetPerson("Mike", "", "Nichols", Gender.MALE);

            c.AddPhone(555, "5551212", "", "Home");

        }

        catch(AppException ex)

        {

            //Do something with the INotification implementation...stay tuned

        }

    }

}

Ok...so now I can throw exceptions in my Domain entity if something is wrong. Big deal, right? Well, that is the foundation...What is important here is that I have a consistent contract (INotification and INotificationItem) to work with...I could even inject a Strategy into my Service to determine whether to rethrow the exceptions or do whatever I want with them. Of course, you could do that with the standard exceptions too right? In my next few posts I'll show how we'll create a consistent way of handling these events in the application and ultimately help us consistently notify the user and (perhaps) logging or other listeners about these things that happened in our Domain.