리팩터링 기법. 조건부 로직을 다형성으로 바꾸기(Replace Conditional with Polymorphism)
조건부 로직을 다형성으로 바꾸기(Replace Conditional with Polymorphism)란 객체의 타입에 따라 분기되는 조건부 로직을 상속 구조를 이용하여 다형성을 적용하여 코드를 간결하고 유연하게 만드는 리팩터링 방법입니다.
조건부 로직은 보통 if-else문, switch-case문 등으로 구현되며, 객체의 타입에 따라 다른 로직을 수행하도록 설계되어 있습니다.
이러한 코드는 코드의 유지보수성이 나쁘며, 새로운 객체 타입이 추가될 때마다 코드의 수정이 필요합니다.
따라서 이러한 조건부 로직을 다형성을 이용하여 분리하고, 객체의 타입에 따라 해당하는 메서드를 호출하는 방식으로 코드를 변경하는 것이 좋습니다.
이 방법을 사용하면, 객체의 타입에 따라 다른 동작을 수행해야 할 때 새로운 객체 타입을 추가하기가 쉬워집니다.
또한, 각 객체 타입마다 특정 동작을 수행하는 메서드가 존재하므로, 코드의 가독성이 높아지고 유지보수성도 향상됩니다.
조건부 로직을 다형성으로 바꾸는 방법은 다음과 같습니다.
- 조건문에 해당하는 부분을 클래스의 메소드로 추출합니다.
- 추출한 메소드를 추상 메소드로 정의하고, 상속받을 클래스에서 구현합니다.
- 추상 클래스를 정의하고, 추상 메소드를 포함합니다.
- 추상 클래스를 상속받아 각 상황에 맞는 클래스를 구현합니다.
간단한 예시로, 도형 클래스를 다루는 코드를 예로 들어보겠습니다.
이전 코드에서는 각 도형의 타입에 따라 분기를 수행하였습니다.
class Shape {
public:
enum Type {
Circle,
Rectangle,
Triangle
};
Type getType() const { return type_; }
double getArea() const {
switch (type_) {
case Circle:
return PI * radius_ * radius_;
case Rectangle:
return width_ * height_;
case Triangle:
return 0.5 * base_ * height_;
}
}
private:
Type type_;
double radius_;
double width_;
double height_;
double base_;
};
이를 조건부 로직에서 다형성을 이용하여 변경하면, 각 도형 클래스를 만들고 각 클래스마다 getArea() 메서드를 구현하게 됩니다.
class Shape {
public:
virtual double getArea() const = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius_(radius) {}
double getArea() const override { return PI * radius_ * radius_; }
private:
double radius_;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
double getArea() const override { return width_ * height_; }
private:
double width_;
double height_;
};
class Triangle : public Shape {
public:
Triangle(double base, double height) : base_(base), height_(height) {}
double getArea() const override { return 0.5 * base_ * height; }
private:
double base;
double height_;
};
위 코드는 다형성을 이용하여 조건부 로직을 처리하도록 바꾼 예시 코드입니다.
기존 코드에서는 다양한 도형에 대한 정보를 하나의 클래스 내에 저장하고 있었습니다.
하지만 이를 다형성을 이용하여 각 도형마다 별도의 클래스로 분리하고, 공통적으로 필요한 부분은 부모 클래스인 Shape 클래스에 정의하여 사용하는 것입니다.
위 코드에서 Circle, Rectangle, Triangle 클래스는 각 도형에 대한 클래스입니다.
이들은 모두 Shape 클래스를 상속받아 getArea() 함수를 오버라이딩하고 있습니다.
이렇게 하면 다른 클래스에서는 Shape 포인터를 이용하여 각 도형의 넓이를 구할 수 있습니다.
이는 조건문 없이 다형성을 이용하여 간결하고 유연한 코드를 작성할 수 있도록 도와줍니다.