OCP 개방-폐쇄 원칙 (Open/closed principle)
• 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다
• 이런 거짓말 같은 말이? 확장을 하려면, 당연히 기존 코드를 변경?
• 다형성을 활용해보자
• 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현
• 역할과 구현의 분리
우테코 1주 차 미션인 자동차 경주 미션을 생각해보자.
public class Car {
private int position;
public void move(int movingValue) {
if (movingValue >= STANDARD_OF_MOVING) {
position++;
}
}
자동차가 움직이기 매개변수로 받은 정수가 기준 이상이어야 한다. 현재 이 movingValue의 정책은 0부터 9까지 중 랜덤 한 숫자를 받는 것이다.
실제로 쓰이는 곳에선 이렇게 쓰일 것이다.
RacingGame 클래스
public RacingResult race(AttemptNumber attemptNumber) {
// ...
Random random = new Random();
do {
cars.forEach(car -> car.move(random.nextInt(10));
// ...
} while (반복 조건);
// ...
}
이렇게 구현했을 때 문제점이 뭘까? movingValue의 정책이 랜덤한 값이 아니라 다른 정책으로 바뀌면 이 RacingGame의 코드가 변경된다. 여러 정책을 번갈아 써야 할 경우도 마찬가지이다. 이러면 기능이 확장될 때 코드 변경이 불가피하다.
때문에 전략패턴을 사용한다.
public interface MovingStrategy {
int generate();
}
public class RandomMovingStrategy implements MovingStrategy {
private static final int RANDOM_VALUE_RANGE = 10;
private static final Random random = new Random();
@Override
public int generate() {
return random.nextInt(RANDOM_VALUE_RANGE);
}
}
movingValue 생성 전략을 MovingStrategy 인터페이스로 추상화한 뒤 구현체인 RandomMovingStrategy를 RacingGame에서 사용하는 것이다.
전략 패턴 적용 후 RacingGame
ublic class RacingGame {
private final MovingStrategy movingStrategy = new RandomMovingStrategy();
public RacingResult race(AttemptNumber attemptNumber) {
// ...
do {
cars.forEach(car -> car.move(movingStrategy.generate()));
} while (반복 조건);
// ...
}
RacingGame를 생성할 때 알맞은 구현체만 넣어준다면 RacingGame의 코드 변경 없이 다양한 전략을 사용할 수 있다. 클라이언트 코드의 변경이 거의 없이 새로운 구현체를 만들어(확장)하면 되는 것이다.
문제점
- RacingGame 클라이언트가 구현 클래스를 직접 선택
- MovingStrategy movingStrategy = new RandomMovingStrategy(); //기존 코드
- MovingStrategy movingStrategy = new XXXXXXMovingStrategy(); //변경 코드
- 현 객체를 변경하려면 클라이언트 코드를 변경해야 한다.
- 분명 전략패턴을 사용했지만 OCP 원칙을 지킬 수 없다.
- 이 문제를 어떻게 해결해야 하나?
- 객체를 생성하고, 연관 관계를 맺어주는 별도의 조립, 설정자가 필요하다.
이 문제점은 향후 스프링을 공부하면서 해결해보려고 한다.
'방법론' 카테고리의 다른 글
소프트웨어와 복잡성 관리 (0) | 2024.09.01 |
---|---|
도메인 vs 엔티티 (feat. DDD) (1) | 2022.05.15 |
MVC(Model-View-Controller) 패턴이란 (0) | 2022.02.15 |
TDD(Test-Driven-Development) 강의 복습 (0) | 2022.02.13 |