3

DDDのファクトリリポジトリ、およびサービスに関していくつか質問があります。次のエンティティがあります: フォルダー、ファイル、FileData。

私の意見では、「フォルダ」は集約ルートであり、File および FileData オブジェクトの作成を担当する必要があります。

したがって、私の最初の質問は、ファクトリを使用してこの集計を作成する必要があるか、それともリポジトリ次第ですか? 現時点では、フォルダー用とファイル用の 2 つのリポジトリがありますが、それらをマージする必要があるようです。次のコード スニペットは、インフラストラクチャ レイヤーにあるフォルダー リポジトリを示しています。

public class FolderRepository : IFolderRepository
{
    #region Fields

    private readonly IFolderContext _context;
    private readonly IUnitOfWork _unitOfWork;

    #endregion

    #region Constructor

    public FolderRepository(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
        _context = _unitOfWork.Context as IFolderContext;
    }

    #endregion

    public IUnitOfWork UnitOfWork
    {
        get { return _unitOfWork; }
    }

    public IQueryable<Folder> All
    {
        get { return _context.Folders; }
    }

    public Folder Find(Guid id)
    {
        return _context.Folders.Find(id);
    }

    public void InsertGraph(Folder entity)
    {
        _context.Folders.Add(entity);
    }

    public void InsertOrUpdate(Folder entity)
    {
        if (entity.Id == Guid.Empty)
        {
            _context.SetAdd(entity);
        }
        else
        {
            _context.SetModified(entity);
        }
    }

    public bool Delete(Guid id)
    {
        var folder = this.Find(id) ?? _context.Folders.Find(id);
        _context.Folders.Remove(folder);

        return folder == null;
    }

