๐Ÿต java

JAVA | ์‚ฌ์น™ ์—ฐ์‚ฐ ๊ณ„์‚ฐ๊ธฐ ์‹ค์Šต - (2)

c0zi 2023. 8. 19. 21:24
์š”๊ตฌ์‚ฌํ•ญ
• ๊ฐ„๋‹จํ•œ ์‚ฌ์น™์—ฐ์‚ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. โ˜‘๏ธ
• ์–‘์ˆ˜๋กœ๋งŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. โ˜‘๏ธ
• ๋‚˜๋ˆ—์…ˆ์—์„œ 0์„ ๋‚˜๋ˆ„๋Š” ๊ฒฝ์šฐ IllegalArgument ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. โ˜‘๏ธ
• MVCํŒจํ„ด(Model-View-Controller) ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค. โ˜‘๏ธ

๐Ÿ“‹ enum์„ ํ™œ์šฉํ•œ ์‚ฌ์น™์—ฐ์‚ฐ ๊ณ„์‚ฐ๊ธฐ

 

ArithmeticOperator

public enum ArithmeticOperator {

    ADDITION("+") {
        @Override
        public int arithmeticCalculate(PositiveNumber operand1, PositiveNumber operand2) {
            return operand1.toint() + operand2.toint();
        }
    }, SUBSTRACTION("-") {
        @Override
        public int arithmeticCalculate(PositiveNumber operand1, PositiveNumber operand2) {
            return operand1.toint() - operand2.toint();
        }
    }, MULTIPLICATION("*") {
        @Override
        public int arithmeticCalculate(PositiveNumber operand1, PositiveNumber operand2) {
            return operand1.toint() * operand2.toint();
        }
    }, DIVISION("/") {
        @Override
        public int arithmeticCalculate(PositiveNumber operand1, PositiveNumber operand2) {
            return operand1.toint() / operand2.toint();
        }
    };

    private final String operator;

    ArithmeticOperator(String operator) {
        this.operator = operator;
    }

    public abstract int arithmeticCalculate(final PositiveNumber operand1, final PositiveNumber operand2);

    public static int calculate(PositiveNumber operand1, String operator, PositiveNumber operand2) {
        ArithmeticOperator arithmeticOperator = Arrays.stream(values())
                .filter(v -> v.operator.equals(operator))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์น™์—ฐ์‚ฐ์ด ์•„๋‹™๋‹ˆ๋‹ค."));

        return arithmeticOperator.arithmeticCalculate(operand1, operand2);
    }
}

 

Calculator

public class Calculator {
    public static int calculate(PositiveNumber operand1, String operator, PositiveNumber operand2) {
        return ArithmeticOperator.calculate(operand1, operator, operand2);
    }
}

 

๋จผ์ €, ์ €๋ฒˆ ์‹œ๊ฐ„์—๋Š” Calculator ํด๋ž˜์Šค ๋‚ด์—์„œ ์‚ฌ์น™์—ฐ์‚ฐ์„ ๊ตฌํ˜„ํ•˜์˜€์ง€๋งŒ ์ด๋ฒˆ์—๋Š” enum์„ ํ†ตํ•ด ์‚ฌ์น™์—ฐ์‚ฐ์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค. ์•„์ง enum์„ ๋งŽ์ด ์‚ฌ์šฉํ•ด๋ณธ์ ์ด ์—†์–ด ๋‚ฏ์„ค์—ˆ๋‹ค. ์—ฌ๊ธฐ์„œ stream์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ stream์€ ํ•œ๋ฒˆ ๋” ๊ณต๋ถ€ํ•ด๋ณด์•„์•ผ ํ•  ๋“ฏ ํ–ˆ๋‹ค.

 

Calculator ํด๋ž˜์Šค์˜ calculate ๋ฉ”์„œ๋“œ๋Š” ArithmeticOperator ๋‚ด์˜ calculate ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ๊ฐ’์„ ์ „๋‹ฌํ•œ๋‹ค.

 

