0

クールなソフトウェア アーキテクト募集:)

Company と User の 2 つのエンティティがあります。

ユーザーが Company に追加されると、Employee エンティティが作成されます。従業員は、ユーザーと会社の間のリンクを表します。Employee エンティティは、アクセス リストがないと役に立ちません。つまり、不変条件があります。親エンティティ (従業員) は、子 (アクセス リスト) と共に作成する必要があります。

この不変条件を C# コードに実装するソリューションを探しています。

従業員エンティティには、必須パラメーターを持つコンストラクターがあります。

public class Employee
{
    public Employee(EmployeeCreationParams creationParams)
    {
        this.Company = creationParams.Company;
        this.User = creationCommand.User;
    }

    public Company { get; protected set; }

    public User { get; protected set; }

    // other state and logic
}

子エンティティ:

public class EmployeeAccessList
{
    public EmployeeAccessList(EmployeeAccessListCreationParams creationParams)
    { /* initialization logic */ }

    public Employee { get; protected set; }

    public OperationEnum Operation { get; protected set; }
}

汎用リポジトリ サービスがあります。

public class Repository
{
    public void Persist<TEntity>(TEntity entity)
    {
        // internal stuff
    }
}

Employee が作成されて永続化されます。

var employee = new Employee(creationParams);

_repository.Persist(employee);

また、 acl も永続化されます。

var accessList = CreateAccessList();

foreach(var acl in accessList)
{
    _repository.Persist(acl);
}

従業員作成ロジックにアクセス リスト作成ログインを挿入する正しい方法が見つかりません。そのため、親と子の両方が 1 つのユニットとして作成されます。

子作成ロジックを親コンストラクターに追加しようとしました:

public class Employee
{
    public Employee(EmployeeCreationParams creationParams)
    {
        this.Company = creationParams.Company;
        this.User = creationCommand.User;

        var accessList = CreateAccessList();

        foreach(var acl in accessList)
        {
            _repository.Persist(acl);
        }
    }
}

..しかし、この解決策は正しくありません。子オブジェクトは、親エンティティの前に永続化されます。

4

3 に答える 3

3

あまりにも少ないオブジェクトに多数の非常に異なるものを収めようとしていると思います。Employee を作成するときは、3 つの異なる責任を区別する必要があります。

  • 従業員のインスタンス化ロジック、つまり、従業員とすべての関連エンティティを新しくします。これはアプリケーションに依存せず、ドメイン層で定義する必要があります。Employee の作成はやや複雑に見えるため、肥大化した Employee コンストラクターではなく、Factoryがそのジョブの適切な候補になる可能性があります。

  • 従業員の永続性。これは、ORM およびリポジトリ実装のインフラストラクチャ レイヤーに属します。Employee を保存するときに、DDD の Aggregate と ORM の概念を利用して、すべてのエンティティを集約 (AccessLists を含む) に自動的に永続化することをお勧めします。

  • 新しい従業員をいつ保存するかを決定します。これはアプリケーション固有であり、従業員を作成するユースケースの最後にアプリケーション層サービスで実行できます。

于 2012-11-30T16:25:54.057 に答える
1

これはどうですか?

public class Employee
{
    public Employee(EmployeeCreationParams creationParams, EmployeeAccessList accessList)
    {
        this.Company = creationParams.Company;
        this.User = creationCommand.User;
        this.Access = accessList
    }
}

public class Repository
{
    public void Persist<TEntity>(TEntity entity)
    {
        // encapsulate the fact that ACLs are stored in a separate way than Employees
    }
}

次に、会社とユーザーの関係の一部としてアクセス権を取得します。これは理にかなっています。実装の詳細として、それらを別のテーブルに格納したい場合がありますが、クライアントはRepository<Employee>それを気にする必要はなく、後でそれらのクライアントを変更せずにその実装の詳細を変更できます。また、トランザクションの実装をRepositoryクライアントに公開せずに、これら 2 つのデータベース呼び出しに関するトランザクションを制御することもできます。

于 2012-11-30T14:21:52.937 に答える
1

これは、境界付けられたコンテキストを実際に混合する、かなり「古典的な」ケースです。Identity and Access Control BC があり、たとえば、Employee BC (または、人事、組織など、あなたのケースで意味のあるもの) があります。Employee に UserId を含めることは問題ありませんが、Employee BC に User オブジェクトを含めることで、必要以上に作業が難しくなっている可能性があります。ただし、ユーザー値オブジェクトがあれば問題ありません。

それが役立つことを願っています。

于 2012-12-01T05:15:18.033 に答える