Remove if-else repetition
Clean Code - Part 1
1. If-Else Repetition π©βπ»
1. Swift
func beverage(_ num: Int) -> String {
if (num == 0) {
return "Juice";
} else if (num == 1) {
return "Soda";
} else if (num == 2) {
return "Beer";
} else if (num == 3) {
return "Wine";
} else if (num == 4) {
return "Tequila";
} else {
return "Water";
}
}
print(beverage(0)) // Juice
print(beverage(3)) // Wine
print(beverage(5)) // Water
2. TypeScript
const beverage = (num: number): string => {
if (num === 0) {
return 'Juice';
} else if (num === 1) {
return 'Soda';
} else if (num === 2) {
return 'Beer';
} else if (num === 3) {
return 'Wine';
} else if (num === 4) {
return 'Tequila';
} else {
return 'Water';
}
};
console.log(beverage(0)) // Juice
console.log(beverage(3)) // Wine
console.log(beverage(5)) // Water
μΌμ νλ©΄μ if-else if-else if-else if...-else
μ΄λ°μμΌλ‘ 50κ°μ 쑰건μ μ°κ²°ν μ½λλ₯Ό λ³Έ μ μ΄ μλ€. π±
μ΄λ°μμ μ½λλ κ°λ
μ±λ λμμ§λ§ 쑰건 κ²μ¬λ₯Ό μ΅μ
μ κ²½μ°μ if, else if μ κ°μλ§νΌ κ²μ¬ν΄μΌνλ μ΅μ
μ Control Flow μκ³ λ¦¬μ¦μ΄ νμνκ²
λλ€. κ°μΈμ μΌλ‘λ μ‘°κ±΄μ΄ 3κ°μΌ κ²½μ°λ κ·Έλ₯ if-else if-else
λ₯Ό μ¬μ©νκ±°λ, if
& Ternary Operator
λ₯Ό μ¬μ©νκ³ , 4κ° μ΄μμΌ κ²½μ°
switch
λλ Key-Value
Types λ₯Ό μ¬μ©νκ³€ νλ€.
2. Switch-Case π©βπ»
μμ κ°μ λ¬Έμ λ₯Ό κ°μ₯ μ½κ² ν΄κ²°ν μ μλ λ°©λ²μ Switch-Case
λ₯Ό μ¬μ©νλ κ²μ΄λ€.
1. Swift
func beverage(_ num: Int) -> String {
switch num {
case 0: return "Juice"
case 1: return "Soda"
case 2: return "Beer"
case 3: return "Wine"
case 4: return "Tequila"
default: return "Water"
}
}
print(beverage(0)) // Juice
print(beverage(3)) // Wine
print(beverage(5)) // Water
μκΉλ³΄λ€ κ°λ μ±μ΄ ν¨μ¬ μ’μμ‘μ λΏ μλλΌ, Hashable Key λ₯Ό μ΄μ©ν΄ Jump Table μ νλ―λ‘ μ±λ₯ λν μ’μμ‘λ€.
2. TypeScript
const beverage = (num: number): string => {
switch (num) {
case 0:
return 'Juice'
case 1:
return 'Soda'
case 2:
return 'Beer'
case 3:
return 'Wine'
case 4:
return 'Tequila'
default:
return 'Water'
}
}
console.log(beverage(0)) // Juice
console.log(beverage(3)) // Wine
console.log(beverage(5)) // Water
κ°μΈμ μΌλ‘ λλΆλΆμ IDE λ λ¬Όλ‘ μ΄κ³ Prettier κ° case μ body λ₯Ό κ°μ μ€λ°κΏ νλ κ²μ΄ λ§μμ λ€μ§ μλλ€. μ€νλ € Dirty Code κ° λλ λλμ΄λκΉ? κ·Έλμ Clean Code μμ Key-Value Types λ₯Ό κΆμ₯νλ κ²μΈκ° μΆκΈ°λ νλ€.
Caution
JavaScript language overview λ₯Ό 보면 λ€μκ³Ό κ°μ΄ λμ¨λ€.
Similar to C, case clauses are conceptually the same as labels, so if you donβt add a break statement, execution will βfall throughβ to the next level. However, they are not actually jump tables β any expression can be part of the case clause, not just string or number literals, and they would be evaluated one-by-one until one equals the value being matched. Comparison takes place between the two using the
===
operator.μ¦, JavaScript μμ Switch λ Hash Table μ μ΄μ©ν Jump λ₯Ό νμ§ μμΌλ―λ‘ μ±λ₯μ μ΄μ μ μλ κ²μΌλ‘ 보μΈλ€.
λ§μ§λ§μΌλ‘ λ€μ μΉμ μμ Switch-Case λ§μ λ μ κ±°ν΄λ³΄λλ‘ νμ.
3. Key-Value Types π©βπ»
μ¬μ€ Switch-Case λ Key-Value λͺ¨λ Key μ ν΄λΉνλ λ°μ΄ν°κ° Hashable μ λ§μ‘±ν΄μΌνλ―λ‘ ν° μ°¨μ΄λ μλ€.
νμ§λ§ Swift μμλ Switch-Case μ κ²½μ° μ‘°κ±΄μ λͺ¨λ 컀λ²νμ§ λͺ»νμ κ²½μ° compiler κ° μλ¬λ₯Ό λμμ£Όλλ°, λ§μ½ compile-time μ νμΈμ΄ λΆκ°λ₯ν κ²½μ°κ° μμ κ²½μ°(κ·Έλ° κ²½μ°κ° μμ μ μμκΉβ¦? π) Runtime Error λ‘ μ΄μ΄μ§ μ μλ€.
κ·Έλ¦¬κ³ κ°μΈμ μΌλ‘ Swift μ Switch-Case λ λλ¦ κ°λ
μ± μ’λ€κ³ μκ°νλλ°, TypeScript μ κ²½μ°λ μλκΈ°λ νκ³ , νΉν TypeScript λ
Enumeration μ κ²½μ° κΈ°μ‘΄μ enum
μ JavaScript λ‘ transpile λ λ IIFE
λ‘ λ³νλμ΄ Bundler μ Tree-shaking
μ΄ μλνμ§
μμ λΆνμν μ½λκ° μ κ±°λμ§ μλ λ¬Έμ κ° μλ€.
μ΄λ‘ μΈν΄ as const
λ₯Ό μ¬μ©ν Enumeration μ μΈμ΄ κΆμ₯λλλ°, μ΄κ±Έ μ¬μ©ν κ²½μ° μ΄μ°¨νΌ Object μ΄κΈ° λλ¬Έμ Switch-Case λ₯Ό μ¬μ©ν νμκ°
μμ΄μ Έ λ²λ¦°λ€(TypeScript μ Switch-Case Syntax κ° μ κΉ¨λνμ§ λͺ»ν κ²λ μκ³ β¦ π€).
μλ¬΄νΌ Clean Code μμ λλΆλΆ Switch λ§μ λ Key-Value Types λ‘ λ°κΎΈλ κ²μ κΆμ₯νλ€. λ°λΌμ μ°λ¦¬λ Switch-Case λ₯Ό Key-Value
Types λ₯Ό μ¬μ©ν μ½λλ‘ λ°κΏλ³΄μ.
1. Swift
func beverage(_ num: Int) -> String {
let switcher: [Int: String] = [
0: "Juice",
1: "Soda",
2: "Beer",
3: "Wine",
4: "Tequila"
]
return switcher[num] ?? "Water"
}
[Int, String]
Type μ Dictionary λ₯Ό μ΄μ©νλ€. λ§μ½ μ΄ Dictionary λ₯Ό λ°μΌλ‘ λΉΌλΌ κ²½μ° ν¨μλ λ κ°λ¨ν΄μ§λ€.
let switcher: [Int: String] = [
0: "Juice",
1: "Soda",
2: "Beer",
3: "Wine",
4: "Tequila"
]
func beverage(_ num: Int) -> String {
switcher[num] ?? "Water"
}
κ·Έλ°λ° μ΄λ κ² νλ©΄ λΆνμν λ³μ μ€μΌμ΄ λ°μνλ€. λ§μ½ μ¬μ¬μ©κΉμ§ κ³ λ €ν΄ Switch-Case
λ₯Ό λμ ν λ‘μ§μ λ³λ Utilities λ‘ λ§λ€ κ²½μ°
λ€μκ³Ό κ°μ΄ Currying μν¬ μ μλ€.
func switchCase<Key: Hashable, Value>(switcher: [Key: Value], defaultValue: Value) -> (_ key: Key) -> Value {
{ key in switcher[key] ?? defaultValue }
}
μ΄μ μ΄ Curry Function
μ μ΄μ©ν΄ λ€μ beverage(_:)
λ₯Ό μ μν΄λ³΄μ.
let beverage = switchCase(switcher: [0: "Juice",
1: "Soda",
2: "Beer",
3: "Wine",
4: "Tequila"],
defaultValue: "Water")
print(beverage(0)) // Juice
print(beverage(3)) // Wine
print(beverage(5)) // Water
2. TypeScript
TypeScript μμ μ¬μ©ν μ μλ Key-Value
Types λ Object, Map, Record λ±μ΄ μλ€. Record μΌ μ΄μ°¨νΌ Object λ‘ transpile
λ κ±°κ³ , Object λ Key κ° κ°μ§ μ μλ Types κ° String λΏμ΄λ€. TypeScript μ½λ μμμμΌ Record λ₯Ό μ΄μ©ν΄ Key μ λ€λ₯Έ Types
λ₯Ό μ μν μ μμ§λ§ JavaScript μ½λμμλ μ¬μ©ν μ μλ λ°©λ²μ΄λ€.
λ°λ©΄ Map
μ μ¬μ©ν κ²½μ° Switch-Case μ default
case λ₯Ό μ ν¨νμ§ μμ Key λ‘ μΈμνλ―λ‘ Record
λ₯Ό μ¬μ©νλ κ²μ΄ λ μ’λ€.
λ°λΌμ TypeScript λ²μ μ Record
λ₯Ό μ¬μ©νκ³ , JavaScript λ²μ μ Map
μ μ¬μ©ν΄ κ°κ° ꡬνν΄λ³΄μ.
const beverage = (num: number): string => {
const switcher: Record<number, string> = {
0: "Juice",
1: "Soda",
2: "Beer",
3: "Wine",
4: "Tequila",
}
return switcher[num] ?? "Water"
}
Record<Int, String>
Type μ μ¬μ©νλ€. μ΄ Record λ₯Ό λ°μΌλ‘ λΉΌλ΄λ³΄μ.
const switcher: Record<number, string> = {
0: "Juice",
1: "Soda",
2: "Beer",
3: "Wine",
4: "Tequila",
}
const beverage = (num: number): string => switcher[num] ?? "Water"
λ§μ°¬κ°μ§λ‘ Currying μμΌλ³΄μ.
type Hashable = string | number
const switchCase = <Key extends Hashable, Value, Switcher extends Record<Key, Value>>(switcher: Switcher, defaultValue: Value) => (key: Key) => (
switcher[key] ?? defaultValue
)
μ΄μ μ΄ Curry Function
μ μ΄μ©ν΄ λ€μ beverage(_:)
λ₯Ό μ μν΄λ³΄μ.
const beverage = switchCase({
0: "Juice",
1: "Soda",
2: "Beer",
3: "Wine",
4: "Tequila"
},
"Water")
console.log(beverage(0)) // Juice
console.log(beverage(3)) // Wine
console.log(beverage(5)) // Wate
3. JavaScript
const beverage = (num) => {
const switcher = new Map([
[0, "Juice"],
[1, "Soda"],
[2, "Beer"],
[3, "Wine"],
[4, "Tequila"]
])
return switcher.get(num) ?? "Water"
}
Map<Int, String>
Type μ μ¬μ©νλ€. μ΄ Map μ λ°μΌλ‘ λΉΌλ΄λ³΄μ.
const switcher = new Map([
[0, "Juice"],
[1, "Soda"],
[2, "Beer"],
[3, "Wine"],
[4, "Tequila"]
])
const beverage = (num) => switcher.get(num) ?? "Water"
λ§μ°¬κ°μ§λ‘ Currying μμΌλ³΄μ.
const switchCase = (switcher, defaultValue) => (key) => switcher[key] ?? defaultValue
μ΄μ μ΄ Curry Function
μ μ΄μ©ν΄ λ€μ beverage(_:)
λ₯Ό μ μν΄λ³΄μ.
const beverage = switchCase(new Map([
[0, "Juice"],
[1, "Soda"],
[2, "Beer"],
[3, "Wine"],
[4, "Tequila"]
]),
"Water")
console.log(beverage(0)) // Juice
console.log(beverage(3)) // Wine
console.log(beverage(5)) // Water
4. Enumeration π©βπ»
Switch-Case κ° μ μ©νκ² μ¬μ©λλ κ³³ μ€ νλκ° Enumeration μ Control Flow μ²λ¦¬ ν λλ€. Enumeration μ Control Flow μμ Switch-Case λμ Key-Value λ₯Ό μ μ©ν΄λ³΄μ.
1. Swift
enum CompassPoint: String {
case north, south, east, west
}
- Switch-Case
func directionToHead(_ direction: CompassPoint) -> String {
switch direction {
case .north: return "Lots of planets have a north"
case .south: return "Watch out for penguins"
case .east: return "Where the sun rises"
case .west: return "Where the skies are blue"
}
}
print(directionToHead(.north)) // Lots of planets have a north
- Key-Value
let compassSwithcer: [CompassPoint: String] = [
.north: "Lots of planets have a north",
.south: "Watch out for penguins",
.east: "Where the sun rises",
.west: "Where the skies are blue"
]
func directionToHead(_ direction: CompassPoint) -> String {
compassSwithcer[direction]!
}
print(directionToHead(.east)) // Where the sun rises
- Curry Function
λ§μ°¬κ°μ§λ‘ Curry Function μ μ μ©ν΄λ³΄μ.
let directionToHead = switchCase(switcher: [CompassPoint.north: "Lots of planets have a north",
CompassPoint.south: "Watch out for penguins",
CompassPoint.east: "Where the sun rises",
CompassPoint.west: "Where the skies are blue"],
defaultValue: "Water")
print(directionToHead(.east)) // Where the sun rises
2. TypeScript
- Switch-Case
TypeScript μ Old Syntax μμ μ¬μ©λλ enum
μ μ¬μ©ν κ²½μ°λ λ€μκ³Ό κ°λ€.
enum CompassPoint {
North = "Lots of planets have a north",
South = "Watch out for penguins",
East = "Where the sun rises",
West = "Where the skies are blue"
}
const directionToHead = (direction: CompassPoint): string => {
switch (direction) {
case CompassPoint.North: return "Lots of planets have a north"
case CompassPoint.South: return "Watch out for penguins"
case CompassPoint.East: return "Where the sun rises"
case CompassPoint.West: return "Where the skies are blue"
}
}
console.log(directionToHead(CompassPoint.North)) // Lots of planets have a north
νμ§λ§ Key-Value Types μμ μ€λͺ
νλ―μ΄ IIFE
λ‘ λ³νλ μ½λμ Tree-shaking
λ―Έμλ λ¬Έμ λ‘
Modern TypeScript μμλ const Object as const
κ° κΆμ₯λλ€.
const CompassPoint = {
North: "Lots of planets have a north",
South: "Watch out for penguins",
East: "Where the sun rises",
West: "Where the skies are blue"
} as const
type CompassPointKeys = keyof typeof CompassPoint
const directionToHead = (direction: CompassPointKeys): string => {
switch (direction) {
case "North": return "Lots of planets have a north"
case "South": return "Watch out for penguins"
case "East": return "Where the sun rises"
case "West": return "Where the skies are blue"
}
}
console.log(directionToHead("North")) // Lots of planets have a north
- Key-Value
const directionToHead = (direction: CompassPointKeys): string => CompassPoint[direction]
console.log(directionToHead("East")) // Where the sun rises
const Object as const
λ₯Ό Enumeration μΌλ‘ μ¬μ©ν κ²½μ° μ΄λ―Έ Object κ° μ μλμ΄ μκΈ° λλ¬Έμ λ³λλ‘ μ μν νμκ° μλ€.
μ΄ κ²½μ° μ€νλ € Switch-Case λ₯Ό μ¬μ©νλ κ²μ΄ λΆνμν μ½λλ₯Ό μμ±νκ³ λΆνμν λ‘μ§μ μΆκ°νλ μ
μ΄ λλ€.
λ§μ°¬κ°μ§λ‘ Key-Value λ₯Ό λ°λ‘ μ μν νμκ° μμΌλ―λ‘ Curry Function μμ νμκ° μλ€.
Reference
- βJavaScript language overview.β MDN, May. 04, 2023, JavaScript language overview.