7-1. 레코드 캡슐화하기

적용 시점

  • 해시맵을 사용해야 하는 곳이 많은 가변 데이터를 저장할 때

  • 계산해서 얻는 값과 그렇지 않은 값을 명확히 구분해 저쟁해야 할 때

절차

  1. 레코드를 담은 변수를 캡슐화

  2. 레코드를 감싼 단순한 클래스로 해당 변수의 내용을 교체. 이 클래스에 원본 레코드를 반환하는 접근자도 정의하고, 변수를 캡슐화하는 함수들이 이 접근자를 사용하도록 수정

  3. 테스트

  4. 원본 레코드 대신 새로 정의한 클래스 타입의 객체를 반환하는 함수들을 제작

  5. 레코드를 반환하는 예전 함수를 사용하는 코드를 4에서 만든 새 함수를 사용하도록 바꿈. 필드에 접근할 때는 객체의 접근자를 사용. 적절한 접근자가 없다면 추가함. 한 부분을 바꿀 때마다 테스트 함.

  6. 클래스에서 원본 데이터를 반환하는 접근자와 원본 레코드를 반환하는 함수들을 제거

  7. 테스트 함

  8. 레코드의 필드도 데이터 구조인 중첩 구조라면 레코드 캡슐화하기와 컬렉션 캡슐화하기를 재귀적으로 적용

예시

❌Before

const obj = {
	peanut: {
		age: 26,
		department: '개발',
		food: '국밥',
		grades: {
			2020: {
				1: {
					computerSicence: 'C'
				}
			}
		}
	},
	Walnut: {
		age: 25,
		department: '디자인',
		food: '피자',
		grades: {
			2020: {
				1: {
					computerSicence: 'C'
				}
			}
		}
	}
}

// 데이터 쓰는 경우
obj[nickname].grades[2020][1] = 'D';

// 데이터 읽는 경우
const gradeToPoint = (nickname, year, month) => {
	const grade = obj[nickname].grades[year][month].computerScience;
	if(grade === 'A') {
		return 100;
	} ...
}

⭕After

class UserData {
	cosntructor(data) {
		this._data = data
	}
	setGrade({ customerId, year, month, grade }) {
		this._data[customerId].grades[year][month].computerScience = grade;
	}
	getGradeToPoint({ customerId, year, month }) {
		const grade = this._data[customerId].grades[year][month].computerScience;
		if(grade === 'A') {
			return 100;
		}	...
	}
}

const obj = new UserData({
	peanut: {
		age: 26,
		department: '개발',
		food: '국밥',
		grades: {
			2020: {
				1: {
					computerSicence: 'C'
				}
			}
		}
	},
	Walnut: {
		age: 25,
		department: '디자인',
		food: '피자',
		grades: {
			2020: {
				1: {
					computerSicence: 'C'
				}
			}
		}
	}
})

// 데이터 쓰는 경우
obj.setGrade({ customerId, year, month, grade });

// 데이터 읽는 경우
obj.getGradeToPoint({ customerId, year, month });

Last updated