Or else what? Hmmf, I don't have to refactor nuthin'.
[CategoryRefactoring/RefactoringLanguage]
You can sometimes simplify conditional logic by "defaulting" to a common result, and then expressing only the deviations from the default in logic:
Private Sub RefactorDefaultOrElse()
From this...
If Condition() Then lvar = Value() Else lvar = Default() End Ifto this...
lvar = Default() If Condition() Then lvar = Value() End IfIt's better to set a default value first if the conditional logic to set the variable is complex. This ensures that you don't end up with an unintialized or improperly initialized variable.
It's not obvious to me why the latter form is safer or more intuitive. Perhaps the example is too simple?
It's better to use the "else ... default" form if the default is complex or expensive to compute.
If both conditions apply, use a flag:
bUseDefault = True If Condition() Then lvar = Value() bUseDefault = False End If If bUseDefault Then lvar = Default() End If(This is way overkill for the simple example given. ;-)
End Sub
Example, pulled from RefactorNegateIf:
Here's an example refactoring, where using the "Refactor Negative IF" rule improved the code:
From...
If ConditionOne?() And ConditionTwo?() Then X = 1 Else X = 2 End If If ConditionOne?() And ConditionThree?() Then Y = 1 Else Y = 2 End Ifto...
X = 2 Y = 2 If ConditionOne?() Then If ConditionTwo?() Then X = 1 End If If ConditionThree?() Then Y = 1 End If End If(It also helps that "ConditionOne?()" is a really strange and unusual condition: The "<var> = 2" lines are the normal business rules, while the "<var> = 1" lines are exceptions/overrides.)
Thus, we end up saying...
Of course, if this block of code is the only code in the body of a method, you can convert if ConditionOne?() to a GuardClause. (if not ConditionOne?() then return end if)
On a somewhat related note, I'm quite a fan of the form that you'd more often see in functional programming. The idea it instead of using several branches, each of which having the side-effect of initialising the variable, you have a single assignment which sets the variable to the result of some expression. For example, in pseudo code:
X = if (Condition) value1; else value2;I find this form quite nice, because it makes it obvious that your variables are all initialised. Unfortunately to factor things like this in C-style languages I suspect you'd often need to make new functions, which might be inconvenient for a lot of simple cases. -- LukeGorrie
Not necessarily. C does have the ?: conditional expression evaluation operator, after all.
That's true, but I still suspect you'd need to go to functions pretty often, good though ?: is for an 'if-else' form. Consider some erlang code which would seemingly need to be function'ified in C: (admittedly its politely asking for function'ification in Erlang too - perhaps I should revise the example if that's a bother)
Threads = case Argument of a_few -> 1; a_fair_few -> 5; quite_a_lot -> 10 end,As a side-note, another thing I love about that form is that the code is only defined for a few special atoms - i.e., there's no "default", so it's undefined for nonsensical arguments. I hate it when I find a bogus value in my code, only to see that it's hopped half way across my program from its source by slipping through defaults and so forth. Java null references spring to mind. -- LukeGorrie
C/C++:
X = Condition ? value1 : value2; Threads = a_few ? 1 : a_fair_few ? 5 : quite_a_lot ? 10 : -1;VisualBasic:
X = IIf(Condition, value1, value2) Threads = IIf(a_few, 1, IIf(a_fair_few, 5, IIf(quite_a_lot, 10, -1)))If "Threads" is a Variant, then you could use "Nothing" instead of "-1", or other arbitrary value.
This might be clearer if you use the Choose function. This function has the following syntax:
Choose(condition1, value1, condition2, value2, ..., conditionN, valueN)Each condition is evaluated, moving left to right, and the first one that evaluates to True causes the corresponding value to be returned. So you could write:
x = Switch(argument = a_few, 1, argument = a_fair_few, 5, argument = quite_a_lot, 10)The biggest drawback is that there is no short-circuiting - all conditions are evaluated.
X = if (Condition) value1; else value2;... in a real functional language is:
operation_on_x (condition_foobar Condition where condition_foobar true is value1 condition_foobar false is value2 )... or something like that
-- AluoNowu (nov17-01)