Click here to Skip to main content
15,898,770 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
This one has been bothering me for a while. I need to check if somewhere around 8 values are not Nothing. I might not need to check them all at once, but a few at a time and then some nested If's. It makes code ugly and unreadable, but how to prevent so many If's or at least make it more readable and understandable?
A Select Case will not do, since ALL values need to be evaluated.

So how could I possibly make code like this better readable?
VB
If Not object1.Property1 Is Nothing AndAlso Not object2.Property1 Is Nothing AndAlso Not object2.Property1.Property1 Is Nothing Then

   Dim object3 = ' LINQ Query.

   If Not object3 Is Nothing Then

      If Not object4 Is Nothing AndAlso Not object3.Property1 Is Nothing Then
      '...
      ElseIf '...
      '...
      End If

   End If

End If

I could put some of it in a seperate Method, but that would only move the problem, not solve it. I am sure this is a problem that has existed for many many years, but I have never found a clear answer to it...
Posted

If cannot prevent it, you can design you code the way it uses much less "ifs". Did you here about totally data-driven development style where there are no a single "if" in application code? To me, this is overkill, but many would say it's not possible. It is possible.

To my taste, two levels of if is still quite acceptable, one more is questionable and more it totally unacceptable. You need to re-factor the code, but better have a good plan on how the whole thing should look like. Thinking on the programming-in-the-large level helps to avoid multilevel checks in first place, but in local place you can re-factor the code. In particular, using local predicates is a very convenient idea.

By the way, how about local predicate. There are methods, and there is no such thing as local method, or it is?
If you need some inspirational example, try to look at my small Tips/Tricks article: Hide Ad-hoc Methods Inside the Calling Method’s Body[^].

I do not insist you use this technique, not at all. I think just the ideas of thinking could be useful for you.

—SA
 
Share this answer
 
v2
Comments
Sander Rossel 20-May-11 15:19pm    
So you are saying I could make a Method inside a Method that validates if everything is as it should be? Kind of D@nish solution, but 'more local'? Interesting thought. But as I said in my question this would move the problem, not solve it. And actually would this not make it more complex? Having lots of if's in a Method is confusing, but having lots of if's in a Method in a Method is even more confusing...
I think I am kind of missing the point?
I do not know VB so will try to explain using C# if it helps.

Three levels of if/else if fine but more than that is a no. This is something you could do to get rid nested of ifs.

Assume following class structure:

C#
class ParentClass
{
    public ChildClass ChildProperty { get; set; }
}
class ChildClass
{
    public int SomeProperty { get; set; }
}


Say, you need to do this kind of processing:

C#
ParentClass parentObj1 = new ParentClass();
ParentClass parentObj2 = new ParentClass();
ParentClass parentObj3 = new ParentClass();
if (parentObj1 != null && parentObj2.ChildProperty != null && parentObj2.ChildProperty.SomeProperty != null)
{
    ParentClass parentObj4 = new ParentClass();
    if (parentObj4 != null)
    {
        if (parentObj3 != null && parentObj4.ChildProperty != null)
        {
            if (parentObj4.ChildProperty.SomeProperty != null)
            {
            }
            else
            {
            }
        }
        else if (parentObj3 != null && parentObj3.ChildProperty != null && parentObj4.ChildProperty.SomeProperty != null)
        {
        }
        else
        {
        }
    }
}


This can be re-written as following:

C#
if (parentObj1 != null && parentObj2.ChildProperty != null && parentObj2.ChildProperty.SomeProperty != null)
{
    ParentClass ob3 = new ParentClass();
    switch (ValidateObjects(parentObj3, ob3))
    {
        case 0:
            // Do something
            break;
        case 1:
            // Do something
            break;
        case 2:
            // Do something
            break;
        case 3:
            // Do something
            break;
        default:
            //Do something
            break;
    }
}


ValidateObjects method could look like this:

C#
private static int ValidateObjects(ParentClass ob4, ParentClass ob3)
{
    int result =0;
    if (ob3 != null && ob4 != null && ob4.ChildProperty != null && ob3.ChildProperty.SomeProperty != null)
    {
        result = 0;
    }
    else if (ob3 != null && ob4 != null && ob3.ChildProperty != null && ob3.ChildProperty.SomeProperty != null)
    {
        result = 1;
    }
    else if (ob3 != null && ob4 != null && ob3.ChildProperty != null)
    {
        result = 2;
    }
    else if (ob3 != null)
    {
        result = 3;
    }
    return result;
}


You can opt for switch case in the method above too.

Still, you have a better understanding of the application so can think of better solutions. :)
 
Share this answer
 
Comments
Sander Rossel 20-May-11 15:32pm    
Nice work, I don't know it that would make the code any more readable though. Especially the person using your ValidateObjects Method would have no idea what to expect.
And I am also not sure if your second method does the same as the first. Because in the first method code will run if certain criteria are true. AFTER that more code will run if another set of criteria are true. In the second example however, only one set of criteria can be through and that code will run. So in your case you would have to check every possible result and then have the same code and then some run if criteria 1 OR 2 is met...

So code like this:
if (obj1 != null)
{
// Do A
if (obj2 != null)
{
// Do B
}
}

Would translate to:
if (obj1 != null) { result = 0; }
if (obj1 != null && obj2 != null) { result = 2; }

case 0:
// Do A
break;
case 1:
// Do A
// Do B
break;

If, like in your case you have 4 possible results you will get stuff like
case 2 // Do A, Do B, Do C
case 3 // Do A, Do C

And having to add another 'if' in your original code (could happen) will end in tears :)
Without knowing more about your code, I have to tell you that the way you're doing it is the only way. You *could* abstract out the comparisons into a few methods, but you'd have to design it carefully.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 19-May-11 11:23am    
Well, this is not about concrete code, more about general approach.
Please see what I advise.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900