In my career, I came across many legacy applications and code and saw many bizarre code samples because it has been served by many different programmers over the period and everybody was probably lazy or under pressure to meet the deadline !!!
I personally hate ugly code and have very bad habit of re-factoring it on the spot whether it's bad naming conventions, incorrect formatting, duplicate code or hard coded string literals etc. because I cannot just read through it without that. One of the thing I observed constantly in all those applications was code duplication and abuse of if-else blocks.
Many programmers just love if else blocks simply because it's convenient to satisfy business logic quickly. There is nothing bad in it because it's very common to have multiple conditional logic in your business requirements but it starts getting ugly when you try adjusting tens (or sometimes hundreds, yes that's right) of conditions in one method or class using if-else blocks.
In one of my recent assignments, we had to write pseudo SWIFT parser to process trade instructions and convert SWIFT message to XML. It was obvious that we had to write Parser to convert all the SWIFT tags (around 200 tags) into XML after doing some processing on each of the swift tag. Here is the sample code we had in it's original form....
I personally hate ugly code and have very bad habit of re-factoring it on the spot whether it's bad naming conventions, incorrect formatting, duplicate code or hard coded string literals etc. because I cannot just read through it without that. One of the thing I observed constantly in all those applications was code duplication and abuse of if-else blocks.
Many programmers just love if else blocks simply because it's convenient to satisfy business logic quickly. There is nothing bad in it because it's very common to have multiple conditional logic in your business requirements but it starts getting ugly when you try adjusting tens (or sometimes hundreds, yes that's right) of conditions in one method or class using if-else blocks.
In one of my recent assignments, we had to write pseudo SWIFT parser to process trade instructions and convert SWIFT message to XML. It was obvious that we had to write Parser to convert all the SWIFT tags (around 200 tags) into XML after doing some processing on each of the swift tag. Here is the sample code we had in it's original form....
public void
uglyMethodWithNastyIfElseBlocks(String tagName){
if(tagName.equals("NetAmount")){
System.out.println("Doing something
with NetAmount and having value :32B:");
} else if(tagName.equals("GrossAmount")){
System.out.println("Doing
something with GrossAmount and having value :32M:");
} else if(tagName.equals("SecurityId")){
System.out.println("Doing
something with SecurityId and having value :35B:");
}
.
.
.
.
} else {
System.out.println("No Tags
Found");
}
}
Now imagine you have around 100 odd tags and doing some of processing on all of them which are accommodated inside same method. So to avoid this kind of situations Java provides you Command Pattern.
Now, lets re-factor this class using Command Pattern. To achieve clean code we will need one interface TagValueProvider to define the command for each tag which is currently inside if-else blocks, Enumeration: TagEnumeration to define Tag properties and Mapper class to map Tags with it's concrete implementation:
TagValueProvider: Each tag with different behavior will implement below command.
public void processTag(TagEnumeration tag);
ReturnTagValueProvider: Concrete implementation of each command.
@Override
public void processTag(TagEnumeration tag) {
System.out.println("Doing something with "+ tag.NETAMOUNT.getTagName() +" and having value " + tag.NETAMOUNT.getTagValue());
}
TagEnumeration: Each tag will have it's own properties and so will be mapped in this enumeration.
NETAMOUNT("NetAmount", ":32B:"), //key value pair of tags
GROSSAMOUNT("GrossAmount", ":32M:"),
SECURITYID("SecurityId", ":35B:");
TagMapper: Schema to map the tags with implementing class. So you can have multiple tags mapping with common class or separate class having specific implementation.
public static Map tagSchemaMapper = new HashMap();
Now imagine you have around 100 odd tags and doing some of processing on all of them which are accommodated inside same method. So to avoid this kind of situations Java provides you Command Pattern.
Now, lets re-factor this class using Command Pattern. To achieve clean code we will need one interface TagValueProvider to define the command for each tag which is currently inside if-else blocks, Enumeration: TagEnumeration to define Tag properties and Mapper class to map Tags with it's concrete implementation:
TagValueProvider: Each tag with different behavior will implement below command.
public void processTag(TagEnumeration tag);
ReturnTagValueProvider: Concrete implementation of each command.
@Override
public void processTag(TagEnumeration tag) {
System.out.println("Doing something with "+ tag.NETAMOUNT.getTagName() +" and having value " + tag.NETAMOUNT.getTagValue());
}
NETAMOUNT("NetAmount", ":32B:"), //key value pair of tags
GROSSAMOUNT("GrossAmount", ":32M:"),
SECURITYID("SecurityId", ":35B:");
TagMapper: Schema to map the tags with implementing class. So you can have multiple tags mapping with common class or separate class having specific implementation.
public static Map
static {
tagSchemaMapper.put(TagEnumeration.NETAMOUNT, new ReturnNetAmount());
tagSchemaMapper.put(TagEnumeration.GROSSAMOUNT, new ReturnGrossAmount());
tagSchemaMapper.put(TagEnumeration.SECURITYID, new ReturnSecurityId());
}
Now, let's see how our ugly method will look like after this re-factoring in below case.
public void correctMethodWithCommandPattern(TagEnumeration tags){
TagMapper.tagSchemaMapper.get(tags).processTag(tags);
}
So as you can see your multiple if else blocks will be replaced with single statement since command for each tag is now moved to concrete classes.
This is much cleaner approach because you don't have to accommodate entire business logic in one single method and more importantly it provides more readability to the code since each tag will have it's concrete implementation.
Advantages:
Separate implementation of each command with interface.
Enumeration to define each tag and it's properties.
HashMap to map the tag with it's behavior.
No comments:
Post a Comment