From d21df180752ce6954c9e2d2da3a2f1940152d81b Mon Sep 17 00:00:00 2001 From: Kangmin Date: Mon, 11 Dec 2023 21:14:40 +0900 Subject: [PATCH] =?UTF-8?q?=08docs/#10:=205=EC=9E=A5=20=EC=9C=A0=EC=82=AC?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=9C=B5=ED=95=A9=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20(#11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs/#10: 5장 유사한 코드 융합하기 (앞부분만!) * docs: chapter 05 * docs/#10: 5장 마무리 * Docs: 5장:타입코드처리하기 --------- Co-authored-by: uuuuujin Co-authored-by: shinequasar --- boring-km/_posts/2023-10-16-chapter05.md | 48 +++++++ shinequasar/_posts/2023-10-26-chapter5.md | 47 +++++++ uuuuujin/_posts/2023-10-25-chapter05.md | 151 ++++++++++++++++++++++ 3 files changed, 246 insertions(+) create mode 100644 boring-km/_posts/2023-10-16-chapter05.md create mode 100644 shinequasar/_posts/2023-10-26-chapter5.md create mode 100644 uuuuujin/_posts/2023-10-25-chapter05.md diff --git a/boring-km/_posts/2023-10-16-chapter05.md b/boring-km/_posts/2023-10-16-chapter05.md new file mode 100644 index 0000000..6efc169 --- /dev/null +++ b/boring-km/_posts/2023-10-16-chapter05.md @@ -0,0 +1,48 @@ +--- +title: "5. Fuse Similar Code Together" +categories: + - boring-km +--- +[You can also read in Notion](https://www.notion.so/5-Fuse-Similar-Code-Together-b742feaccf9640e89676ae87ce3fc049?pvs=4) + +## 5.1 유사한 클래스 통합하기 + +- 반복작업을 자꾸 시켜서 손목이 아프다 +- 비슷한 성격을 가진 두 객체의 동작이 거의 다르지 않다면, 하나로 만들되 `if/else` 를 사용하지 말고 만들자 +- 책에서는 처음엔 enum으로 바꿨다가 interface로 바꿨는데 이러한 패턴을 **“클래스로 타입 코드 대체”** 라고 한다. +- 사실 뭐 이름이 중요한가 싶다. 일일이 외우기 보단 손가락으로 익히는 게 맞는거 같다. + +https://github.com/FiveLinesofCodeStudy/2D-Puzzle-Compose/commit/e9b2b43b5f101de142aaf656edcc2e6365af320e + +## 5.2 단순한 조건 통합하기 + +- if 문 갯수 줄이는 것은 정말 좋은 방법인 것 같다. + +### 절차 + +1. 본문이 실제로 동일한지 확인한다. +2. 첫 번째 if 문의 닫는 괄호와 else if 문의 여는 괄호 사이의 코드를 선택하고 삭제한 후 `||`을 삽입한다. if 뒤에 여는 괄호를 삽입하고 `{` 앞에 닫는 괄호를 삽입한다. 동작을 변경하지 않도록 항상 표현식을 괄호로 묶는다. + +## 5.3 복잡한 조건 통합하기 + +- 코드 동작에 대한 명확한 이해가 받쳐줘야 가능하다. +- SRP (단일 책임 원칙)에 따른 메서드를 만드는 걸 목적으로 리팩토링 해보자 + +https://github.com/FiveLinesofCodeStudy/2D-Puzzle-Compose/commit/d3b75296b6a5a47b4d6e0d9df24a23c8d1a6ebe3 + +## 5.4 클래스 간의 코드 통합 + +- 컴포지션을 사용하는 대표적인 디자인 패턴이다. +- https://stackify.com/oop-concepts-composition/ + +https://github.com/FiveLinesofCodeStudy/2D-Puzzle-Compose/commit/e21106afe6097d2147ba3bbdb1eee3ac6d55149b + +## 5.5 유사 함수 통합하기 + +https://github.com/FiveLinesofCodeStudy/2D-Puzzle-Compose/commit/2718970221007d9a7985b81a9347aefa1aceef96 + +## 5.6 유사한 코드 통합하기 + +https://github.com/FiveLinesofCodeStudy/2D-Puzzle-Compose/commit/79ec4d0a596471b21db40184f46edfbc553c983d + +- 전략 패턴 동일하게 사용 \ No newline at end of file diff --git a/shinequasar/_posts/2023-10-26-chapter5.md b/shinequasar/_posts/2023-10-26-chapter5.md new file mode 100644 index 0000000..c82d668 --- /dev/null +++ b/shinequasar/_posts/2023-10-26-chapter5.md @@ -0,0 +1,47 @@ +--- +title: "5장 유사한 코드 융합하기" +categories: + - shinequasar +--- +# 5장 유사한 코드 융합하기 + +### 실습 중인 레포 +https://github.com/FiveLinesofCodeStudy/five-lines-soyeon.git + +## 5-1 유사한 클래스 통합하기 + +- || 로 묶인 상태를 하나의 함수로 묶으니 가독성이 좋아졌다. 변수명으로 바로 유추 가능 +- 앞에서 다양한 메서드들을 쪼개고, 클래스들도 많이 만들어 놨어서 왜 이렇게 나누지 의문이 좀 있었는데(중복된 기능들을 반복해서 사용하는 모습이 의문스러웠었음) 5장을 위해서 이렇게 했구나 싶음. +- 유사한 메서드나 기능을 if 불리언으로 합치고, 그걸 다시 .is~~~() 형태로 클래스에 내재화 해서 한 클래스에 모은 후 비슷한 클래스를 삭제해 합치는 과정이 나와서 마음이 편해졌다. +- 이 과정에서 생성자를 활용하여 초기 상태를 정하는 것도 잘 활용해볼 수 있을 것 같다. + +## 5-1-1 리팩토링 패턴 : 유사 클래스 통합 + +- 트래픽 예제로 다시한번 복습 + +## 5-2 단순한 조건 통합하기, 리팩토링 패턴 : if문 결합 + +- 당연하게 써오던 같은 본문은 합친다~! 를 다시한번 강조 +- 5-1에서 언급한 ‘|| 로 묶인 상태를 하나의 함수로 묶기’ 같은 방법은 코드를 연구하지 않아도 리팩토링할 수 있는 패턴이라는 점이 공식같아서 새로운 시각을 가지게 되었다. + +## 5-3 복잡한 조건 통합하기 + +- 코드는 다르지만 논리적으로 같은 부분을 같은 코드로 바꾸고, 그 메서드 두 개를 합치는 방법 +- 이 부분은 코드의 의미를 어느정도 파악한 후에 적용할 수 있는 기법인 듯하다. +- 맡고있는 프로젝트에 대한 이해가 높아지면 적용해봐도 좋을 듯. + +### 5-3-1 조건을 위한 산술규칙 사용 + +- 코드를 덧셈법칙, 곱셈법칙처럼 수식의 모습으로 사고하는 방식이 인상깊었다. +- 이 부분은 당장 적용해볼 수 있을 것 같아서 조건을 고려할 때 바로 도입해봐야겠다는 생각을 했다. +``` +//변경 전 +if(map[y][x].isStony() && map[y][x].isAir()) || map[y][x].isBoxy() && map[y][x].isAir()) { +... +} + +//변경 후 +if((map[y][x].isStony() || map[y][x].isBoxy()) && map[y][x].isAir()) { +... +} +``` diff --git a/uuuuujin/_posts/2023-10-25-chapter05.md b/uuuuujin/_posts/2023-10-25-chapter05.md new file mode 100644 index 0000000..faf0826 --- /dev/null +++ b/uuuuujin/_posts/2023-10-25-chapter05.md @@ -0,0 +1,151 @@ +# 5장 - 유사한 코드 융합하기 + +## 5.1 유사한 클래스 통합하기 + +- 상수 메서드: 상수를 반환하는 메서드 + - 경우에 따라 다른 값을 반환하는 상수 메서드를 공유한다면 두 클래스는 합칠 수 있음 + +- 클래스를 합치는 방법 + 1. 상수 메서드를 제외한 클래스의 모든 것을 동일하게 만든다. + 2. 클래스를 합친다. + +- 구체적인 절차 + 1. 모든 비기준 메서드를 동일하게 만듦 + 2. 기준 메서드에 대한 필드를 도입하고 생성자에서 상수를 할당하는 것으로 시작 + 3. 상수 대신 도입한 필드를 반환하도록 메서드 변경 + 4. 문제 없는지 확인 위해 컴파일 + 5. 각 클래스에 대해 한 번에 하나의 필드씩 다음 수행 + - 필드의 기본값을 매개변수로 지정 + - 컴파일러 오류 살펴보고 기본값 인자로 전달 + 6. 모든 클래스 동일하면 통합한 클래스 중 하나를 제외한 모두를 삭제하고, 삭제하지 않은 클래스로 바꾸어 모든 컴파일러 오류를 수정 + +
+ +### Stone과 FallingStone 통합하는 방법 +1. 두 개의 moveHorizontals를 동일하게 만듦 +2. 상수메서드 isFallingStone만 다르므로 falling 필드를 새로 도입하고 생성자에서 그 값을 할당 +3. isFallingStone을 변경해서 새로운 falling 필드를 반환 (상수 대신 필드 반환) +4. 문제 없는지 컴파일 +5. 각 클래스에 대해 falling의 기본값을 매개변수로 받도록 만들고 기본값을 인자로 전달 +6. 통합 중인 클래스 중 하나를 제외한 모든 클래스를 삭정한 후, 컴파일 오류를 남아 있는 클래스로 바꿔서 수정 + +
+📌 클래스를 결합할 때 기대하는 효과 + +- 잠재적으로 숨겨진 타입을 가리키는 코드를 찾을 수 있음 + +
+ +> **class에서 consturctor** +>
+> - 클래스의 인스턴스 객체를 생성, 초기화하는 역할 +> - 클래스 내부 혹은 다른 클래스에 상속한 경우, 해당 클래스 내부에서 사용하기 위한 객체를 정의 +> - 생성자는 하나만 가질 수 있음 +> - 매개변수 앞에 public, private 키워드 넣으면 자동으로 인스턴스 변수 만들고 인자 값 할당함 + +```typescript +// 방법 1 +class Stone implements Tile { + private falling: boolean + constructor(falling: boolean) { + this.falling = falling; + } +} + +// 방법 2 +class Stone implements Tile { + constructor(private falling: boolean) {} +} +``` + +## 5.3 복잡한 조건 통합하기 +📌 조건을 위해 산술 규칙을 사용할 떄 순수 조건을 사용해야 함 +- 조건은 항상 순수 조건(순수조건: 조건이 변수에 값 할당하거나 예외 발생시키거나 I/O와 상호작용하는 동작이 없는 것) +- if, while뒤에 오는 것과 for 루프의 가운데에 있는 것 + +
+ +📌 명령에서 질의 분리 +- 명령: 부작용이 있는 모든 것 +- 질의: 순수한 것 +- => void 메서드에서만 부수적인 동작 허용하기!! (부수적인 동작 하거나, 무언가 반환하거나 둘 중 하나만!) + +
+ +## 5.4 클래스 간의 코드 통합 +> **UML(Unified Modeling Language)**
+> - 코드에 대한 속성 전달하기 위해 다양한 유형의 표준 다이어그램으로 구성 +> - 시퀀스 다이어그램, **클래스 다이어그램**, 활동 다이어그램 +> - 전략 패턴 -> 클래스 다이어그램 사용 + +> **클래스 다이어그램** +> - 인터페이스와 클래스의 구조가 서로 어떤 관계가 있는지 보여줌 +> - 주로 공개 메서드만 묘사함 +> - 인터페이스는 위에 interface라고 표기 +> ```typescript +> class Cls { +> private text: string = "Hello"; +> public name: string; +> private getText() { return this.text } +> printText() { console.log(this.getText()) } +> } +> ``` +> 이미지 +> +>
+>
+> + +> ⭐️️**클래스와 인터페이스 간의 관계**⭐️️ +> +> 이미지 +> +> - X가 Y를 사용한다 (의존, 연관) +> - 관계가 무엇인지 모르거나 신경 쓰지 않을 떄 사용 +> - X는 Y다 +> - X가 하나 또는 여러 개의 Y를 가진다 +> - 대부분 **컴포지션**과 **구현** 사용 + +> **구현(implements)** +> ```typescript +> interface A { +> m(): void; +> } +> class B implements A { +> m() { console.log("Hello"); } +> } +> ``` +> 이미지 +> +> - 인터페이스로 이미 알 수 있어서 클래스 B에도 m 메서드가 있음을 보여줄 필요 없음 + +> **구성(composed)** +> ```typescript +> class A { +> private b: B; +> } +> class B {} +> ``` +> 이미지 + +
+ +### 전략 패턴 +- 다른 클래스를 인스턴스화해서 변형(variance)을 도입하는 개념 + - 이미지 +- 클래스를 추가해서 변경이 가능하게 한다!! +- 전략 패턴 도입 상황 + - 1. 코드에 변형 도입하고 싶어서 리팩터링 수행하는 경우 + - 2. 클래스 간의 동작 통합하려는 경우 +- 구현체가 하나뿐인 인터페이스 만들지 말 것 + - 가독성 도움 안 됨 + +
+
+ +> ⭐️ 이번주에 진행할 것 +> 1. 3장 ~ 5장 복습하기 (코드 다시 쳐보기!!) +> - 레포 새로 파기 +> - 커밋 나눠하기 +> - 파일 나누기 +> - 웹스톰 단축키 익숙해지기 \ No newline at end of file