Многоуровневый дизайн приложений

Прежде чем все будут бросать в меня камни, я искал в Google / MSDN / StackOver поток связанных вопросов и ответов, но ни один из них не соответствовал моим потребностям.

Я работаю над довольно большим приложением на С# - Windows Forms, которое в настоящее время делится на следующее:

  1. Уровень данных
  2. Домен-уровень
  3. UI-слой

В основном в моей текущей ситуации роли этих слоев следующие:

  1. Уровень данных отвечает за связь с хранилищем данных, в основном операции CRUD.
  2. Ответственность доменного уровня заключается в том, чтобы хранить модель наших объектов, создавать объекты, применять бизнес-правила и т. д.
  3. UI-Layer — это то, что пользователь видит и с чем взаимодействует.

Моя проблема заключается в следующем:

Из слоя пользовательского интерфейса пользователь имеет доступ к таким полям, как: имя, имя проекта, номер проекта, которые в основном являются текстовыми полями, календарями и т. д. — все они являются компонентами пользовательского интерфейса.

После ввода пользователя я вызываю метод с именем: AddExplorerNode(string name, string projectName, int projectNumber), который находится на уровне домена. Этот метод отвечает на основе переданных параметров за создание ExplorerNode Object ("особый" TreeNode), который требует, чтобы переданные параметры действительно были действительными.

После того, как объект был создан, очищен, проверен и т. д., тот же метод, упомянутый выше, передает созданный объект на уровень данных, который помещает его в кэш-репозиторий, а затем сохраняет его в хранилище данных, если все прошло нормально в Кэш.

Так что до сих пор в основном все разделено UI -> Domain -> DataLayer.

Мой вопрос: могу ли я заменить подпись метода домена из

AddExplorerNode(string name, string projectName, int projectNumber) в AddExplorerNode(TreeNode node) и на основе объекта TreeNode и его свойств построить фактический объект, который мне нужен? Я спрашиваю об этом, потому что, если доменные уровни знают о пользовательском интерфейсе (в данном случае о компоненте пользовательского интерфейса TreeNode), в основном мы нарушаем разделение.

Например, если в следующем году мы заменим WindowsForms на Консольное приложение, то проект будет нарушен из-за того, что Консольное приложение не будет иметь компонент пользовательского интерфейса TreeNode.

В этом случае лучше ли иметь доменный метод, который принимает, например, 5-10 параметров (целые, строки и т. д.) и на основе этих параметров создает мой объект или заменяет параметры компонентом пользовательского интерфейса TreeNode, который?

Заранее спасибо.

@РЕДАКТИРОВАТЬ:

Я задаю этот вопрос, потому что мой коллега просмотрел мой код и начал его рефакторить. Путем рефакторинга он выставлял фактический компонент пользовательского интерфейса TreeNode на уровень домена. Мой подход был AddExplorerNode (строковое имя, строковое имя проекта, int projectNumber) и т. д.


person darksleep    schedule 30.06.2016    source источник
comment
Я думаю, что если ExplorerNode является специальным (производным классом?) TreeNode, то вам уже не удалось разделить домены. Уровень вашего пользовательского интерфейса пронизывает ваш домен и уровень данных. Если это отдельный объект, не связанный с WinForms TreeNode, то это неприменимо, и это хорошо (но вы по-прежнему связываете домен с данными). Не добавляйте TreeNode, потому что он... соединит их, вы уже думали об этом. Если вам нужна абстракция (чтобы избежать функций с более чем 2/3 параметрами), введите еще один класс. Хотите назвать его ViewModel?   -  person Adriano Repetti    schedule 30.06.2016
comment
ExplorerNode не является производным классом, это глупое имя, которое я использовал. Буквально это сопоставленная таблица, которая будет содержать информацию об TreeNode, который пользователь создает в пользовательском интерфейсе, на основе TreeNode, созданного пользователем в пользовательском интерфейсе, я храню определенные свойства в базе данных, например: имя, текст, дата создания и т. д.   -  person darksleep    schedule 30.06.2016
comment
Если treenode является компонентом Windows Forms, я бы не стал раскрывать его на уровне домена; Я бы рекомендовал создать объект, представляющий нужный вам API, а затем преобразовать его в узлы дерева в проекте форм Windows при загрузке и преобразовать обратно в объект домена при попытке сохранить его или что-то еще, что вы делаете для его добавления.   -  person Brian Mains    schedule 30.06.2016
comment
@ Брайан Мейнс - ты прав. По сути, у меня есть объект, который имитирует TreeNode, называемый MockNode. Этот MockNode содержит такие свойства, как: текст, имя, идентификатор и т. д. Этот объект MockNode используется на уровне пользовательского интерфейса для хранения свойств фактического компонента пользовательского интерфейса TreeNode. После создания компонента пользовательского интерфейса TreeNode я назначаю эти свойства классу MockNode. На основе свойств MockNode я создаю свой фактический объект, который после проверки и т. д. передается в DataLayer, который его сохраняет.   -  person darksleep    schedule 30.06.2016
comment
Сохраняйте любой пользовательский интерфейс, относящийся к этому слою. Итак, нет, не передавайте TreeNode, специфичный для пользовательского интерфейса. Просто передайте модель данных, необходимую для создания рассматриваемого объекта.   -  person ManoDestra    schedule 30.06.2016


Ответы (1)


Вы можете создать свой собственный класс, который действует аналогично TreeNode, не являясь на самом деле TreeNode.

class TreeNodeModel
{
    public string Name { get; set; }
    public string ProjectName { get; set; }
    public int ProjectNumber { get; set; }
}

Затем вы можете написать метод в пользовательском интерфейсе для сопоставления (копирования) TreeNodeModel с фактическим TreeNode.

person Kip Morgan    schedule 30.06.2016
comment
Это то, что у меня есть прямо сейчас. Класс, который имитирует реальный компонент пользовательского интерфейса TreeNode :-). - person darksleep; 30.06.2016
comment
@darksleep В таком случае вы делаете это правильно на данный момент. Уровень вашей модели данных должен отражать только данные, и вы можете перевести то, как это представлено на уровне пользовательского интерфейса, и это зависит от слоя пользовательского интерфейса, будь то формы, консоль, сеть и т. д. :) - person ManoDestra; 30.06.2016