Part 2, 루프와 논리를 단순화 하기
Part 1, 표면적 수준에서의 개선 에서는 코드의 가독성을 좋게하기 위한 방법을 살펴 보았습니다.
이번 장에서는 코드의 복잡한 루프, 거대한 표현, 많은 변수로 이해하기 어려운 코드를 흐름제어(controll flow), 논리식(logical expression), 변수를 단순화 시켜 코드를 이해하기 쉽도록 해보겠습니다.
읽기 쉽도록 흐름제어 만들기 👀
흐름을 제어하는 조건과 루프는 한번에 읽을 수 있도록 노력해야합니다. 해당 흐름을 이해하기 위해 다시 되돌아 가지 않도록 만들어야 합니다.
조건문에서 인수의 순서
조건문에서 변화하는 값을 왼쪽, 안정적인 값을 오른쪽에 놓자!
1
2
3
4
if length >= 10 { }
// not
// if 10 <= length { }
if/else 블록의 순서
- 부정이 아닌 긍정을 다루어라. 즉,
if !debug
가 아니라if debug
를 선호하자! - 쉽고, 확실한 것을 먼저 다루어라.
(삼항 연산자) ? :
이용하는 조건문 표현
삼항 연산자를 사용하면 다음과 같은 코드는 간단하고, 직관적으로 사용할 수 있습니다.
1
time_str += hour >= 12 ? "pm" : "am"
하지만, 한 줄이 넘어가는 삼항 연산자는 “모든 것을 한 줄에 쓰기” 이상 아무것도 아니기 때문에 지양해야 합니다.
중첩을 최소화하기
로직이 중첩이 된다면 코드를 읽으면서 위의 조건을 계속 머리속에 상기해야 되기 때문에 이해를 방해합니다.
1
2
3
4
5
6
7
8
9
10
11
if userResult == .success {
if permissionResult != .success {
reply.writeErrors("error reading permissions")
reply.done()
return
}
reply.writeErrors("")
} else {
reply.writeErrors(userResult)
}
reply.done()
위 코드는 userResult
에서 permissionResult
이라는 조건이 추가 되면서 생성된 코드 입니다.
만약 처음 코드를 보게 된다면 permissionResult
조건문을 볼때, userResult
을 계속 염두에 두고 있어야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if userResult != .success {
reply.writeErrors(userResult)
reply.done()
return
}
if permissionResult != .success {
reply.writeErrors("error reading permissions")
reply.done()
return
}
reply.writeErrors("")
reply.done()
위에 코드는 조건문의 중첩을 없애도 같은 작업을 할 수 있습니다. 이처럼 중첩을 없애면 코드를 읽으면서 한가지 조건만 생각하면 되기 때문에 편하게 읽을 수 있습니다.
거대한 표현을 잘게 쪼개기 🪚
거대한 표현을 더 소화하기 쉽도록 여러 조각으로 나눠야 합니다.
설명 변수
커다란 표현을 쪼개는 쉬운 방법은 작은 하위표현을 설명변수를 만드는것입니다.
1
if line.split(':')[0].strip() == "root" { }
위 코드는 "root"
가 무엇을 뜻하는지 알수 없습니다. 설명변수를 추가한다면
1
2
let username = line.split(':')[0].strip()
if username == "root" { }
요약 변수
중복되는 조건 코드는 따로 네이밍을 해두는 것이 좋습니다!
1
2
3
4
5
6
7
if request.user.id == document.ownerId {
// 사용자가 이 문서를 수정할 수 있다...
}
if request.user.id != document.ownerId {
// 문서는 읽기 전용이다...
}
위의 코드에서는 request.user.id == document.ownerId
라는 중복코드가 발생합니다.
1
2
3
4
5
6
7
8
9
let userOwnsDocument = (request.user.id == document.ownerId)
if userOwnsDocument {
// 사용자가 이 문서를 수정할 수 있다...
}
if userOwnsDocument {
// 문서는 읽기 전용이다...
}
이렇게 따로 변수로 네이밍 했을 경우에는, userOwnsDocument
개념으로 쉽게 읽을 수 있습니다.
드모르간의 법칙 사용하기
not
연산자는 한번에 사용하지 말고 분배하여 사용하자!
1
2
3
// if !(fileExists && !isProtected) { Error("미안합니다. 파일을 읽을 수 없습니다.") }
// 보다는
if !fileExists && isProtected { Error("미안합니다. 파일을 읽을 수 없습니다.") }
변수와 가독성 📝
프로그램에서 변수는 덜 사용하고, 최대한 ‘가볍게’ 만들어야 가독성을 높을 수 있습니다.
변수를 제거하기
- 불필요한 임시 변수들 삭제
- 중간 결과 삭제
- 흐름 제어 변수 제거
각 변수의 범위를 최대한 작게 줄여라
private
을 이용하여 독립성을 각인 시키자.- 커다란 클래스를 여러 작은 클래스로 나누자.
- 각각의 변수는 사용하기 바로 직전 위치로 옮기자.
값이 한 번만 할당되는 변수를 선호하라.
let
을 이용하여, 최대한 변수가 변경되는 범위를 줄이자.