[F-Lab 모각코 챌린지] 21일차 - 아무런 기능이 없는 장식품

F-lab 모각코 챌린지 21일차 학습 내용입니다 책을 정리하려 했으나, 정리 할 내용을 찾지 못하여 이전에 객체지향 토론에서 얻은 인사이트를 정리 하였습니다.

[F-Lab 모각코 챌린지] 21일차 - 아무런 기능이 없는 장식품

장식품은 객체인가?

💡
객체는 역할, 책임, 협력으로 이루어진 집합이다

객체는 결국 세포로 부터 시작되어 유기적인 협력 끝에 하나의 객체로 만들어진다

여러 객체가 모여 하나의 군집을 이루고 아무리 복잡한 비즈니스도 말끔히 해결한다

하지만 그 과정에서 여러 논리적 궁금증이 생긴다

💡
아무런 기능도 없는 그저 조그마한 장식품 하나를 객체라고 부를 수 있을까?

이 질문에 대해 공부한 내용들을 토대로 정리해본다

정말로 기능이 없을까?

어떤 객체건 추상화를 통해 우리 프로그램으로 들어왔을 때에는 어떠한 목적성을 가져야 한다.

장식품이 아무런 기능도 하지 않는 비즈니스가 있는가 하면, 장식품이 주된 비즈니스가 되는 문맥(Context) 도 있다

예를 들어 장식품 판매점을 운영한다고 가정해보자

장식품은 아래와 같이 선언 될 수 있을 것이다

public class Ornament {
  private String name;
  private Money amount;
  private Location location;
  private Percentage demageRate;
  private Percentage discountRate;
}  

눈썰미가 좋은 개발자는 보기만 해도 '이 객체는 팔릴 수 있겠구나' 라고 생각 할 것이다

가격, 손상도, 할인율 이라는 단어만 보아도 충분히 유추 할 수 있을 것이다

그럼 이 객체는 행동을 가지지 않는가?

아니다. 이 장식품은 판매될 수 있다. 그렇기에 상품의 가격을 가져오는 메시지가 필요하다. 모든 가게의 주인들이 상품들의 모든 가격을 알고 있는 것은 아니기 때문이다.

이처럼 객체를 어떤 시각에서 바라보느냐에 따라 행위가 없더라도 비즈니스적인 행위를 가질 수 있다.

정말 아무런 기능이 없는 객체

그럼 위에서 말했던 '정말로 아무런 기능이 없는 장식품' 인 경우를 예제로 보자

public class Ornament { }

이 장식품은 가격도 필요 없고 이름도 필요없다.

아무 곳에서도 사용되지 않으며 작성자가 누구인지 궁금하게 만드는 코드이다

그럼 이 객체는 객체라 부를 수 있는가?

먼저번 글에서 '객체는 역할과 책임, 협력을 가져야 한다' 고 이야기 하였다

이러한 관점에서 바라본다면 Ornament 클래스는 객체가 될 수 없다.

조건으로 사용되는 객체

만일 '특정 장식품을 조건으로 사용' 한다면 어떻게 될까

public enum Ornament {
  OLD, NEW
}

이렇게 한다면 Ornament 는 특정한 목적성을 가지고 있는 대상이 된다.

값을 가질수도 있고 그 값은 조건에 따라 사용될 수도 있다

하지만 정말 오래되었는지, 오래되지 않았는지를 판단하기 위해서 이 클래스를 사용하는 것이라면, 이것은 정말 '장식품' 이 맞는가?

아래의 코드가 더 적합하지 않을까?

public enum VintageLevel {
  OLD, NEW, FUTURE
}

이렇게 되면 장식품은 더 이상 '장식품' 이 아니게 된다.
즉, 이 비즈니스에서는 '장식품' 이 필요하지 않다

값으로 사용되는 객체

그럼 예시를 바꿔서 '타입으로 사용되는 객체' 의 경우를 생각해보자

'전화번호' 라는 값이 있다.

public class PhoneNumber {
  private Contry contry;
  private String value;
  
  public PhoneNumber(String contryCode, String number) {
    this.contry = new Contry(contryCode);
    this.value = number;
  }
  
  public Contry getContry() {
    return this.contry;
  }
  
  public String getValue() {
    return this.value;
  }
}
  

이 전화번호는 오로지 값으로서만 사용 되며 특정한 정보만을 가지고 있다.
편의를 목적으로 입력 받은 contryCode 를 Contry 로 변환하는 로직이 포함되어 있고 외부에서는 해당 값을 얼마든지 빼서 사용할 수 있다.

실제로 스스로의 협력을 위한 외부 인터페이스는 적으며 외부에서도 이를 '값' 으로 취급하고 사용한다.

이럴 경우, 이는 객체라고 부를 수 있을까

물론 객체라고 부를 수 있다. 하지만 이 객체는 immutable 한 객체로 사용되는 이른바 '값 객체(VO:Value Object)' 라고 불리게 된다.

값 객체

값 객체는 변할 수 없는 객체이다

우리는 이 개념을 잘 알고 있는데, String 이 바로 값 객체이며 우리가 아주 자주 사용하는 객체이기 때문이다

아래의 코드를 보자

String value = "hello, pollra!";
value = "hello, java!";

System.out.println(value); // print:hello, java!

String value2 = "hi, pollra!";
"hi, java!" = "holla, java!";
System.out.println(value2) // print: ????????

value2 는 어떤 값을 리턴할까?

아니, 리턴 할 수가 있을까?

정답은 리턴 할 수 없다. 그 윗 줄에서 컴파일 에러가 발생하기 때문이다.

이처럼 '값' 은 변할 수 없는 대상을 말한다

만일 우리가 새로운 값이 필요하다면 2번째 줄의 value = "hello, java!"; 처럼 재 할당을 통해 값을 변경해야 한다.

그럼 아래의 부분에서 이상한 점은 무엇일까?

public class PhoneNumber {
  private Contry contry;
  private String value;
  
  public PhoneNumber(String contryCode, String number) {
    this.contry = new Contry(contryCode);
    this.value = number;
  }
  
  public Contry getContry() {
    return this.contry;
  }
  
  public String getValue() {
    return this.value;
  }
  
  public void setValue(String newValue) {
    this.value = newValue;
  }
}
  

정답은 setValue 이다.

이전 String 예제에서 보았듯, 값은 변경될 수 없고 변경되어서는 안된다.

그런데 setValue 라는 함수를 외부로 노출시켰고, 이로서 '어디서든 변경될 수 있는 값' 이 되었다. 더 이상 값객체가 아니게 되었다.