10-1 整合性とは
- 矛盾がなく一貫性のあること・ズレがないこと
- 注文書で例えると
- ヘッダ部かボディ部のどちらかが欠けても注文書は成り立たない
- ヘッダ部がないと誰に届ければいいかわからないし、ボディ部がないと注文明細を届け先がわかっても何を届ければいいかわからない
- 注文明細にはヘッダ部とボディ部の両方が存在する一貫性、すなわち整合性が必要です
- プログラムにおいては、整合性に問題が発生するのは、不正終了してしまった時です
10-2 致命的な不具合を確認する
- これまでのコード例で致命的な不具合があった
- UserApplicationServiceに整合性を破綻させる可能性を秘めた問題が存在していた
class UserApplicationService {
constructor(private readonly userRepository: IUserRepository, private readonly userService: UserService) {}
async register(command: UserRegisterCommand): Promise<void> {
const userId = new UserId(command.id);
const userName = new UserName(command.name);
const user = new User(userId, userName);
if (this.userService.exists(user)) {
throw new Error("ユーザはすでに存在しています。");
}
await this.userRepository.save(user);
}
}
- ユーザ登録処理にはユーザ名の重複を許可しないという重大なルールがある
- ある特定の条件下では、このルールが機能しなくなる
- 複数人のユーザがほぼ同時刻に登録処理を行った場合に、片方のユーザのデータベースに登録する前に、もう片方のユーザが登録処理を実行していたら、重複チェックをすり抜けて複数登録ができてしまう
10-3 ユニークキー制約による防衛
- 整合性を保つ手段として、ユニークキー制約が挙げられる
- データベースの特定のカラムがユニーク、唯一無二のものであると保証する機能
10-3-1 ユニークキー制約を重複確認の主体としたときの問題点
- ユニークキーだけに頼って、重複チェックのコードを省くと、コードから重複は許可しないという重要なルールが読み取れなくなる
- データベースの特定の技術基盤に依存しているのもよくない
- 7章でもビジネスロジックが特定の技術基盤に依存するのは避けるべきと解説してきた
- ドメインの重大なルールに関わる処理が本来記述されるべき場所以外に漏れ出してしまう
- 重複のルールが変わった時を想像しましょう
- この時に、データベースのテーブルの制約も変更しなくてはならないと開発者は気づけなくなる
10-3-2 ユニークキー制約との付き合い方
- ルールを守る主体としてではなく、セーフティネットとして活用する機能である
- コードとユニークキー制約を併用するのがいい
参考
ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本