ドメイン知識の実装について質問です。
ユーザー編集の可否判定に以下のルールがあります:
- 編集権限を持ったユーザーのみ編集可能
- 対象ユーザーのステータスが無効の場合は編集不可
- システム設定で編集が許可されていない場合は編集不可
これをドメイン層に実装する際、以下のクラスを考えています:
- Userクラス(氏名、ステータス等を保持)
- Contextクラス(権限、システム設定等を保持)
実装案:
案A: ドメインサービス
public class UserEditService {
public boolean canEdit(User user, Context context) {
return !user.getStatus().equals("invalid")
&& context.hasPermission("edit")
&& context.isEditAllowed();
}
}
案B: 各クラスに責任を分散
public class User {
public boolean isEditable() {
return !this.status.equals("invalid");
}
}
public class Context {
public boolean canPerformEdit() {
return this.hasPermission("edit") && this.isEditAllowed();
}
}
// 使用時
if (user.isEditable() && context.canPerformEdit()) {
// 編集処理
}
案C: 一方に他方を渡す
public class User {
public boolean canBeEditedBy(Context context) {
return !this.status.equals("invalid")
&& context.hasPermission("edit")
&& context.isEditAllowed();
}
}
どのアプローチが適切でしょうか? それともいずれも間違いでしょうか
基本は「整合性の取れたインスタンスしか存在させない」設計を優先します。
そのため、編集可否の判定結果をもとに、型で不正操作を防ぐのが良いです。
- contextの編集メソッドに、必要な情報(user含む)を渡す
- 権限判定は専用クラスで行い、その結果オブジェクトを編集メソッドに渡す
(判定クラスのインスタンスは外から生成できないように制限)
言語によって実装方法は異なりますが、
Kotlinなら以下の記事の「実装方法2の改善案」が参考になります。
https://little-hands.hatenablog.com/entry/2021/03/08/aggregation