More than a year ago I was presented with a business requirement that has an accompanying process flow chart. The requirement was basically validating an Insurance Agent. The following information were used to perform business rules/validation on a specific agent and see if he/she can do business at a certain area, or is able to use current authorization or if his/her current contract is valid.
4. Managing Agent
Looking from the document, there were sets of processes that contains business rules that needs to be performed but each process completion can lead to one or more possible processes to be run. This scenario is depicted below.
I chose a pattern to basically build the framework that will allow for easy integration of new processes into the mix and not complicate the validation implementation. If this is to be implemented without a framework, deeply nested if - else statements arises and increases cyclomatic complexity issues. The Chain of Responsibility Pattern seem to perfectly fit this requirement. This pattern comprise of several chains all link together and each chain is aware of if the request coming in is intended for it or not. If it is then it applies whatever process is needed on that request data. If not then it just passes the request to the next chain in the link. The process in the figure above is represented as a chain. In this case we have 9 chains in the link.
Each of the 9 chains contains thick business logic validation implemetation that takes in an input and redirects the output to a different chain for further request validation. The process continues until one of the chains mark the validation process as completed and package the output data to whatever format the requester is expecting.
This is the Class Diagram that reflects this design. In addition to the chain pattern, the Template Method Pattern was also used as can be seen from the hierarchy relationship of Chain interface, AbstractChain and its subclasses.
There are four things to consider from this diagram - Chain interface, ChainManager, AbstractChain and its implementation(chains).
Defines the contract for implementing the methods add(Chain chain), processNext() and isLast(). The latter identifies a chain if its the last one to be executed.
It is responsible for creating the chains, linking them altogether and kicking off the first chain. The pseudo code below shows this implementation.
Chain process1Chain = new Process1Chain();
Chain process2Chain = new Process2Chain();
Chain process3Chain = new Process3Chain();
Chain process4Chain = new Process4Chain();
Chain process5Chain = new Process5Chain();
Chain process6Chain = new Process6Chain();
Chain process7Chain = new Process7Chain();
Chain process8Chain = new Process8Chain();
Chain process9Chain = new Process9Chain();
DefaultChain defaultChain = new DefaultChain();
// Assign the point of entry chain,
Chain entryPointChain = process1Chain;
//Kick of the first chain
The process() method of this class reflects the Template Method Pattern. The power of polymorphism lies here. Its subclasses plugin the right logic at run time and these chains are decoupled from each other.
As you notice the DefaultChain is included in the diagram. If you want to do some post-processing cleanup, provide the logic here.
The beauty of this chain pattern is its extensible. From our example above, if we need to add another set of validation logic, all we have to do is create another chain and add it in the link and provide the business logic in its process() method. If a validation is no longer needed, just remove that chain from the link that implements the validation and the application should still run without any side effects.