1
0

More than 3 years have passed since last update.

Goでエンティティを表現する

Last updated at Posted at 2020-06-15

はじめに

前回の記事で「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回目)

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0