Сначала перепроверьте домен для StepsProgression: если мы спросим эксперта домена о шагах нашего процесса, я думаю, мы получим приемлемый ответ. Тогда мы можем сказать, что это часть нашего домена.
Далее, как вы говорите, это лицо или ВО? Да, он выглядит как объект ценности и фактически является объектом значения, так как вы не заботитесь об идентичности всего набора данных, он не имеет уникального значения (если я не понял, что неправильно неправильно).
Если у вас есть пользовательский интерфейс, как и мастер формы и входы каждый шаг разные, я бы Реализовать так:
public class StepsProgression
{
private readonly string _userId;
public Step1 step1 { get; set; }
public Step2 step2 { get; set; }
public Step3 step3 { get; set; }
public StepsProgression(string userId)
{
_userId = userId;
}
}
// Immutable Step Object
public class Step1
{
public string input1 { get; }
public string input2 { get; }
public string input3 { get; }
}
Вы инстанцирует StepsProgression на первом этапе, поэтому я полагаю, вы знаете только чьими шагами. Поэтому конструктор устанавливает только идентификатор пользователя. Затем, когда пользователь заполняет входы step1 и клики Далее, тогда вы создаете новый (неизменный) объект Step и устанавливаете его на step1. Если пользователь нажимает Назад, что-то изменит с шага 1 и снова нажмет Далее, затем вы снова создаете новый объект Step1 и назначаете его StepsProgression.
Вы можете представить более общую реализацию (шаг), но поскольку входы все разные между шагами, этот явный способ дает вам соглашение о кодировании.
Отредактировано Реализация: Я понимаю, что StepsProgressions содержит динамического набор шагов, которые вы определяете непосредственно перед созданием StepsProgression. Тогда если вы знаете stepTypes заранее я хотел бы изменить свою реализацию следующим образом:
public class StepsProgression
{
private readonly string _userId;
private readonly IStepProgressionBuilder _builder = new StepProgressionBuilder();
public IEnumerable<IStep> Steps { get; set; }
public StepsProgression(string userId, IEnumerable<string> stepTypes)
{
_userId = userId;
foreach (var step in stepTypes) // foreach smells here but you got the point
{
_builder.AddConcreteStep(step) // step = "Step1" for instance.
}
Steps = _builder.Build();
}
}
// Immutable Step Object
public class Step1 : IStep
{
public string input1 { get; }
public string input2 { get; }
public string input3 { get; }
}
// Builder Pattern with Fluent Methods
public interface IStepProgressionBuilder
{
// stepType = "step1" for instance. You have concrete Step1 class, so you return it.
// Start with a switch, then you refactor. (May involve some reflection)
void AddConcreteStep(string stepType);
IEnumerable<IStep> Build();
}
Опять вы можете использовать один общий класс Step, но тогда ваш строитель должен shomehow строить шаг, принимая каждый данные шаг должен содержать. Затем это становится кодовым кодом, если ваши шаги могут иметь более 3 свойств.Вот почему я предпочитаю иметь конкретные классы Step, чтобы я мог построить его как целый набор данных.
Будьте осторожны с сеттерами: VO являются неотразимыми, поэтому сеттеры должны возвращать новый объект –
Спасибо! StepsData действительно является чем-то вроде состояния, потому что когда мы что-то наполняем, мы меняем состояние. Таким образом, я могу сделать StepsData объектом значения с сеттерами, который вернет мне новый объект значения, который я буду использовать для замены старого? – Clickbeetle