if문

확인방법: 바이트코드

if(a && b && c && d && e && f && g)

if(a)
 if(b)
  if(c)
   if(d)
    if(e)
     if(f)
      if(g)

:둘다 동일한 바이트코드로 컴파일됨.

boolean a=true, b=true, c=true, d=true, e=true, f=true, g=true;
   0: iconst_1
   1: istore_1
   2: iconst_1
   3: istore_2
   4: iconst_1
   5: istore_3
   6: iconst_1
   7: istore        4
   9: iconst_1
  10: istore        5
  12: iconst_1
  13: istore        6
  15: iconst_1
  16: istore        7

if(a && b && c && d && e && f && g) {}
  18: iload_1
  19: ifeq          45
  22: iload_2
  23: ifeq          45
  26: iload_3
  27: ifeq          45
  30: iload         4
  32: ifeq          45
  35: iload         5
  37: ifeq          45
  40: iload         6
  42: ifeq          45

if(a) if(b) if(c) if(d) if(e) if(f) if(g) {}
  45: iload_1
  46: ifeq          72
  49: iload_2
  50: ifeq          72
  53: iload_3
  54: ifeq          72
  57: iload         4
  59: ifeq          72
  62: iload         5
  64: ifeq          72
  67: iload         6
  69: ifeq          72

최적화

1.스위치문

public int calculate(int a, int b, String operator) {
    int result = Integer.MIN_VALUE;
 
    if ("add".equals(operator)) {
        result = a + b;
    } else if ("multiply".equals(operator)) {
        result = a * b;
    } else if ("divide".equals(operator)) {
        result = a / b;
    } else if ("subtract".equals(operator)) {
        result = a - b;
    }
    return result;
}
public int calculateUsingSwitch(int a, int b, String operator) {
    switch (operator) {
    case "add":
        result = a + b;
        break;
    // other cases    
    }
    return result;
}

장점 : 간단, 유지보수용이 단점 : 복잡한논리엔 부적합

리팩토링

3.1 팩토링클래스 ::원하는 타입 객체를 반환

연산 인터페이스

public interface Operation {
    int apply(int a, int b);
}

구현

public class Addition implements Operation {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}

구현클래스들의 hashmap소유 클래스 //map으로 두면 더빠름

public class OperatorFactory {
    static Map<String, Operation> operationMap = new HashMap<>();
    static {
        operationMap.put("add", new Addition());
        operationMap.put("divide", new Division());
        // more operators
    }
 
    public static Optional<Operation> getOperation(String operator) {
        return Optional.ofNullable(operationMap.get(operator));
    }

숫자, 연산자를 받아 , 팩터링클래스에 넘긴후 객체를 return받기

public int calculateUsingFactory(int a, int b, String operator) {
    Operation targetOperation = OperatorFactory
      .getOperation(operator)
      .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
    return targetOperation.apply(a, b);
}

3.2 Enums

logic에 enum 부여 ,if , switch , factor의 조건으로 사용

  1. 연산 label 지정
    public enum Operator {
     ADD, MULTIPLY, SUBTRACT, DIVIDE
    }
    
  2. 구현
ADD {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
},
// other operators
 
public abstract int apply(int a, int b);

3.라우터

public int calculate(int a, int b, Operator operator) {
    return operator.apply(a, b);
}

Operator#valueOf() method 로 String 을 operator로 변환해서 사용

@Test
public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
    assertEquals(7, result);
}

3.3명령패턴

명령을받는 Calculator#calculate which can be executed on the inputs. //중첩 if 개선

1.커맨드

public interface Command {
    Integer execute();
}

2.add커맨드

public class AddCommand implements Command {
    // Instance variables
 
    public AddCommand(int a, int b) {
        this.a = a;
        this.b = b;
    }
 
    @Override
    public Integer execute() {
        return a + b;
    }
}

3.command를 받는 method

public int calculate(Command command) {
    return command.execute();
}

4.AddCommand객체생성, Calculator#calculate method에 보내기:

@Test
public void whenCalculateUsingCommand_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(new AddCommand(3, 7));
    assertEquals(10, result);
}

3.4룰엔진

중첩 if문 평가 규칙 규칙과 입력에따라 반환 복잡성제거

1.rule

public interface Rule {
    boolean evaluate(Expression expression);
    Result getResult();
}

2.rule engine

public class RuleEngine {
    private static List<Rule> rules = new ArrayList<>();
 
    static {
        rules.add(new AddRule());
    }
 
    public Result process(Expression expression) {
        Rule rule = rules
          .stream()
          .filter(r -> r.evaluate(expression))
          .findFirst()
          .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
        return rule.getResult();
    }
}

RuleEngine은 Expression object를받아 결과반환 Expression:

public class Expression {
    private Integer x;
    private Integer y;
    private Operator operator;        
}        //두 정수와 연산의 expression

addrule

public class AddRule implements Rule {
    @Override
    public boolean evaluate(Expression expression) {
        boolean evalResult = false;
        if (expression.getOperator() == Operator.ADD) {
            this.result = expression.getX() + expression.getY();
            evalResult = true;
        }
        return evalResult;
    }    
}

호출: engin.process(expression)

@Test
public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult() {
    Expression expression = new Expression(5, 5, Operator.ADD);
    RuleEngine engine = new RuleEngine();
    Result result = engine.process(expression);
 
    assertNotNull(result);
    assertEquals(10, result.getValue());
}

assert문:: //jdk1.4 이상

assert expression1; //참:pass 거짓:AssertionError

assert expression1: expression2; //exp1참 : pass 거짓 : exp2출력


출처::

https://www.baeldung.com/java-replace-if-statements