Currently I'm refactoring my old code, so I have some time to think about how code should look like for somebody else. I managed much of problems, but I always wonder how to prepare good syntax for some nested logical condition. Let's assume that we have following part of code:
bool param1;
int param2;
var result = ( param1 == toCheck.param1) && // to achive condition it always has to be true
((param2 == toCheck.param2)) ||
( (!param1) &&
(param2 == defaultValueForParam2));
// to pass condition param! has to be always true AND ( (params 2 has to be equal) OR (param1 has to be false AND param2 has to be equal with default value)
How should it be formated to be more readable for anybody? Are there some rules of formating conditions? Maybe the general solution is just wrong if I need so complicated condition?
My intention was to ask about: how I should use brackets, how I should use indents, grouping, etc?
If you have a complicated condition, that you cannot make less complicated, it helps to
Have good variable names
Write a small helper function with a clear name so that the calling code is clear
If the conition is used in more that one place Don't Repeat Yourself (see 2.)
Reconsider if you can simplify this. Do you really need boolean flags?
Related
This is just a wondering question for the c# language. I have checked in the MSDN operators and can't see anything close.
When I use LINQ to XML to retrieve some elements, I am passing some lambda expressions in WHERE methods to select specific elements.
But I can see that I am using the following statement which annoys me a bit.
bool myCondition;
// some codes
var elements = xDocument.Descendants("items").
Where(x=>x.Attribute("id")!=null&&
(myCondition)x.Element("blah").Value=="blah":
x.Element("blah").Value!="blah").ToList();
But somehow I keep writing to code as below(no idea why :)):
// some codes
var elements = xDocument.Descendants("items").
Where(x=>x.Attribute("id")!=null&&
x.Element("blah").Value?myCondition="blah").ToList();
I kind of see the boolean myCondition as !(exclamation mark) or =(equal sign).
if true then = if false then !.
I just wonder would that be any possibility in the future to add these types of operators? or there are some better operators that would shorten my condition?
Would this work with any other programming language out there? maybe javascript?
and if you are downgrading then please tell why.
You can already express that condition in C# without conditional operator:
myCondition?
xDocument.Element("item").Value=="blah":
xDocument.Element("item").Value!="blah"
is the same as:
myCondition == (xDocument.Element("item").Value == "blah")
Whether it is more readable is open question. You may consider having helper method with good name instead.
I am try to control multiple strings variables is empty or not at once:
My first approach is very simple:
if(string.isNullOrEmpty(val1) && string.isNullOrEmpty(val2) && string.isNullOrEmpty(val3))
My second way looks like this
if(string.isNullOrEmpty(val1 + val2 + val3))
Which one is fastest and elegant?
Is there any options to do this operation?
The first was faster in my test (just had to): 6ms vs. 70ms and that was on 10,000,000 iterations each (so the speed difference probably doesn't matter very much unless you're doing this on a massive scale).
Anyway, i find the first to be more clear.
Also it doesn't rely on behavior of IsNullOrEmpty that is not immediately obvious (you might just as well think that passing null parameters causes an ArgumentNullException if you don't know better), which i think is important.
Note: The test was with all variables set to null, but setting them to other values confirms it, the longer the strings get, the longer option 2 takes, while option 1 stays at about 30ms max.
Also, the first returns true if any of the strings is null or empty, while the second does it only if all of them are null or empty. So it's not the same check.
They are not equivalent. The first one checks if any of them is null. The second one checks if all of them are null. Make up your mind.
How about this?
new string[] {val1, val2, val2}.All(s => string.IsNullOrEmpty(s))
Or something similar.
I would expect 'fastest' to depend on how often you expect one or more of the strings to actually be null or empty.
For example, if val1 is often going to be null or empty then the first option is likely to be best; if they are all rarely going to be null or empty then I'm not sure of the answer, but it can't take more than five minutes to knock together a few benchmarks for your particular expectations.
(Also, note that the two options don't do the same thing, the first is true if ANY of them are null or empty the second is not doing that)
if(string.isNullOrEmpty(val1 + val2 + val3)) seems to me the fastest
I would advice you to also use concat
but behind the scenes it uses the '+' operator.
I think this is the fastest.
If it werent nullable I suggest summing their length and check ==0
The second one:
if(string.isNullOrEmpty(val1 + val2 + val3))
equals
if(string.isNullOrEmpty(val1) && string.isNullOrEmpty(val2) && string.isNullOrEmpty(val3))
(note the && instead of ||)
but will create an intermediate string, whereas my second version will not create extra strings and stop checking as soon as one string is not empty.
If you have a number of string variables, then I think it is more readable to use the first construction:
if(string.isNullOrEmpty(val1) &&
string.isNullOrEmpty(val2) &&
string.isNullOrEmpty(val3))
{
}
This way, it seems like each variable is treated separately, and this code is a little easier to change if you need to treat one of the variables in another way.
But in case all of the string variables are to be treated in the same way, they are very likely to be represented as an array or another kind of enumeration. Then it's definitely better to use John M Gant's suggestion:
if(myStrings.All(s => string.IsNullOrEmpty(s)))
{
}
I am validating input on a form and attempting to prompt the user of improper input(s) based on the combination of controls used.
For example, I have 2 combo boxes and 3 text boxes. The 2 combo boxes must always have a value other than the first (default) value, but one of three, or two of three, or all text boxes can be filled to make the form valid.
In one such scenario I have a 6 line if statement to try to make the test easily readable:
if ((!String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString())
&& !String.IsNullOrEmpty(TextBoxA.Text)
&& !String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString()))
||
(!String.IsNullOrEmpty(TextBoxB.Text)
|| !String.IsNullOrEmpty(TextBoxC.Text)))
{
//Do Some Validation
}
I have 2 questions:
Should this type of if statement be avoided at all cost?
Would it be better to enclose this test in another method? (This would be a good choice as this validation will happen in more than one scenario)
Thanks for your input(s)!
In such a case I find it helps to move some of the logic out of the if statement and into some more meaningfully named booleans. Eg.
bool comboBoxASelected = !String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString());
bool comboBSelected = !String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString());
bool textBoxAHasContent = !String.IsNullOrEmpty(TextBoxA.Text);
bool textBoxBHasContent = !String.IsNullOrEmpty(TextBoxB.Text);
bool textBoxCHasContent = !String.IsNullOrEmpty(TextBoxC.Text);
bool primaryInformationEntered = comboBoxASelected && textBoxAHasContent && comboBSelected;
bool alternativeInformationEntered = textBoxBHasContent || textBoxCHasContent;
if (primaryInformationEntered || alternativeInformationEntered)
{
//Do Some Validation
}
Obviously, name the combo and text boxes to reflect their actual content. When someone has to work their way through the logic several months down the line they'll thank you.
a) Doesn't have to necesarily be avoided at all costs. The code works. But it is certainly messy, confusing and I would say could be difficult to maintain.
b) Yes. Give it a relevant name so that the code reader knows what is going on there.
I personally wouldn't have a big issue with code like this. (Your last set of parentheses seem unnecessary.)
Generally, I'd like to keep my if statements simpler. But all your conditions are simple ones. If you really need to test that many tests, then I'd keep it like it is.
It is not very readable yes. But you can shorten it:
!String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString()
could also be written as:
ComboBoxA.SelectedValue.ToString()!=DEFAULT_COMBO_A_CHOICE
I presume DEFAULT_COMBO_A_CHOICE is already of string to ToString si superflous.
also the parenthese around
(!String.IsNullOrEmpty(TextBoxB.Text)
|| !String.IsNullOrEmpty(TextBoxC.Text))
are not necessary.
IMO such conditions should be avoided (though not at all costs). They are very difficult to read an maintain.
There are several ways of doing that
Try and group the conditions according to the behavior they represent. For example
if (OrderDetailsSelected() && ShippingAddressProvided() )
{
This way you can also avoid the duplication of the conditions within your form.
Secondly, you can use the Boolean Algebra to simplify the expression and
Use Extract Method refactoring to move conditions, which are difficult to read in functions to avoid duplication and make them more readable.
For ex. The condition
String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString())
can be extracted into a function
private bool IsDefaultA() { return ... }
Is there a better way for writing a condition with a large number of AND checks than a large IF statement in terms of code clarity?
Eg I currently need to make a field on screen mandatory if other fields do not meet certain requirements. At the moment I have an IF statement which runs over 30 LOC, and this just doesn't seem right.
if(!(field1 == field2 &&
field3 == field4 &&
field5 == field6 &&
.
.
.
field100 == field101))
{
// Perform operations
}
Is the solution simply to break these down into smaller chunks and assign the results to a smaller number of boolean variables? What is the best way for making the code more readable?
Thanks
I would consider building up rules, in predicate form:
bool FieldIsValid() { // condition }
bool SomethingElseHappened() { // condition }
// etc
Then, I would create myself a list of these predicates:
IList<Func<bool>> validConditions = new List<Func<bool>> {
FieldIsValid,
SomethingElseHappend,
// etc
};
Finally, I would write the condition to bring forward the conditions:
if(validConditions.All(c => c())
{
// Perform operations
}
The right approach will vary depending upon details you haven't provided. If the items to be compared can be selected by some sort of index (a numeric counter, list of field identifiers, etc.) you are probably best off doing that. For example, something like:
Ok = True
For Each fld as KeyValuePair(Of Control, String) in CheckFields
If fld.FormField.Text fld.RequiredValue Then
OK = False
Exit For
End If
Next
Constructing the list of controls and strings may be a slight nuisance, but there are reasonable ways of doing it.
Personally, I feel that breaking this into chunks will just make the overall statement less clear. It's going to make the code longer, not more concise.
I would probably refactor this check into a method on the class, so you can reuse it as needed, and test it in a single place. However, I'd most likely leave the check written as you have it - one if statement with lots of conditions, one per line.
You could refactor your conditional into a separate function, and also use De Morgan's Laws to simplify your logic slightly.
Also - are your variables really all called fieldN?
Part of the problem is you are mixing meta data and logic.
WHICH Questions are required(/must be equal/min length/etc) is meta data.
Verifying that each field meets it's requirements is program logic.
The list of requirements (and the fields that apply too) should all be stored somewhere else, not inside of a large if statement.
Then your verification logic reads the list, loops through it, and keeps a running total. If ANY field fails, you need to alert the user.
It may be useful to begin using the Workflow Engine for C#. It was specifically designed to help graphically lay out these sorts of complex decision algorithms.
Windows WorkFlow Foundation
The first thing I'd change for legibility is to remove the almost hidden negation by inverting the statement (by using De Morgan's Laws):
if ( field1 != field2 || field3 != field4 .... etc )
{
// Perform operations
}
Although using a series of && rather than || does have some slight performance improvement, I feel the lack of readability with the original code is worth the change.
If performance were an issue, you could break the statements into a series of if-statements, but that's getting to be a mess by then!
Is there some other relationship between all the variables you're comparing which you can exploit?
For example, are they all the members of two classes?
If so, and provided your performance requirements don't preclude this, you can scrape references to them all into a List or array, and then compare them in a loop. Sometimes you can do this at object construction, rather than for every comparison.
It seems to me that the real problem is somewhere else in the architecture rather than in the if() statement - of course, that doesn't mean it can easily be fixed, I appreciate that.
Isn't this what arrays are basically for?
Instead of having 100 variables named fieldn, create an array of 100 values.
Then you can have a function to loop combinations in the array and return true or false if the condition matches.
Ahh, don't you just love a good ternary abuse? :) Consider the following expression:
true ? true : true ? false : false
For those of you who are now utterly perplexed, I can tell you that this evaluates to true. In other words, it's equivalent to this:
true ? true : (true ? false : false)
But is this reliable? Can I be certain that under some circumstances it won't come to this:
(true ? true : true) ? false : false
Some might say - well, just add parenthesis then or don't use it altogether - after all, it's a well known fact that ternary operators are evil!
Sure they are, but there are some circumstances when they actually make sense. For the curious ones - I'm wring code that compares two objects by a series of properties. It would be pretty nice if I cold write it like this:
obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4)
Clear and concise. But it does depend on the ternary operator associativity working like in the first case. Parenthesis would just make spaghetti out of it.
So - is this specified anywhere? I couldn't find it.
Yes, you can rely on this (not only in C# but in all (that I know) other languages (except PHP … go figure) with a conditional operator) and your use-case is actually a pretty common practice although some people abhor it.
The relevant section in ECMA-334 (the C# standard) is 14.13 §3:
The conditional operator is right-associative, meaning that operations are grouped from right to left.
[Example: An expression of the form a ? b : c ? d : e is evaluated as a ? b : (c ? d : e). end
example]
If you have to ask, don't. Anyone reading your code will just have to go through the same process you did, over and over again, any time that code needs to be looked at. Debugging such code is not fun. Eventually it'll just be changed to use parentheses anyway.
Re: "Try to write the whole thing WITH parentheses."
result = (obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
(obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
(obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4))))
Clarification:
"If you have to ask, don't."
"Anyone reading your code..."
Following the conventions common in a project is how you maintain consistency, which improves readability. It would be a fool's errand to think you can write code readable to everyone—including those who don't even know the language!
Maintaining consistency within a project, however, is a useful goal, and not following a project's accepted conventions leads to debate that detracts from solving the real problem. Those reading your code are expected to be aware of the common and accepted conventions used in the project, and are even likely to be someone else working directly on it. If they don't know them, then they are expected to be learning them and should know where to turn for help.
That said—if using ternary expressions without parentheses is a common and accepted convention in your project, then use it, by all means! That you had to ask indicates that it isn't common or accepted in your project. If you want to change the conventions in your project, then do the obviously unambiguous, mark it down as something to discuss with other project members, and move on. Here that means using parentheses or using if-else.
A final point to ponder, if some of your code seems clever to you:
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. — Brian W. Kernighan
The assertion that parentheses detract from the readability of the code is a false assumption. I find the parenthetical expression much more clear. Personally, I would use the parentheses and/or reformat over several lines to improve readability. Reformatting over several lines and using indenting can even obviate the need for parentheses. And, yes, you can rely on the fact that the order of association is deterministic, right to left. This allows the expression to evaluate left to right in the expected fashion.
obj1.Prop1 != obj2.Prop1
? obj1.Prop1.CompareTo(obj2.Prop1)
: obj1.Prop2 != obj2.Prop2
? obj1.Prop2.CompareTo(obj2.Prop2)
: obj1.Prop3 != obj2.Prop3
? obj1.Prop3.CompareTo(obj2.Prop3)
: obj1.Prop4.CompareTo(obj2.Prop4);
x = cond1 ? result1
: cond2 ? result2
: cond3 ? result3
: defaultResult;
vs
if (cond1) x = result1;
else if (cond2) x = result2;
else if (cond3) x = result3;
else x = defaultResult;
I like the first one.
Yes, you can rely on conditional operator associativity. Its in the manual, at the link kindly provided by dcp, stated as "The conditional operator is right-associative", with an example. And, as you suggested and I and others agreed, the fact that you can rely on it allows clearer code.
Refer to msdn:
http://msdn.microsoft.com/en-us/library/ty67wk28%28VS.80%29.aspx
"If condition is true, first expression is evaluated and becomes the result; if false, the second expression is evaluated and becomes the result. Only one of two expressions is ever evaluated."