Open1

【DDD】Repository関連のメモ

nitonito

ラッパー(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();
    }
}