    public int AmountOfFilesIncluded(Folder folder)
    {
        throw new NotImplementedException();
        //return folder.Files.Count();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

次に、アプリケーション層にサービスを作成しました。これは「IoService」と呼ばれます。サービスの場所について疑問があります。ドメイン層に移動する必要がありますか?

public class IoService : IIoService
{
    #region Fields

    private readonly IFolderRepository _folderRepository;
    private readonly IFileRepository _fileRepository;
    private readonly IUserReferenceRepository _userReferenceRepository;

    #endregion

    #region Constructor

    public IoService(IFolderRepository folderRepository, IFileRepository fileRepository, IUserReferenceRepository userReferenceRepository)
    {
        if(folderRepository == null)
            throw new NullReferenceException("folderRepository");
        if(fileRepository == null)
            throw new NullReferenceException("fileRepository");
        if (userReferenceRepository == null)
            throw new NullReferenceException("userReferenceRepository");

        _folderRepository = folderRepository;
        _fileRepository = fileRepository;
        _userReferenceRepository = userReferenceRepository;
    }

    #endregion

    #region Folder Methods

    /// <summary>
    /// Create a new 'Folder'
    /// </summary>
    /// <param name="userReference"></param>
    /// <param name="name"></param>
    /// <param name="parentFolder"></param>
    /// <param name="userIds">The given users represent who have access to the folder</param>
    /// <param name="keywords"></param>
    /// <param name="share"></param>
    public void AddFolder(UserReference userReference, string name, Folder parentFolder = null, IList<Guid> userIds = null, IEnumerable<string> keywords = null, bool share = false)
    {
        var userReferenceList = new List<UserReference> { userReference };

        if (userIds != null && userIds.Any())
        {
            userReferenceList.AddRange(userIds.Select(id => _userReferenceRepository.Find(id)));
        }

        var folder = new Folder
        {
            Name = name,
            ParentFolder = parentFolder,
            Shared = share,
            Deleted = false,
            CreatedBy = userReference,
            UserReferences = userReferenceList
        };

        if (keywords != null)
        {
            folder.Keywords = keywords.Select(keyword =>
                new Keyword
                {
                    Folder = folder,
                    Type = "web",
                    Value = keyword,
                }).ToList();
        }

        //insert into repository
        _folderRepository.InsertOrUpdate(folder);

        //save
        _folderRepository.UnitOfWork.Save();
    }

    /// <summary>
    /// Get 'Folder' by it's id
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public Folder GetFolder(Guid id)
    {
        return _folderRepository.Find(id);
    }

    #endregion

    #region File Methods

    /// <summary>
    /// Add a new 'File'
    /// </summary>
    /// <param name="userReference"></param>
    /// <param name="folder"></param>
    /// <param name="data"></param>
    /// <param name="name"></param>
    /// <param name="title"></param>
    /// <param name="keywords"></param>
    /// <param name="shared"></param>
    public void AddFile(UserReference userReference, Folder folder, FileData data, string name, string title = "", IEnumerable<string> keywords = null, bool shared = false)
    {
        var file = new File
        {
            Name = name,
            Folder = folder,
            FileData = data,
            CreatedBy = userReference,
            Type = data.Type
        };

        if (keywords != null)
        {
            file.Keywords = keywords.Select(keyword =>
                new Keyword
                {
                    File = file,
                    Type = "web",
                    Value = keyword,
                }).ToList();
        }

        folder.Files.Add(file);
        folder.Updated = DateTime.UtcNow;

        _folderRepository.InsertOrUpdate(folder);

        //save
        _folderRepository.UnitOfWork.Save();
    }

    /// <summary>
    /// Get 'File' by it's id
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public File GetFile(Guid id)
    {
        return _fileRepository.Find(id);
    }

    #endregion
}

要約すると、フォルダー オブジェクトの作成にサービスを使用する必要があります。それとも、サービスは、オブジェクトを作成し、作成されたオブジェクトをリポジトリに送信する責任を持つファクトリを使用する必要がありますか? サービスの依存性注入についてはどうですか? Unityのような IOC コンテナーを使用して UI レイヤーからサービスを注入する必要がありますか、それともサービスの依存性をハードコードするだけですか?

ありがとう

4

1 に答える 1

8

したがって、私の最初の質問は、ファクトリを使用してこの集計を作成する必要があるか、それともリポジトリ次第ですか?

ファクトリは作成を担当し、リポジトリは永続化を担当します。再構成すると、リポジトリは効果的にインスタンスを作成します。ただし、多くの場合、この作成プロセスはリフレクションで行われ、作成時にのみ発生する初期化を防ぐためにファクトリを経由しません。

現時点では、フォルダー用とファイル用の 2 つのリポジトリがありますが、それらをマージする必要があるようです。

DDD では、集計ごとにリポジトリが存在します。このリポジトリは、集約の一部であるすべてのエンティティと値オブジェクトを永続化する責任があります。

サービスの場所について疑問があります。ドメイン層に移動する必要がありますか?

IMO では、アプリケーション サービスをドメイン層に配置することができます。これは、既にファサードとして機能しており、それらをまとめることで結束の利点がもたらされるためです。IoServiceのようなメソッドAddFileは通常、インスタンスではなく集約 ID によってパラメーター化されると考えられます。アプリケーション サービスはすでにリポジトリを参照しているため、必要に応じて適切な集計をロードできます。それ以外の場合、コードの呼び出しがリポジトリの呼び出しを担当します。

フォルダ オブジェクトの作成にサービスを使用する必要がありますか。それとも、サービスは、オブジェクトを作成し、作成されたオブジェクトをリポジトリに送信する責任を持つファクトリを使用する必要がありますか?

インスタンスではなく ID によってパラメーター化されるというIoService前のコメントを除いて、 はそのままで良さそうです。

サービスの依存性注入についてはどうですか? Unity のような IOC コンテナーを使用して UI レイヤーからサービスを注入する必要がありますか、それともサービスの依存性をハードコードするだけですか?

これは好みの問題です。IoC コンテナーを使用するメリットがある場合は、それを使用してください。ただし、ただ使うためだけに使用しないでください。ファンシーな IoC コンテナーがなくても、既に依存性注入を行っています。

サンプル

class File
{
    public File(string name, Folder folder, FileData data,  UserReference createdBy, IEnumerable<string> keywords = null)
    {
        //...
    }
}

...

class Folder
{
    public File AddFile(string name, FileData data, UserReference createdBy, IEnumerable<string> keywords = null)
    {
        var file = new File(name, this, data, createdBy, keywords)
        this.Files.Add(file);
        this.Updated = DateTime.UtcNow;
        return file;
    }
}

...

public void AddFile(UserReference userReference, Guid folderId, FileData data, string name, string title = "", IEnumerable<string> keywords = null, bool shared = false)
{
    var folder = _folderRepository.Find(folderId);
    if (folder == null)
        throw new Exception();

    folder.AddFile(name, data, keywords);

    _folderRepository.InsertOrUpdate(folder);
    _folderRepository.UnitOfWork.Save();
}

この例では、より多くの動作が Folder 集約と File エンティティに委譲されています。アプリケーション サービスは、集約に対して適切なメソッドを単純に呼び出します。

于 2013-03-05T16:37:35.980 に答える