工单编号

让我们再次思考一下我们的工单管理系统。目前,我们的工单模型是这样的:

#![allow(unused)]
fn main() {
pub struct Ticket {
    pub title: TicketTitle,
    pub description: TicketDescription,
    pub status: Status
}
}

这里缺少了一样东西:一个用来唯一标识工单的编号。这个编号对每个工单都应该是唯一的。我们可以在创建新工单时自动生成编号来保证这一点。

优化模型

编号应该存储在哪里呢?我们可以在 Ticket 结构体中添加一个新的字段:

#![allow(unused)]
fn main() {
pub struct Ticket {
    pub id: TicketId,
    pub title: TicketTitle,
    pub description: TicketDescription,
    pub status: Status
}
}

但我们在创建工单之前是不知道这个编号的。因此,一开始它不能存在。它必须是可选的:

#![allow(unused)]
fn main() {
pub struct Ticket {
    pub id: Option<TicketId>,
    pub title: TicketTitle,
    pub description: TicketDescription,
    pub status: Status
}
}

这也不是理想的情况——每次我们从存储中检索工单时,都不得不处理 None 的情况,尽管我们知道一旦工单被创建,编号就应该始终存在。

最佳的解决方案是设置工单的两种状态,由两个不同的类型表示:TicketDraft(工单草稿)和 Ticket(正式工单):

#![allow(unused)]
fn main() {
pub struct TicketDraft {
    pub title: TicketTitle,
    pub description: TicketDescription
}

pub struct Ticket {
    pub id: TicketId,
    pub title: TicketTitle,
    pub description: TicketDescription,
    pub status: Status
}
}

TicketDraft 是尚未创建的工单,它没有编号,也没有状态。而 Ticket 是已经创建的工单,它既有编号也有状态。由于 TicketDraftTicket 中的每个字段都嵌入了自己的约束,我们不需要在两个类型之间重复逻辑。