수행 내용
- 자신이 제작한 구구단 코드 소개
- 상호 코드 리뷰
- 구성원 간 페어 프로그래밍을 통한 구구단 코드 재작성
- Driver, Navigator, Observer 구성으로 진행
- Swift 문법 학습
학습 내용
다른 사람의 코드에 대한 피드백 방법
코드 작성 시 최대한 의미 단위로 나누어 작성
- 본인의 코드를 설명하기 용이함.
- 코드 리뷰 시 가독성이 좋고 작성자의 의도 및 내용 파악이 용이함.
String Interpolation
- Backslach(\)와 소괄호()를 사용하여 변수 또는 상수로 할당한 값들을 불러올 수 있음.
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
Optional
- 포장된 값(wrapped value) 또는 값이 없음(nil)를 나타내는 타입
- 값이 없는 경우(
nil
)를 대응 가능
- 정수형 예시로,
Optional<Int>
또는 Int?
로 표현 가능
let shortForm: Int? = Int("42")
let longForm: Optional<Int> = Int("42")
- 연산에 이용하고자 할 때 Optional binding 또는 Unconditional Unwrapping을 통해 포장 해제 (unwrap) 후 사용 가능
var serverResponseCode: Int? = 404
serverResponseCode = nil
Optional Binding
- 포장된 optional instance를 새로운 변수에 할당하고자 할 때
if let
, guard let
및 switch case-let
과 같은 조건문을 통해 포장을 해제할 수 있음.
let imagePaths = ["star": "/glyphs/star.png",
"portrait": "/images/content/portrait.jpg",
"spacer": "/images/shared/spacer.gif"]
if let starPath = imagePaths["star"] {
print("The star image is at '\(starPath)'")
} else {
print("Couldn't find the star image")
}
if let
, guard let
모두 optional instance가 해당 자료형
또는 nil
이 반환되었을 경우에 대한 대응을 할 수 있으나, 아래와 같은 차이점이 있음
if let
: 선언한 변수가 if
문 안에서만 사용될 수 있음
guard let
: 선언한 변수를 guard
문이 실행된 아래 코드부터 함수 내부의 지역상수처럼 사용할 수 있음.
Optional Chaining
- 포장이 해제된 인스턴스의 프로퍼티 혹은 메서드에 안전하게 접근하고자 할 때 접미사 ‘?’를 사용
- Optional에 속해 있는
nil
일지 모르는 프로퍼티, 메서드, 서브스크립션 등을 가져오거나 호출할 때 사용할 수 있음.
- 중첩된 optional 중 하나라도 nil이면 nil을 반환
if imagePaths["star"]?.hasSuffix(".png") == true {
print("The star image is in PNG format")
}
Unconditional Unwrapping
if let
, guard let
, switch case-let
과 같은 조건문을 거치지 않고 무조건으로 포장을 해제하는 방법. nil
입력이 없음을 확신할 때 사용 가능하나, nil
입력을 받을 경우 런타임에러를 일으키므로 optional binding 사용 권장.
let number = Int("42")!
print(number)
- 접미사 ‘!’를 사용하여 unconditional optional chaining 가능
let isPNG = imagePaths["star"]!.hasSuffix(".png")
print(isPNG)
Nil-Coalescing Operator
- 해당 operator(??)를 사용하여 optional instance가
nil
인 경우 default값을 불러올 수 있음.
let defaultImagePath = "/images/default.png"
let heartPath = imagePaths["heart"] ?? defaultImagePath
print(heartPath)
문제점 / 고민한 점
- 클래스 내의 한 함수를 얼마나 작은/큰 의미 단위로 나누어 표현해야 하는가?
- 타입 변환 시 optional의 unwrapping 방법
- 문자형 입력(
readLine()
)의 조건문 처리 시 정수형 입력(-1, 0, 1)과 문자형 입력(“exit”)을 나누어 처리하거나 한 가지 타입으로 처리하는 방법
- String Interpolation 사용을 위해
readLine()
으로 입력 받은 문자형 입력값을 어느 시점에 정수형으로 변환하여야 하는가?
- 구현 방법의 정당성에 대한 고민
- 왜
for
문이 아니라 while
문을 사용하였는가?
guard let
과 if let
중 if let
을 사용한 이유는?
해결 방법
미해결
- 코드 작성 시 어떤 크기의 의미 단위로 나누어 함수로 표현해야 하는지에 대한 조사와 경험이 더 필요하다. 현재로써는
print(“종료”)
와 같이 한 줄로 의미 파악이 가능한 단위까지는 쪼개어 별도로 나타내지 않는 것이 더 좋지 않을까 생각한다. 하지만 종료 구문에 특정 동작을 넣거나 로그를 남겨야 할 것을 대비하여 따로 떼어놓는 것도 합리적이라고 생각한다. 의견 교환이 필요함.
해결
- Optional의 unwrapping에
if let
, guard let
, unconditional unwrapping
이 검토되었으나, nil
입력이 가능하고, 조건문 사용을 위해 선언된 변수가 해당 구문 밖에서 사용될 필요가 없었기에 if let
을 사용하여 optional을 unwrapping하였다.
readLine()
으로 입력 받은 문자형 입력을 if
또는 switch
를 통해 조건문 처리가 가능한 상황에서 비교적 간결하게 표현 가능한 switch
문을 사용하기로 결정하였다. “exit” 입력에 따른 코드 종료를 처리하기 위해 readLine()
입력값의 자료형 변환 없이 문자형으로 switch
판단식에 넣되 -1, 0, 1을 “-1”, “0”, “1”과 같은 문자형으로 변환하여 조건문에 활용하는 방식으로 특정 입력값에 대한 출력이 가능하게 하였다.
- 구구단 출력을 위해 문자형 입력값을 정수형으로 변환하는 시점은 정수형이 사용되는 시점인
switch
문의 default
(구구단 출력부)에서 수행하였다.
- 예상치 않은 입력(정수와 “exit” 이외의 입력)은
switch
의 default
에서 Optional String을 Optional Int로 변환하는 과정에서 nil
이 될 것이므로 if let
의 else
부에 작동할 내용을 작성하였다.
공부할 것 (모르는 것)
- 서브스크립션(용어)
- switch case-let의 사용
- Optional Chaining의 사용
- 한 함수에 어떠한 의미 단위까지 포함할 것인가
참고 링크