티스토리 뷰
모듈을 잘 분리하는 가장 중요한 기준은
각 모듈이 자신을 제외한 외부에 드러내지 않아야 할 비밀을 얼마나 잘 숨기느냐에 있다.
- 대표적인 데이터 구조 캡슐화
- 7.1 레코드 캡슐화하기
- 7.2 컬렉션 캡슐화하기
- 기본형 데이터 캡슐화
- 7.3 기본형을 객체로 바꾸기
- 길어진 함수를 쪼개는
- 7.4 임시 변수를 질의 함수로 바꾸기
- 추출하기/인라인의 클래스 버전
- 7.5 클래스 추출하기
- 7.6 클래스 인라인하기
- 클래스 사이의 연결 관계를 숨기는
- 7.7 위임 숨기기
- 너무 많이 숨길 경우를 위한 반대 기법
- 7.8 중개자 제거하기
- 알고리즘을 통채로 바꿔야 할 때
- 7.9 알고리즘 교체하기
7.1 레코드 캡슐화하기 (Encapsulate Record)
개요
- 레코드(해시)를 데이터 클래스로 전환하는 리팩터링
- 해시맵은 다양한 프로그래밍 작업에 유용하지만, 필드를 명확히 알려주지 않는 단점이 있음
적용 시점
- -
효과
- 객체를 사용하면 어떻게 저장했는지를 숨긴 채 메서드로 제공할 수 있음
- 불분명함으로 인해 발생하는 문제를 줄임
before
organization = {name: "Acme Gooseberries", country: "GB"};
after
class Organization {
constructor(data) {
this._name = data.name;
this._country = data.country;
}
get name() {return this._name;}
set name(arg) {this._name = arg;}
get country() {return this._country;}
set country(arg) {this._country = arg;}
}
7.2 컬렉션 캡슐화하기 (Encapsulate Collection)
개요
- 컬렉션 원본을 외부에서 직접 변경할 수 없도록 하는 리팩터링
- 기본적으로 컬렉션 조작은 메서드로만 제공함
- 또한, 접근한 컬렉션을 직접 수정하지 못하도록 해야함
- 복제본을 반환하는 방법
- 읽기전용으로 제공하는 방법
- 중요한 점은 코드베이스에서 컬렉션 접근 처리 방식이 통일되어야 함
적용 시점
- -
효과
- 모듈 밖에서 컬렉션이 수정되어 발생하는 문제를 예방함 (발생 시 굉장히 찾기 어려움)
before
class Person {
get courses() {return this._courses;}
set courses(aList) {this._courses = aList;}
after
class Person {
get courses() {return this._courses.slice();}
addCourse(aCourse) { ... }
removeCourse(aCourse) { ... }
7.3 기본형을 객체로 바꾸기 (Replace Primitive with Object)
개요
- 단순한 정보를 표현하는 데이터도 개발이 진행되면서 더 이상 간단하지 않게 변하게 되는 경우가 많음
적용 시점
- 단순한 출력 이상의 기능이 필요해지는 순간 전요 클래스를 정의하는 편
효과
- 시작은 기본형 데이터를 감싼 것과 큰 차이가 없으나 나중에 특별한 동작이 필요해지면 유용한 도구가 됨
before
orders.filter(o => "high" === o.priority
|| "rush" === o.priority);
after
orders.filter(o => o.priority.higherThan(new Priority("normal")))
7.4 임시 변수를 질의 함수로 바꾸기 (Replace Temp with Query)
개요
- 임시 변수를 사용하면 코드가 반복되는 걸 줄이고 값의 의미를 설명할 수도 있어 유용함
- 임시 변수를 아예 함수로 만들어 사용하는 편이 나을 때도 있음
적용 시점
- 클래스 안에서 적용할 때 효과가 가장 큼
효과
- 비슷한 계산 처리를 재 사용할 수 있어 코드 중복이 줄어든다
- 코드간에 부자연스러운 의존관계나 부수효과를 찾고 제거할 수 있음
before
const basePrice = this._quantity * this._itemPrice;
if (basePrice > 1000)
return basePrice * 0.95;
else
return basePrice * 0.98;
after
get basePrice() {this._quantity * this._itemPrice;}
...
if (this.basePrice > 1000)
return this.basePrice * 0.95;
else
return this.basePrice * 0.98;
7.5 클래스 추출하기 (Extract Class)
개요
- 클래스에 새로운 역할을 덧씌우기 시작하면 굉장히 복잡해지고 어느새 전자레인지로 바짝 익힌 음식처럼 딱딱해진다
- 메서드와 데이터가 너무 많은 클래스는 이해하기가 쉽지 않으니 잘 살펴보고 적절히 분리하는것이 좋음
적용 시점
- 일부 데이터와 메서드를 따로 묶을 수 있을 때
효과
- 클래스를 이해하기 쉬워짐
7.6 클래스 인라인하기 (Inline Class)
개요
- 클래스 추출하기를 거꾸로 돌리는 리팩터링
- 리팩터링 후 클래스에 남은 역할이 거의 없어졌을때 가장 많이 사용하는 클래스로 흡수시키는 작업
적용 시점
- 클래스에 남은 역할이 거의 없을때
효과
- 불필요하게 분리된 클래스 제거
7.7 위임 숨기기 (Hide Delegate)
개요
- 예컨대 서버 객체의 필드가 가리키는 위임 객체의 메서드를 호출하려면 클라이언트는 이 위임 객체를 알아야 함
- 이러한 의존성을 없애려면 A 자체에 위임 메서드를 만들어서 위임 객체를 존재함 숨길수 있음
적용 시점
- 상황에 맞게
효과
- 위임 객체가 수정 되더라도 클라이언트는 영향을 받지 않음
before
manager = aPerson.department.manager;
after
manager = aPerson.manager;
class Person {
get manager() {return this.department.manager;}
7.8 중개자 제거하기 (Remove Middle Man)
개요
- 단순히 전달만하는 위임 메서드들만 계속해서 추가될 경우 점점 번거로워짐
- 이런 경우 클래스가 단순 중개자 역할로 전락할 수 있어 차라리 위임 객체를 직접 호출하는게 나아지게 됨
적용 시점
- 상황에 맞게
효과
- 클래스가 단순한 중개자 역할로 전락하는걸 막음
before
manager = aPerson.manager;
class Person {
get manager() {return this.department.manager;}
after
manager = aPerson.department.manager;
7.9 알고리즘 교체하기 (Substitute Algorithm)
개요
- 어떤 목적을 달성하는 알고리즘은 여러가지가 있으며 그중에서도 다른 것보다 더 쉬운 방법이 분명히 존재함
적용 시점
- 기존 코드보다 훨씬 간결한 알고리즘을 찾아낸 경우
- 내 코드와 똑같은 기능을 제공하는 라이브러리를 찾은 경우
- 단, 거대하고 복잡한 알고리즘의 경우 교체하기 상당히 어려우니 먼저 메서드를 분리하여 알고리즘을 간소화 해야 함
효과
- 복잡한 알고리즘을 쉽게 바꾼다
before
function foundPerson(people) {
for(let i = 0; i < people.length; i++) {
if (people[i] === "Don") {
return "Don";
}
if (people[i] === "John") {
return "John";
}
if (people[i] === "Kent") {
return "Kent";
}
}
return "";
}
after
function foundPerson(people) {
const candidates = ["Don", "John", "Kent"];
return people.find(p => candidates.includes(p)) || '';
}
참고
http://www.yes24.com/Product/Goods/89649360
https://refactoring.com/catalog
'소프트웨어공학, CS > 리팩터링 2판' 카테고리의 다른 글
[리팩터링 2판] 11장 API 리팩터링 (0) | 2021.05.16 |
---|---|
[리팩터링 2판] 10장 조건부 로직 간소화 (0) | 2021.04.18 |
[리팩터링 2판] 9장 데이터 조직화 (0) | 2021.04.04 |
[리팩터링 2판] 8장 기능 이동 (2) | 2021.03.28 |
[리팩터링 2판] 6장 기본적인 리팩터링 (0) | 2021.03.04 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Debugging
- Refactoring
- 리팩터링이란
- https
- 일 잘하는 사람은 단순하게 말합니다
- 위임
- 변경함수
- 조건부 로직
- aws fargate
- 지시의 언어
- Debug It! 실용주의 디버깅
- amazon vpc
- 그림으로 배우는 HTTP & Network
- 코드악취
- 매개변수화
- 박소연
- 마틴파울러
- 안심 첫 문장
- SSL
- 제어플래그
- 리팩토링
- 일잘러
- 코드스멜
- 그림으로 공부하는 IT 인프라 구조
- 질의함수
- Debug
- amazon aurora
- AWS
- 디버깅
- HTTP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
글 보관함