0

I would like to eliminate ifs in my application, but i have hit a brick wall. Here is my code. The problem i am facing is that i bought into the idea of using a dictionary to do the switching, however, in this case, the ifs depend on 2 different variables, weighted and bee(these i cannot combine into one variable). so originally it was

if(weighted)
    return WeightedCalculator;
else if (bee)
    return BeeCalculator;
else
    return DefaultCalculator;

So i have changed it to the following, which eliminates the ifs, but feels wrong. i do know that the dictionary is meant for cases where the if is on a single variable, but i feel there must be a way of using it if there are 2 or more variables. Any ideas as to how i could eliminate the ifs in a clean way. here is the link to this 'pattern'

http://joelabrahamsson.com/invoking-methods-based-on-a-parameter-without-if-else-statements-in-c/

public class CalculateDayCountFractionFactory : ICalculateDayCountFractionFactory
{
    private static readonly Dictionary<string, Func<ICalculateDayCount>> _dayCountCalculators = new Dictionary<string, Func<ICalculateDayCount>>
                                                                                                    {
                                                                                                        {"weighted", new WeightedDayCountCalculator()},
                                                                                                        {"bee", new BeeDayCountCalculator()}
                                                                                                    };


    public ICalculateDayCount Create(bool weighted, bool bee)
    {
        var key = weighted
                      ? "weighted"
                      : (bee
                             ? "bee"
                             : "");


        return _dayCountCalculators.ContainsKey(key)
                   ? _dayCountCalculators[key]()
                   : DefaultDayCountCalculator();
    }
}
sawe
  • 1,141
  • 14
  • 24
  • 1
    "eliminate ifs" any reason for that? The `?:` is basically no different from `if ... else`. – Corak Jul 05 '13 at 09:18
  • thats quite a big topic i think.. recently discovered that, and they say, for each if, it means it is a block of code that must be maintained separately... and .. and.. – sawe Jul 05 '13 at 09:20
  • no, didnt try linq, how so? – sawe Jul 05 '13 at 09:20
  • "a block of code that must be maintained separately" the same goes for methods, or classes, or ... anything. Do you also suggest to get rid of all method calls and classes? It sounds like you are on a very very bad path of premature optimization. Repent now! ^_^; – Corak Jul 05 '13 at 09:32
  • well... the thing is, yes i am still on a refactoring,clean code,ddd, journey, and at times when the seasoned developers say so, you dont question too much. The reason i gave is not the only reason, and i did not put it correctly or clearly, one thing about the ifs is that in SOLID, S stands for Single responsiblity, and by having an if, most likely the method or class is doing more than it should, and oftentimes u need to break it apart. hence i said, you can do a little research on the topic (it being a big topic out there) – sawe Jul 05 '13 at 09:44
  • Yes. Big fan of single responsibility. But that doesn't mean ifs are evil! What you do *inside* one branch of an if, you *might* want to put into a separate method, but you still need the `if` to determine which way to go. And in some way or another, the `if` will still be present. Like I said, `?:` is just a fancy `if ... else`. So you hid the `if`, but you didn't "eliminate" it. And for a case like you've shown, I think you shouldn't. – Corak Jul 05 '13 at 09:54
  • I'm as confused as @Corak , on this one, all you are doing (if anything) is a micro optimization that will just defer micro seconds of a users time into minutes of a developers time as you write harder to read (IMO) code. I'm not even convinced that on a compiler level, there is any difference – Sayse Jul 05 '13 at 09:54
  • ok, @somebody please bail me here, but first things first, if Jon Skeet says i use a conditional... so be it... on a more serious note, here is the thing, the question of whether u use an if or not, that will require creating a new question and getting the views of others, i am for the idea, hence my ques. for instance, the O in SOLID, it means if you use an if, most likely u will need to Modify your code just to add/modify behavior, which is bad(or do i need to explain why it is bad).if done well, the 'no-if' pattern will go a long way. my example is not the best to illustrate my point – sawe Jul 05 '13 at 11:46
  • yes, the switching must be implemented, and it is possible without an if, see the example in the link that i posted in my question. but that does not answer why not an if, and at times they do say in the worst case scenario, u will have to move the decision making away from your logic, into maybe a Factory class. but again, dont shoot the messenger here, maybe one day u will come accross the same issue and get a better explanation (not that i will attempt to win you over to this way of doing things, ...). – sawe Jul 05 '13 at 11:51
  • here is one discussion, http://stackoverflow.com/questions/1554180/why-is-the-if-statement-considered-evil – sawe Jul 05 '13 at 11:56
  • 1
    Well, joelabrahamsson also uses an `if` in the link you provided. And from the SO link it looks like over 90 people agree that "`if` statements are evil in the way hammers are evil". Even the "Anti-if" campaign (dafuq?) quickly qualifies, that they only want to get rid of "bad, dangerous `if`s". If you find *easy to read and maintain* ways to not use `if` and SOLIDify the code along the way, then go for it! Just don't treat it as a religion and don't demonize the `if`. – Corak Jul 05 '13 at 12:21
  • +1 well said @Corak, thats kind of where i hope to get to.. not everything is as clear yet for me – sawe Jul 05 '13 at 13:59

1 Answers1

2

You don't need a dictionary here... just use a conditional operator in the way you already have, but in a return statement. Personally I like the following way of formatting it.

return weighted ? WeightedCalculator
     : bee ? BeeCalculator
     : DefaultCalculator;

You can add as many : condition ? result lines as you like before the final default value.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194