본문 바로가기
Open API/API design

멤버 변수 감추기

by 이재만박사 2017. 2. 9.

* 캡슐화

- 어떤 데이터가 필요한 메서드에 데이터를 전달하는지를 설명할 때도 사용


- 잘 설계된 API의 관점에서 본다면 멤버 변수를 public으로 선언하는 일은 절대로 하지 말아야 함

- 만약 데이터 멤버가 API의 논리적 인터페이스 중 일부라면 멤버 변수가 간접적으로 노출되도록

  Getter와 Setter 메서드를 제공



다음은 좋은 방법이 아니다


class Vector3

{

public:

    double x, y, z;

};


그렇기 때문에 아래 방법 사용


class Vector3

{

public:

    double GetX() const;

    double GetY() const;

    double GetZ() const;

    void SetX(double val);

    void SetY(double val);

    void SetZ(double val);


private:

    double x, y, z;

};



- 위보다 아래 방법이 좋은 이유


1. 유효성 체크

- 클래스의 내부의 상태 값들이 항상 유효하고 일관성 있는지를 확인하기 위해서 값들의 유효성 체크

- 예를 들어 RGB 할당 메서드는 0과 255 사이 혹은 0.0과 1.0 사이에 존재하는지 그 값의 유효성 체크


2. 지연된 평가

- 변수의 값을 계산하는 일은 많은 비용을 발생시킬 수 있기 때문에 그 값이 필요할 때까지 값의 연산을 지연 필요

- Getter를 사용해 내부 값에 접근하지만 실제로 값이 필요할 때까지 식의 연산을 지연시켜 비용 줄임


3. 캐싱

- 클래스 최적화 기법은 자주 계산되는 값을 저장한 후 나중에 저장하고 있던 값을 재연산 없이 바로 리턴

- 전체 메모리 양을 확인하려는 요청이 발생할 때마다 메모리 크기를 다시 계산하지 않고 저장해둔 값을 리턴


4. 추가 연산

- 필요하다면 클라이언트가 변수에 접근하려고 할 때마다 추가 연산을 수행할 수 있다

- 사용자가 응용 프로그램의 환경 설정 값을 변경할 때마다 UserPreference라는 객체의 현재 값을 구성 파일에 씀


5. 알림

- 어떤 모듈은 클래스 값이 언제 변경되는지를 알고 싶어 함

- 바를 표현하는 데이터 모델을 구현하고 있다면 사용자 인터페이스 코드는 진행 상태 바가 업데이트될 때마다 GUI로 표현하기 위해서 그 발생 시점을 알아야 하는데, 이 때는 Setter 메서드를 사용해서 변경에 대한 알림을 발생


6. 디버깅

- 클라이언트가 변수에 언제 접근했고 언제 값을 변경했는지 추적하기 위해서 디버깅이나 로깅을 추가하거나 어떤 실행 결과 값의 예상치가 맞는지 확인하기 위해서 assert 문을 넣을 수도 있다


7. 동기화 

- 첫 API를 릴리즈한 다음에 API가 스레드에 안전하게 동작할 수 있도록 버전을 업그레이드 해야 할 수도 있다

- 이 경우 해결책은 어떤 변수가 사용될 때마다 뮤텍스 잠금 추가

- 이 방법은 Getter/Setter 메서드로 데이터 변수를 래핑하고 있을 때만 가능


8. 훌륭한 접근 제어

- 멤버 변수를 public으로 선언했다면 클라이언트는 자신이 원하는 대로 값을 읽거나 저장

- 하지만 Getter/Setter 메서드를 사용한 경우라면 더 좋은 읽기/쓰기 수준 제공

- 예를 들어 읽기 전용으로 만들기 위해 Setter 메서드를 제공하지 않는 경우


9. 바뀌지 않는 관계 유지

- 내부적으로 사용되는 일부 데이터 값은 서로 의존하기도 함

- 예를 들어, 자동차 애니메이션 시스템에서 프레임을 이동하기 위해 속도와 가속도 계산

- 이 때 속도는 사긴이 지나면서 바뀌는 위치 계산, 가속도는 속도에 따라 값을 계산

- 그러나 클라이언트가 이 같은 계산에 연관된 내부 상태 값을 접근할 수 있어서 자동차 속도와 관계 없이 가속도만 변경시킨다면 예상치 못한 결과 나옴



* 멤버 변수를 protected 선언하는 경우

- 서브 클래스를 구현하는 클라이언트는 직접 그 멤버 변수에 접근할 수 있고 이는 public으로 선언한 경우와 정확히 같은 효과를 만든다

- 그렇기 때문에 멤버 변수를 protected로 선언해서도 안된다

- 객체 지향 프로그래밍 언어에서 상속은 캡슐화의 장점을 얻기 위해 그만큼의 타협을 요구


* 클래스의 데이터 멤버는 항상 public이나 protected가 아닌 private으로 선언











댓글