디미터 법칙 (The Law of Demeter)

최지환·2022년 3월 7일
1

객체지향

목록 보기
2/3
post-thumbnail

디미터 법칙 - 최소 지식 원칙

디미터 법칙은 무엇일까?

객체 안에 있는 메소드에 디미터 법칙에 위배되는 강한 결합도를 가진 메서드가 있다고 하자.

만약 이 메소드와의 결합도를 가진 로직 하나를 수정하면, 소스코드의 많은 곳에서 수정이 필요하다. 이러한 문제 때문에 디미터 법칙을 준수 해야한다.

디미터 법칙은 객체 지향 디자인 원칙중 하나이다. '최소 지식 원칙'이라는 말 처럼, 프로그래밍 시 객체 간 관계를 설정 할 때, 객체 간의 결합도를 낮추는 방법 중 하나이다.

디미터 법칙의 핵심은 객체간 결합도를 낮추는 것이다.
→ 결합도를 낮추는 방법
: 객체 자신의 멤버 메소드를 이용하거나, 직접 생성한 객체의 메소드를 사용한다.

예를들어 A, B, C 객체가 있다고 가정하고, A는 B를 사용하고, B는 C를 사용한다. 이때 A는 C에 대해 알 필요가 없다는 것이다.

A에게 C는 그저 낯선 객체이다.

예를들어 우리가 자동차 경주를 하는 프로젝트를 한다고 가정해보자.

그러기 위해서는 경주용 자동차 클래스를 만들어야한다.

경주용 자동차를 의미하는 RacingCar

자동차를 의미하는 Car

기름을 의미하는 Oil

이렇게 세개의 클래스가 있다.

우선적으로 우린 자동자의 기록에 대한 클래스 Record 와 이런 기록을 갖고 있는 Car 클래스, 또한 경주용 자동차의미하는 RacingCar 클래스를 만들었다.

RacingCar 객체 안에는 Car 객체가 있다.

또한 Car 객체 안에는 자동차의 기록을 저장 있는 Oil 객체가 있다.

public class RacingCar {
    Car car;

    public Car getCar() {
        return car;
    }

    public RacingCar(Car car) {
        this.car = car;
    }
}
//-----------------------------------------------------------------------------

public class Car {
    private Oil oil;

    public Oil getOil() {
        return oil;
    }

    public Car(Oil oil) {
        this.oil = oil;
    }
}

//------------------------------------------------------------------------------
public class Oil {
    private final int value;

    public Oil(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

그렇다면 racingCar라는 경주용 자동차 객체가 있다. 이때 이 경주용 자동차의 남은 기름 잔량을 보려면 어떻게 해야할까?

racinCar.getCar().getOil().getValue();

의 형태로 생각 할 수 있다. 이것이 디미터 법칙을 위배한 것이다.

cars는 자신이 알고 싶어하는 자동차의 기록에 대한 정보만 알고 싶은데, .getRecord().getValue()의 과정을 거치면서 기존에 자신이 갖고 있지 않던 Record 에 대한 정보 또한 알게 된다.

그렇다면 어떻게 리팩터링을 하면 좋을까?

racingCar.getStoredOil()

의 형태로 남은 기름 잔량을 얻는 getStoredOil()라는 메서드를 만들어주면 된다.

public class RacingCar {
    Car car;

    public Car getCar() {
        return car;
    }

    public RacingCar(Car car) {
        this.car = car;
    }

    **public int getStoredOil(){
        return car.getRemainingOil();
    }**

//------------------------------------------------------------------------------

public class Car {
    private Oil oil;

    public Oil getOil() {
        return oil;
    }

    public Car(Oil oil) {
        this.oil = oil;
    }

    public int **getRemainingOil(**){
        return oil.getValue();
    }
}

//------------------------------------------------------------------------------

public class Oil {
    private final int value;

    public Oil(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

디미터 법칙의 이점과 단점

이점

그렇다면 디미터 법칙을 사용하는 이점은 무엇일까?

  1. 클래스간 의존성(객체간 의존성)을 낮출 수 있다.
  2. 객체의 목적이 명확히지기 때문에, 재사용성이 높아진다.
  3. 후에 소스 코드를 변경하기 더 쉬워진다.

단점

  1. wrapper 메소드를 더 작성해야 하기 때문에, 코드를 작성하는데 더 많은 비용이 들어간다.
    → 사실 재사용성을 우선으로 생각한다면, 코드 작성하는 것은 큰 단점이 아니라고 생각한다.
  2. 공간 복잡도 / 시간 복잡도가 증가
    → 하드웨어가 발전 했기 때문에, 이런 하드웨어적인 문제보다 소프트웨어적인 이점(유지 보수의 이점)을 취할 수 있기 때문에 큰 단점은 아니라고 생각된다.

0개의 댓글