✏️6.6 변수 캡슐화하기 (Encapsulate Variable)
let defaultOwner = {firstName = "마틴", lastName = "파울러"};리팩터링 후
let defaultOwnerData = {firstName = "마틴", lastName = "파울러"};
export function defaultOwner() {return defaultOwnerData;}
export function setDefaultOwner(arg) {defaultOwnerData = arg;}🧷 배경
데이터는 함수보다 다루기 까다롭다. 데이터는 참조하는 모든 부분을 한 번에 바꿔야 코드가 제대로 작동한다. 유효범위가 넓어질 수록 다루기 어려워진다. 접근할 수 있는 범위가 넓은 데이터를 옮길 때는 먼저 그 데이터로의 접근을 독점하는 함수를 만드는 식으로 캡슐화하는 것이 가장 좋은 방법이다.
유효범위가 함수 하나보다 넓은 가변 데이터는 이런식으로 캡슐화해서 그 함수를 통해서만 접근하게 만든다. 데이터의 유효범위가 넓을 수록 캡슐화해야한다. 자주 사용하는 데이터에 대한 결합도가 높아지는 것을 막을 수 있다.
객체지향에서 객체의 데이터를 항상 private으로 유지해야한다. public 필드를 캡슐화해서 가시 범위를 제한한다.
불변데이터는 가변 데이터보다 캡슐화할 이유가 적다. (데이터가 변경될 일이 없다.)
🧷 절차
- 변수로의 접근과 갱신을 전담하는 캡슐화 함수들을 만든다. 
- 정적 검사를 수행한다. 
- 변수를 직접 참조하던 부분을 모두 적절한 캡슐화 함수 호출로 바꾼다. 하나씩 바꿀 때마다 테스트한다. 
- 변수의 접근 범위를 제한한다. 
- 테스트한다. 
- 변수 값이 레코드라면 레코드 캡슐화하기를 적용할지 고려해본다. 
🧷 예시
- 전역 변수에 중요한 데이터가 담겨 있는 경우 
let defaultOwner = {firstName = "마틴", lastName = "파울러"};- 참조하는 코드 
spaceship.owner = defaultOwner;- 갱신하는 코드 
defaultOwner = {firstName = "레베카", lastName = "파슨스"};- 기본적인 캡슐화를 위해 가장 먼저 데이터를 읽고 쓰는 함수부터 정의한다. 
function getDefaultOwner() {return defaultOwner;}
funtion setOwner(arg) {defaultOwner = arg;}- defaultOwner를 참조하는 코드를 찾아서 방금 만든 게터 함수를 호출하도록 고친다. 대입문은 세터 함수로 바꾼다 
spaceship.owner = getDefaultOwer();setDefaultOwner({firstName = "레베카", lastName = "파슨스"});- 변수의 가시 범위를 제한한다. 나중에 수정하는 코드에서도 이 변수에 직접 접근하지 못하게 만들 수 있다. (저자는 게터 이름 앞에 get을 싫어한다고 한다. 
// defaultOwner.js
let defaultOwnerData = {firstName = "마틴", lastName = "파울러"};
export function defaultOwner() {return defaultOwnerData;}
export funtion setDefaultOwner(arg) {defaultOwnerData = arg;}🧷 값 캡슐화하기
변수 캡슐화가 정확히 이해되면 값 캡슐화 리팩터링 기법에 대해 정리하겠다.
캡슐화하기 기법으로 데이터 구조로의 참조를 캡슐화하면, 구조로의 접근이나 구조 자체를 다시 대입하는 행위를 제어할 수 있다. 하지만 필드 값을 변경하는 일은 제어할 수 없다.
const owner1 = defaultOwner();
assert.equel("파울러", owner1.lastName, "처음 값 확인");
const owner2 = defaultOwner();
owner2.lastName = "파슨스";
assert.equal("파슨스", owner1.lastName, "owner2를 변경한 후"); // 성공할까?기본 캡슐화 기법은 데이터 항목을 참조하는 부분만 캡슐화한다. 변수뿐 아니라 변수에 담긴 내용을 변경하는 행위까지 제어할 수 있게 캡슐화하고 싶을 때는 어떻게 하면 좋을까?
저자는 주로 게터가 데이터의 복제본을 반환하도록 수정하는 식으로 처리한다.
// defaultOwner.js
let defaultOwnerData = {firstName = "마틴", lastName = "파울러"};
export function defaultOwner() {return defaultOwnerData;}
export funtion setDefaultOwner(arg) {defaultOwnerData = arg;}Last updated