객체가 자기 데이터를 스스로 관리하고, 밖에서는 그 속을 모르게 하는 것. 객체지향의 네 가지 특성 가운데 나머지 셋이 기대는 바탕이다.
완성도와 낮아진 의존성
캡슐화가 하는 일은 두 층으로 나뉜다. 하나는 완성도다. 객체가 어떤 책임을 맡았다면 그 일에 필요한 데이터와 동작이 그 객체 안에 다 있어야 한다. 밖에서 데이터를 꺼내다 계산해 다시 넣는다면 그 객체는 데이터 보관함일 뿐 책임을 진 것이 아니다. 관련된 것을 잘 모아 갖고 있을수록 응집도가 높다고 말하는 것도 같은 이야기다.
다른 하나가 정보 은닉이다. 접근 제어자로 밖에서 내부에 손대지 못하게 막는다. 캡슐화를 제대로 하면 정보 은닉은 자연스럽게 따라온다.
얻는 것은 낮아진 의존성이다. 밖에서 내부를 모르면 내부를 바꿔도 밖이 깨지지 않는다. 디자인 패턴의 첫 번째 원칙이 달라지는 부분을 찾아 감싸라고 말하는 것과 캡슐화는 같은 이야기다.
필드를 감추고 메서드로 받기
중요한 필드는 감추고, 그 필드는 메서드를 통해서만 건드리게 한다. 값을 그냥 대입하게 두면 검사할 자리가 없다.
Mydate date = new Mydate();
date.month = 2;
date.day = 31; // 2월 31일이 그대로 들어간다필드를 private으로 막고 메서드로 받으면 그 안에 조건문을 넣어 2월에 31일이 들어오는 것을 걸러낼 수 있다. 값을 대입하는 통로가 하나로 좁혀지기 때문에 가능한 일이다.
메서드에 어떤 이름을 붙이느냐도 같은 문제다. setPassword() 대신 updatePassword()처럼 무엇을 하는 변경인지 이름이 말해주면, 그 객체가 허용하는 변경의 종류가 정해진다.
getter와 setter만 늘어놓은 코드
필드를 private으로 막고 getter와 setter를 전부 만들어두는 코드가 흔한데, 그것은 이름만 캡슐화다. 아무 데서나 아무 값이나 바꿀 수 있으니 public 필드와 다를 것이 없다.
이런 코드가 나오는 원인이 데이터 주도 설계다. 객체가 무엇을 할지보다 무엇을 가질지를 먼저 정하면, 그 데이터를 어디서 쓸지 모르니 전부 열어두게 된다.