Мое текущее приложение позволяет пользователям определять пользовательские веб-формы с помощью набора экранов администратора. это, по сути, приложение типа EAV. Таким образом, я не могу написать код HTML или ASP.NET для рендеринга данной страницы. Вместо этого пользовательский интерфейс запрашивает экземпляр объекта Form из служебного уровня, который, в свою очередь, строит один, используя несколько таблиц RDMBS. Форма содержит типы классов, которые вы ожидаете увидеть в таком контексте: Form
= > IEnumerable<FormSections>
= > IEnumerable<FormFields>
Вот как выглядит сервисный слой:
public class MyFormService: IFormService{
public Form OpenForm(int formId){
//construct and return a concrete implementation of Form
}
}
Все работает великолепно (на некоторое время). Пользовательский интерфейс не является более разумным в отношении того, какие разделы/поля существуют в данной форме: он с радостью отображает объект Form, который он получает, на функциональную страницу ASP.NET.
Несколько недель спустя я получаю новое требование от бизнеса: при просмотре не редактируемых (т.е. только для чтения) версий формы некоторые значения полей должны быть объединены вместе, а другие надуманные/рассчитанные поля должны быть добавлены, Без проблем я говорю. Просто измените мой класс обслуживания, чтобы его методы были более явными:
public class MyFormService: IFormService{
public Form OpenFormForEditing(int formId){
//construct and return a concrete implementation of Form
}
public Form OpenFormForViewing(int formId){
//construct and a concrete implementation of Form
//apply additional transformations to the form
}
}
Снова все работает отлично, и равновесие восстановлено силой. Пользовательский интерфейс продолжает быть агностическим в отношении того, что находится в Форме, и наше разделение проблем достигнуто. Однако всего несколько коротких недель спустя бизнес выдвигает новое требование: в некоторых сценариях мы должны применять только некоторые из преобразований формы, на которые я ссылался выше.
На данный момент похоже, что подход "явного метода" достиг тупиковой ситуации, если я не хочу в конечном итоге вызвать взрыв методов (OpenFormViewingScenario1, OpenFormViewingScenario2 и т.д.). Вместо этого я вводил еще один уровень косвенности:
public interface IFormViewCreator{
void CreateView(Form form);
}
public class MyFormService: IFormService{
public Form OpenFormForEditing(int formId){
//construct and return a concrete implementation of Form
}
public Form OpenFormForViewing(int formId, IFormViewCreator formViewCreator){
//construct a concrete implementation of Form
//apply transformations to the dynamic field list
return formViewCreator.CreateView(form);
}
}
На первый взгляд это похоже на приемлемый подход, и все же есть определенный запах. А именно, пользовательский интерфейс, который жил в невежественном блаженстве о деталях реализации OpenFormForViewing, должен обладать знаниями и создавать экземпляр IFormViewCreator.
- Мои вопросы двоякие: есть ли лучший способ достичь Я могу последовать за композицией? (возможно, использование контейнера IoC или дома показывается factory, чтобы создать конкретный IFormViewCreator)?
- Я принципиально испортил абстракция здесь?