はじめに
前回の記事で「Goで値オブジェクトを表現する」という内容を書きました。
今回は引き続き、エンティティについて書いてみたいと思います。
実装
main.go
package main
import (
"fmt"
"github.com/AwataKyosuke/qiita/domain/model/user"
)
func main() {
// 無効なユーザーの作成
_, err1 := user.New(0, "sample")
if err1 != nil {
fmt.Println(err1)
}
// 無効なユーザーの作成
_, err2 := user.New(1, "")
if err2 != nil {
fmt.Println(err2)
}
// 有効なユーザーの作成
user1, err := user.New(1, "sample1")
if err != nil {
fmt.Println(err)
}
// 有効なユーザーの作成
user2, err := user.New(1, "sample2")
if err != nil {
fmt.Println(err)
}
// ユーザー情報の表示
fmt.Println(user1, user2)
fmt.Println(user1.Equals(*user2))
}
user.go
package user
type user struct {
id id
name name
}
// ユーザーを作成する際に呼び出す関数
func New(id int, name string) (*user, error) {
createdID, err := newID(id)
if err != nil {
return nil, err
}
// ChangeNameを使うべきなんだろうか、、、。
createdName, err := newName(name)
if err != nil {
return nil, err
}
user := user{
id: *createdID,
name: *createdName,
}
return &user, nil
}
// ユーザーのnameプロパティを変更
func (u user) ChangeName(value string) error {
name, err := newName(value)
if err != nil {
return err
}
u.name = name
return nil
}
// 比較メソッド
// エンティティは識別子で判断する
func (u user) Equals(target user) bool {
return u.id == target.id
}
id.go
package user
import "errors"
// id型を定義
type id int
// idを作成する場合は、この関数を呼ぶ
func newID(value int) (*id, error) {
// ここにルールを指定することで、不正なデータを作成できないようにする
if value < 1 {
return nil, errors.New("idは1以上の整数である必要があります。")
}
id := id(value)
return &id, nil
}
name.go
package user
import "errors"
// name型を定義
type name string
// nameを作成する場合は、この関数を呼ぶ
func newName(value string) (*name, error) {
// ここにルールを指定することで、不正なデータを作成できないようにする
if len(value) < 1 {
return nil, errors.New("nameは1文字以上である必要があります。")
}
name := name(value)
return &name, nil
}
実行結果
$ go run main.go
idは1以上の整数である必要があります。
nameは1文字以上である必要があります。
&{1 sample1} &{1 sample2}
true
終わりに
値オブジェクトとエンティティの違いについてはきっちり理解しておきたいところです。
DDDもGoも初心者なので、間違っていれば指摘をもらえると嬉しいです!
ちなみに「ドメイン駆動設計入門」ですが、既に買ってよかった感が凄いので、おすすめです!(2回目)
...これであってるんだろうか(2回目)