アプリケーションサービス
ドメインオブジェクトを協調させてユースケースを実現する.
CRUDなど.
取得処理において,返り値をドメインオブジェクトにすると,クライアントがドメインオブジェクトのメソッドを呼び出せてしまい,意図しない利用をされる危険性がある.
ドメインオブジェクトへの依存が大きくなる.
DTOを用いてクライアントに返却するのがおすすめ.
DTOへの変換はアプリケーションサービスで行う.
更新処理をエンティティ単位で提供するか属性単位で提供するかは悩ましい問題.
UpdateUserMailorUpdateUser
Commandを利用することでUpdateのシグネチャの変更を回避できる.
code:UserUpdateCommand.cs
public class UserUpdateCommand {
public UserUpdateCommand(string id) => Id = id;
public string Id { get; }
public string Name { get; set; }
public string MailAddress { get; set; }
}
code:UserApplicationService.cs
public class UserApplicationService {
private readonly IUserRepository userRepository;
private readonly UserService userService;
public UserApplicationService(IUserRepository userRepository, UserService userService) {
this.userRepository = userRepository;
this.userService = userService;
}
public void Register(string name) {
var user = new User(new UserName(name));
if(userService.Exists(user)) {
throw new CanNotRegisterUserException(user, "User already exists.");
}
userRepository.Save(user);
}
// ここで返り値にドメインオブジェクトをそのまま用いるとよくないので,DTOに変換して返す.
public UserData Get(string userId) {
var targetId = new UserId(userId);
var user = userRepository.Find(targetId);
if (user == null) return null;
var userData = new UserData(user);
return userData;
}
// Commandクラスを利用してシグネチャを固定する.
public void Update(UserUpdateCommand command) {
var targetId = new UserId(command.Id);
var user = userRepository.Find(targetId);
if (user == null) throw new UserNotFoundException(targetId);
var name = command.Name;
if (name != null) {
var newUserName = new UserName(name);
user.ChangeName(newUserName);
if (userService.Exists(user))
throw new CanNotRegisterUserException(user, "User already exists.");
}
var mailAddress = command.MailAddress;
if (mailAddress != null) {
var newMailAddress = new MailAddress(mailAddress);
user.ChangeMailAddress(newMailAddress);
}
userRepository.Save(user);
}
public void Delete(UserDeleteCommand command) {
var targetId = command.Id;
var user = userRepository.Find(targetId);
if (user == null) throw new UserNotFoundException(targetId);
userRepository.Delete(user);
}
}