ボトムアップドメイン駆動設計のエンティティについて、Pythonで書きました。
C#で書かれているコードをPythonに翻訳したので、厳密に再現できていない箇所もあります。また、それぞれの呼び出しをテストコードで表し、ソースコードレベルで目的を明確にしました。
用語の説明やコードの詳細説明に関して、下記の参考文献を参照ください。
参考文献: ボトムアップドメイン駆動設計
バージョン
- Python 3.7.0
目次
- エンティティとは
- 可変である
- 同じ属性でも区別される
- 同一性を持つ
- 参考文献
- おまけ
エンティティとは
詳しいエンティティの説明は、参考文献を参照してください。
ここでは、エンティティの3つの特徴だけおさえておきます。
- 可変である
- 同じ属性でも区別される
- 同一性を持つ
可変である
import dataclasses
import unittest
@dataclasses.dataclass(frozen=True)
class FullName:
full_name: str
@dataclasses.dataclass
class User:
def __init__(self, full_name: FullName):
self.full_name = full_name
def change_full_name(self, new_name: FullName) -> None:
if new_name is None:
raise ValueError(f"{new_name} is invalid argument")
self.full_name = new_name
class TestUserEntity1(unittest.TestCase):
def test_属性を変更できる(self):
user = User(FullName("matsuoka kota"))
user.change_full_name(FullName("tanaka satoshi"))
self.assertEqual(FullName("tanaka satoshi"), user.full_name)
if __name__ == "__main__":
unittest.main()
同じ属性でも区別される
import dataclasses
import unittest
import uuid
@dataclasses.dataclass(frozen=True)
class FullName:
full_name: str
@dataclasses.dataclass(frozen=True)
class UserId:
value: str
@dataclasses.dataclass
class User:
full_name: FullName
id: UserId
class TestUserEntity2(unittest.TestCase):
def test_同じ属性でも区別される(self):
tom1 = User(FullName("Tom Cruise"), UserId(str(uuid.uuid4())))
tom2 = User(FullName("Tom Cruise"), UserId(str(uuid.uuid4())))
self.assertNotEqual(tom1, tom2)
if __name__ == "__main__":
unittest.main()
同一性を持つ
from __future__ import annotations
import dataclasses
import uuid
import unittest
@dataclasses.dataclass(frozen=True)
class FullName:
full_name: str
@dataclasses.dataclass(frozen=True)
class UserId:
value: str
@dataclasses.dataclass
class User:
full_name: FullName
id: UserId
def change_full_name(self, new_name: FullName) -> None:
if new_name is None:
raise ValueError(f"{new_name} is invalid argument")
self.full_name = new_name
def __eq__(self, other: User):
# idのみで比較する
return isinstance(other, User) and (self.id == other.id)
class TestUserEntity3(unittest.TestCase):
def test_オブジェクトの属性が変化しても同一性が保証される(self):
tom = User(FullName("Tom Cruise"), UserId(str(uuid.uuid4())))
before_tom = tom
tom.change_full_name(FullName("Tom Hanks"))
self.assertEqual(before_tom, tom)
if __name__ == "__main__":
unittest.main()
参考文献
おまけ
参考文献に載せたブログ記事にはいつも助けられています。ぜひ、みなさんも読みながら、ご自身が使い慣れている言語で写経してみてください。
Renttleというサービスを開発中です。ぜひ、使ってみて、レビューをください。