今天我們會用以下表單作為範例來設計資料模型。
domain modeling (資料模型設計)的過程其實就是解析需求的過程 ,藉由一些技巧把需求大致上如何解決在設計草稿上過一遍,這樣就能在草稿階段用很低的修改成本把可能遇到的問題先解決掉一些,減少真的寫下去了發現錯誤又要修改的可能性。
在進行領域驅動開發團隊合作的時候,通常還會有腦力激盪、建立共用心智模型 (shared mental model) 的過程,詳細可以參考Think in Domain-Driven Design 系列。
關於如何設計資料模型我也正在學習中,有時候還是會遇到寫到一半才發現當初沒設計好的情形,真的是說起來簡單做起來難呀( ´•̥ו̥` )
我們先用課程名稱當範例。
一個課程名稱有三種可能性 - 合格、不合格、初始狀態,這時候我們可以用 union type
來拆解它
union type
表示一個型別是多個型別的其中一種
type CourseName = ValidCourseName | InvalidCourseName | InitialCourseName
不合格的課程名稱由 value
和 reason
組成,這時候我們可以用 product type
來拆解它
product type
表示一個型別由多個型別組成
interface InitialCourseName {
value: '',
}
interface ValidCourseName {
value: string,
}
interface InvalidCourseName {
value: string,
reason: string,
}
有了 union type
與product type
其實還不太夠,這是因為實務上還常常會需要知道「 課程名稱到底是哪一種課程名稱」並做相應的處理,但比較遺憾的是 TS 難以幫助我們從上面的範例做到這件事情,所以我們要給它一個 _tag
來輔助 TS 做型別推演,也就是 建立 sum type
。
sum type
可以做型別推演的、有 tag 的 union type
interface InitialCourseName {
_tag: 'InitialCourseName',
value: '',
}
interface ValidCourseName {
_tag: 'ValidCourseName',
value: string,
}
interface InvalidCourseName {
_tag: 'InvalidCourseName',
value: string,
reason: string,
}
藉由 sum type
與 product type
,參考以上範例以此類推,最終我們就可以把表單模型建立出來
interface AddCourseForm {
name: CourseName
dateRange: DateRane
description: CourseDescription
users: CourseUsers
}
這邊再額外提供一個 DateRange
範例給大家參考,剩下的欄位大家有興趣可以練習看看!
type DateRange = ValidDateRange | InvalidDateRange | InitialDateRange
interface ValidDateRange {
_tag: "ValidDateRange"
start: Date
end: Date
}
interface InvalidDateRange {
_tag: "InvalidDateRange"
start: Date
end: Date
reason: string
}
interface InitialDateRange {
_tag: "InitialDateRange"
}