DaedTech

Stories about Software

By

Chain of Responsibility

Quick Information/Overview

Pattern Type Behavioral
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Easy

Up Front Definitions

N/A

The Problem

Let’s say that you’re doing something reasonably standard. You have some desktop application that deals with a persistence structure (file, web service, remote database, whatever) and displays things for the user. Since it’s not 1996 anymore, you don’t want to treat the user to an endless series of dialog boxes for feedback, so you decide to create some kind of status message scheme, whereby there is a piece of screen real estate that is updated with messages as processing occurs, to give the user feedback. Think of an install wizard:

You get some requirements that you’re to have three types of status messages: informational, warning, and error, to be displayed in black, yellow and red text, respectively. From your extensive experience as a developer, you know that business analysts and users love nothing more than to tinker with the GUI, so you decide that you need a better scheme than simply displaying text and changing its color — you need to encapsulate the message generation logic so that when it is decided that the error messages should really be more of a brick red, you don’t have to do a giant find and replace in your presentation layer. So, you create the following object to which the GUI will bind:

    public class Message
    {
        public virtual string Text { get; set; }
        public Color Color { get; set; }
        public FontWeight Font { get; set; }
    }

Further, you create some classes that understand how to populate these bindable objects:

    public abstract class MessageGenerator
    {
        public const int LowPriority = 0;
        public const int Normal = 1;
        public static int Warning = 2;
        public static int Error = 3;
        public static int Critical = 4;

        public abstract Message GenerateMessage(string messageText);
    }

    public class InformationalMessageGenerator : MessageGenerator
    {
        public override Message GenerateMessage(string messageText)
        {
            return new Message() { Color = Colors.Black, Font = FontWeights.Normal, Text = messageText };
        }
    }

    public class WarningMessageGenerator : MessageGenerator
    {
        public override Message GenerateMessage(string messageText)
        {
            return new Message() { Color = Colors.Yellow, Font = FontWeights.SemiBold, Text = messageText };
        }
    }

    public class ErrorMessageGenerator : MessageGenerator
    {
        public override Message GenerateMessage(string messageText)
        {
            return new Message() { Color = Colors.Red, Font = FontWeights.Bold, Text = messageText };
        }
    }

