Контейнеры данных против объектов в сочетании с поведением - PullRequest
0 голосов
/ 24 октября 2011

Я пишу решение для хранилища для иерархии рабочих процессов.

Чтобы упростить картину, у меня есть 2 типа объектов, Workflow и WorkflowStep.

Несмотря на то, что WorkflowStep иерархически подчиняется рабочему процессу, рабочий процесс не агрегирует 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 внутри Workflow (даже если это логически подходит) состоит в том, что эти объекты просто рассматриваются как контейнеры данных, и они могут подвергаться изменениям позже, и мы хотим сохранить хранилище этих объектов отделенным от сами объекты

Другой альтернативой, конечно, было бы сделать что-то вроде этого:

 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() { }
}

Каковы плюсы и минусы любого подхода? Есть ли литература, которая говорит об обоих проектах?

1 Ответ

1 голос
/ 24 октября 2011

Несмотря на то, что Workflow и WorkflowStep являются контейнерами данных, но сохранение их в стороне от иерархических мер не решит проблему разделения.

Логичнее сохранить WorkflowStep в иерархии Workflow и для того, чтобы справиться с развязкой, вы должны ввести IoC в этом случае.

Прелесть IoC в том, что изменение определений WorkflowStep, являющегося списком в классе Workflow, будетпросто прозрачно, когда вы будете рассматривать регистрацию типов в вашем контейнере IoC.

Позвольте мне привести пример с 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
}

Это единственное место, где вы связываете свои интерфейсы с конкретными классами.А в остальном мире вы просто запрашиваете экземпляр определенного интерфейса.

Чтобы разрешить ваш тип, вам нужно создать Ninject Kernel, который имеет тип IKernel и конкретную реализацию * 1030.* загрузив определенный вами модуль .

Что-то вроде

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

Теперь все, что вам нужно сделать, это определить нужный интерфейс, например:

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

Прелесть здесь в том, что вам не нужно беспокоиться о конкретной реализации, которая тесно связана с вашей системой.Именно интерфейс, с которым вы будете иметь дело, а остальное - забота вашей реализации контейнера IoC.

Поскольку вас больше беспокоит то, что реализация WorkflowStep должна быть изменена и не связана с Workflow,Я думаю, это то, где IoC начинает играть.

Обратите внимание, что вы можете использовать любой IoC контейнерный фреймворк, такой как Unity , Spring.NET , StructureMap и т. Д. Я использовал Ninject, потому что мне это удобно.

...