๋˜ํ•œ, ArithmeticOperator calculate๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

  1. values() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ArithmeticOperator ์—ด๊ฑฐํ˜•์— ์ •์˜๋œ ๋ชจ๋“  ์—ฐ์‚ฐ์ž๋“ค์„ ๊ฐ€์ ธ์˜จ๋‹ค.
  2. ๊ฐ€์ ธ์˜จ ์—ฐ์‚ฐ์ž๋“ค ์ค‘์—์„œ ์ž…๋ ฅ๋œ operator์™€ ์ผ์น˜ํ•˜๋Š” ์—ฐ์‚ฐ์ž๋ฅผ ์ฐพ๋Š”๋‹ค.
  3. findFirst() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ผ์น˜ํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ์—ฐ์‚ฐ์ž๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ๋งŒ์•ฝ ์ผ์น˜ํ•˜๋Š” ์—ฐ์‚ฐ์ž๊ฐ€ ์—†๋‹ค๋ฉด, orElseThrow() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด "์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์น™์—ฐ์‚ฐ์ด ์•„๋‹™๋‹ˆ๋‹ค."๋ผ๋Š” ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค.
  4. ์ฐพ์€ ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•˜์—ฌ operand1๊ณผ operand2๋ฅผ ๊ฐ€์ง€๊ณ  ํ•ด๋‹น ์—ฐ์‚ฐ์ž์˜ arithmeticCalculate ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‹ค์ œ ์‚ฌ์น™์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 


 

์š”๊ตฌ์‚ฌํ•ญ ์ค‘ ๋‘๋ฒˆ์งธ, '์–‘์ˆ˜๋กœ๋งŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค'๋ฅผ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด PositiveNumber class๋ฅผ ๋งŒ๋“ค๊ณ  value๊ฐ’์ด ์Œ์ˆ˜์ผ ๋•Œ IllegalArgumentException์„ ๋˜์ง„๋‹ค.

 

PositiveNumber

public class PositiveNumber {

    private final int value;

    public PositiveNumber(int value) {
        validate(value);

        this.value = value;
    }

    private void validate(int value) {
        if(isNegativeNumber(value)) {
            throw new IllegalArgumentException("0๋˜๋Š” ์Œ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
        }
    }

    private boolean isNegativeNumber(int value) {
        return value <=0;
    }

    public int toint() {
        return value;
    }
}

 

์ด์™€ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•˜๋ฉด ๋‚˜๋ˆ—์…ˆ์—์„œ 0์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒฝ์šฐ ์—ญ์‹œ ์ œ์™ธ๋œ๋‹ค.

 

๋งˆ์ง€๋ง‰์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Test ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

CalculatorTest

public class CalculatorTest {

    // 1 + 2 ---> Calculator
    //   3   ---<
    @DisplayName("๋ง์…ˆ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.")
    @Test
    void additionTest() {
        int result = Calculator.calculate(new PositiveNumber(1), "+", new PositiveNumber(2));

        assertThat(result).isEqualTo(3);
    }

    @DisplayName("๋บ„์…ˆ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค")
    @Test
    void subtractionTest() {
        int result = Calculator.calculate(new PositiveNumber(2), "-", new PositiveNumber(1));

        assertThat(result).isEqualTo(1);
    }

    @DisplayName("์‚ฌ์น™์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.")
    @ParameterizedTest
    @MethodSource("fomulaAndResult")
    void calculatorTest(int operand1, String operator, int operand2, int expect) {
        int result = Calculator.calculate(new PositiveNumber(operand1), operator, new PositiveNumber(operand2));
        assertThat(result).isEqualTo(expect);
    }

    private static Stream<Arguments> fomulaAndResult() {
        return Stream.of(
                arguments(1, "+", 2, 3),
                arguments(1, "-", 2, -1),
                arguments(1, "*", 2, 2),
                arguments(1, "/", 1, 1)
        );
    }

    @DisplayName("๋‚˜๋ˆ—์…ˆ์—์„œ 0์„ ๋‚˜๋ˆ„๋Š” ๊ฒฝ์šฐ IllegalArgument ์˜ˆ์™ธ ๋ฐœ์ƒ")
    @Test
    void calculateExceptionTest() {
        assertThatCode(() -> Calculator.calculate(new PositiveNumber(10), "/",new PositiveNumber(0)))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("0๋˜๋Š” ์Œ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
    }
}

 

AssertThatCode๋ฅผ ํ†ตํ•ด 0์„ ๋‚˜๋ˆ„๋Š” ๊ฒฝ์šฐ์˜ ์˜ˆ์™ธ ๋ฐœ์ƒ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜์˜€์ง€๋งŒ, ์ด๋Š” PositiveNumber ์ ์šฉ ์ „์„ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ์˜€์œผ๋ฉฐ ์–‘์ˆ˜๋งŒ์œผ๋กœ ์‚ฌ์น™์—ฐ์‚ฐ์ด ์ด๋ฃจ์–ด์ ธ ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜์˜€์œผ๋ฉด ์œ„ ํ…Œ์ŠคํŠธ๋Š” ์ง„ํ–‰ํ•  ํ•„์š” ์—†๋‹ค.