wood burning stoves 2.0*
The moose likes OO, Patterns, UML and Refactoring and the fly likes what to do about chained if-then-else? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "what to do about chained if-then-else?" Watch "what to do about chained if-then-else?" New topic
Author

what to do about chained if-then-else?

Jim Bassy
Greenhorn

Joined: May 21, 2008
Posts: 5
I am studying on how to use some design patterns in my latest project and I am having trouble with applying any of them. I am modifying existing code on my team and its just rife with if then else blocks. The problems is that clients send us messages, codes are attached to the message body and based on the code we do something with the message.
For example these are 3 variations of the same message that we can receive
Ex1
MT500
121z:GFSD|45TR|AB1

Ex2
MT500
121z:GFSD|45TR|B3

Ex3
MT500
121z:GFSD|45TR|AB2

The Mt500 message is the same except for the last code separated with a bar "AB1, B3 and AB2" are 3 different codes and they have meanings to perform some action. What was done was to create an enumeration of all Codes Mt500 can have and use chain if-then-else to decide on what to do. Lucky me the client added a new code called "CC4" that I have to add.

I'm trying to see how I can best do this in an OO way but i'm stuck. I was thinking of Java classes for each type of code but that doesn�t seem right. I looked at some of the solutions on the net for switch statements but they dont seem to apply. They seem to suggest the "thing" you are checking for should be an Object, like "if type == Cat then do something." To make matters worse you can have different combinations of these code. For instance
if((code.equals("AB1") || code.equals("B3"))
{
doSomething();
}
else if(code.equals("AB2")
{
doSomething2();

}

With new codes possibly being added it seems this if block will get a lot bigger. I will appreciate some direction on how I can do solve this. I could just add the new if condition and move on to some other task but I know there has to be a better way. Thanks.
Stevi Deter
Ranch Hand

Joined: Mar 22, 2008
Posts: 265

Jim,

I'd highly recommend you take a look at Refactoring by Martin Fowler, et al., Refactoring Workbook by William C. Wake, and Refactoring to Patterns by Joshua Kerievsky. These three books will really help you understand the best approaches to take to modifying an existing code base, and how to take advantage of patterns and begin to see where to apply them in the process.

For example, in Refactoring Workbook, Wake suggests that several if statements or a switch statement that operate on the same field/code, such as your example, could represent Simulated Inheritance. He suggests you refactor the code to use subclasses or a state/strategy instead of the code.

The Workbook is especially useful as he gives the series of steps you should go through to minimize disruption and introduction of bugs as you refactor.

And welcome to the JavaRanch!
[ May 21, 2008: Message edited by: Stevi Deter ]

There will always be people who are ahead of the curve, and people who are behind the curve. But knowledge moves the curve. --Bill James
Jim Bassy
Greenhorn

Joined: May 21, 2008
Posts: 5
Ok thanks. I took a quick peek at the description of the books on amazon it looks promising. I'm reading Head First Design Patterns right now. After doing some more research on the net it seems that I think I narrowed down where the state pattern and my problem lie. The State Pattern said the actions that cause the state to change should be method calls described as state transition actions. This is fine for when you know what method to call but in determine which method to call is where I'm stumped. The only way for state to change is from parsing a message file that can be variable, how does that fit into method delegation in the State class. If certain conditions are met in the file then state can change.

The following is a typical requirement spec for state transitions
if 89==DEAL && 5J==[JAMA|TOR|SINJA] - state=Rejected
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61451
    
  67

"Jim",

There aren't many rules that you need to worry about here on the Ranch, but one that we take very seriously regards the use of proper names. Please take a look at the JavaRanch Naming Policy and adjust your display name to match it.

In particular, your display name must be a first and a last name separated by a space character, and must not be obviously fictitious.

Thanks!
bear
JavaRanch Sheriff


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Andrew Laughlin
Greenhorn

Joined: Jan 02, 2007
Posts: 19
Jim,

In the code above, could you elaborate on the doSomething() methods?

Andrew
Jim Bassy
Greenhorn

Joined: May 21, 2008
Posts: 5
The dosomething() methods is nothing special. Based on the condition I just set the current state to Open, Rejected, etc. There are about 15 or so of these states.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
I have thought about what you are asking many times. Chained if/else resolves to a design pattern, I remember that ... but I forgot how I did it. Several notes do not forget though:
  • If you have 15 states, then one thing is changing the state - that's a variable.
  • If all fifteen states are to be recognized, then that information has to be somewhere.
  • Moving the resolution to method call names is limited in power.
  • Consider the problem of storing state as possibly yielding to a lookup table.
  • If that does not work, consider the collections.
  • Then, from memory, shortly after working on the last question I recover the overall approach. It is one that works.
    steve souza
    Ranch Hand

    Joined: Jun 26, 2002
    Posts: 861
    A couple different approaches you could take...



    1) A better solution than to have different method names for doSomething() would be to use doSomething() in all cases and put this method in a DoSomething interface. All of you objects must implement this interface. You could then have a static factory method that returned objects implementing this interface.





    2) A more flexible approach could be based on the DoSomething interface mentioned above. You could have a factory object that allows users to check implementations of your doSomething() interface.

    It would sort of work like a hashmap, however you would have to have a little more logic like a regexp as the key or perhaps even something of your own creation. The advantage of the first approach is you don't have to modify 'if' statements to add new DoSomething objects. Examples:



    3) If you must use different method names for some reason you could do an approach like the above, but put the method name in the factory and call it dynmaically. It really isn't a factory in this case, but would allow you to determine what methods execute on the fly. Something like this.



    http://www.jamonapi.com/ - a fast, free open source performance tuning api.
    JavaRanch Performance FAQ
    Peter Hu
    Ranch Hand

    Joined: Apr 15, 2005
    Posts: 33
    For condition branchings, sometimes it can get very complex. Like the conditions may have haierachy structure that involves multiple objects. I just use a combination of possible values as keys -

    obj1-value1 + "|" + obj2-value1
    obj1-value1 + "|" + obj2-value2
    obj1-value1 + "|" + obj2-value3
    obj1-value2 + "|" + obj2-value1
    obj1-value2 + "|" + obj2-value2
    obj1-value3 + "|" + obj2-value3
    ....
    [ July 05, 2008: Message edited by: Peter Hu ]
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: what to do about chained if-then-else?