设计域时更喜欢可选还是非可选?

Prefer optional or non-optional when designing domain?

在为我的应用程序定义模型时,我应该声明哪些属性是可选的,哪些是非可选的?我需要考虑哪些方面?

例如,我想创建实体 Carengine 应该是什么类型?

struct Car {
    let engine: Engine?
}

struct Car {
    let engine: Engine

    init(engine: Engine) {
        self.engine = engine
    }
}

struct Car {
    let engine: Engine = Engine()
}

简介

我们中的许多人(包括我在内)都不熟悉这个问题。

事实上 Objective-C(以及许多其他语言,如 C、Java 1...7 等...)强制使用基本类型(Int、Double、... ) 总是 被填充。 而且他们还总是将 reference/pointer 变量强制设置为 始终可能为零 。 这些年来我们只是适应了这些限制。

最初许多 Swift 开发人员使用隐式解包选项

var something: Something!

这是最接近声明引用变量的方式,其行为类似于上述编程语言,但这样我们并没有真正使用 Optionals 的强大功能。

我什么时候应该将模型的 属性 声明为可选?

你要问自己的问题是

In my data domain, can this entity exist and have no value for this specific property?

如果答案是,则属性应声明为非可选

例子

表示应用程序用户的 User 结构将始终填充 usernamepassword

struct User {
    let username: String
    let password: String
    let profileImageURL: NSURL?
}

另一方面,profileImageURL 可能有一个 nil 值,这可能是因为用户没有上传个人资料照片。

在这种情况下,没有 usernameUser 值是没有意义的,它不可能发生,在处理 User 值时,我们应该始终保证(由编译器提供)其中有 username 个值。

所以我们让username成为非可选的

这真的取决于域

Entity 的 属性 的 "optionality" 可能因数据域而异。

例如此实体用于邮件列表系统

struct Person {
    let name: String?
    let email: String
}

是有道理的,因为我们不知道 name 但我们肯定知道它的 email 地址。

另一方面,另一个上下文中的同一个实体(如地址簿)可能会变成

struct Person {
    let name: String?
    let email: String?
}

因为我们可能 created/saved 一张空牌。

大拇指统治

作为个人建议,我建议您在有疑问时避免使用可选值。如果你声明了一个非可选 属性实际上应该是可选的东西,问题很快就会出现。

另一方面,如果您声明了可选的东西,但您永远找不到。

重要

当然,永远不要使用 property/variable 域的值来表示值

的缺失
let birthyear = -1 // 
let name = "" // 
let username = "NOT_PROVIDED" //