However, after reading this wonderful article (If you have not read it, please start now), I found that Im very uncomfortable with the "Switch-Case" (or if - elseif - elseif - else) statements, just like:
Though those code is clean, but everytime if we wanna add a new type of Argument, we have to add new if-else statement in "parseSchemaElement" method, and add new case statement in "errorMessage". If your Args have to support more than 10 types argument, your if-else(switch-case) statements will be huge and ugly.
Bad smell.
So, can we avoid the Switch-Case statement in our system? Fortunately, the answer is yes: Just use the loop statement instead of it.
Let us see a new version of Args library:
First, the Args Class:
Look, in new version of "ParseSchema" method, the if-else statements were gone, and a static method which named "SupportedArguments.Instance.GetArgumentMarshaler(argumentTypeSymbol);" instead of them.
So, let see how "GetArgumentMarshaler(string argumentTypeSymbol)" works:
"GetArgumentMashaler" method check all supported argumentMashalers in _commonArgs collection, check them one by one and find the correctly Argument Mashaler.
And the ArgumentMarshalerBase is:
The BooleanArgumentMarshaler implement as below:
Pretty simply,huh? Now, if we wanna add new type of argument, we just need:
1. Write a new class which implement abstract class: ArgumentMashalerBase
2. In the new class constructor, set the a symbol for it. This symbol will be used in schema string. E.g. the symbol of boolean is "?" and symbol "#" is for integer type argument.
You can will see the new argument will works well.
Is that all? NO! Please, do not forget add new test cases for your new argumet ;)
Full source code and unit test are HERE. Any suggest is welcome.
linkcd
2006/02/21
Update 2006/02/22
Uncle Bob said:
"As for the argument about if/else and switch, that's a religious argument IMHO. Switches and if/else chains may be badly abused, and may never be necessary, but sometimes they are pleasant to read. My rule for them is that they should never appear more than once."
My Reply:
"But Uncle Bob, EVERYTIME if we wanna add a new argument type, we have to modify the if-else statement in Args class, and switch-case statement in exception class. We are hit by SAME bullet again and again. I think it violates "Open Close Principle". Yes, i agree the Switch statement are pleasant to read, but if our users ALWAYS want us to support new argument type, we should better avoid if-else/switch statements."
Uncle Bob reply:
"You make a good point. The two switch statements, while not identical, are related; and this violates my rule. On the other hand there is no benefit to turning the switch statement in ArgsException into a table, since it would still need to be modified under the same conditions. I could eliminate the ArgsException switch statement by deferring the messages back to the ArgumentMarshaller, but that couples Messages (UI) with business rules and therefore violates SRP.
I think yours is a good argument for eliminating the messages in the ArgsException class altogether. On the other hand, that just pushes the switch statement out into the user code.
Another solution would be to create a hierarchy of ArgsException derivatives. That would get rid of the switch, but does not completely solve your OCP complaint, since we'd have to add new exception derivatives every time we added a new type.
That leaves us with eliminating the messages and pushing that switch out to the application code. I'm not happy that. So I think the switch in ArgsException, though it violates OCP, helps to keep user code cleaner, and maintains a good separation of concerns (SRP)."