Calculator_6

봄이아빠·2024년 11월 25일
1

Sparta Project

목록 보기
6/10
post-thumbnail

Refactoring

공부하기 전에 책상을 꼭 치워야 하는 사람이 있다.
새로운 기능을 넣기 전에 코드 정리를 꼭 하고 싶은 사람도 여기 있다.

길다,,

이것도..

여기도 길다..

하나 더,,

...

case

enum Numbers: Equatable, Hashable {
        case one, two, three, four, five, six, seven, eight, nine, zero, dot
    }
    
    enum Symbols: Equatable, Hashable {
        case plus, minus, multiply, divide, equal, percent, negate, clear, allClear
    }

위에서부터 하나씩 블립시켜보겠다.
여기는 사실 원시값을 넣게 되면 어쩔 수 없이 늘어나겠지만 일단 줄여두었다.

==

다음 코드는 Equatable을 준수할 때 비교 연산인 ==를 정의해준 부분이다.
지난 숫자야구 게임을 만들 때 가장 상위 열거형에 Equatable을 준수했음에도 Hashable과 더불어 관련 메서드가 자동으로 구현되지 않았다.
이때 자동 구현이 안 될때의 해결방법으로 수동 구현을 배워서 내부 연관값으로 열거형을 추가하면 무조건 수동 구현을 해줘야 한다고 잘못알고 있었다.
자동 구현이 되지 않았던 이유는 내부연관값에 해당 프로토콜을 준수시키지 않아서였다.
따라서 이 코드는 바로 삭제했다.


내부 연관값에도 프로토콜을 잘 준수시키자.

getButtonCase()

이번 메서드는 문자열에 따라 열거형 케이스를 반환시켜준다.

우선 1:1 매핑이 필요하니 스위치문보다 딕셔너리가 더 빠르게 접근할 수 있어서 좋다고 판단된다.
코드 또한 더 간소화됐다.

buttonTitle()

케이스에 따른 문자열 반환 메서드는 개선 방법에 2가지가 존재한다.
1. 케이스의 원시값을 추가하여 원시값 반환받기
2. getButtonCase()에 사용하기 위해 선언한 딕셔너리를 활용하기

원시값을 설정한다면 컴파일러가 타입을 체크해준다. 성능상으로도 좀 더 낫다고 한다. 대신 매핑이 두 곳으로 분산되고 원시값을 지정해주는 추가적인 작업이 필요하다.
딕셔너리를 활용한다면 하나의 자료구조에서 매핑이완료되므로 간결하다. 대신 런타임까지 매핑 에러를 발견하기 어렵고 해시테이블 조회로 인해 약간의 성능 오버헤드가 발생한다.

이미 길게 선언해둔 딕셔너리를 재사용할 수 있으면 좋겠지만 그래도 성능적으론 원시값을 가진 것이 더 빠르니 원시값으로 처리해보겠다.
(사실 애초에 연관값은 원시값을 아예 못가진다고 애매하게 알아서 만들었다. 원시 좋아.)

  private var buttonTitle: String {
        switch self {
        case .number(let number):
            return number.rawValue
        case .symbol(let symbol):
            return symbol.rawValue
        }
    }

getCalculateDictionary()

드디어 마지막 메서드다.
0...9가 모두 동일하게 numberTapped(num:)을 추가하기 때문에 반복문으로 추가해주면 좋을 것이다.
반복문에서 사용하기 위해 Buttons.Numbers에만 추가적으로 CaseIterable을 준수해주었다.

 Buttons.Numbers.allCases.forEach { number in
	dictionary[.number(number)] = {[weak self] in
		guard let self = self else { return }
		self.numberTapped(num: text)
	}
}

고차함수 forEach를 사용해주면 이렇게 중복 코드를 모두 지울 수 있게 된다!

Result

beforeafter

이건 마지막 클로저 딕셔너리의 전후사진이다.
열거형의 코드도 이전 미니맵을 찍어둘걸 아쉽다.
리팩터링을 해보니 사실 처음부터 이렇게 짜나갈 수 있을 정도의 코드였는데 경험이 부족해서인지 맘이 조급해서인지 바로바로 생각이 안 났다.
다시 한 번 많이 경험해봐야겠다고 생각이 드는 리팩터링 시간이었다.

0개의 댓글