Open1
【DDD】Repository関連のメモ

ラッパー(Proxy)の利用
概要
Repositoryパターンに限った話ではないが,ラッパーを実装することで多少便利になるかも.
以下のIUserRepository
で実装例を示す.
public interface IUserRepository {
UniTask AddAsync(User user);
UniTask<User> FindByIdAsync(UserId id);
UniTask<IEnumerable<User>> GetAllAsync();
}
キャッシュによる効率化
データの追加や検索が頻繁に行われる場合,ローカルにキャッシュを設ける.
public sealed class CachedUserRepository : IUserRepository {
private readonly IUserRepository _innerRepository;
private readonly ConcurrentDictionary<UserId, User> _cache = new();
public CachedUserRepository(IUserRepository innerRepository) {
_innerRepository = innerRepository;
}
public async UniTask AddAsync(User user) {
await _innerRepository.AddAsync(user);
_cache[user.Id] = user;
}
public async UniTask<User> FindByIdAsync(UserId id) {
if (_cache.TryGetValue(id, out var user)) {
return user;
}
user = await _innerRepository.FindByIdAsync(id);
if (user != null) {
_cache[user.Id] = user;
}
return user;
}
public async UniTask<IEnumerable<User>> GetAllAsync() {
if (_cache.Any()) {
return _cache.Values;
}
var users = await _innerRepository.GetAllAsync();
foreach (var user in users) {
_cache[user.Id] = user;
}
return _cache.Values;
}
}
ログ出力
ログ出力を追加する.
public sealed class LoggingUserRepository : IUserRepository {
private readonly IUserRepository _innerRepository;
public LoggingUserRepository(IUserRepository innerRepository) {
_innerRepository = innerRepository;
}
public async UniTask AddAsync(User user) {
Console.WriteLine($"[INFO] Adding user: {user.Name} (ID: {user.Id.Value})");
await _innerRepository.AddAsync(user);
}
public async UniTask<User> FindByIdAsync(UserId id) {
Console.WriteLine($"[INFO] Finding user by ID: {id.Value}");
return await _innerRepository.FindByIdAsync(id);
}
public async UniTask<IEnumerable<User>> GetAllAsync() {
Console.WriteLine("[INFO] Fetching all users");
return await _innerRepository.GetAllAsync();
}
}