캡슐화의 정의와  C++에서의 응용

캡슐화란 객체가 가지고 있는 내부의 속성을 외부에서 제어하지 못하도록 하는 것을 의미한다.

완벽한 캡슐화라면 내부의 속성값을 직접적으로 바꾸는 행위는 적절하지 않겠지만, 우리는 보통 Setter를 이용하여 속성을 변경하고 Getter를 이요하여 값을 가져오는 것으로 캡슐화를 유지한다.

문제는 Setter는 만들지 않고 Getter만 생성하고 값을 이용하려고 할때 발생한다. Getter는 값을 가져오는 것이라 캡슐화를 깨지 않아야 하지만 속성 객체를 레퍼런스로 넘겨 받게 되면 Getter이자 Setter가 되어 버린다.

Getter가 가진 이런 문제를 해결하기 위해 C++에서는 반환 시 const 형의 레퍼런스를 반환하여 사용자가 수정할 수 없도록 처리 했다

 

class Group

{

public:

//- 빌트인 타입( int, double ......)

int GetID() { return m_nID; }

void SetID(int nID) { m_nID = nID; }

 

//- 객체 타입

const Item& GetItem() { return m_item; }

protected:

int m_nID;

Item m_item;

};

 

위와 같은 심플 객체 외에 List 와 같은 자료구조가 속성인 경우 Getter/Setter를 만드는 것은 대단히 위험한 일 중의 하나였기때문에 필자같은 경우 만든 사례가 없었으며 그런 자료구조를 통채로 넘겨 받아야 하는 구조라면 구조가 잘못된 것이니 고쳐야지 코딩의 기법으로 해결할 문제는 아니라고 생각한다. 자료구조에 접근하는 것은 자료구조를 가지고 있는 클래스에게 요청하여 하나씩 가져오도록 구혔했다.

 

  • C#에서의 캡슐화 적용 방법에 대한 고민 1 - 단순 객체

c#을 공부하면서 이놈 한테는 const가 없고, 모든 클래스는 레퍼런스로 반환되어 Getter를 만드는 것이 상당히 조심스러웠다. 어설프게 Getter를 만들면 넘겨받은 객체가 뭔짓을 해도 막을 방법이 없게 되고, 자신의 속성임에도 불구하고 제어권이 넘어가 버린다. 따라서 개발을 진행하면서 가급적 Setter/Getter를 만들지 않고 꼭 필요한 경우 Getter는 Clone 객체를 생성해서 반환하는 식으로 구현하였다.

 

public class Test2

{

protected Item _slectedItem;

 

public Item SelectedItem

{

get { return _selectedItem.Clone(); } 

//set { _selectedItem = value; }

}

 

}

 

  • C#에서의 캡슐화 적용 방법에 대한 고민 2 - MVVM 을 위한 콜렉션 객체 반환

C#을 이용한 WPF 프로그래밍 시 MVVM 을 이용하여 UI와 모델을 분리하고 Binding 하는 것은 가장 중요한 개발 패러다임의 하나이다. 필자는 이 매커니즘이야 말로 WPF 의 핵심 개발 아키텍처라고 생각한다. 하지만 이때문에 C++과는 다르게 내부의 콜렉션을 넘겨줄 필요성이 있었다.

콜렉션 객체를 클론하여 넘겨주는 것은 부담이 컸고, 그대로 넘겨 버리면 넘겨 받은 쪽에서 마음대로 객체를 추가해도 막을 수 없게 된다. 콜렉션이 가지고 있는 요소들의 변형은 어찌 되었던 간에 최소한 콜렉션 자체가 가지고 있는 추가 삭제 기능만은 막아야 한다고 생각 했다. 한동안 고민을 지속 하다가 콜렉션을 반환할 때 껍데기인 콜렉션을 배열로 변경해 버리는 방식으로 처리했다.

 

public class Test2

{

protected List<Item> _items = new List<Item>();

 

//- 이렇게 넘겨주면 넘겨받은 쪽에서 Items를 통해 마음껏 객체를 추가할 수 있게 된다.

public List<Item> Items1

{

get { return _items; } 

}

 

//- 이렇게 넘겨주면 넘겨받은쪽에서 루프를 이용해서 사용할 수 있지만 객체를 추가할 수 없게된다.

public Item[] Items2

{

get { return _items.ToArray(); }


}

 

}

 

  • 남아있는 과제

Items2 와 같은 방식으로 변경하면 객체를 추가 삭제 할 수는 없지만 MVVM에 필수적인으로 활용되는 ItemsSource 로 binding 할 수 있게된다. 아직은 완전히 해결된 것은 아니다 콜렉션이 가지고 있는 Item의 변형을 막을 방법은 없기 때문이다. 자 캡슐화를 이정도까지 하면 될까? 대부분의 경우 이정도면 충분하겠지만 item의 변경까지 막을 방법을 생각해 봐야겠다.

물론 보다 디자인적인 접근으로 Setter의 작성은 언제나 최소화해야 할 것이다. 완벽한 설계는 더이상 넣을 것이 없을때가 아니라 뺄것이 없을 때가 아니겠는가.

 

+ Recent posts