Now, when the error message needs to be a little lighter than brick red, but a little darker than normal red, and maybe with a hint of purple, you can go to one place, the ErrorMessageGenerator, and you’re done. This is good, except that generating these things will be a little tedious. You’re going to have to instantiate the specific generator that you want and use it to generate your message. So, all over the code, you’re going to have things like this:

    public class CustomerViewModel : INotifyPropertyChanged
    {
        private CustomerService _customerService;

        private Message _statusMessage;
        public Message StatusMessage { get { return _statusMessage; } set { _statusMessage = value; RaisePropertyChanged("StatusMessage"); } }

        public void DoSomething()
        {
            var myCustomer = _customerService.GetCustomerById(12);
            if (myCustomer == null) //Oops, let's tell the GUI about this
            {
                var myGenerator = new ErrorMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Customer not found!");
            }
            else
            {
                var myGenerator = new InformationalMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Located customer 12.");
            }
        }
....

Generating those objects is sort of annoying, and it also defeats the purpose of having an abstract base class. You could always factor the generation into some view model base, but you don’t get around the problem of having to tell the new method what kind of error generation you want, but that only works for view models that inherit from a base view model. Another option would be to create a factory method or instance that generated the appropriate generator… but, generating generators seems like overkill here. It would also be sort of redundant and wrong feeling to do that, as the information about how to generate messages is all stored inside of the MessageGenerator hierarchy, but you’d be introducing some external class to figure out how these things are wired. So, you decide to leave well enough alone and plow ahead with this not quite elegant, but good enough implementation.

Now, let’s say some time goes by, and your message coloring scheme is such a hit that the users/BAs want every color in the rainbow and even some ultra-violet and infra-red messages. I mean, there are messages that are critical, and then messages that are CRITICAL. The latter should be in red, but with hints of white, to evoke images of a hospital. And, there are really several different kinds of warnings – those that you can ignore, and those that are almost errors, which should be an angry orange. There should also be messages that are green to say “Good job, user!”

You’re glad that your code is such a hit, but dismayed to see your “DoSomething()” method and all those like it ballooning in size like there’s no tomorrow:

        public void DoSomething()
        {
            var myCustomer = _customerService.GetCustomerById(12);
            if (myCustomer == null) //Oops, let's tell the GUI about this
            {
                var myGenerator = new ErrorMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Customer not found!");
            }
            else if (myCustomer.IsValid == false)
            {
                var myGenerator = new WarningMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Customer not in valid state!");
            }
            else if (PositiveFeedback)
            {
                var myGenerator = new FeelGoodMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Way to go!");
            }
            //...
            else
            {
                var myGenerator = new InformationalMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Located customer 12.");
            }
        }

Now, since this is GUI code, some of this ballooning is unavoidable – if there are 20 different things that can be displayed for customer retrieval, you’re going to need at least 20 lines for 20 strings. You might rethink the factory method at this point, for generating the generators or even the messages, thus saving yourself some lines of code, but it won’t be a huge gain in terms of the complexity of these methods. So, you forget the factory method and resign yourself to this complexity.

But, let’s say that a new wrinkle comes along. Some of your users think that the BAs got a little carried away with all of the colors, and they just want the old red/yellow/black scheme back. Others love the colors. So, you’re tasked with coming up with a way to please both sets of users. There is a “rich colors” setting in a config file that you’ll read in and, if that’s enabled, you’ll display all of the additional colors, but if not, then the first three.

Now, things get away from the realm of “unavoidable complexity for displaying lots of information to the user” and into “downright hideous” territory:

        public void DoSomething()
        {
            var myCustomer = _customerService.GetCustomerById(12);
            if (myCustomer == null) //Oops, let's tell the GUI about this
            {
                var myGenerator = new ErrorMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Customer not found!");
            }
            else if (myCustomer.IsValid == false)
            {
                var myGenerator = new WarningMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Customer not in valid state!");
            }
            else if (myCustomer.IsSemiValid)
            {
                if (RichColors)
                {
                    var myGenerator = new WishyWashyMessageGenerator();
                    StatusMessage = myGenerator.GenerateMessage("Well, you're almost there!");
                }
                else
                {
                    var myGenerator = new InformationalMessageGenerator();
                    StatusMessage = myGenerator.GenerateMessage("Well, you're almost there!");
                }
            }
            else if (PositiveFeedback)
            {
                if (RichColors)
                {
                    var myGenerator = new FeelGoodMessageGenerator();
                    StatusMessage = myGenerator.GenerateMessage("Way to go!");
                }
                else
                {
                    var myGenerator = new InformationalMessageGenerator();
                    StatusMessage = myGenerator.GenerateMessage("Way to go!");
                }
            }
            //...
            else
            {
                var myGenerator = new InformationalMessageGenerator();
                StatusMessage = myGenerator.GenerateMessage("Located customer 12.");
            }
        }

Now, you’re duplicating code in a big way. Using a factory method here could stop the bleeding somewhat, but not completely. You’ll see why when you learn what the BAs have in store for you next. When you were able to shoehorn in the selective color scheme from the last release, they got the taste of your blood in their mouths and they liked it.

You see, customers in Miami like teal messages because it’s one of the Dolphins’ colors, while males over 50 seem to be partial to muted shades of gray, and we also need a universal beige when the application is in safe mode. So, the application now needs to be able to read in all of those settings and selectively enable disable those message generators. Now, even your factory method solution is convoluted and nasty. It needs to be in a class with a bunch of booleans or take those booleans as parameters. It may buy you a little reprieve in lines of code, but it won’t buy you any help with your ominously growing complexity. Abandon all hope, ye who enter the presentation tier.

… well, okay, before you start dusting off the resume or pitching version 2.0 to management, there is another way, if you’re up for a bit of refactoring.

So, What to Do?

This is where the Chain of Responsibility pattern enters the picture. If you pull back for a moment and think of what really needs to happen here, it isn’t simply a matter of picking a message generator implementation to use. It’s a matter of prioritizing the message creators. What you’ve really got is a set of rules like “If X and Y, use creator A, otherwise, if Z, use creator B, etc”. You’ve been successful at not duplicating the actual construction of the message by using the generator polymorphs, but you are duplicating the prioritization logic.

So, first things first. Let’s introduce a concept of message priority to the creation method, since it’s already sort of defined in the base class anyway:

    public abstract class MessageGenerator
    {
        public const int LowPriority = 0;
        public const int Normal = 1;
        public static int Warning = 2;
        public static int Error = 3;
        public static int Critical = 4;

        public abstract Message GenerateMessage(string messageText, int severity);
    }

Now, each implementer has additional information that it can use to decide whether or not to bother processing a message:


    public class InformationalMessageGenerator : MessageGenerator
    {
        public override Message GenerateMessage(string messageText, int severity)
        {
            if (severity == Normal)
            {
                return new Message() { Color = Colors.Black, Font = FontWeights.Normal, Text = messageText };
            }
            return null;
        }
    }

Now, the scheme is a bit different. Each generator may or may not return a message. This doesn’t exactly help you, but it’s interesting. You’ve introduced the notion that a generator can examine a passed in parameter and then choose or decline to generate a message. To fully implement Chain of Responsibility, and solve the problem, it is now necessary to teach your generators how to pass the buck.

The idea is to give your generators a sense of “I’ll handle this message if it’s appropriate, and if it’s not, the next guy will handle it.” This, combined with some heuristics for which generators handle which priorities will move a lot of those unsightly if conditions out of your code. So, let’s start with the base class:

    public abstract class MessageGenerator
    {
        public const int LowPriority = 0;
        public const int Normal = 1;
        public static int Warning = 2;
        public static int Error = 3;
        public static int Critical = 4;

        public MessageGenerator Next { get; set; }

        public virtual Message GenerateMessage(string messageText, int severity)
        {
            return Next != null ? Next.GenerateMessage(messageText, severity) : null;
        }
    }

Here, you’ve defined a concept of next generator that can be set by clients. The formerly abstract method is now virtual to encapsulate the buck passing so that clients don’t have to do it. By default, you’ll get buck passing, and you now have to opt in to handling the message yourself. The clients will now look as follows:


    public class InformationalMessageGenerator : MessageGenerator
    {
        public override Message GenerateMessage(string messageText, int severity)
        {
            if (severity == Normal)
            {
                return new Message() { Color = Colors.Black, Font = FontWeights.Normal, Text = messageText };
            }
            return base.GenerateMessage(messageText, severity);
        }
    }

Now your code is looking promising for saving you a lot of bloat. The new message generator examines a message, handles the generation if the severity parameter is appropriate and passes if not. The real slick part of this is that the burden of message generation is still removed from the client, but so too can the burden of prioritizing message generation handling. Here’s what the new client code looks like:


    public class CustomerViewModel : INotifyPropertyChanged
    {
        private CustomerService _customerService;

        private MessageGenerator _messageGenerator;

        public CustomerViewModel(CustomerService customerService, MessageGenerator messageGenerator)
        {
            _customerService = customerService;
            _messageGenerator = messageGenerator;
        }

        private Message _statusMessage = null;
        public Message StatusMessage { get { return _statusMessage; } set { _statusMessage = value; RaisePropertyChanged("StatusMessage"); } }

        public void DoSomething()
        {
            var myCustomer = _customerService.GetCustomerById(12);
            if (myCustomer == null) //Oops, let's tell the GUI about this
            {
                StatusMessage = _messageGenerator.GenerateMessage("Customer not found!", MessageGenerator.Error);
            }
            else if (myCustomer.IsValid == false)
            {
                StatusMessage = _messageGenerator.GenerateMessage("Customer is not in valid state!", MessageGenerator.Warning);
            }
            else if (myCustomer.IsSemiValid)
            {
                StatusMessage = _messageGenerator.GenerateMessage("Well, you're almost there!", MessageGenerator.WishyWashy);
            }
            else if (PositiveFeedback)
            {
                StatusMessage = _messageGenerator.GenerateMessage("Way to go!", MessageGenerator.FeelGood);
            }
            //...
            else
            {
                StatusMessage = _messageGenerator.GenerateMessage("Located customer 12.", MessageGenerator.Normal);
            }
        }
    ...

Wow, that looks much better. One condition, one message — the cyclomatic complexity is now order linear with the actual complexity of the conditions that need to be reported, instead of condition complexity and business analyst imagination complexity multiplied. And, as a nice bonus, you’re not instantiating generators anymore – you’ve got only one that you use, and it’s injected as a dependency. Furthermore, this is accomplished without any factory method. Going back to the original example (error/warning/info), here’s the wireup for it:


    public class Wireup
    {
        public MessageGenerator BuildMessageGeneratorChain()
        {
            return new ErrorMessageGenerator() 
            { 
                Next = new WarningMessageGenerator()
                { 
                    Next = new InformationalMessageGenerator() 
                    {
                        Next = new DefaultMessageGenerator() 
                    } 
                }
            };
        }
    }

(Sorry about the nested conditional initializers — it’s late, and for some reason that amused me a lot more than it should have. It’s like some kind of code ugly-chic.) So, in this simple wireup, you have the chain of responsibility setup with some DefualtMessageGenerator defined to handle all messages not handled elsewhere. I won’t bother picturing it, but this would simply return a message every time, should the responsibility be passed to it. This would ensure that the message was always at least generated, if not with colors and fonts and whatnot.

Now, you’ve really separated responsibilities. The ViewModel and other clients don’t need to worry about message generation – it’s now a black box to them. They have a generator and the generator gives them messages from their passed in string/severity pairs. They have a “Bob’s your uncle” attitude toward the generator’s chain of delegation. And now, when the business analysts get crazy with the colors, you have exactly one place to make changes in existing code — the wireup class (you may need to add new generators as well). This is powerful because one of the more desirable situations for a code base is one in which requirements changes mean adding new code instead of modifying existing code. You can’t introduce regressions to brand new code, after all.

The only exception to not modifying existing code may be a need to periodically revisit the priorities. For instance, if every color in the rainbow has been added to the code base, you may have your default black/yellow/red handle priorities 0-10, 11-20, and 21-30 respectively, but giving the custom colors a bite at the apple first. That allows a teal message of priority 4 to be handled with TealGenerator for Miami customers, but the basic generator for all others simply by omitting the teal generator for the responsibility chain for non-Miami customers. But, if you have this scenario and the 31st color is introduced, you may need to expand the scope of the defaults and shuffle the priorities a bit.

Of course, other schemes are possible too. The generate method could take on another parameter, or you could use a different numbering scheme. The important part is that you’re creating multiple objects that can handle a request using different criteria, with easily customizable ordering scheme.

A More Official Explanation

The original Gang of Four definition of the pattern was:

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

The algorithm in question calls for a recursive handling of requests. A scheme is setup whereby a client invokes some service to satisfy a request, and the service does so by walking a pre-determined graph of potential handlers until one agrees to service the request. The aforementioned decoupling occurs because the client is oblivious to which potential servicer will actually handle it.

Polymorphism is a convenient mechanism for this paradigm but certainly not the only one. The only requirement is a customizable chain of handlers be given the chance to do so, and given that chance in response to a single request from the client.

Other Quick Examples

Here are some other scenarios that seem as though they’d lend itself well to Chain of Responsibility:

  1. Event handling in the a GUI context (WPF works this way, for instance, with routed events). A control can raise an event that will bubble up the logical tree until some other control handles it.
  2. Modeling a situation with approvers or handlers. For instance, consider a software scheme for managing vacation/PTO requests at a business. Approvers might include managers, VPs, etc. Requests may be handled by person X unless person X is out of office, and then they are handled by person Y, etc.
  3. In a sense, exception handling works this way — code generates an exception, and each layer of the call stack (either explicitly or implicitly) opts to handle the exception or let it bubble up.

A Good Fit – When to Use

This pattern is good to use any time the scheme for handling a request is somewhat involved and should be configurable on the fly. In the example in this post, the pattern wasn’t really important until the scheme for message handling started to get pretty customized and involved. Generally, when this is happening, Chain of Responsibility should enter the discussion.

Likewise, if there is a situation where multiple parties should have input to a request/event, the pattern may be a good idea. With a bit of modification, the example above could be used to generate composite messages (for instance, one message generator could take the message returned by another and make it bold).

Square Peg, Round Hole – When Not to Use

As always, there is the YAGNI princple. Jeff Atwood says

Don’t use fancy OOP features just because you can. Use fancy OOP features because they have specific, demonstrable benefit to the problem you’re trying to solve. You laugh, but like Rico, I see this all the time. Most programmers never met an object they didn’t like. I think it should be the other way around: these techniques are guilty until proven innocent in the court of KISS.

You could substitute “Design Patterns” for “fancy OOP features” here and the message would remain valid. In the example here, if all messages were black and with normal font, it wouldn’t make any sense to use Chain of Responsibility just in case the BAs wanted other colors. Wait until they add one or two before jumping to that conclusion and implementing this pattern. (I have a rule of thumb, which is to wait for at least two and usually three similar requests before deeming the request a pattern and adjusting accordingly. But, as soon as you hit three, do a 180 and bank on more such requests).

In addition, this pattern may not make sense if a rigid ordering is acceptable. For example, if you’re modeling a department structure, and all requests are always approved by a manager and then the VP, it may not be necessary to line up the handlers just yet. If that is unlikely ever to change, there’s no need for a complex design pattern where a simple && will suffice.

Finally, don’t confuse this with assembly. If you’re modeling the construction of a house, you don’t want a “Chain of Responsibility” where one handler builds the basement, and passes it on, the next adds a ground floor and passes it on, etc. That’s an inappropriate metaphor and it will be confusing in the long run. The house construction has a rigid ordering and isn’t in response to anything. This is a creational situation, and Chain of Responsibility is a behavioral pattern. I realize that we were, in the example, ‘constructing’ a message, but the purpose of that construction is to figure out who would build the message — not to partition the message’s construction into different spheres of responsibility (there’s another pattern for that).

So What? Why is this Better?

Chain of Responsibility is an improvement where appropriate because it introduces flexibility. It separates the handling of an event or servicing of request from the place where the event/request is generated. The requester doesn’t need to take care of this itself — it can delegate that. In the example above, the View Model class is responsible for displaying information to the user. But, before implementing the pattern, the View Model was developing a greater and greater responsibility for figuring out how to construct a message. By delegating that responsibility elsewhere, the class was simplified. By using Chain of Responsibility to do it, the whole application was made more flexible by virtue of the fact that the scheme for message construction was made easily swappable on the fly.

This pattern is not a hard sell in terms of utility, given that it’s already widely in use within frameworks, such as in the aforementioned cases of GUI events in WPF and exceptions in general.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback
12 years ago

[…] Chain of Responsibility structures where some nodes handle events and others simply figure out who to hand them over […]