We need constructive proposals for nested conditions

I need to write logic with many conditions (up to 30 conditions) in one set of rules with many if else conditions, and this may end between or after all conditions.

Here is an example of the code I tried with some possible script. This gives me the result, but it doesn’t look very good, and any minor misses in one condition will be forever tracked.

What I have tried so far is to deduce the general conditions and reorganize some methods. I tried to create an interface with conditions and various sets to implement it.

If you have any suggestions for developing this, I would be helped. Not looking for a 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; } 
+5
source share
4 answers

The stream gets more complicated because you have a normal stream, plus many possible exception flows when some of the values ​​are exceptional (for example, invalid).

This is an ideal candidate for processing with the try / catch / finally block .

Your program can be rewritten as follows:

 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 exceptions like RuntimeException

 class ValidationException extends RuntimeException { public ValidationException(String arg0) { super(arg0); // TODO Auto-generated constructor stub } /** * */ private static final long serialVersionUID = 1L; } 

You can learn more about this in

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

+1
source

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); } } 
+1
source

Think of each test of the rule as an object, or as a strategy that returns whether the rule passes. Each test should implement the same IRuleCheck interface and return a RuleCheckResult, which indicates whether the test passed or the reason for the failure.

 public interface IRuleCheck { public RuleCheckResult Check(Input input); public String Name(); } public class RuleCheckResult { private String _errorMessage; public RuleCheckResult(){}//All Good public RuleCheckResult(String errorMessage) { _errorMessage = errorMessage; } public string ErrorMessage() { return _errorMessage; } public Boolean Passed() { return _errorMessage == null || _errorMessage.isEmpty(); } } public class CheckOne implements IRuleCheck { public RuleCheckResult Check(Input input) { if (input.d.equals("Z1")) { return new RuleCheckResult();//passed } return new RuleCheckResult("d did not equal z1"); } public String Name(); } 

Then you can simply create a list of rules and skip them, and either jump when it fails, or compile the list of failures.

 for (IRuleCheck check : checkList) { System.out.println("checking: " + check.Name()); RuleCheckResult result = check.Check(input); if(!result.Passed()) { System.out.println("FAILED: " + check.Name()+ " - " + result.ErrorMessage()); //either jump out and return result or add it to failure list to return later. } } 

And the advantage of using the interface is that the checks can be as complex or simple as necessary, and you can create arbitrary lists to check any combination of rules in any order.

+1
source

@leeyuiwah's answer has a clear structure of conditional logic, but exceptions here are not a suitable tool to work with.

You must not use exceptions to deal with non-exclusive conditions. First, exceptions are very expensive to build, because you need to go through the entire call stack in order to build a stack trace; but you don’t need a stack trace at all.

Check out Effective Java 2nd Ed Paragraph 57: “Use exceptions for exceptional conditions only” to discuss in detail why you should not use exceptions like this.

A simpler option is to define a small helper method:

 private static boolean printAndReturnFalse(String message) { System.out.println(message); return false; } 

Then:

 if(!input.a.equals("v1")) { return printAndReturnFalse("Failed aat first"); } // etc. 

which I find more simple; and it will be much faster.

+1
source

Source: https://habr.com/ru/post/1263074/


All Articles