f8b21af4be
10_Wiki/Topics 대규모 정리: - 오류 캡처/미완성 stub 문서 227개 제거 - 교차폴더 중복 43클러스터 병합 (63파일 → redirect) - 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건 - 카테고리 MOC 6개 신규 생성 - Graph 섹션 미해결 related-keyword 링크 10,058건 제거 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
188 lines
5.5 KiB
Markdown
188 lines
5.5 KiB
Markdown
---
|
|
id: wiki-2026-0508-switch-statements-switch-문
|
|
title: Switch Statements (Switch 문)
|
|
category: 10_Wiki/Topics
|
|
status: verified
|
|
canonical_id: self
|
|
aliases: [Switch Statement, Pattern Matching, Replace Switch]
|
|
duplicate_of: none
|
|
source_trust_level: A
|
|
confidence_score: 0.9
|
|
verification_status: applied
|
|
tags: [refactoring, code-smell, polymorphism]
|
|
raw_sources: []
|
|
last_reinforced: 2026-05-10
|
|
github_commit: pending
|
|
tech_stack:
|
|
language: multi
|
|
framework: refactoring
|
|
---
|
|
|
|
# Switch Statements (Switch 문)
|
|
|
|
## 매 한 줄
|
|
> **"매 type-tagged switch 의 polymorphism 의 missed opportunity"**. 매 classic code smell 의 — 매 type 의 switch 의 새 type 의 추가 시 매 모든 switch 의 update 의 필요. 2026 의 modern lang 의 sealed types + pattern matching 의 acceptable.
|
|
|
|
## 매 핵심
|
|
|
|
### 매 왜 smell 인가
|
|
- **OCP 위반**: 매 새 type 의 추가 의 매 switch 의 modify 의 필요.
|
|
- **Shotgun surgery**: 매 동일 switch 의 codebase 의 scatter.
|
|
- **Type safety hole**: 매 default 의 fallthrough — 매 unhandled case 의 silent.
|
|
|
|
### 매 acceptable cases
|
|
- Sealed/exhaustive matching (Kotlin, Rust, Swift, Java 21+).
|
|
- Single switch — 매 dispatch 의 한 곳.
|
|
- Performance-critical hot path (jump table).
|
|
- Parsing / state machines.
|
|
|
|
### 매 refactoring 전략
|
|
- **Replace with polymorphism**: type-tagged switch → method override.
|
|
- **Replace with strategy**: behavior-tagged switch → strategy injection.
|
|
- **Replace with map**: data-tagged switch → lookup table.
|
|
- **Sealed pattern match**: 매 modern lang 의 exhaustive 의 보장.
|
|
|
|
### 매 응용
|
|
1. AST visitor (legitimate switch).
|
|
2. State machine (legitimate).
|
|
3. Domain logic dispatch (refactor to polymorphism).
|
|
|
|
## 💻 패턴
|
|
|
|
### Smell — type-tagged switch
|
|
```java
|
|
// BAD
|
|
double area(Shape s) {
|
|
switch (s.type) {
|
|
case CIRCLE: return Math.PI * s.radius * s.radius;
|
|
case SQUARE: return s.side * s.side;
|
|
case TRIANGLE: return 0.5 * s.base * s.height;
|
|
default: throw new IllegalStateException();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Refactor — polymorphism
|
|
```java
|
|
sealed interface Shape permits Circle, Square, Triangle {
|
|
double area();
|
|
}
|
|
record Circle(double r) implements Shape {
|
|
public double area() { return Math.PI * r * r; }
|
|
}
|
|
record Square(double side) implements Shape {
|
|
public double area() { return side * side; }
|
|
}
|
|
record Triangle(double base, double h) implements Shape {
|
|
public double area() { return 0.5 * base * h; }
|
|
}
|
|
// caller: shape.area()
|
|
```
|
|
|
|
### Java 21 — pattern matching switch (exhaustive)
|
|
```java
|
|
double area(Shape s) {
|
|
return switch (s) {
|
|
case Circle c -> Math.PI * c.r() * c.r();
|
|
case Square sq -> sq.side() * sq.side();
|
|
case Triangle t -> 0.5 * t.base() * t.h();
|
|
// no default — compiler proves exhaustive
|
|
};
|
|
}
|
|
```
|
|
|
|
### Kotlin — sealed when
|
|
```kotlin
|
|
sealed class Event
|
|
data class Click(val x: Int, val y: Int) : Event()
|
|
data class Key(val code: Int) : Event()
|
|
object Close : Event()
|
|
|
|
fun handle(e: Event) = when (e) {
|
|
is Click -> "click at ${e.x},${e.y}"
|
|
is Key -> "key ${e.code}"
|
|
Close -> "bye"
|
|
} // exhaustive — no else needed
|
|
```
|
|
|
|
### Rust — match
|
|
```rust
|
|
enum Msg { Quit, Move { x: i32, y: i32 }, Write(String) }
|
|
|
|
fn process(m: Msg) {
|
|
match m {
|
|
Msg::Quit => println!("quit"),
|
|
Msg::Move { x, y } => println!("move to {x},{y}"),
|
|
Msg::Write(s) => println!("write {s}"),
|
|
}
|
|
}
|
|
```
|
|
|
|
### Replace with map (data dispatch)
|
|
```typescript
|
|
// BAD
|
|
function fmt(t: string, v: number): string {
|
|
switch (t) {
|
|
case "usd": return `$${v}`;
|
|
case "eur": return `€${v}`;
|
|
case "krw": return `₩${v}`;
|
|
}
|
|
}
|
|
|
|
// GOOD
|
|
const PREFIX: Record<string, string> = { usd: "$", eur: "€", krw: "₩" };
|
|
const fmt = (t: string, v: number) => `${PREFIX[t] ?? ""}${v}`;
|
|
```
|
|
|
|
### Replace with strategy
|
|
```python
|
|
class Discount(Protocol):
|
|
def apply(self, price: float) -> float: ...
|
|
|
|
class Pct(Discount):
|
|
def __init__(self, p): self.p = p
|
|
def apply(self, price): return price * (1 - self.p)
|
|
|
|
class Fixed(Discount):
|
|
def __init__(self, amt): self.amt = amt
|
|
def apply(self, price): return max(0, price - self.amt)
|
|
|
|
# caller injects Discount, no switch
|
|
```
|
|
|
|
## 매 결정 기준
|
|
| 상황 | Approach |
|
|
|---|---|
|
|
| Type dispatch (open set) | Polymorphism |
|
|
| Type dispatch (closed set) | Sealed + pattern match |
|
|
| Data lookup | Map / dict |
|
|
| Complex behavior swap | Strategy pattern |
|
|
| AST / state machine | Switch (legitimate) |
|
|
|
|
**기본값**: 매 sealed types + exhaustive pattern matching — 매 modern lang 의 ergonomic + safe.
|
|
|
|
## 🔗 Graph
|
|
- 부모: [[Code Smells]] · [[Refactoring_Best_Practices|Refactoring]]
|
|
- 변형: [[Pattern Matching]] · [[Polymorphism]]
|
|
- 응용: [[State Machine]] · [[Visitor Pattern]] · [[ADT]]
|
|
- Adjacent: [[Open-Closed Principle]]
|
|
|
|
## 🤖 LLM 활용
|
|
**언제**: 매 switch 의 detect 의 refactor suggestion, type 의 sealed 의 propose.
|
|
**언제 X**: legitimate switch (AST, state machine) 의 전체 refactor 의 — 매 false positive.
|
|
|
|
## ❌ 안티패턴
|
|
- **Refactor every switch**: 매 legitimate cases 의 보존 — AST, parser.
|
|
- **Visitor for trivial dispatch**: 매 over-engineering — 매 polymorphism 의 충분.
|
|
- **Strategy without need**: 매 single-impl 의 strategy 의 yagni.
|
|
|
|
## 🧪 검증 / 중복
|
|
- Verified (Fowler, "Refactoring" 2nd ed.; Effective Java 3rd ed.; JEP 441).
|
|
- 신뢰도 A.
|
|
|
|
## 🕓 Changelog
|
|
| 날짜 | 변경 |
|
|
|---|---|
|
|
| 2026-05-08 | Phase 1 |
|
|
| 2026-05-10 | Manual cleanup — refactor patterns, modern pattern matching |
|