天天看點

是什麼使代碼 “Swifty”? —— Expressive

Swift的官方網站上的About頁面列出了三個關鍵字:

  • 安全(Safe):為了最大限度地減少開發人員的錯誤;
  • 迅速(Fast):執行的速度要快;
  • 表現力(Expressive):因為Swift的目标是盡可能清晰易懂。

是什麼使代碼 “Swifty”? —— Safe 介紹了如何有選擇地使用類型系統的各個方面和功能,以使我們的代碼更易于了解和使用。

是什麼使代碼 “Swifty”? —— Fast 介紹了如何利用系統的一些内置方法來提示性能

是什麼使代碼 “Swifty”? —— Expressive

Swifty Code —— Expressive

清晰明确的命名(Clear, expressive naming)

最後,讓我們看一下第三個關鍵字——富有表現力(Expressive)。盡管很容易将表現力視為純粹的修飾,并且涉及挑剔的方法名稱,直到它們都被閱讀成文法上完美的英語句子為止,但最終還是要使我們的代碼清楚地傳達其含義。

假設我們編寫了一個目前稱為

getContent

的函數,該函數會為捆綁的

Content

模型加載資料,然後對其進行解碼:

func getContent(name: String) -> Content? {
    guard let url = Bundle.main.url(
        forResource: name,
        withExtension: "json"
    ) else {
        return nil
    }

    guard let data = try? Data(contentsOf: url) else {
        return nil
    }

    return try? JSONDecoder().decode(Content.self, from: data)
}           

複制

同樣,乍看之下,上面的功能似乎非常好。沒有明顯的錯誤,可以完成工作。但是,就表達能力而言,絕對可以改進。

首先,它的目前名稱“get content”并沒有真正告訴我們如何檢索内容。

  • 是否将其簡單地建立為新執行個體?
  • 是否将其通過網絡加載或其他?
  • 此外,萬一發生錯誤,它僅傳回

    nil

    的事實會使萬一發生任何故障而使調試變得更加困難——因為我們将無法得知實際出了什麼問題。

是以,讓我們先将功能重命名為

loadBundledContent

(以明确我們正在從應用程式包中加載内容),看看我們是否可以改善這些問題。我們還将為它提供一個外部參數标簽,使它讀起來更好一些,最後,使它通過抛出它來報告遇到的任何錯誤,如下所示:

func loadBundledContent(named name: String) throws -> Content {
    guard let url = Bundle.main.url(
        forResource: name,
        withExtension: "json"
    ) else {
        throw Content.Error.missing
    }

    guard let data = try? Data(contentsOf: url) else {
        throw Content.Error.missing
    }

    do {
        return try JSONDecoder().decode(Content.self, from: data)
    } catch {
        throw Content.Error.decodingFailed(error)
    }
}           

複制

有關上述設計抛出API的方式的更多資訊,請檢視Swift: 提供統一的錯誤API。

更改前後,調用的對比如下:

// Before
let content = getContent(name: "Onboarding")

// After
let content = try loadBundledContent(named: "Onboarding")           

複制

重要的是不要過分依賴我們命名的函數和類型(畢竟,通常這取決于口味和偏好),但如果我們能夠找到更清晰地傳達每個API的功能的方法,那巨大的勝利——因為它不僅使新開發人員更容易熟悉我們的代碼庫,而且通常還可以使我們的代碼更加愉快的長期使用。

結語

在我看來,編寫“ Swifty”代碼不是要使用盡可能多的語言功能,也不是通過部署Swift的最進階功能來解決簡單的問題來使我們的代碼不必要地變得複雜——而是要調整我們設計和表達代碼的方式,并它具有Swift的核心原則集的各種API。

通過充分利用标準庫,并通過表達性命名和API設計傳達我們的代碼意圖,使我們的代碼使用Swift的類型系統來確定正确性并使其功能更加清晰,我們常常最終得到了更好的代碼比對Swift本身,這難道不是編寫“ Swifty Code”要講述的嗎?

文章來自 John Sundell的What makes code “Swifty”?中關于Expressive的内容

是什麼使代碼 “Swifty”? —— Safe 介紹了如何有選擇地使用類型系統的各個方面和功能,以使我們的代碼更易于了解和使用。

是什麼使代碼 “Swifty”? —— Fast 介紹了如何利用系統的一些内置方法來提示性能