26.레코드를 데이터 클래스로 전환 Replace Record with Data Class

#1

타입코드를 클래스로 리팩토링하는 주된 이유는 코드의 안정성을 보장하려는 것이다.
그러기 위한 한가지 방법은 대입이나 동일성 검사에 사용될 수있는 값을 제한 하는것이다.

장점 : 부적절한 값의 대입이나 유효하지 않는 동일성 검사로부터 코드를 보호한다.
단점 : 타입 안정성이 결여된 경우보다 더 많은 코드가 필요하다.

타입 안정성이 없는 상수라는 용어는 int 등의 기본 타입 또는 string으로 정의된 상수를 말한다.

#2
클래스의 동작 영향을 미치지 않는 숫자로 된 타입 코드(numberic type code)가 있으면 숫자를 클래스로 바꿔라.

숫자를 파라미터로 받는 임의의 메소드가 있다고 가정하면 이는 코드의 가독성을 떨어뜨리고 버그의 위험성도 지니고 있다.
만약 숫자를 클래스로 대체한다면 컴파일러는 클래스에 대해서 타입을 검사하게 된다.
이 클래스에 factory 메소드를 제공함으로써 유효한 instance가 생성되는지 객체가 전달되었는지를 정적으로 확인할 수 있다.

Before
// Person 객체에 정적 변수에 값이 할당되어 있다. ( readonly = 상수 ) 
class Person
{
   public static readonly int O = 0;
   public static readonly int A = 1;
   public static readonly int B = 2;
   public static readonly int AB = 3;

   private int BloodGroup { get; private set; }

  public Person(int bloodGroup)
  {
      _bloodGroup = bloodGroup;
  }
}
After
class Person
{
   public BloodGroup BloodGroup { get; private set; }

   public Person(BloodGroup bloodGroupCode)
  {
   BloodGroup = BloodGroup;
   }
}

// 객체로 
class BloodGroup
{
  public static readonly BloodGroup O = new BloodGroup(0);
  public static readonly BloodGroup A = new BloodGroup(1);
  public static readonly BloodGroup B = new BloodGroup(2);
  public static readonly BloodGroup AB = new BloodGroup(3);

  private static BloodGroup[] groups = new BloodGroup[] { O, A, B, AB };
  private int Code { get; set; }

  private BloodGroup(int code)
  {
      Code = code;
  }

  public override bool Equals(object obj)
  {
      return Code == ((BloodGroup)obj).Code;
  }

  // 두 객체가 같다면(Equals(...) == true) GetHashCode()  대해 동일한 값을 반환해야 함.
  public override int GetHashCode()
  {
      return Code.GetHashCode();
  }
}