단일 책임 원칙, 하나의 객체는 하나의 책임을 갖는다.

2023. 3. 14. 23:42자바

728x90
반응형

SOLID 원칙 중 'S'


 

하나의 객체가 하나의 책임만 져야한다!

→ 클래스를 단 한 가지의 목표만 가지고 작성해야 한다는 것을 의미한다.

 

애플리케이션 전반에서 높은 유지보수성과 가시성 제어 기능을 유지하는 원칙이다.


만약 클래스 하나가 여러 개의 목표를 가지고 있는 경우에는?

단일 책임 원칙을 따르지 않는 경우

 

직사각형 면적을 구하고 단위를 변환하는 문제를 다음과 같은 클래스에서 구현할 수 있다.

package SingleResponsePrinciple;

public class RectangleAreaCalculator {
    private static final double INCH_TERM = 0.0254d;

    private final int width;
    private final int height;

    public RectangleAreaCalculator(int width, int height) {
        this.width = width;
        this.height = height;
    }

    // 면적을 구하는 기능
    public int getArea() {
        return width * height;
    }

    // 면적을 인치로 변환하는 기능 -> **단일 책임 원칙에 위배된다.**
    public double metersToInches(int area) {
        return area /INCH_TERM;
    }
}

위에서의 RectangleAreaCalculator 클래스는 면적을 구하는 기능과 면적을 인치로 변환하는 기능을 담당한다.

만약 면적을 인치로 변환하는 기능의 변화가 있을 때면적을 구하는 기능에 변경 사항이 생긴다면

이는 RectangleAreaCalculator를 매번 바꿔야한다는 단점이 발생한다.


🤨 그러면 한번에 관리하니까 좋은 거 아니야?

만약에 RectangleAreaCalculator가 100개의 기능을 담당한다고 해볼게요!

package SingleResponsePrinciple;

public class RectangleAreaCalculator {
    private static final double INCH_TERM = 0.0254d; // 인치
    **private static final double FEET_TERM = 0.3048d; // 피트**

		...

    private final int width;
    private final int height;

    public RectangleAreaCalculator(int width, int height) {
        this.width = width;
        this.height = height;
    }

    // 면적을 구하는 기능
    public int getArea() {
        return width * height;
    }

    // 면적을 인치로 변환하는 기능
    public double metersToInches(int area) {
        return area / INCH_TERM;
    }

    **// 면적을 피트로 변환하는 기능
    public double metersToFeet(int area) {
        return area / FEET_TERM;
    }**
		
		...
}

하나의 클래스가 100개의 기능을 담당한다고 하면

기능 하나가 변경될 때 해당 클래스에서 변경을 진행해야합니다.

 

이때 두 가지 문제점이 있을 수 있겠네요!

 

1. 의존성이 있는 클래스인 경우에는 함수를 쉽게 바꿀 수 없습니다.

객체지향적인 코드라는 것은 객체들 간의 협력에 기반해 코드를 작성하는 것입니다.

이에 따라 수정사항이 발생하더라도 다른 객체에 영향을 주지 않고 코드를 수정할 수 있는 것이죠!

하지만 기능이 많아질수록 다른 클래스와의 연관성이 높아지기에 코드 수정이 어려워집니다!

이를 유지보수가 어려워진다!고 표현합니다.

위의 코드는 그러한 잠재적인 문제가 있을 수 있겠죠 ㅎㅎ

 

2. 가독성이 나쁘다!

어떤 부분을 수정해야하는 지 한눈에 파악하기가 어려워요!

개발자도 사람이기 때문에 가독성이 나쁜 코드는 이해하기도 어려워지고, 수정도 어려워져서 유지보수가 어려워진다는 단점이 있습니다.

결과적으로 유지보수가 어려워진다는 단점이 생깁니다!


🤨 그러면 어떻게 할 수 있을까?

단일 책임 원칙을 따르는 경우

클래스를 분할하면 위의 문제를 해결할 수 있어요!

 

1. 면적을 구하는 클래스

package SingleResponsePrinciple;

public class RectangleAreaCalculator {
    private final int width;
    private final int height;

    public RectangleAreaCalculator(int width, int height) {
        this.width = width;
        this.height = height;
    }

    // 면적을 구하는 기능
    public int getArea() {
        return width * height;
    }
}

 

2. 면적을 변환하는 클래스

package SingleResponsePrinciple;

public class AreaConverter {
    private static final double INCH_TERM = 0.0254d;
    private static final double FEET_TERM = 0.3048d;

    // 면적을 인치로 변환하는 기능
    public double metersToInches(int area) {
        return area / INCH_TERM;
    }

    // 면적을 피트로 변환하는 기능
    public double metersToFeet(int area) {
        return area / FEET_TERM;
    }
}

위와 같이 기능별로 클래스를 분할하면 유지보수가 쉬워진다는 장점이 있습니다!

728x90
반응형