0

ワークフロー階層のストレージ ソリューションを作成しています。

図を単純化するために、Workflow と WorkflowStep の 2 種類のオブジェクトがあります。

WorkflowStep は Workflow の下に階層的に配置されますが、Workflow は WorkflowStep を集約しません。これは、これらのオブジェクトを単なるデータ コンテナーと見なすためです。

したがって、これにより、次のクラスが残ります。

 public class Workflow : Node {
    public string UID;
    public string parentID;
}

public class WorkflowStep : Node {
    public string UID;
    public string parentID;
}

public class WorkflowEngine {
    public void Store(Workflow wf) {
    }

    public void Store(WorkflowStep wfs) {
    }
}

ワークフロー内で WorkflowStep を集約しない理由は (論理的には適合しますが)、これらのオブジェクトは純粋にデータ コンテナーとして表示され、後で変更される可能性があり、これらのオブジェクトのストレージをオブジェクト自体から分離したままにしておく必要があるためです。

もちろん、他の代替手段は、次のようなことを行うことです。

 public class Workflow : Node {
    public List<WorkflowStep> steps;
    public string UID;
    public string parentUID;

    public void Store() { }
}

public class WorkflowStep : Node {
    public string UID;
    public string parentID;

    public void Store() { }
}

どちらのアプローチの長所と短所は何ですか? 両方のデザインについて述べている文献はありますか?

4

1 に答える 1

1

WorkflowとはどちらもWorkflowStepデータ コンテナーですが、これらを階層メジャーから切り離しても、デカップリングの問題は解決しません。

WorkflowStepの階層を維持し、この場合Workflow導入しなければならないデカップリングとうまくやっていく方がより論理的です。IoC

の美しさは、クラス内のリストであるIoC定義を変更すると、コンテナに型を登録することのみを検討する場合に透過的になることです。WorkflowStepWorkflowIoC

Ninject IoCコンテナ フレームワークの例を挙げましょう。

インターフェイスを定義し、それに応じてデータ コンテナーを実装します。

public interface IWorkflow {
    string UID { get; set; }    
    string parentID { get; set; }
    IList<IWorkflowStep> Steps { get; set; }
}

public interface IWorkflowStep {
    string UID { get; set; }    
    string parentID { get; set; }
}

 public class Workflow : IWorkflow, Node {

    public string UID { get; set; };
    public string parentID { get; set; };
    public IList<IWorkflowStep> Steps { get; set; }
}

public class WorkflowStep : IWorkflowStep, Node {
    public string UID { get; set; };
    public string parentID { get; set; };
}

そして今、Ninject モジュールは次のようになります。

public class WorkflowModule : NinjectModule
{
    #region Overrides of NinjectModule

    public override void Load()
    {
        Bind<IWorkflow>().To<Workflow>();
        Bind<IWorkflowStep>().To<WorkflowStep>();
        Bind<IList>().To<List>();
    }

    #endregion
}

これは、インターフェイスを具象クラスにバインドする単一の場所です。それ以外の場合は、定義済みのインターフェイスのインスタンスを要求するだけです。

タイプを解決するには、定義済みのモジュールをロードしてKernelIKernelタイプと具体的な実装である Ninject を作成する必要があります。StandardKernel

これは、次のようなものです。

var kernel = new StandardKernel(new WorkflowModule());

あとは、次のように目的のインターフェイスを解決するだけです。

IWorkflow workflow = kernel.Get<IWorkflow>();
IWorkflowStep workflowStep = kernel.Get<IWorkflowStep>();

ここでの利点は、具体的な実装について心配する必要がなく、システム内で非常に緊密に結合されていることです。それはあなたが扱うインターフェースだけであり、残りはIoCコンテナ実装の心配です。

WorkflowStepの実装が変更され、 と結合しないことが心配ですWorkflow。私は、これがIoC遊びに来るところだと思います。

UnitySpring.NETStructureMapIoCなどの任意のコンテナー フレームワークを使用できることに注意してください。私はそれに慣れているため、Ninject を使用しました。

于 2011-10-24T10:24:37.533 に答える