ITEM 20 : 변경불가능한 아토믹 값타입을 선호해라

|

ITEM 20 :  Prefer Immutable Atomic Value Type

           (변경불가능한 아토믹 값타입을 선호해라)



■ 요약 및 장점


+ 다른 곳에서 해당 type의 내부의 상태를 변경하기 못하게 하려면 immutable한 type을 선언해줘야 한다.

  그것이 보장되지 않으면 내부의 상태를 변경하지 못하게 검사하는 비용이 많이 들어가게 된다.

  여기에서는 초기에 생성된 후에는 변경되지 않게 보장하는 방법에 대해서 설명한다.


1. Immutable type은 생성된후에 변경하지 못하는 타입이다. 즉 상수(constant)이다.


2. Immutable type은 hash-based collection에서 더 잘 동작한다.


3. atomic type은 하나의 엔터티로 구성되어진 것을 말한다. 즉 더 쪼갤수 없는 단위를 말한다.


4. 아래의 예제는 변경을 하게 되면 유효하지 않는 데이터가 일시적으로 유지된다. 
  별 문제 없어 보이지만 만약에 멀티쓰레드 환경에서는 문제가 될수 있다. 
  즉, 한쪽에서 바꾸는 중간에 다른쪽에서 읽어 갈수 있기 때문이다.

// Mutable Address structure.
public struct Address
{
        private string state;
        private int zipCode;

        // Rely on the default system-generated
        // constructor.
        public string Line1
        {
            get;
            set;
        }

        public string Line2
        {
            get;
            set;
        }

        public string City
        {
        get;
        set;
        }

        public string State
        {
            get { return state; }
            set
            {
                ValidateState(value);
                state = value;
            }
        }
        public int ZipCode
        {
            get { return zipCode; }
            set
            {
                ValidateZip(value);
                zipCode = value;
            }
        }

    // other details omitted.
}

// Example usage:
Address a1 = new Address();
a1.Line1 = "111 S. Main";
a1.City = "Anytown";
a1.State = "IL";
a1.ZipCode = 61111;
// Modify:
a1.City = "Ann Arbor"; // Zip, State invalid now.
a1.ZipCode = 48103; // State still invalid now.
a1.State = "MI"; // Now fine.

5. 아래의 예제는
 immutable한 구조체를 선언한것이다. 위는 변경이 불가능하지만 엄격하게보면 내부적으로는
setter가 있기때문에 변경이 가능하긴하다. 다만 외부에서는 변경이 불가능하다.

 public struct Address2
    {
        // remaining details elided
        public string Line1
        {
            get;
            private set;
        }
        public string Line2
        {
            get;
            private set;
        }
        public string City
        {
            get;

            private set;
        }
        public string State
        {
            get;
            private set;
        }
        public int ZipCode
        {
            get;
            private set;
        }
    }

6. 완벽하게 immutable하게 하려면 implicit properties를 explicit properties로 변경하고 backing field(해당 프로퍼티에 
  해당하는 멤버변수)를 readonly로 한정해줘야한다.

public string Line1
 {
    get { return Line1; }
 }

 private readonly string line1;

7. immutable type을 선언할때 주의할점이 있다. 프로퍼티가 외부의 참조타입을 참조하면 외부에서 수정될 가능성이 존재한다.

public struct PhoneList
    {
        private readonly Phone[] phones;
        public PhoneList(Phone[] ph)
        {
            phones = ph;
        }
        public IEnumerable<Phone> Phones
        {
            get
            {
                return phones;
            }
        }
    }

    Phone[] phones = new Phone[10];
    // initialize phones
    PhoneList pl = new PhoneList(phones);
    // Modify the phone list:
    // also modifies the internals of the (supposedly)
    // immutable object.
    phones[5] = Phone.GeneratePhoneNumber();

8.이때는 생성자에서 해당 참조값에 대해서 복사본은 생성한 다음에 초기화 한다.

 public PhoneList2(Phone[] ph)
   {
     phones = new Phone[ph.Length];
     // Copies values because Phone is a value type.
     ph.CopyTo(phones, 0);
   }

■ Terms



■ 단어


Immutable:불변의,변경할 수 없는

validate:입증하다,인증하다,승인하다.

export:내보내다,수출하다.

invariant:변함없는,불변의

harmless:무해한.

fragment:조각,파편

specify:명시하다.

interim:중간의, 잠정적인

strictly:엄격하게

pitfall:함정,위험




And