是什么使代码 “Swifty”? —— Expressive

2020-03-20 16:19:04 浏览数 (1)

Swift的官方网站上的About页面列出了三个关键字:

  • 安全(Safe):为了最大限度地减少开发人员的错误;
  • 迅速(Fast):执行的速度要快;
  • 表现力(Expressive):因为Swift的目标是尽可能清晰易懂。

是什么使代码 “Swifty”? —— Safe 介绍了如何有选择地使用类型系统的各个方面和功能,以使我们的代码更易于理解和使用。

是什么使代码 “Swifty”? —— Fast 介绍了如何利用系统的一些内置方法来提示性能

Swifty Code —— Expressive

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

最后,让我们看一下第三个关键字——富有表现力(Expressive)。尽管很容易将表现力视为纯粹的修饰,并且涉及挑剔的方法名称,直到它们都被阅读成语法上完美的英语句子为止,但最终还是要使我们的代码清楚地传达其含义。

假设我们编写了一个当前称为getContent的函数,该函数会为捆绑的Content模型加载数据,然后对其进行解码:

代码语言:javascript复制
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(以明确我们正在从应用程序包中加载内容),看看我们是否可以改善这些问题。我们还将为它提供一个外部参数标签,使它读起来更好一些,最后,使它通过抛出它来报告遇到的任何错误,如下所示:

代码语言:javascript复制
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。

更改前后,调用的对比如下:

代码语言:javascript复制
// 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 介绍了如何利用系统的一些内置方法来提示性能

0 人点赞