본문 바로가기

OOP

[OOP] 디미터의 법칙

728x90

개요

최근 계속해서 객체 지향에 대한 공부를 하던 중 디미터의 법칙을 접하게 되었다.

객체 지향의 핵심을 꿰고 있는 개념이라고 생각이 되어 이에 대한 내 생각을 기록으로 남기려고 한다.

 

디미터의 법칙과 관련하여 객체 지향 세계와 현실 세계의 비교와 이 비교를 코드를 통해 이해해 볼 것이다.

디미터의 법칙

객체 지향을 공부하다 보면 반드시 마주하게 되는 법칙이다.

  • Don`t Talk to Stranger
  • Principle of least knowledge

위 문장들로도 알려져 있다.

전달하고자 하는 것은 '캡슐화를 통해 객체의 자율성과 응집도를 높이자'이다.

객체 지향의 세계는 현실 세계의 많은 것들을 반영한다.
정확히 말하면, 객체 지향의 복잡한 세상을 이해하기 위해 현실 세계를 반영해 은유를 활용한다.

객체 지향과 현실 세계의 가장 큰 차이점은
객체 지향의 세계에 모든 객체는 자율성을 가진다는 것이다.

현실 세계의 사물들은 수동적이다. 
음식을 먹는다던가, 물을 마신다던가 우리는 사물의 상태를 직접 바꾼다.

하지만 객체 지향의 세계에서는 음식도 물도 자율성을 가진다.
우리는 음식과 물에게 일부를 달라는 요청을 보낼 것이고, 
음식과 물은 본인의 양(상태)을 줄이고 그만큼을 우리에게 응답으로 반환해 줄 것이다.

객체 지향의 세계에 현실 세계를 반영했을 때 보다 직관적으로 이해할 수 있다는 장점이 있지만,
가끔 객체의 자율성을 무시하고 상태를 직접 변경하는 등 자율성을 침해하는 실수를 저지르기도 한다.

디미터의 법칙은 우리가 무시했던 객체의 자율성을 지키라고 말한다.

위 예시를 코드를 통해 보자.

현실 세계

먼저 Water라는 클래스가 있다.

public class Water {  
  
    private int amount = 10;  
  
    public void setAmount(final int vol) {  
        this.amount = vol;  
    }  
  
    public int getAmount() {  
        return amount;  
    }  
}

그리고 이 물을 멤버 변수로 가지는 House라는 클래스가 있다.

public class House {  
  
    private final Water water;  
  
    public House() {  
        this.water = new Water();  
    }  
  
    public void drinkWater() {  
        water.setAmount(water.getAmount()-1);
	int remainAmount = water.getAmount();
	System.out.println(remainAmount);  
    }  
}

House에서는 멤버 변수인 Water를 마실 수 있다.
그리고 마시고 남은 물의 양을 출력하고 싶다고 해보자.

하지만 위 코드는 객체 지향의 세계가 아닌 현실 세계에서의 Water일 때 코드이다.
위에서 말했듯 모든 객체는 자율성을 가진다. 하지만 코드에서 Water 객체는 수동적으로 상태가 변경되고 있다.

그럼 water를 어떻게 자율성을 가지도록 바꿀 수 있을까?

객체 지향의  세계

public class Water {  
  
    private static final int ONCE_DRINK_AMOUNT = 1;  
  
    private int amount = 10;  
  
    public int drink() {  
        amount -= ONCE_DRINK_AMOUNT;  
        return amount;  
    }  
}

위 Water 객체는 drink라는 행동을 자율적으로 수행할 수 있다.

수동적으로 외부에 의해 상태가 변경되는 것이 아닌,
House 객체에서 필요로 하는 drink라는 협력을 통한 부수 효과로 본인의 상태를 변경시키고 있다.

House 객체와 water 객체의 협력 관계는 어떻게 변할까?

public class House {  
  
    private final Water water;  
  
    public House() {  
        this.water = new Water();  
    }  
  
    public void drinkWater() {  
        int remainAmount = water.drink();  
        System.out.println(remainAmount);  
    }  
}

House 객체는 water에게 물을 한 번 마시고, 남은 물의 양을 알려달라고 요청을 보낸다.
Water 객체는 위 행동을 내부에서 처리하고 House가 원하는 물의 양을 응답으로 반환한다.

여기서 중요한 것은 Water를 자율적인 객체로 봤다는 것이다. 
Water 객체의 남은 물의 양을 직접 바꾸는 것이 아닌 Water에게 drink라는 행동을 요청했고, 그 응답으로 남은 물의 양을 반환받았다.

이렇게 객체끼리의 협력 관계는 "무엇을"해주는가에만 초점을 둬야 한다.
"어떻게" 그 일을 처리하는가는 그 객체가 결정할 일이다.

객체들은 본인의 상태를 외부로 노출시키고, 수동적으로 변경되는 것이 아닌
자율성을 가지고 행동을 요청받아 내부적으로 그 요청을 처리하며, 요청에 대한 응답을 해주면 된다.

마무리

객체 지향을 공부하는 중이기 때문에 틀린 내용이 있을 수 있습니다.

잘못된 정보에 대한 지적과 피드백은 환영입니다:)

 

감사합니다.

참고

 

[OOP] 디미터의 법칙(Law of Demeter)

1. 디미터의 법칙(Law of Demeter) [ 디미터의 법칙(Law of Demeter) 이란? ] 디미터의 법칙은 “Object-Oriented Programming: An Objective Sense of Style” 에서 처음으로 소개되었다. Demeter라는 프로젝트를 진행하던 개

mangkyu.tistory.com

 

객체지향의 사실과 오해 - 예스24

『객체지향의 사실과 오해』는 객체지향이란 무엇인가라는 원론적면서도 다소 위험한 질문에 답하기 위해 쓰여진 책이다. 안타깝게도 많은 사람들이 객체지향의 본질을 오해하고 있다. 가장

www.yes24.com

 

728x90

'OOP' 카테고리의 다른 글

[OOP] SOLID원칙 정리  (0) 2024.03.20