Разделение UI и логики в C#

У кого-либо есть совет относительно хранения логики из моих классов GUI? Я пытаюсь использовать хороший дизайн класса и сохранить как можно больше разделенным, но мои классы Формы обычно заканчиваются с большим количеством материала неUI, смешанного в том, чем я хотел бы, и он имеет тенденцию делать обслуживание реальной болью.

(Профессионал Visual Studio 2008 года, C#, Приложения Windows).

Большое спасибо.

14
задан Andy 25 June 2010 в 12:05
поделиться

8 ответов

Поместите вашу логику в отдельную сборку; и создайте эту сборку без ссылки на какие-либо пакеты графического интерфейса (например, System.Drawing , System.Windows.Forms и т. д.).

14
ответ дан 1 December 2019 в 09:00
поделиться

На самом деле это просто вопрос практики и самодисциплины. Я имею в виду, мы все это сделали. И все мы продолжаем делать это время от времени в неподходящих условиях (менеджер / клиент кричит, чтобы что-то было сделано «прямо сейчас», а не «правильно» и т. Д.).

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

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

7
ответ дан 1 December 2019 в 09:00
поделиться

Трехуровневая архитектура - это то, что вы ищете.

Вы создаете 2 повторно используемых уровня:

  • Уровень доступа к данным (DAL), который содержит только код, необходимый для чтение / запись из базы данных
  • Business Logic Layer (BLL), которая потребляет DAL, содержит бизнес правил, проверки и предоставляет фасад для использования пользовательского интерфейса

Затем в своем проекте пользовательского интерфейса вы ссылаетесь на повторно используемые слои и обрабатываете только специфические для пользовательского интерфейса материалы. Проект пользовательского интерфейса взаимодействует только с BLL, без прямого подключения к DAL:

UI <---> BLL <---> DAL

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

4
ответ дан 1 December 2019 в 09:00
поделиться

Узнайте, как писать классы контроллеров, которые могут быть привязаны к форме, и как выполнять привязку к базе данных. В WinForms это в основном сводится к интерфейсам INotifyPropertyChanged и IDataErrorInfo в классе контроллера и использованию экземпляров BindingSource в классе формы.

Тогда вы можете написать класс контроллера, который содержит ВСЕ данные и логику для пользовательского интерфейса, а класс пользовательского интерфейса просто привязывается к нему. Тогда ваш класс UI становится очень тонким, а логика UI (хранящаяся в контроллере) становится очень тестируемой (модульные тесты сложны, когда они выполняются против классов UI, но гораздо проще, когда они выполняются против классов контроллера).

Это основа всех конструкций MVC/MVVM.

Херби

1
ответ дан 1 December 2019 в 09:00
поделиться

Одним словом, это называется Рефакторинг.

Есть только пара причин для размещения кода в пользовательском интерфейсе:

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

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

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

Посмотрите книги Мартина Фаулера о рефакторинге, например "Рефакторинг: Improving the Design of Existing Code". Еще одно громкое слово - разделение задач. Я знаю, что все это можно сделать в одном классе, но код становится гораздо более читабельным и легким для отладки, когда он разделен на классы, как я описал выше.

0
ответ дан 1 December 2019 в 09:00
поделиться

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

Что касается разделения логики; определите, какие ключевые компоненты являются ключевыми, и рефакторите их в класс вспомогательного метода. Например, если я обрабатываю GridView для обновления записей на основе того, выбраны они или нет, и если выбраны, то обновляю дату отгрузки в форме; я сначала выясню, выбрана ли строка, затем извлеку поле Id, затем ShipDate, а затем передам Id и ShipDate в метод моего вспомогательного класса, который сделает всю работу.

Здесь вашим другом могут стать модульные тесты; по сути, если у вас есть код, который выполняет "логические" действия, он должен иметь модульный тест. Если он находится в классах GUI, его трудно протестировать, однако после рефакторинга юнит-тест должен быть тривиальным.

0
ответ дан 1 December 2019 в 09:00
поделиться

Вам следует рассмотреть следующие паттерны:

MVC (Model-View-Controller) MVVM (Model-View-View-Model) - наиболее часто используется в WPF с его богатой поддержкой привязки данных. MVP (Model-View-Presenter) - часто используется в WinForms и веб-приложениях (из-за отсутствия статического представления)

Посмотрите эту статью в блоге, в которой приводится пример использования MVP для создания веб- и WinForms представлений с помощью одного презентатора: http://www.cerquit.com/blogs/post/MVP-Part-I-e28093-Building-it-from-Scratch.aspx

Кроме того, еще одна статья в блоге описывает использование паттерна MVP для юнит-тестирования бизнес-логики: http://www.cerquit.com/blogs/post/Model-View-Presenter-Part-II---Unit-Testing.aspx

0
ответ дан 1 December 2019 в 09:00
поделиться

Вам необходимо изучить такие шаблоны проектирования, как:

Модель-Представление-Контроллер (MVC), часто используемый веб-сайтами (ASP.NET)
Модель-Представление-Представление Модель (MVVM ), часто используемый WPF

. Придерживаясь одного из них, вы сможете разделить различные части вашего приложения.

Есть и другие шаблоны, выполняющие аналогичную работу.

Кроме того, может помочь разработка с использованием WPF, поскольку пользовательский интерфейс определяется XAML, а код, выполняющий эту работу, - это C #. Это может обеспечить базовую степень разделения. Если вы обнаружите, что пишете код C #, который просто манипулирует пользовательским интерфейсом, вы можете сделать шаг назад и подумать: «Следует ли мне делать это в XAML?». Очевидно, что в коде могут быть вещи, которые вам нужно будет сделать, но это только начало.

4
ответ дан 1 December 2019 в 09:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: