It\'s something that\'s bugged me in every language I\'ve used, I have an if statement but the conditional part has so many checks that I have to split it over multiple lines, u
First, I'd remove all the == true
parts, that would make it 50% shorter ;)
When I have big condition I search for the reasons. Sometimes I see I should use polymorphism, sometimes I need to add some state object. Basically, it implies a refactoring is needed (a code smell).
Sometimes I use De-Morgan's laws to simplify boolean expressions a bit.
I resort to separate boolean values:
Bool cond1 == (var1 && var2);
Bool cond2 == (var3 && var4);
if ( cond1 && cond2 ) {}
If I was doing it in Perl, This is how I might run the checks.
{
last unless $var1;
last unless $var2;
last unless $var3;
last unless $var4;
last unless $var5;
last unless $var6;
... # Place Code Here
}
If you plan on using this over a subroutine replace every instance of last
with return
;
I like to break each condition into descriptive variables.
bool isVar1Valid, isVar2Valid, isVar3Valid, isVar4Valid;
isVar1Valid = ( var1 == 1 )
isVar2Valid = ( var2.Count >= 2 )
isVar3Valid = ( var3 != null )
isVar4Valid = ( var4 != null && var4.IsEmpty() == false )
if ( isVar1Valid && isVar2Valid && isVar3Valid && isVar4Valid ) {
//do code
}
I'm surprised no one got this one yet. There's a refactoring specifically for this type of problem:
http://www.refactoring.com/catalog/decomposeConditional.html
There are two issues to address here: readability and understandability
The "readability" solution is a style issue and as such is open to interpretation. My preference is this:
if (var1 == true && // Explanation of the check
var2 == true && // Explanation of the check
var3 == true && // Explanation of the check
var4 == true && // Explanation of the check
var5 == true && // Explanation of the check
var6 == true) // Explanation of the check
{ }
or this:
if (var1 && // Explanation of the check
var2 && // Explanation of the check
var3 && // Explanation of the check
var4 && // Explanation of the check
var5 && // Explanation of the check
var6) // Explanation of the check
{ }
That said, this kind of complex check can be quite difficult to mentally parse while scanning the code (especially if you are not the original author). Consider creating a helper method to abstract some of the complexity away:
/// <Summary>
/// Tests whether all the conditions are appropriately met
/// </Summary>
private bool AreAllConditionsMet (
bool var1,
bool var2,
bool var3,
bool var4,
bool var5,
bool var6)
{
return (
var1 && // Explanation of the check
var2 && // Explanation of the check
var3 && // Explanation of the check
var4 && // Explanation of the check
var5 && // Explanation of the check
var6); // Explanation of the check
}
private void SomeMethod()
{
// Do some stuff (including declare the required variables)
if (AreAllConditionsMet (var1, var2, var3, var4, var5, var6))
{
// Do something
}
}
Now when visually scanning the "SomeMethod" method, the actual complexity of the test logic is hidden but the semantic meaning is preserved for humans to understand at a high-level. If the developer really needs to understand the details, the AreAllConditionsMet method can be examined.
This is formally known as the "Decompose Conditional" refactoring pattern I think. Tools like Resharper or Refactor Pro! can making doing this kind of refactoring easy!
In all cases, the key to having readable and understandable code is to use realistic variable names. While I understand this is a contrived example, "var1", "var2", etc are not acceptable variable names. They should have a name which reflects the underlying nature of the data they represent.