Wednesday, April 25, 2012

Usage of Chain Of Responsibility in a practical application

Recently I have come across a situation where I had to process a collection of incoming XML files and run some logic according to the content of each and every XML message. At my office we are using file based electronic data interchange. Yes, I know that file based electronic data interchange may be somewhat an old timers approach , but still there are situations that you got to use it. Without stepping into any arguments , I just wanted to show you how this could be achieved using Chain Of Responsibility pattern.

There are few different operations that were needed on the incoming set of messages. Validation , Filtering , Sorting , Mapping and Aggregation. While these are the currently needed operations , in future we may have more and more different types of processing.

  • Validation : The set of the XML messages must be validated for a given set of rules. The rules are coming from a data base and those would be configurable depending on the requirement. The rules are configured based on the type of the message. Ex : if the property "message type" of an incoming XML message is "Sales Order" , then "project name" must not be empty
  • Filtering : The set of the XML messages must be filtered for a given set of rules. The rules are coming from a data base and those would be configurable depending on the requirement. The rules are configured based on the type of the message. Ex: if the XML message file name starts with "TMP_" , then filter all those messages
  • Sorting : Sorting happens based on the message content of each XML message. Ex: sort all the order items in a given XML message based on the order sequence number
  • Mapping & Aggregation : There operations are also done at each message level
When looking at each operation above , we could take each of those operations into individual classes and chain those classes according to requirement. Sometime you may want to execute Filtering first and Validation second or other way around. Sometimes you may want to turn off one operation , let's say Mapping and just go with the other operations. Later on there may be a new requirement for a completely new operation type on all the messages etc.. By considering all these it is better to have these operations separated into independent classes and combining them configurable.

Below is a possible high level design for this,

Below are some of the class diagrams , and sequence diagrams which may realize the above high level design.
VALIDATION
AGGREGATION
MAPPING

Friday, April 13, 2012

Going Technical...Memento Pattern

Today let's talk about another pattern , namely "Memento" pattern. This pattern is quite simple compared to many other pattern. So let's try to think about an analogy for this pattern first and later we will try to understand the pattern with the help of the analogy.

Imagine that your brother is calling you from home and he wants you to buy a new hard drive for his computer since the old one is no longer working. During the telephone conversation , your brother mentions the product code of the old hard drive. Let's say this product code is as long as 16 characters and you need to remember them before your brother hangs up the phone. Well in this situation , assume that you have not got a pen or a pencil with you making the situation even more difficult for you. But luckily a friend of yours is around in your apartment at this moment and you ask him to remember those characters for you.

Once the conversation is over , you would ask your friend those characters and then would probably write it down somewhere for future usage. In this scenario your friend did not really know for what those characters were and you did not give him any information about the conversation either. All you asked your friend was to keep the characters in his memory and give it back to you later when needed.

In "Memento" pattern this is what you would do. Asking another object B(let's say this is your friend) to keep the current state of the object A (let's say this is you) and later on when the object A needs to revert back to it's previous state , it would request object B to provide the needed information which is analogous to your friend telling you back the product code.

In general this is useful in undo operations in a particular process. It is also important to note that the external object (analogous to Object B , or your friend) which keeps track of the state of another object (analogous to Object A , or you) would not be able to see the internal information of the object A. Hence object A's information is not exposed (in other words , encapsulation is not violated). Usually the token which contains the information about the Object A is named as "Memento" and object B would manages such "Memento"s internally.

Well, now it is our time to see this in code,

//This class is analogous to YOU
public class ClassA{
 private String currentProductCode = "";

//this is analogous to asking your friend to keep this code recorded
 public Memento getState(){
  Memento _memento = new Memento();
  _memento.setProducCode("ABC-PRO-6767-REWS...");
  return _memento;
 }

//this is analogous to getting the product code from your friend and use it for your purpose
 public void updateState(Memento memento){
  this.currentProductCode = memento.getProductCode();
 }
}


//This class is analogous to your FRIEND
import java.util.HashMap;
import java.util.Map;

public class ClassB{
 private Map store = new HashMap();

//analogous to your friend recording the product code for you
//may be in a paper
 public void addMemento(Integer sequence , Memento state){
  this.store.put(sequence,state);
 }
//analogous to the time where you ask your friend the produce code back
 public Memento getMemento(Integer sequence){
  return this.store.get(sequence);
 }
}

//This is the structure which carries the internal information of object A
//usually in the analogy , you could assume this one could be a note book

public class Memento{
 private String productCode;
 public String getProductCode(){
  return this.productCode;
 }
 public void setProducCode(String productCode){
  this.productCode = productCode;
 }
}


//everything in a main method
public static void main(String[] args){
 //you are telling the product code to your friend here
 ClassA a = new ClassA();
 Memento state = a.getState();

 //your friend is recording the product code
 ClassB b = new ClassB();
 b.addMemento(1,state);

 //later , you will get that back from your friend
 Memento memento = b.getMemento(1);
 a.updateState(memento);

}