I have been finding myself using the Chain of Responsibility pattern often (3 times is often for me) in my current project and I'm wondering if I have become a little over-enthusiastic about the solution. Specifically, I have been using the Apache Commons chain project. So, far I have been quite impressed by how it has simplified a number of complex interchangeable pieces of app logic into a more cohesive and organized whole. However, a few of the newer people on the project seem to have difficulty "getting it." What are your experiences with it? What problems have you encountered in its implementation?
So far, the only problem I have noticed that it is when you are trying to deal with objects that need to be closed. Having those objects stored in your Context class makes for a pain when you have completed the execution of your chain. I was able to work around this using Filters instead of Commands, but it seems a little unintuitive because your close statements are often very far away from where the object was instantiated.
Anyways, I would love to hear the thoughts from some developers who have more experience that I with this pattern.
Thanks in advance.
I'm tempted to say it works well for an unspecific problem (e.g. framework code) but works less well for specific problems. Frameworks are written for other people to use, and you want to give the client total freedom of implementation. Once you know exactly what you are going to do to solve the problem, I think other solutions are better.
The danger of the Chain of Responsibility pattern is much the same as for the Blackboard pattern: it's really easy to end up creating a lot of abstractions that mostly don't provide value in delivering your end goal. The command objects and processing objects really just hide the logic of your application behind a processing chain instead of putting it right up front where your most important code is. It is much easier to understand and maintain this if you just program a method (or several methods) that represents the full processing chain without the abstractions of the processing chain. The processing chain can really hide the business logic of your application, and I think you prioritize the technical artifact over the business code.
So basically you replace what could have been very straight-forward application code that reads very easily with much more abstract processing chains. You are doing meta-programming. Personally I never do any meta-programming any more, so I'd tend to agree with those colleagues that dislike it. ;)
I think it is fair to say that in general it is worth using a given design pattern if it gives you more benefits then costs. Every pattern introduces extra level of indirection in the code, so it is more difficult to follow, especially for junior members of the team. Having said that I think that the Chain of Responsibility pattern is definitely useful if you don't know upfront what are the classes going to be that are going to do the processing (so being in the chain), or you reuse these classes in different contexts, create different chains in different scenarios, etc.
In general I think it is pretty bad to over-engineer your solutions (because as you said new people struggle with understanding it), but there are some cases where the design patterns are very useful.