Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need design suggestions for nested conditions

Tags:

java

I need to write the logic with many conditions(up to 30 conditions) in one set of rule with many if else conditions and it could end in between or after all the conditions.

Here is the sample code I have tried with some possible scenario. This gives me result but doesn't look good and any minor miss in one condition would take forever to track.

What I have tried so far is, Take out common conditions and refactored to some methods. Tried creating interface with conditions and various set would implement it.

If you have any suggestion to design this, would help me. Not looking for detailed solution but even a hint would be great.

private Boolean RunCondition(Input input) {
    Boolean ret=false;
    //First if
    if(input.a.equals("v1")){
        //Somelogic1();
        //Second if
        if(input.b.equals("v2"))
            //Third if
            if(input.c >1)
                //Fourth if
                //Somelogic2();
                //Go fetch key Z1 from database and see if d matches.
                if(input.d.equals("Z1"))                        
                        System.out.println("Passed 1");
                    // Fourth Else
                    else{
                        System.out.println("Failed at fourth");
                    }

            //Third Else
            else{
                if(input.aa.equals("v2"))
                    System.out.println("Failed at third");
                }
        //Second Else
        else{
            if(input.bb.equals("v2"))
                System.out.println("Failed at second");
            }
    }
    //First Else
    else{
        if(input.cc.equals("v2"))
            System.out.println("Failed aat first");
        }

    return ret;
}

public class Input {
    String a;
    String b;
    int c;
    String d;
    String e;       
    String aa;
    String bb;
    String cc;
    String dd;
    String ee;  

}
like image 326
Paresh Avatar asked Jan 19 '17 19:01

Paresh


2 Answers

The flow is complicated because you have a normal flow, plus many possible exception flows when some of the values are exceptional (e.g. invalid).

This is a perfect candidate to be handled using a try/catch/finally block.

Your program can be rewritten into following:

private Boolean RunCondition(Input input) {
    Boolean ret=false;
    try {
        //First if
        if(!input.a.equals("v1")) {
            throw new ValidationException("Failed aat first");
        }
        //Somelogic1();

        //Second if
        if(!input.b.equals("v2")) {
            throw new ValidationException("Failed at second");
        }
        //Somelogic2()

        //Third if
        if(input.c<=1) {
            throw new ValidationException("Failed at third");
        } 

        //Fourth if
        //Somelogic2();
        //Go fetch key Z1 from database and see if d matches.
        if(!input.d.equals("Z1")) {
            throw new ValidationException("Failed at fourth");
        }
        System.out.println("Passed 1");

    } catch (ValidationException e) {
            System.out.println(e.getMessage());
    }

    return ret;
}

Where you can define your own ValidationException (like below), or you can reuse some of the existing standard exception such as RuntimeException

class ValidationException extends RuntimeException {

    public ValidationException(String arg0) {
        super(arg0);
        // TODO Auto-generated constructor stub
    }

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

}

You can read more about this in

https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html

like image 118
leeyuiwah Avatar answered Oct 16 '22 06:10

leeyuiwah


Make a separate class for the condition:

package com.foo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class App 
{
    static class Condition<T> {
        final int idx;
        final T compareValue;
        public Condition(final int idx, final T compareValue) {
            this.idx = idx;
            this.compareValue = compareValue;
        }
        boolean satisfies(final T other) {
            return other.equals(compareValue);
        }

        int getIdx() {
            return idx;
        }
    }
    public static void main( String[] args )
    {
        final List<Condition<String>> conditions = new ArrayList<Condition<String>>();
        conditions.add(new Condition<String>(1, "v1"));
        conditions.add(new Condition<String>(2, "v2"));
        final List<String> inputs = new ArrayList<String>(Arrays.asList("v1", "xyz"));
        boolean ret = true;
        for (int i = 0; i < inputs.size(); i++) {
            if (!conditions.get(i).satisfies(inputs.get(i)))
            {
                System.out.println("failed at " + conditions.get(i).getIdx());
                ret = false;
                break;
            }
        }
        System.out.println("ret=" + ret);
    }
}
like image 1
Kristjan Veskimäe Avatar answered Oct 16 '22 04:10

Kristjan Veskimäe