Recent Posts
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 개성국밥
- VARCHAR (1)
- PersistenceContext
- table not found
- 오블완
- JanusGateway
- taint
- 티스토리챌린지
- 코루틴 컨텍스트
- JanusWebRTC
- terminal
- 코루틴 빌더
- 자원부족
- 깡돼후
- JanusWebRTCServer
- k8s #kubernetes #쿠버네티스
- 겨울 부산
- preemption #
- Value too long for column
- 헥사고날아키텍처 #육각형아키텍처 #유스케이스
- pytest
- Spring Batch
- PytestPluginManager
- python
- tolerated
- mp4fpsmod
- JanusWebRTCGateway
- kotlin
- vfr video
- 달인막창
Archives
너와 나의 스토리
[리팩토링] Replace Primitive with Object 기본형을 객체로 바꾸기(데이터 항목 -> 객체) 본문
개발/Refactoring
[리팩토링] Replace Primitive with Object 기본형을 객체로 바꾸기(데이터 항목 -> 객체)
노는게제일좋아! 2021. 10. 26. 00:46반응형
단순한 출력 이상의 기능이 필요해지는 순간 그 데이터를 표현하는 전용 클래스를 정의하라
-> 나중에 특별한 동작이 필요해지면 이 클래스에 추가함으로써 점점 유용해진다.
절차
- 변수 캡슐화
- 단순한 값 클래스(value class) 만들기
- 생성자는 기존 값을 인수로 받아서 저장(setter), 이 값을 반환하는 getter 추가
- 정적 검사
- 값 클래스의 인스턴스를 새로 만들어서 필드에 저장하도록 setter를 수정
- 새로 만든 클래스의 getter를 호출한 결과를 반환하도록 getter 수정
- 테스트
- 함수 이름 바꾸기 리팩터링
예시: 레코드 구조에서 데이터를 읽어 들이는 단순한 주문(Order) 클래스
- Before:
- Order 클래스의 우선순위(priority) 필드를 단순히 string 타입으로 사용
-
class Order { constructor(data){ this.priority = data.priority; } }
- 클라이언트에서는 이를 다음과 같이 사용한다.
-
highPriorityCount = orders.filter( o=> "high" == o.priority || "rush" == o.priority).length;
- Step 1: 캡슐화
- priority 변수 캡슐화
-
class Order { constructor(data) { this.priority = data.priority; } get prirority() {return this._priority;} set priority(aString) {this.priroriy = aString;} }
- Step 2: 단순한 값 클래스(value class) 만들기.
- Priority 값 클래스를 생성
-
class Priority { constructor(value) {this._value = value;} toString() {return this._value;} }
- 이 클래스는 표현할 값을 받는 생성자와 그 값을 문자열로 반환하는 변환 함수로 구성된다.
- 여기서는 getter 대신 toString()을 사용하였다.
- 클라이언트 입장에서 보면 우선순위 속성 자체를 받은 게 아니라 해당 속성을 문자열로 표현한 값을 얻는 것이기 때문이다.
- Step 3: 정적 검사
- Step 4, 5: 값 클래스를 사용하도록 접근자들을 수정
-
class Order { Order(data) { this.priority = data.priority; } get prirority() { return this._priority.toString(); } set priority(aString) { this.priroriy = new Priority(aString); } }
-
- Step 6: 테스트
- Step 7: 함수 이름 바꾸기 리팩터링
- getter를 보면 함수 이름이 부적절하다. 반환하는 값은 우선순위 자체가 아니라 우선순위를 표현하는 문자열이기 때문이다.
- 그러니 "우선순위 문자열"을 반환하는 메서드임을 나타내도록 함수 이름을 변경해주자.
-
get prirorityString() { return this._priority.toString(); }
- getter를 보면 함수 이름이 부적절하다. 반환하는 값은 우선순위 자체가 아니라 우선순위를 표현하는 문자열이기 때문이다.
+ 더 가다듬기
- priority 클래스에 동작을 추가해보자.
- 우선순위 값을 검증하고 비교하는 로직을 추가하였다.
- 우선순위 값은 string 객체이기 때문에 값 비교를 위해 equals() 메서드를 추가하였다.
-
class Priority { constructor(value) { if (value instanceof Priority) return value; if (Priority.legalValues().includes(value)) this._value = value; else throw new Error('<${value} is invalid>') } toString() { return this._value; } get _index() { return Priority.legalValues().findIndex(s => s === this._value); } static legalValues() { return ['low', 'normal', 'high', 'rush']; } equals(other) { return this._index === other._index; } higherThan(other) { return this._index > other._index; } lowerThan(other) { return this._index < other._index; } }
- 이제 클라이언트 코드를 좀 더 의미 있게 작성할 수 있게 되었다.
-
highPriorityCount = orders.filter(o => o.priority.higherThan(new Priority("normal"))) .length;
이해 안 되는 부분:
- Priority 클래스를 Order 클래스에서만 사용하는 게 아니라 다른 곳에서도 유용하게 사용할 수 있도록 생성자를 수정하고 order 클래스에서 priority 객체를 제공하는 게터를 추가로 생성함.
class Order {
// ...
get priority() { return this, _priority; }
get prirorityString() { return this._priority.toString(); }
set priority(aString) { this.priroriy = new Priority(aString); }
}
class Priority {
constructor(value) {
if (value instanceof Priority) return value;
this._value = value;
}
// ...
}
-> ???
출처:
- [리팩터링 2판]
반응형
'개발 > Refactoring' 카테고리의 다른 글
[리팩토링] Substitute Algorithm 알고리즘 교체하기 (0) | 2021.11.08 |
---|---|
[리팩토링] Extract Class 클래스 추출하기 (0) | 2021.11.01 |
[리팩토링] Combine Functions into Transform 여러 함수를 변환 함수로 묶기 (0) | 2021.10.19 |
[리팩토링] Introduce Parameter Object 매개변수 객체 만들기 (0) | 2021.10.14 |
[리팩토링] Change Function Declaration 함수 선언 바꾸기 (0) | 2021.10.03 |
Comments