더욱 swifty 코드를 재구성

3629 단어
원문은 실수로 트위터에서 한 문장을 훑어보았는데 swifty의 swift 코드가 무엇인지 잘 설명하였다.신용카드 유형을 어떻게 측정하는가, 매개 변수는 아래 표에 나와 있다(주요 4개, 그리고 각종 난장판도 있다)
Issuing Network
IIN ranges
Card Number Length
American Express
34, 37
15
MasterCard
51–55,2221–2720
16
Visa
4
13, 16, 19
Discover
65,6011,644–649,622126–622925
16, 19

Option 1: if 대법


먼저 가장 거친 알고리즘을 시도해 보자.
4로 시작하면visa, 3으로 시작하면 Amex, Diners, or JCB, 6로 시작하면 Discover
여기에 이미 만들어진 코드인 PaymentKit가 있는데, swift로 번역하면 대개 이렇다
// ...
// Discover
if cardString.hasPrefix("6011") || cardString.hasPrefix("65") {
    return .discover
}
else if cardString.hasPrefix("622") {
    // If the number has a prefix in the range 622126-622925, it's Discover
    let prefixLength = 6;
    if (cardString.characters.count >= prefixLength) {
        let prefixIndex = number.index(cardString.startIndex, offsetBy: prefixLength)
        let sixDigitPrefixString = cardString.substring(to: prefixIndex)
        let sixDigitPrefixInt = Int(sixDigitPrefixString)!
        if sixDigitPrefixInt >= 622126 && sixDigitPrefixInt <= 622925 {
            return .discover;
        }
    }
    return .unknown
}
else if cardString.hasPrefix("64") { ... }
// ...

이게 무슨 꿍꿍이수작이야, 다른 사람이 얼마나 고통스러워하는지, 특히 은행이 조그마한 수단을 써서 많이 고칠 때, 이 코드들을 수정하는 것은 정말 악몽이야.

Option2: 정규 대법


지금 우리는 정규로if대법을 대체한다
//amex starts with 34 or 37 and is 15 digits
case .amex:
    return "^3[47][0-9]{13}$"

쿨하고 깔끔하죠? 지금 봅시다.masterCard:
//MasterCard starts with 51 through 55 
//or 2221 through 2720. All have 16 digits.
case .masterCard:
   return "^(?:5[1-5][0-9]{2}|" +
            "222[1-9]|" +
            "22[3-9][0-9]|" +
            "2[3-6][0-9]{2}|" +
            "27[01][0-9]|" +
            "2720)" +
            "[0-9]{12}$"
...

흑인 물음표???정규 표현식은 매우 강력한 도구이지만 정규 표현식은 수치 범위를 표현할 때 그다지 우아해 보이지 않는다. 이런 가변 길이의 숫자는 말할 것도 없고 이해하기 어렵다. 이것도pass이다.

보다 간결한 역점 코드:


우리가 사용하는 것은 swift이다. 분명히 비슷한 상황을 처리하는 더 좋은 방법이 있을 것이다. 먼저 컴파일러의 비웃음을 바꾸지 말고 위조 코드를 먼저 쓴다.
case .amex:         prefix = ["34", "37"]
                    length = [15]
 
case .diners:       prefix = ["300"..."305", "309", "36", "38"..."39"]
                    length = [14]
 
case .discover:     prefix = ["6011", "65", "644"..."649", "622126"..."622925"]
                    length = [16]
 
case .jcb:          prefix = ["3528"..."3589"]
                    length = [16]
 
case .masterCard:   prefix = ["51"..."55", "2221"..."2720"]
                    length = [16]
 
case .visa:         prefix = ["4"]
                    length = [13, 16, 19]

지금 판단하는 규칙이 상당히 간결하고 명료해졌는지, 어떻게 해야 할지, 당신은 먼저 코드카드 파서스를 볼 수 있습니다.swift.

강력한 ENUM:


CardType은 swift의 중간 매거 유형입니다. swift 매거는 강력한 무기로 패턴 매칭을 할 수 있을 뿐만 아니라 규칙도 검증할 수 있습니다.
enum CardType {
    case visa
    case masterCard
    ...
 
    var segmentGroupings: [Int] {...}
    var cvvLength: Int {...}
    ...
 
    func isValid(_ accountNumber: String) -> Bool {...}
    func isPrefixValid(_ accountNumber: String) -> Bool {...}
}

visa.cvvLength          // 3
visa.isPrefixValid("4") // true
visa.isValid("4")       // false

강력한 프로토콜


계속

좋은 웹페이지 즐겨찾기