7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ドメイン駆動設計Advent Calendar 2020

Day 7

Goで書くDDDの仕様(Specification)パターン

Last updated at Posted at 2020-12-06

この記事はドメイン駆動設計 Advent Calendar 2020 7日目の記事です。

DDDで紹介される戦術パターンの一つの仕様(Specification)パターンのGoでの実装を(自分へのメモ用と整理も兼ねて)2つ紹介します。

interfaceを利用

DDDはJavaで紹介されることが多いのですが、1つ目はこのJavaで紹介されるインターフェースを利用したものを素直に書いたパターンです。

例で見てみましょう。

// 仕様はRuleの集合で表現する
type Specification struct {
	rules []rule
}

// 検証を表すインターフェース
type rule interface {
	IsValid() bool
}

// 名前の長さのルール
type nameLengthRule struct {
	name string
}

func (n nameLengthRule) IsValid() bool {
	return len(n.name) < 20
}

// 有効な年齢のルール
type ageRangeRule struct {
	age int
}

func (a ageRangeRule) IsValid() bool {
	return 0 <= a.age && a.age < 200
}

func NewSpecification(name string, age int) Specification {
	return Specification{
		rules: []rule{
			nameLengthRule{name},
			ageRangeRule{age},
		},
	}
}

func (s Specification) Satisfied() bool {
	for _, rule := range s.rules {
		if !rule.IsValid() {
			return false
		}
	}
	return true
}

検証内容をruleとしてinterfaceに切り出すことで、今後検証内容が増えても既存の影響はSpecificationの生成だけになります。
ビジネスルールは比較的頻繁に変わるので、変更に強いプログラムになると言われています。
(とはいえ、このくらいの検証でやるのは過剰ですが。。)

typeを利用

もう一つはruleの関数自体を型にしてしまうものです。

これも例をみてみましょう。

type Specification struct {
	rules []rule
}

type rule func() bool

func nameLengthRule(name string) rule {
	return func() bool {
		return len(name) < 20
	}
}

func ageRangeRule(age int) rule {
	return func() bool {
		return 0 <= age && age < 200
	}
}

func NewSpecification(name string, age int) Specification {
	return Specification{
		rules: []rule{
			nameLengthRule(name),
			ageRangeRule(age),
		},
	}
}

func (s Specification) Satisfied() bool {
	for _, rule := range s.rules {
		if !rule() {
			return false
		}
	}
	return true
}

検証の内容は変わりませんが、structの宣言がなくなった分コードがスッキリします。
ポイントは関数のfunc() boolを型にしてしまうところです。
これによって関数宣言だけでルールが作れるので、シンプルな形になっています。

Goでは関数も型にできるので、うまく利用するとインターフェースを使うよりもシンプルな形で実装できるので、参考になれば幸いです。

7
4
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
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?