유사한 클래스로 통합하기
준비. 괄호로 묶인 두 개의 || 에 대해 각기 하나의 함수 도입
메서드가 상수를 반환할 때 상수 메소드라고 한다.
경우에 따라 다른 값을 반환하는 상수 메서드를 공유하기 때문에 이 두 클래스를 합칠 수 있다.
1. 두 개의 moveHorizontal을 동일하게 만들기
a. 각 moveHorizontal 본문의 기존 코드 주위에 if(true) {} 를 추가
b. true를 각기 isFallingStone() === true, isFallingStone() === false로 바꿉니다.
c. 각 moveHorizontal 본문을 복사하여 else와 함께 다른 moveHorizontal 에 붙여넣기
2. 상수 메서드 isFallingStone만 다르므로 두번째 단계는 falling 필드를 새로 도입하고 생성자에서 그 값을 할당하는 것으로 시작
3. isFallingStone을 변경해서 새로운 falling 필드를 반환
4. 문제가 없는지 확인을 위해 컴파일
5.각 클래스에 대해
a. falling의 기본값을 매개변수로 받도록 만들기
b. 컴파일러 오류를 살펴보고 기본값을 인자로 전달
6. 통합 중인 클래스 중 하나를 제외한 모든 클래스를 삭제한 후, 컴파일 오류를 남아있는 클래스로 바꿔서 수정하기
타입스크립트에서는
생성자를 하나만 가질 수 있으며 항상 constructor라는 명칭을 사용한다.
생성자의 매개변수 앞에 public 또는 private 키워드를 넣으면 자동으로 인스턴스 변수를 만들고 인자의 값을 할당한다.
horison 여전히 else 문이 존재
* Stone 클래스에 있던 bool인자를 Enum으로 추출하여 가독성을 높임 -> enum : 클래스로 타입코드 대체 가능해짐!
* 클래스로 타입 코드 대체
[리팩터링 패턴] 유사 클래스 통합
설명
- 상수 메서드를 공통으로 가진 두 개 이상의 클래스에서 이 상수 메서드가 클래스에 따라 다른 값을 반환할 때마다 사용
- 일련의 상수 메서드 집합을 기준(basis)이라고 한다.
- 상수 메서드가 두개일때 두개의 접점을 가진 기준 이라고 한다
절차
- 첫 번째 단계는 모든 비기준 메서드를 동일하게 만든다. 이런 메서드에 각각 다음 수행
- 각 메서드 버전 본문의 기존 코드 주위에 if(true) {} 추가
- true 를 모든 기본 메서드를 호출하여 그 결과를 상수 값과 비교하는 표현식으로 바꾼다.
- 각 버전의 본문을 복사하고 else와 함께 다른 모든 버전에 붙여 넣습니다.
- 이제 기준 메서드만 다르므로 두 번째 단계는 기준 메서드에 각 메서드에 대한 필드를 도입하고 생성자에서 상수를 할당하는 것으로 시작한다.
- 상수 대신 도입한 필드를 반환하도록 메서드를 변경합니다.
- 문제가 없는지를 확인하기 위해 컴파일한다.
- 각 클래스에 대해 한 번에 하나의 필드씩 다음을 수행한다.
- 필드의 기본값을 매개변수로 지정하게 한다.
- 컴파일러 오류를 살펴보고 기본값을 인자로 전달한다.
- 모든 클래스가 동일하면 통합한 클래스 중 하나를 제외한 모두를 삭제하고, 삭제하지 않은 클래스로 바꾸어 모든 컴파일러 오류를 수정한다.
단순한 조건 통합하기
updateTile을 진행하기 위해 몇몇 if 문의 내용을 더 비슷하게 만들기
새로운 falling 필드를 설정하거나 설정을 해지하기 위한 메서드 도입
updateTile에서 바로 rest 메서드 사용 가능
마지막 두 if 문의 내용이 동일하므로 두 조건 사이에 || 을 넣어 합치기
|| 표현식을 클래스로 이관하고 두 가지 메서드 이름의 공통점을 이용해 ifFalling이라고 이름짓기
[리팩터링 패턴] if 문 결합
설명
- 동일한 본문을 가진 if 문을 결합해서 중복을 제거 하는 방법이다.
절차
- 본문이 실제로 동일한지 확인한다.
- 첫 번째 if 문의 닫는 괄호와 else if 문의 여는 괄호 사이의 코드를 선택하고 삭제한 후 || 을 삽입한다 if 뒤에 여는 괄호를 삽입하고 { 앞에 닫는 괄호를 삽입합니다. 동작을 변경하지 않도록 항상 표현식을 괄호로 묶는다.
- 표현식이 단순하면 불필요한 괄호를 제거한다.
복잡한 조건 통합하기
첫 두개 if 문의 본문이 동일하므로 || 로 결합하기
조건 표현식이 무엇을 하는지는 알지 못해도 조작 할 수 있다.
[규칙] 순수 조건 사용
정의
- 조건은 항상 순수 조건이어야 한다.
설명
- '조건'은 if 또는 while 뒤에 오는 것과 for 루프의 가운데에 있는 것
- '순수'라는 말은 조건에 부수적인 동작이 없음을 의미
- '부수적인 동작'이란 조건이 변수에 값을 할당하거나 예외를 발생시키거나 출력, 파일 쓰기 등과 같은 I/O와 상호 작용하는 것을 의미
절차
- 본문이 실제로 동일한지 확인한다.
- 첫 번째 if 문의 닫는 괄호와 else if 문의 여는 괄호 사이의 코드를 선택하고 삭제한 후 || 을 삽입한다 if 뒤에 여는 괄호를 삽입하고 { 앞에 닫는 괄호를 삽입합니다. 동작을 변경하지 않도록 항상 표현식을 괄호로 묶는다.
- 표현식이 단순하면 불필요한 괄호를 제거한다.
스멜
- '명령'은 부작용이 있는 모든 것을 의미하고 '질의'는 순수한 것을 의미한다.
- 메서드는 한 가지 작업을 해야한다.
- 부수적인 동작은 한가지 작업이고 무언가를 반환하는 것은 별개
의도
- 데이터를 가져오는 것과 변경하는 것을 분리하는 것
클래스 간의 코드 통합
클래스 관계를 묘사하기 위한 UML 클래스 다이어그램 소개
아키텍처나 일이 일어나는 순서 같은 코드에 대한 속성을 전달할 필요가 있을 때 다이어그램을 사용한다.
UML(Unified Modeling Language) 프레임워크 사용
클래스 다이어 그램
- 인터페이스와 클래스의 구조가 서로 어떤 관계가 있는지 보여준다.
- 인터페이스는 클래스처럼 표시되지만, 제목 위에 interface라고 표시한다.
- 메서드가 private(-)인지 public(+)인지를 나타내기도 한다. 보통 인터페이스에 관심이 있으므로 public/private 은 잘 표시하지 않는다.
Cls |
- text: string + name: string |
- getText(): string + printText(): string |
- 클래스 다이어그램에서 가장 중요한 부분은 클래스와 인터페이스 간의 관계
[리팩터링 패턴] 전략 패턴의 도입
설명
다른 클래스를 인스턴스화해서 변형을 도입하는 개념
절차
- 분리하려는 코드에 대해 메서드 추출을 추생한다. 다른 것과 통합하려면 메서드가 동일한지 확인한다.
- 새로운 클래스를 만든다.
- 생성자에서 새로운 클래스를 인스턴스화한다.
- 메서드를 새로운 클래스로 옮긴다.
- 필드에 종속성이 있을 경우 다음을 수행한다.
- 필드를 새로운 클래스로 옮기고 옮긴 필드에 대한 접근자를 만든다.
- 새로운 접근자를 사용해서 원래 클래스에서 발생하는 오류를 바로 잡는다.
- 새로운 클래스의 나머지 오류에 대해 해당 값을 대체할 매개변수를 추가한다.
- 메서드의 인라인화를 사용해서 1단계의 추출을 반대로 한다.
[규칙] 구현체가 하나뿐인 인터페이스를 만들지 말 것
정의
구현체가 하나뿐인 인터페이스를 사용하지 마라
설명
- 구현클래스가 하나밖에 없는 인터페이스는 가독성에 도움이 되지 않는다.
- 인터페이스는 변형을 전제로 한다.(변형이 있을 때 사용한다.
- 인터페이스와 구현체는 보통 각 파일로 작성하므로 필요 이상의 파일이 존재하게 된다.
- 아무런 구현체가 없는 인터페이스를 갖는 것이 합리적일 때도 있다. (comparator)
스멜
- 추상화는 인지된 복잡성의 감소를 위해 실제의 복잡성의 증가를 허용하는 것이다
- 즉 추상화에 신중해야 한다.
의도
- 불필요한 상용구 제한
상용구란
(Boilerplate text)는 자주 사용하는 문장이나 수식, 명령어 등을 입력해 놓았다가 필요할 때에 간단한 키 입력으로 불러내어 쓰는 것을 말한다.
참조
- 프레드 조지의 "애자일의 은밀한 가정" 강연
[리팩터링 패턴] 구현에서 인터페이스 추출
설명
- 인터페이스를 만드는 것이 필요할 때 (변형을 도입하고 싶을 때)까지 연기할 수 있어서 유용하다
절차
- 추출할 클래스와 동일한 이름으로 새로운 인터페이스를 만든다.
- 인터페이스를 추출할 클래스의 이름을 변경하고 새로운 인터페이스를 구현하게 한다.
- 컴파일하고 오류를 검토한다.
- new 때문에 오류가 발생하면 인스턴스화 하는 부분을 새로운 클래스의 이름으로 변경한다
- 그렇지 않으면 오류를 일으키는 메서드를 인터페이스를 추가한다.
유사한 함수 통합하기
- 전략패턴의 도입 활용
유사한 코드 통합하기
'스터디 > Five Lines of Code' 카테고리의 다른 글
7장 컴파일러와의 협업 (1) | 2023.11.04 |
---|---|
Five Lines of Code 6장. 데이터 보호 (1) | 2023.10.29 |
Five Lines of Code 4장 타입 코드 처리하기 (1) | 2023.10.14 |
Five Lines of Code 3장 긴 코드 조각내기 (0) | 2023.09.22 |
Five Lines of Code 1-2장 리팩터링이란 (0) | 2023.09.20 |