From b6e9fcfdb54638cd8f0fa81b0c4cae73ab8a52fb Mon Sep 17 00:00:00 2001 From: minkyung Date: Sun, 30 Jun 2024 01:52:47 +0900 Subject: [PATCH] Create 15-3.md (#179) --- new/15-3.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 new/15-3.md diff --git a/new/15-3.md b/new/15-3.md new file mode 100644 index 0000000..a1302e0 --- /dev/null +++ b/new/15-3.md @@ -0,0 +1,89 @@ +# 파이브 라인스 오브 코드 +## 4. 타입 코드 처리하기 +### 규칙: if 문에서 else 를 사용하지 말 것 +- 프로그램에서 이해하지 못하는 타입인지를 검사하지 않는 한 if 문에서 else 를 사용하지 않는다. + +- `if-else` 를 사용하면 코드에서 결정이 내려지는 지점을 고정하게 된다. + +- 독립된 if 문은 검사로 간주하고, if-else 문은 의사 결정으로 간주한다. + +``` js +// AS IS +function average(ar: number[]) { + if (size(ar) === 0) { + throw new Error("Cannot take average of empty array"); + } + return sum(ar) / size(ar); +} + +// TO BE +function average(ar: number[]) { + assertNotEmpty(ar); + return sum(ar) / size(ar); +} + +function assertNotEmpty(ar: number[]) { + if (size(ar) === 0) { + throw new Error("Cannot take average of empty array"); + } +} +``` +#### 스멜 +- 이른 바인딩: if-else 같은 의사결정 동작은 컴파일 시 처리되어 애플리케이션에 고정되면 재컴파일 없이는 수정할 수 없다. +- 늦은 바인딩: 코드가 실행되는 순간 동작이 결정됨 + +#### 의도 +- if 는 흐름을 제어 -> 다음에 실행할 코드를 결정한다는 뜻 + +### 리펙터링: 클래스로 타입 코드 대체 +- 열거형을 인터페이스로 변환하고 열거형의 값들을 클래스가 되도록 변환한다. +- 해당 리펙터링 패턴은 자체적으로 많은 가치를 가지지 않지만, 추후 개선을 가능하기 한다. + +### 리펙터링: 클래스로 코드 이관하기 +- 기능을 클래스로 옮기면서 클래스로 타입 코드 대체 패턴의 자연스러운 연장선 +- 특정 값과 연결된 기능이 값에 해당하는 클래스로 이동하기 때문에 불변속성을 지역화 + +### 리펙터링: 메서드의 인라인화 +- 프로그앰에서 더 이상 가독성에 도움이 되지 않는 메서드를 제거 +- 단, 메서드를 인라인으,로 사용하는 것과는 다른 개념 + +- 메서드가 인라인화 하기 너무 복잡한가? + -> 낮은 수준의 연산에 의존하여 가독성에 도움이 되는 경우에는 인라인화하지 않는다. + +### 리펙터링: 메서드 전문화 +- 일반화하고 재사용하려는 본능적인 욕구가 있지만 그렇게 하면 책임이 흐려지고, 다양한 위치에서 코드를 호출할 수 있기 때문에 문제가 될 수 있음 +- 전문화된 메서드는 더 적은 위치에서 호출되어 필요성이 없어지면 더 쉽게 제거 가능함 + +### 규칙: switch 를 사용하지 말것 +- default 케이스가 없고 모든 case 에 반환값이 존재하는 경우에는 switch 를 사용하지 않는다. + +#### switch 의 문제점 + +- 컴파일러 입장에서 새로 추가한값의 처리에 대한 누락을 알 수 없다. +- break 키워드 누락으로 인한 버그 + +#### 스멜 +- switch 문은 값을 처리하는 방법에 초점, 클래스에 기능을 추가할때는 값이 상황을 처리하는 방법에 초점 +- 컨텍스트에 초점을 맞춘다는 것은 불변속성을 전역화하는 것을 의미 + +#### 의도 +- switch -> else if -> 클래스로 변환 + +- 인터페이스 대신 추상 클래스를 사용할 수 없을까? + - 사용할 수 있다. 코드의 중복을 피할 수 있다. + - 하지만 인터페이스를 사용하면 개발자가 능동적으로 무엇인가를 해야함. 즉, 누락으로 인한 오류를 방지할 수 있음 + +#### 규칙: 인터페이스에서만 상속받을 것 +- 상속은 오직 인터페이스를 통해서만 받는다. + +- 추상 클래스를 사용하는 것은 일부 메서드의 기본 구현을 제공하고, 다른 메서드를 추상화 하기 위함 + - 중복을 줄이고 코드의 줄을 줄이고자 할 경우 편리 +- 하지만 추상 클래스의 코드 공유는 커플링을 유발하고, 기본 구현으로 인해 재정의가 필요한 메서드 인지 컴파일러를 통해 확인이 어려움 + +#### 스멜 +> 상속보다는 컴포지션이 더 좋다 <> + +### 리팩터링: 삭제 후 컴파일하기 +- 인터페이스에서 사용하지 않는 메서드를 제거하는 것 +- 메서드를 삭제하고 컴파일러에서 허용하는지 확인하는 것 +