重構出更加swifty的程式碼
原文
不小心在推特上瀏覽到一個文章,很好的詮釋了什麼是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") { ... }
// ...
這特麼是什麼鬼程式碼,別人維護起來得多痛苦,尤其是銀行玩點么蛾子多改下的時候,修改這些程式碼簡直是噩夢
Option 2:正則大法
現在我們用正則來替代if大法
//amex starts with 34 or 37 and is 15 digits
case .amex:
return "^3[47][0-9]{13}$"
很cooool 很簡潔是吧,現在來看看.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]
現在判斷的規則是不是變的相當的簡潔明瞭,如何做到呢,你可以先看程式碼 CardParser.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
強大的協議
待續
相關文章
- 程式碼重構--大話重構
- 程式碼重構
- 程式碼重構之法——方法重構分析
- 程式碼重構:類重構的 8 個小技巧
- .NET重構—單元測試的程式碼重構
- 重構你的javascript程式碼JavaScript
- “硬核”程式碼重構
- 重構 PHP 程式碼PHP
- PHP程式碼重構PHP
- 程式碼重構(四)
- 程式碼重構:函式重構的 7 個小技巧函式
- 程式碼的壞味道和重構
- 程式碼重構技巧(二)
- 談談程式碼重構
- 【讀程式碼重構有感】
- 重構:程式碼異味
- 架構重構--改善既有程式碼的設計架構
- Groovy探索 使用集合方法,寫出更加Groovy風格的程式碼
- 重構:改善既有程式碼的設計
- 重構-改善既有程式碼的設計
- 重構程式碼的7個階段
- 怎樣寫出漂亮整潔的程式碼?聊聊 Clean Code 的編碼、重構技巧
- 程式碼重構那些事兒
- 重構 - 程式碼優化技巧優化
- 日記9(程式碼重構)
- 重構 - 程式碼整潔之道
- 重構之提煉程式碼
- 如何讓自己的程式碼更加安全?
- 重構:改善既有程式碼的設計(第二版讀書筆記) - 重構、壞程式碼、寫好程式碼筆記
- 重構改善既有的程式碼設計(重構原則)
- [譯] 重寫 loadView() 方法使 Swift 檢視程式碼更加簡潔ViewSwift
- 《重構——改善既有程式碼的設計》感想
- 重構:幹掉有壞味道的程式碼
- 程式碼重構與單元測試——“提取方法”重構(三)
- 重構程式碼(應如寫詩)
- 記一次程式碼重構
- 高效重構 C++ 程式碼(下)C++
- 高效重構 C++ 程式碼(上)C++