• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Avoid clumsy 'if' statements but avoid reflection too.

 
James Bowen
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, I was looking for a way to handle business rules according to a char. I.e. if I receive char 'x' fire Business rule 1, if I receive char 'y' fire Business rule 2, etc.
I thought that an 'if' statement would be hard to maintain if new rules came along, and I thought reflection to generate a rule object based on the char might be overkill.
Is there a way of mapping business rules to a simple char without making a hard to maintain 'if' statement or expensive reflection?

Intuition tells me there's a factory pattern solution somewhere, but I can't work it out for sure!
Anyone have any ideas?
Thanks,
James
 
Marilyn de Queiroz
Sheriff
Posts: 9066
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I only had 2 rules, I think I would use the if/else construct. Otherwise I would probably look for a way to use polymorphism.
 
Michael Ernest
High Plains Drifter
Sheriff
Posts: 7292
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The next primitive step up is a case statement. It's an honorable tool; even when they grow, at worst they're tedious to read.
You could pass each character as an event object, rather than a primitive, and treat your business rules as event listeners. You can arrange it so that the business rule 1 object is only interested in 'a' events, etc., etc.
And there are some more complex approaches, such as a combination of Interpreter and Command design patterns (see this book) which would make sense if you anticipated a large-scale association here.
 
Blake Minghelli
Ranch Hand
Posts: 331
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's something I've done on more than one occassion and had very good success. Personally, I think it is a good OO approach and it definitely avoids using an ugly "if/else" structure.
1. Create a "RuleHandler" interface or abstract class that defines a method to handle the rule processing, e.g. process(), handle(), validate() or whatever. Most likely, the method will have to take as a parameter some kind of object that encapsulates the data that needs to be validated. Also, you may want to throw a custom "RuleViolationException" that can describe what went wrong.
2. Then create a class that implements/extends RuleHandler for each business rule you have. Each subclass will provide the specific implementation of handling a business rule.
3. So how do you dynamically use the right RuleHandler depending on your char? Create the mapping in a properties file. I prefer XML but you can also use a standard properties (my.key=value). For example the XML props file would look like this:
...
<RuleHandler>
<!-- The ID (char) for your rule -->
<RuleID>x</RuleID>
<!-- A class that implements/extends RuleHandler -->
<RuleHandlerClass>XRule</RuleHandlerClass>
</RuleHandler>
<RuleHandler>
<RuleID>y</RuleID>
<RuleHandlerClass>YRule</RuleHandlerClass>
</RuleHandler>
...
4. Then dynamically getting an instance of your rule handler and processing the rule is easy:

Of course, I'm open to any criticism on this approach. Good luck!
 
Peter den Haan
author
Ranch Hand
Posts: 3252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can convert the run-time reflection into initialisation-time reflection by using a Map which maps handlerNames to RuleHandler instances. That should address any performance concerns you might have.
In the original problem, the approach can be simpler and faster still, as you can probably convert the char to an integer index into a RuleHandler[] array.
The simplest approach would be to use a properties configuration file of the formEtcetera. This can be loaded up in a java.util.Properties object. At initialisation time,Will initialise the array of business rule handlers (the character 'A' corresponding to the zeroth element).
- Peter
[ January 06, 2003: Message edited by: Peter den Haan ]
 
Michael Ernest
High Plains Drifter
Sheriff
Posts: 7292
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I had thought of a hashtable too, but never having used the approach myself I didn't mention it. Have you used this approach, Peter?
I've been getting wary myself of using properties for this kind of work, since it a) implies a start/restart routine to bring in changes, and b) leaves a proper restart in the hands of correct editing. My recent work with a lot of Sun ONE products in particular makes me wonder if XML-everything for config files is such a cool idea.
 
Blake Minghelli
Ranch Hand
Posts: 331
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've been getting wary myself of using properties for this kind of work, since it a) implies a start/restart routine to bring in changes, and b) leaves a proper restart in the hands of correct editing. My recent work with a lot of Sun ONE products in particular makes me wonder if XML-everything for config files is such a cool idea.

Storing the RuleHandlers in a map still requires that the map is populated somehow, most likely during initialization, so that by itself does not get you away from needing a restart to load new RuleHandlers.
If you don't want to restart in order to change handlers then you could consider replacing the properties lookup with a db lookup, or implement an "auto-refreshing" properties object.
However, that would still leave you with your concern about improper editing... I guess that depends on your deployment methodology. We always deploy to a test environment first, that way if there are any config errors (e.g. spelling error in a properties file or a db record), they'll be caught before moving to production.
Using XML for a config file is a matter of preference. At first I didn't like the idea, but the more I learned about it, it became very comfortable for me. We still use a lot of regular props files too!
Bottom line - make it as configurable as possible and stay away from hard-coding your rule handling.
That's my opinion for what it's worth!
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Start/restart is really only a problem for long running processes such as servlets. Assuming that this is part of some batch process, you don't have to worry about reloading the handler array. If it is part of a servlet/jsp application then reloading is an issue. Make the handler array static (it should probably be anyway) and then write a servlet to run a reload method against the handler array. Whenever you create a new rule or update an old rule, you run the reload servlet and your handler array is up to date.
 
Peter den Haan
author
Ranch Hand
Posts: 3252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Michael Ernest:
I had thought of a hashtable too, but never having used the approach myself I didn't mention it. Have you used this approach, Peter?
Yes. The Charity Technology Trust raffle engine (see eg the current Royal British Legion raffle) uses a similar approach to define validation rules for various card types. As you don't see new types every day or even every year, the problems you rightly describe aren't very important in this case.
- Peter
 
Peter den Haan
author
Ranch Hand
Posts: 3252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Blake Minghelli:
If you don't want to restart in order to change handlers then you could consider [...] an "auto-refreshing" properties object.
However, that would still leave you with your concern about improper editing...
For our in-house controller, we implemented an auto-refresh by checking the configuration file timestamp every X seconds. This will read the new file and parse it into a new Configuration object. If an exception is thrown during the parsing and validation phase, this is logged and the new Configuration is discarded, leaving the old, working, configuration in its place. Only when the new configuration is valid it is actually installed.
This solves not only the restart problem, but also the editing problem. Not if you're editing the config file while the system is down, of course, but if you've taken the system down for maintenance anyway the editing problem isn't much of a problem in the first place.
You could do the same thing here. Just replace the old handler[] array only if you could successfully create the new one, including all object instantiations.
- Peter
[ January 06, 2003: Message edited by: Peter den Haan ]
 
Michael Ernest
High Plains Drifter
Sheriff
Posts: 7292
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Peter!
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by James Bowen:
I thought that an 'if' statement would be hard to maintain if new rules came along,

Do you feel the same about the switch-statement proposed above? If so, why?
I think for rather static situations (rules don't come along very often and it would be okay to change the source code in that cases), the switch solution would be quite ok. If your requirements are more dynamic, you will need one of the more complex solutions, of course.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic