Путь для отделения слоя представления от существующего приложения winforms?

Данный:

  1. В нашей организации есть стандартное приложение windows form
  2. Форма и бизнес-логика взаимосвязаны, например автономный просмотр. . Мы знаем, что шаблон Autonomous View усложняет написание модульных тестов. Цель состоит в том, чтобы взять единую форму и отделить логику представления от самой формы, чтобы у нас была автономная сущность/объект предметной области, для которой было бы легче написать модульные тесты.
  3. Мы НЕ делаем полную переработку. Я рассматриваю постепенный подход, который позволяет работать с одним экраном изолированно.
  4. После некоторых исследований я думаю, что шаблон Модель презентации или MVVM наиболее подходят для того, как работает эта организация.
  5. Эта организация обычно предпочитает меньшее количество уровней косвенности, поэтому чем проще (хотя и менее надежно), тем лучше.
  6. Переход от того, что было, к тому, что будет, должен быть шаблонным (легко обучить любого разработчика, уже знакомого с внутренними концепциями). Вот почему они хотят придерживаться форм Windows, а не других новых технологий, таких как WPF.
  7. Модель предметной области ничего не знает о представлении (форме). Форма будет полностью осведомлена об изменениях в модели предметной области. Это делает 2 уровня косвенности. Еще 1 было бы хорошо (поэтому я бы разрешил MVVM).

Большинство примеров MVVM, которые я нашел, иллюстрируют, как он сочетается с WPF, а не с простыми старыми формами Windows.

Два вопроса:

Учитывая все это, есть ли что-то из того, что я сказал, что вы думаете, что я не на правильном пути или что я на неправильном пути? Я хочу дать некоторые рекомендации руководству.

Наконец, знаете ли вы хороший онлайн-пример кода, который помог бы мне конкретизировать прототип?


person Mario    schedule 16.05.2013    source источник
comment
winforms не поддерживает MVVM. На самом деле MVVM был создан специально ДЛЯ WPF, в основном на основе Модели представления Мартина Фаулера.   -  person Federico Berasategui    schedule 17.05.2013
comment
Если вы ожидаете, что winforms будет поддерживать MVVM, вам понадобится фреймворк на основе winforms с поддержкой таких вещей, как (Real) DataBinding, DataTemplates, DataTriggers и так далее. Без этих концепций MVVM не может существовать. Такого фреймворка нет, поэтому вам придется создать его самостоятельно. Это огромные усилия, которые не имеют никакого смысла. Это похоже на создание среды пользовательского интерфейса Windows для QBasic.   -  person Federico Berasategui    schedule 17.05.2013
comment
Спасибо Хайкор. Я уверен, что существует гибридный (или альтернативный) подход, который делает что-то вроде того, что я прошу (даже если WPF является естественным компаньоном MVVM). Мне интересно узнать мнение любого, кто тоже думал пересечь этот мост.   -  person Mario    schedule 17.05.2013
comment
Шаблон MVP будет более подходящим для ваших требований и может быть реализован постепенно.   -  person Big Daddy    schedule 17.05.2013


Ответы (4)


Возможно, лучшее, что вы можете сделать, — это взглянуть на свой код с точки зрения принципа единой ответственности. . Одна из основных причин того, что автономное представление (и winforms, которое его поддерживает) так трудно тестировать, заключается в том, что разработчики склонны смешивать все вместе в обработчике событий.

Возьмите этот вопрос на SO - https://stackoverflow.com/questions/16599778/asp-net-mvc3-linq-make-multiple-related-rows-fields-in-a-1-to-many-relationshi, речь идет о MVC3, но это полный беспорядок - один метод, который отвечает за настройку представления сетки, настройку ответа и получение данных для заполнения представления сетки. Трудно даже понять, с чего начать отвечать на вопрос, не говоря уже о написании каких-либо разумных (читай: кратких и быстрых в выполнении) тестов, чтобы убедиться, что решение работает.

Если вы можете тщательно просмотреть свой код и тщательно инкапсулировать всю бизнес-логику и/или точки интеграции в сервисы/компоненты/интерфейсы (и реализации), предпочтительно в отдельные сборки снаружи.

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

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

Я думаю, что класс winform будет иметь конструктор, который принимает много аргументов (смесь различных сервисов, обсуждавшихся выше). Платформа DI будет отвечать за предоставление услуг классу winform. После этого, в идеале, ваши обработчики событий winforms будут относительно небольшими, просто вызывая методы службы со значениями параметров, собранными из различных полей формы.

Вот сообщение об использовании Castle Windsor (среда внедрения зависимостей ) с winforms: Использование Castle.Windsor с приложениями Windows Forms. Существует множество различных DI-фреймворков, я использую Castle Windsor, потому что это тот, который я изучил первым, все они делают по сути одно и то же, поэтому все, что вам нужно сделать, это найти тот, который вам удобен.

Вот руководство по разделению проблем который основан на веб-приложении, но должен быть инструктивным в отношении того, как идентифицировать и реорганизовать сервисы из существующего приложения "кухонная раковина".

Этот ответ превращается в книгу, и все это очень абстрактно. Главное, вам нужно думать о приложении как о наборе блоков лего, которые вы комбинируете для создания функциональности (каждый блок представляет собой проблему), а пользовательский интерфейс — это просто клей, который скрепляет блоки (эта аналогия не идеальна). .

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

person Jason    schedule 17.05.2013
comment
Спасибо, что нашли время поделиться своим мнением. Я уверен, что наша команда (включая меня) могла бы разработать подход для извлечения бизнес-логики в отдельный слой. Моя главная цель в вопросе заключалась в том, чтобы не изобретать заново, если можно было бы извлечь разумные принципы из какого-то подхода, который уже был опробован и отшлифован. В любом случае, ваши очки хорошо приняты. Спасибо. - person Mario; 17.05.2013

В WPF мы можем выполнять привязку данных между объектами в представлении и содержимым в ViewModel, и поэтому MVVM является идеальным шаблоном для WPF.

Я изучил MVVM на этом примере: http://www.scottlogic.co.uk/blog/colin/2011/05/a-simple-windows-phone-7-mvvm-tombstoneing-example/

Это учебник по Windows Phone, но если вы понимаете, как он работает, вы можете легко использовать его с любым приложением WPF.

person cap7    schedule 17.05.2013

Я думаю, что ваш лучший вариант — поставить ElementHosts< /a> в вашем существующем приложении winforms и поместите в них содержимое WPF. Затем вы можете использовать WPF и MVVM и постепенно обновлять приложение winforms до WPF.

Даже если вы используете какой-то вспомогательный фреймворк в winforms, вы всегда будете сталкиваться с ограничениями, которые приведут к грязным, хакерским решениям, которые загрязняют чистоту, которой вы пытаетесь достичь.

Например, в winforms нет ничего, что могло бы обеспечить ту же функциональность, что и WPF ItemsControl с DataTemplates. Взгляните на этот пример ListBox с некоторыми DataTemplates в WPF. Вы не сможете добиться чего-либо подобного в winforms с помощью ListBox, независимо от того, сколько сторонних фреймворков вы используете.

Итог: поместите ElementHosts с содержимым WPF в каждую форму, и вы сможете постепенно очистить весь беспорядок winforms в чистом, MVVM, тестируемом, независимом от разрешения, просто красивом пользовательском интерфейсе WPF. Я настаиваю (и никто еще не смог доказать мне обратное), что это единственный способ получить что-то приличное из winforms.

person Federico Berasategui    schedule 17.05.2013
comment
Я ценю ваш вдумчивый отзыв, но этот магазин не хочет переходить на WPF. В этом магазине есть несколько приложений уровня предприятия, построенных на основе одной и той же внутренней среды. Многие разработчики хотели бы перейти на более новые технологии, но это не наш выбор. - person Mario; 17.05.2013

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

Идеальным решением было бы такое, при котором извлечение предметной области само по себе было бы очень похоже на методы проектирования, используемые в организации. По сути, это было бы извлечение визуальной формы во всем ее великолепии пользовательского интерфейса в более абстрактную форму («VM» или модель представления), которая воплощает концепции, используемые в формах (комбо, кнопки и т. д.) без с использованием реальных пользовательских элементов управления. Затем виртуальная машина будет привязана к представлению, в котором фактически находятся элементы управления.

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

Возьмем, к примеру, простое внутреннее поле со списком. Комбинация представляет собой ввод с ограниченным набором вариантов выбора. Наша модель данных представляет собой набор данных в памяти. Комбинация привязывается к конкретной таблице, и по мере того, как пользователь заполняет форму и, таким образом, предоставляет критерии, его допустимые варианты выбора дополнительно фильтруются. Эта комбинация отображает значение для пользователя (DisplayMember) и сохраняет другое значение в БД (ValueMember). Там, вероятно, немного больше, чем это; однако абстракция «поля» для комбо должна учитывать некоторые из этих концепций, чтобы в конечном итоге ее можно было правильно сопоставить с представлением. Кроме того, наша форма подписывается на множество событий, исходящих от ее элементов управления. Они должны быть отображены каким-то образом. Так что мне кажется, что большая часть функций формы (представления) должна иметь аналог в виртуальной машине. Таким образом, ВМ становится в некоторой степени тенью физической формы, которую она представляет.

Первоначально я думал, что можно извлечь очень общую абстракцию формы и составляющих ее элементов управления, а затем отобразить эту абстракцию (которая очень похожа на исходную форму) на представление. Хотя это и возможно, сейчас я считаю, что это нецелесообразно и само по себе может создать множество новых проблем.

Поэтому, хотя я и хотел избежать запуска тестов с фактическим экземпляром формы, я думаю, что это может быть лучше, чем пытаться добавить уровень абстракции. Построение этой абстракции было бы похоже на попытку переписать наши экраны с использованием другой парадигмы и, таким образом, не сохранить исходную форму экрана. То есть, даже если бы мы могли переписывать одну форму за раз, обеспечивая постепенный переход, окончательная версия не будет повторно использовать столько исходной структуры, как хотелось бы.

person Mario    schedule 17.05.2013