重構出更加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 個小技巧
- 重構你的javascript程式碼JavaScript
- “硬核”程式碼重構
- 重構 PHP 程式碼PHP
- 程式碼重構:函式重構的 7 個小技巧函式
- 程式碼的壞味道和重構
- 【讀程式碼重構有感】
- 談談程式碼重構
- 程式碼重構技巧(二)
- [譯] 重寫 loadView() 方法使 Swift 檢視程式碼更加簡潔ViewSwift
- 如何讓自己的程式碼更加安全?
- 重構:改善既有程式碼的設計(第二版讀書筆記) - 重構、壞程式碼、寫好程式碼筆記
- 程式碼重構那些事兒
- 重構改善既有的程式碼設計(重構原則)
- leobert重構程式碼二三事--一.可怕的低階程式碼
- 重構:幹掉有壞味道的程式碼
- 《重構——改善既有程式碼的設計》感想
- 程式碼重構與單元測試——“提取方法”重構(三)
- 重構程式碼(應如寫詩)
- 記一次程式碼重構
- 基礎程式碼重構的若干建議(一)
- JS 程式碼的簡單重構與優化JS優化
- 重構 - 改善程式碼的各方面問題
- 程式碼重構與單元測試——重構1的單元測試(四)
- 專案的改造——RemoveButterKnife外掛程式碼的重構REM
- 簡單的3步,重構我們的程式碼
- jscodeshift入門簡介&程式碼重構&程式碼分析&&ReactJSReact
- 你的 JS 程式碼本可以更加優雅JS
- 程式碼重構-業務中臺化
- 3個例子教你重構 Python 程式碼Python
- 6 個例子教你重構 Python 程式碼Python
- 出庫重構
- 程式碼重構與單元測試——對方法的引數進行重構(五)
- 重構聚合支付案例教你如何寫出高擴充套件性易讀的程式碼套件
- 重構-改善既有程式碼的設計(七)– 在程式碼之間搬移特性
- 程式碼重構之道:消滅冗長的if語句,提升程式碼質量
- 使用職責鏈模式來重構你的程式碼模式
- 還重構?就你那程式碼只能鏟了重寫!