본능적으로 모호함을 피하려하는 프로그래머들 사이에서도 캡슐화(encapsulation)라는 용어의 의미는 명확하지 않다. 가장 많이 사용되는 몇 가지 정의는 다음과 같다.

  • 정보 숨김(information hiding)과 동의어
  • 구현 숨김(implementation hiding)과 동의어
  • 데이터 숨김(data hiding)과 동의어
  • 응집을 통한 새로운 정체성 형성

정보 숨김의 정의는 논란의 여지가 없다. 70년대 초 David Parnas는 어려운 설계 결정과 변경될 가능성이 높은 설계 결정을 파악하는 것으로 모듈화를 시작하라 제안했고 이런 결정들이 다른 모듈로부터 숨겨지는 것을 정보 숨김이라 표현했다.

 

구현 숨김은 자주 사용되진 않지만 정보 숨김과 동일한 뜻을 가진다.

반면 데이터 숨김은 주로 두 가지 의미로 사용된다. 하나는 정보 숨김과 같은 의미이다. 다른 하나는 개체지향 프로그래밍에서 개체의 상태를 공개 노출하지 않고 접근자(속성)를 통하도록 접근 경로를 제한하는 것이다. 이것은 데이터와 입력값 검증 및 후처리 코드를 응집시키는 효과와 이런 구현을 숨기는 효과를 가진다. 따라서 후자의 의미로 데이터 숨김이 사용된다면 정보 숨김 그 자체가 아닌 일부 사례라고 볼 수 있다.

하지만 마지막 정의는 정보 숨김에 의존하지 않는다. 연관된 개별 코드가 모여 보다 높은 수준의 정체성을 만드는 것으로 캡슐화를 해석한다. 특히 개체지향 프로그래밍에서는 밀접하게 관련된 상태와 논리를 모아 경계를 형성하는 것을 뜻한다. 정보 숨김은 의도되지 않은 결합(coupling)을 줄이는 것이 목적이지만 이러한 관점의 캡슐화는 응집(cohesion)의 문제다.

다음 클래스를 보자.

public class Vector(double x, double y)
{
    public double X = x;
    public double Y = y;
    public double GetLength() => Sqrt(X * X + Y * Y);
}

double 형식의 X, Y 필드와 GetLength() 메서드가 응집되어 Vector 클래스를 형성했다. 이것은 캡슐화지만 정보 숨김은 적용되지 않았다.

내가 응집 관점의 캡슐화 해석을 선호하는 이유는 Vector 클래스 설계법은 정보를 숨기지 않더라도 이름을 가지기에 충분한 가치가 있기 때문이다. 캡슐화를 정보 숨김과 동의어로 정의하면 이 설계법은 이름을 가지지 못한다.

번외

정보 숨김이 적용된 Vector 클래스는 다음과 같다.

public class Vector(double x, double y)
{
    public double X { get; set; } = x;
    public double Y { get; set; } = y;
    public double Length => Sqrt(X * X + Y + Y);
}

숨겨진 정보는 X, Y, Length 속성의 구현이다. 속성들의 구현 결정이 숨겨졌기 때문에 Length 속성에 캐싱이 적용되더라도 변경에 의한 피해는 발생하지 않는다.

public class Vector(double x, double y)
{
    private double _x;
    private double _y;
    private double? _length;

    public double X
    {
        get { return _x; }
        set { _x = value; InvalidateLength(); }
    }

    public double Y
    {
        get { return _y; }
        set { _y = value; InvalidateLength(); }
    }

    private void InvalidateLength() => _length = null;

    public double Length =>
        _length == null
        ? (_length = Sqrt(X * X + Y + Y)).Value
        : _length.Value;
}