이전에 만들었던 Lv4는 의존성 역전 원칙(DIP, Dependency Inversion Principle) 을 수행한 내용이지만 OOP의 원칙 중 하나인 개방-폐쇄 원칙(OCP, Open-Closed Principle)을 어긴 사례이다,,,

class Calculator {

    fun calculator(num1: Double, num2: Double, op: AbstractOperation): Double {
        return when (op) {
            is AddOperation -> {op.operation(num1,num2)}
            is SubstractOperation -> {op.operation(num1,num2)}
            is MultiflyOperation -> {op.operation(num1,num2)}
            is DivideOperation -> {op.operation(num1,num2)}
            else -> throw IllegalArgumentException("잘못된 연산자 입력값입니다.")
        }
    }
}

 

추상화 클래스를 적용했을 때 Lv3 보다는 깔끔해지기도 했고 해서 괜찮게 했다 생각했으나, 마음 한 편으로는 기능 추가할 때 한 줄씩 계속 추가해야 한다면 기능이 100개가 추가가 된다면 100줄 추가해야하는데 그게 유지 보수가 간편하다 말해도 되나? 싶었다. 물론 그 전보다는 코드량이 꽤 줄었지만 상위 모듈은 코드 수정 필요없이 작동시키고 싶어서 찾아봤다.

 

찾아보니 개방-폐쇄 원칙이라는게 있었다. 개방-폐쇄 원칙이란 '소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다'는 프로그래밍 원칙이다.

 

즉, 기능이 변하거나 확장 가능하지만, 함수의 본질적인 코드(해당 기능의 코드)는 수정하면 안된다는 원칙이다.

 

하지만, 나는 기능이 확장되거나 변하면 calculator 함수의 내용을 수정해야 한다. 앞선 글에서 이야기한거와 같이

제곱연산자 기능을 넣으면 is SquareOperation -> {op.operation(num1,num2)} 이 내용도 상위모듈에 추가해야 한다.

이 자체가 개방-폐쇄 원칙을 위반한 코드다.

 

원칙에 부합하게 열심히 방법을 찾아보고 코드를 눈 뚫어져라 쳐다보니 이를 획기적으로 고치는 방법이 있었다.

class Calculator {

    fun calculator(num1: Double, num2: Double, op: AbstractOperation): Double {
        return op.operation(num1,num2)
    }
}

 

생각해보니 op를 받아올 때 이미 연산 클래스를 받아오기에 그 안에 있는 연산 메서드를 이용하면 끝이었다.

이 한줄을 통해 연산 클래스의 기능이 확장이 되거나 변경이 되어도 같은 기능을 수행하게 된다.

즉, 상위 모듈의 코드 변경없이 기능 확장이 가능해졌다.

//main 안에 op 입력 구현 부분

fun isValidOperator() : AbstractOperation {
    while (true) {
        try {
            var op = readLine()!!.toInt()
            if (op in 1..4) {
                when(op) {
                    1 -> return AddOperation()
                    2 -> return SubstractOperation()
                    3 -> return MultiflyOperation()
                    4 -> return DivideOperation()
                }
            }
            else println("1부터 4까지 연산자에 해당하는 숫자를 입력하세요")
        } catch (e: NumberFormatException) {
            println("입력값 오류! 숫자를 입력해주세요.")
        }
    }
}

 

실행 결과

 

이번 개인 과제에서 정말 많은 내용들을 공부할 수 있었고 앞으로 어떻게 어려움들을 헤쳐나가야 할지 어느정도 감이 잡혔다. 이해를 도와주신 장세진 튜터님께 감사의 말씀 올립니다!!

'MyProject' 카테고리의 다른 글

개인 과제 계산기 만들기 Lv4  (0) 2023.11.30
개인 과제 계산기 만들기 Lv3  (0) 2023.11.29
개인 과제 계산기 만들기 Lv2  (0) 2023.11.29
개인 과제 계산기 만들기 Lv1  (0) 2023.11.28

+ Recent posts