요즘 우리 학교를 졸업하신 선배에게 멘토링을 받고 있다.
그리고, 자동차 경주 미션을 받고 코드 리뷰를 받는데 이런 리뷰를 받았다.
OCP를 적용하여 리팩토링을 진행해보는게 어떤지에 대한 리뷰였는데 막막했다.
OCP : Open-Close Principle
기존의 코드를 변경하지 않고 기능을 추가할 수 있도록 설계하는 원칙.
여기서 기존 코드를 변경하지 않는다는것이 너무 헷갈렸다.
OCP의 개념에 대해 알아보기 전, if-else 혹은 switch-case의 문제점에 대해서 생각해보자.
조건이 많아질수록 코드가 길어지며 복잡해진다. 즉, 유지보수가 어려워진다는 단점이 존재한다.
이를 이용해 과연 Clean Code를 작성할 수 있을까?
필자는 아니라고 본다. "클린코드 : 에자일 소프트웨어 장인 정신"에서 Clean Code를 위해서는 함수를 작게 만들어야 한다고 한다. 하지만, 위에 언급한 두 조건식은 기능을 추가하고 리팩토링을 할수록 함수가 커진다.
함수가 커지는것 뿐 아니라, '한 가지'작업만 하는것이 아니며 SRP,OCP를 위반한다.
Clean Code에 대해서 위에 잠깐 이야기를 했다. 왜 이런 이야기가 나왔을까?
당연한 말 이지만 OCP는 Clean Code와 연관이 깊다고 할 수 있다.
코드의 변경은 닫혀있고, 코드의 확장은 열려있어야 한다.
이게 과연 무슨소리일까?
public interface CarMoveStrategyable {
public boolean move();
}
public FiveOverMoveImpl implements CarMoveStrategyable {
@Override
public boolean move() {
if(new Random().nextInt(10) >= 5) {
return true;
}
return false;
}
}
public FourUnderMoveImpl implements CarMoveStrategyable {
@Override
public boolean move() {
if(new Random().nextInt(10) <= 4) {
return true;
}
return false;
}
}
이런 형태로 구조가 짜여 있다고 생각을 해 보자.
CarMoveStrategyable
인터페이스가 있고, 이를 구현한 구현체인 FiveOverMoveImpl
, FourUnderMoveImpl
라는 두 구현체가 있다.
자, 그렇다면 아래와 같은 코드를 본 적 있는가?
CarMoveStrategyable carMoveStrategyable = new FourUnderMoveImpl();
이처럼 인터페이스로 인해 구현된 구현체는 인터페이스 변수가 참조할 수 있다.
그렇다면, carMoveStregyable
은 FourUnderMoveImpl
구현체의 기능을 수행하게 된다.
즉, CarMoveStregyable
로 구현된 구현체들을 참조하면 참조된 구현체의 기능을 사용할 수 있다는 것이다.
위 내용을 본다면 캐치한 사람도 있으리라 생각이 된다. 바로 확장성이 굉장히 좋아진다는 점 이다.
즉, 이미 잘 작동하고있는 코드를 수정하지 않고 추가를 함으로써 더욱 편리하게 확장을 할 수 있다는 장점이 존재한다.
필자도 이번 미션을 진행하며 정말 헷갈린 내용이 바로 이 OCP이다.
Clean Code가 중요하다는것은 알고 있지만서도 과연 내가 Clean Code를 작성하고 있을까 라는 생각을 가지고 있었는데 이번 미션을 계기로 나는 전혀 Clean한 Code를 작성하지 않았다 라는 생각을 갖게 되었다.