Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

if/else, good design

Is it acceptable/good-style to simplify this function:

bool TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
    {
        return Do(obj);
    }
    else
    {
        return false;
    }
}

as:

bool TryDo(Class1 obj, SomeEnum type)
{
    return obj.CanDo(type) && Do(obj);
}

The second version is shorter but arguably less intuitive.

like image 873
Captain Comic Avatar asked Nov 03 '10 13:11

Captain Comic


11 Answers

What I would code is :

return obj.CanDo(type) ? Do(obj) : false;
like image 180
KevinDTimm Avatar answered Oct 02 '22 04:10

KevinDTimm


Version with brackets:

bool TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
    {
        return Do(obj);
    }

    return false;
}

Or version without brackets (in answer comments is high debate about it):

bool TryDo(Class1 obj, SomeEnum type)
{
    /*
     * If you want use this syntax of
     * "if", this doing this on self
     * responsibility, and i don't want
     * get down votes for this syntax,
     * because if I remove this from my
     * answer, i get down votes because many
     * peoples think brackets i wrong.
     * See comments for more information.
     */
    if (obj.CanDo(type))
        return Do(obj);

    return false;
}

Your first code example is better, but I think my version is even better.

Your second version is not good readable and makes code harder to maintain, this is bad.

like image 24
Svisstack Avatar answered Oct 02 '22 05:10

Svisstack


The else is useless and the &&, however obvious, is not as readable as pure text.

I prefer the following:

bool TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
    {
        return Do(obj);
    }   
    return false;
}
like image 33
Paulo Guedes Avatar answered Oct 02 '22 06:10

Paulo Guedes


Yes.

Especially with names similar to your chosen names, i.e. CanDoSomething and DoSomething it is absolutely clear to any competent programmer what the second code does: “if and only if the condition holds, do something and return the result”. “if and only if” is the core meaning of the short-circuited && operator.

The first code is convoluted and unnecessarily long without giving any more information than the second code.

But in general, the two conditions may not form such an intimate relationship (as in CanDo and Do) and it might be better to separate them logically because putting them in the same conditional might not make intuitive sense.

A lot of people here claim that the first version is “much clearer”. I’d really like to hear their arguments. I can’t think of any.

On the other hand, there’s this closely related (although not quite the same) code:

if (condition)
    return true;
else
    return false;

this should always be transformed to this:

return condition;

No exception. It’s concise and still more readable to someone who is competent in the language.

like image 44
Konrad Rudolph Avatar answered Oct 02 '22 06:10

Konrad Rudolph


The shortened version hides the fact that Do does something. It looks like you're just doing a comparison and returning the result, but you're actually doing a comparison and performing an action, and it's not obvious that the code has this "side effect".

I think the core of the problem is that you're returning the result of an evaluation and the return code of an action. If you were returning the result of two evaluations in this way, I wouldn't have a problem with it

like image 21
Kevin O'Donovan Avatar answered Oct 02 '22 04:10

Kevin O'Donovan


Another alternative that may be a bit more readable is using the conditional operator:

bool TryDo(Class1 obj, SomeEnum type) {
  return obj.CanDo(type) ? Do(obj) : false;
}
like image 22
Guffa Avatar answered Oct 02 '22 06:10

Guffa


The 1st version is much easier to read with less chance of being misunderstood, and I think that is important in real world code.

like image 35
kaliatech Avatar answered Oct 02 '22 06:10

kaliatech


I do not like this design, and maybe not for the obvious reason. What bothers me is. return Do(obj); To me it makes no sense for the Do function to have a bool return type. Is this a substitute for property pushing errors up? Most likely this function should be void or returning a complex object. The scenario should simply not come up. Also if a bool somehow makes sense now, it can easily stop making sense in the future. With your code change it would require more re factoring to fix

like image 39
Andrey Avatar answered Oct 02 '22 05:10

Andrey


In this case, I would go with the first option - it is much more readable and the intention of the code is much clearer.

like image 24
Oded Avatar answered Oct 02 '22 05:10

Oded


Neither, because when TryDo returns False, you can't determine whether it was because 'Not CanDo' or 'Do returned False'.

I fully understand that you can ignore the result, but the way it's expressed implies that the result has meaning.

If the result is meaningless, the intent would be clearer with

void TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
        Do(obj);
    return;
}

If the result does have a meaning then there should be a way to differentiate between the two 'false' returns. I.E. What does 'If (!TryDo(x))' mean?

Edit: To put it another way, the OP's code is saying that 'I can't swim' is the same as 'I tried to swim and drowned'

like image 36
smirkingman Avatar answered Oct 02 '22 04:10

smirkingman


I don't like the second version as I'm not really a fan of taking advantage of the order of sub-expression evaluation in a conditional expression. It's placing an expected ordering on sub-expressions which in my mind, should have equal precedence (even though they don't).

At the same time, I find the first version a bit bloated, so I'd opt for the ternary solution which I consider highly readable.

like image 4
asdfjklqwer Avatar answered Oct 02 '22 05:10

asdfjklqwer