🌟

GolangでValueObjectの実装

2025/02/11に公開

ValueObjectの学習をしたので、そのアウトプットとして記載します。

1.ValueObjectとは

・日本語では、値オブジェクトとか記載されいてる。
 ・システムで利用される項目の条件を1つのオブジェクトにまとめたもの
 ・イミュータブル(変更不可)である。

2.なぜ必要なのか

なぜこのような面倒なことをする必要があるのか?普通にGetter/Setterを使えばいいじゃないか。と思ってしまいます。ちゃんと意味があり、ValueObjectが実装されています。その意味を以下に記載します。
①:型安全

各業務、各機能で利用されている項目は、全て入力される条件が存在しています。
その条件を無視して実装してしまえば、当然バグとなってしまいます。
その条件を1つにまとめ、データが生成される段階で、入力条件は全てクリアしている状態で作成されると、そのデータは、間違いなく正しいと言えます。
それが型安全となります。
※条件を他のコード(例えばServiceとか)に書けばいいじゃんと思うかもしれませんが、そうした場合、入力条件の判定分が、いろいろなコードに散らばってしまい、コードを変更しようとした場合、思わぬところでエラーが発生する可能性が出てきます。そうなると、品質が低下していしまいます。

②:データの不変性

各処理で作成されるデータは、すべて目的を持って作成されます。
データが変更される場合、作成された目的が異なるという事になります。
そのため、同じ変数を使い回すと、作成された目的が何か分からなくなってしまいます。
また、どこでそのデータが更新されたか、調査にも時間がかかるようになります。

3.実装

 package main

import (
	domain "VALUEOBJECT/domain"
	"fmt"
)

func main() {

	usercd, _ := domain.NewUsercd("TEST")

	fmt.Println(usercd.Value())

}

package domain

import "errors"

type Usercd struct {
	usercd string
}

// NewUsercdはUsercdのコンストラクタ
// データを登録する際は、この関数を使ってUsercdを生成する
func NewUsercd(usercd string) (Usercd, error) {
	// ユーザーCDが空の場合はエラーを返す
	if usercd == "" {
		return Usercd{}, errors.New("usercd is required")
	}

	// ユーザーCDに禁則文字が含まれている場合はエラーを返す
	if !check_forbidden_char(usercd) {
		return Usercd{}, errors.New("usercd is required")
	}

	return Usercd{usercd: usercd}, nil
}

// UsercdはユーザーCDを返す
// Constructorで生成したUsercdの値を取得する
func (n Usercd) Value() string {
	return n.usercd
}

// 禁則文字チェック
func check_forbidden_char(usercd string) bool {
	if usercd == "***" {
		return false
	}
	return true
}

※ちなみに、main.go内の変数:usercdに別の値を設定しようとすると、エラーとなります。

4.結果

実行した結果、以下のような回答がありました。

 $ go run main.go
 TEST

5.実行したコード

https://github.com/NoriStock1983/GO_ValueObject/tree/main/ValueObject

6.参考にしたサイト

https://zenn.dev/devkono/articles/20231201_ddd_943df624fbf004#デメリットはないのか?

https://zenn.dev/jy8752/articles/757f37b3a7c7cd

Discussion