Рефакторинг большого, сложного пользовательского интерфейса - PullRequest
9 голосов
/ 25 июня 2011

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

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

Ответы [ 3 ]

11 голосов
/ 25 июня 2011

Рассмотрим свою цель, прежде чем начать.Вы хотите стремиться к ТВЕРДЫМ принципам , по моему мнению.Это означает, среди прочего, что класс / метод должен иметь одиночную ответственность .В вашем случае код вашей формы, вероятно, координирует элементы пользовательского интерфейса и бизнес-правил / доменных методов.

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

Кроме того, исследуйте шаблоны проектирования пользовательского интерфейса. MVC очень популярен и хорошо зарекомендовал себя, хотя его трудно реализовать в современных приложениях на основе настольных компьютеров.Это дало начало шаблонам MVP / пассивного просмотра и MV-VM .Лично я предпочитаю MVVM, но вы можете в конечном итоге создать много «фреймворк-кода» при реализации в WinForms, если не будете осторожны - оставайтесь простыми.

Кроме того, начните думать в терминах «Задачи» или«Действия», следовательно, создают основанный на задачах пользовательский интерфейс , а не то, что составляет create / read / update / delete (CRUD) UI.Считайте, что объект, связанный с первой вкладкой, является совокупным корневым и имеет кнопки / панели инструментов / ярлыки ссылок, по которым пользователи могут нажимать для выполнения определенных задач.Когда они это делают, они могут перейти на совершенно другую страницу, которая объединяет только определенные поля, необходимые для выполнения этой работы, что устраняет сложность.

Командный процессор

Шаблон Командный процессор:в основном синхронный шаблон издатель / потребитель для событий, инициируемых пользователем.Ниже приведен базовый (и довольно наивный) пример.

По сути, с помощью этого шаблона вы пытаетесь добиться перемещения обработки событий из самой формы.Форма может по-прежнему иметь дело с такими проблемами пользовательского интерфейса, как скрытие / удаление элементов управления, анимация и т. Д., Но вы стремитесь к четкому разделению проблем для реальной бизнес-логики.Если у вас модель обогащенного домена , «обработчики команд» по существу будут координировать вызовы методов в модели домена.Командный процессор сам по себе дает вам удобное место для переноса методов-обработчиков в транзакциях или для предоставления таких вещей в стиле AOP , как аудит и ведение журнала.

public class UserForm : Form
{
    private ICommandProcessor _commandProcessor;

    public UserForm()
    {
        // Poor-man's IoC, try to avoid this by using an IoC container
        _commandProcessor = new CommandProcessor();
    }

    private void saveUserButton_Click(object sender, EventArgs e)
    {
        _commandProcessor.Process(new SaveUserCommand(GetUserFromFormFields()));
    }
}

public class CommandProcessor : ICommandProcessor
{
    public void Process(object command)
    {
        ICommandHandler[] handlers = FindHandlers(command);

        foreach (ICommandHandler handler in handlers)
        {
            handler.Handle(command);
        }
    }
}
2 голосов
/ 25 июня 2011

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

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

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

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

1 голос
/ 25 июня 2011

Я бы посоветовал вам прочитать о CAB (блок приложения составного пользовательского интерфейса) из практики и шаблонов Microsoft, который включает следующие шаблоны: шаблон команд, шаблон стратегии, шаблон MVP ... и т. Д.

Практика и шаблоны Microsoft

Блок приложения составного пользовательского интерфейса

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...