Моя компания разрабатывает приложение с графическим интерфейсом, которое позволяет пользователям запрашивать устаревшую систему баз данных и отображать результаты на экране (результаты просто возвращаются в виде простого текста). Я борюсь с лучшим способом структурировать взаимодействие между пользовательским интерфейсом и уровнем домена, особенно проверкой пользовательского ввода.
Базовый вариант использования
- Пользователь выбирает запрос для запуска из меню в приложении.
- Код приложения отображает форму ввода данных для выбранного запроса.
- Пользователь вводит параметры для запроса. Если поле содержит недопустимые данные, оно сразу же выделяется красным цветом, и его текст всплывающей подсказки изменяется для отображения сообщения об ошибке (т. Е. Если вы вводите запрос Person и вводите дату рождения в будущем, например, поле даты рождения сразу станет красным).
- Когда пользователь нажимает
Run Query
, приложение запускает второй проход проверки; этот второй проход проверки необходим для запуска проверочных проверок, включающих несколько полей. Если эта проверка проверки пройдена, и все поля действительны, запрос отправляется; в противном случае пользователю предлагается исправить все оставшиеся ошибки.
Моя текущая стратегия проверки / сообщения об ошибках
В настоящее время я использую валидацию, ориентированную на домен, но общий дизайн кажется мне неопрятным и, возможно, слишком излишним. Краткий обзор текущего дизайна:
Доменный слой : у меня есть один класс на запрос. Каждый класс запросов содержит коллекцию IQueryField
объектов, которые содержат значения, введенные пользователем. Каждый класс запросов реализует общий интерфейс IQueryMessage
, который определяет (среди прочего) метод Validate
. Этот метод вызывается для применения правил проверки на уровне сообщений (т. Е. Правил, которые должны проверять состояние нескольких полей одновременно). Интерфейс IQueryField
также определяет метод Valdate (среди прочего). Это должно поддерживать правила валидации для каждого поля.
Проверка каждого поля : Для обработки проверки каждого поля и сообщения об ошибках код ввода данных связывает каждый элемент управления ввода с IQueryField
; всякий раз, когда пользователь изменяет значение элемента управления, он вызывает соответствующий метод IQueryField
Validate
, который, в свою очередь, заполняет объект Notification
(просто набор строк в данный момент) любыми ошибками, обнаруженными в значение, введенное пользователем. Затем код пользовательского интерфейса проверяет объект Notification
и изменяет внешний вид пользовательского элемента управления, чтобы при необходимости указать состояние ошибки.
Проверка на уровне сообщения : Когда пользователь пытается отправить запрос, приложение вызывает метод Validate
в экземпляре IQueryMessage
, связанном с формой ввода данных (на этом этапе данные связующий код также обеспечил заполнение всех полей сообщения из элементов управления вводом в форме и выполнение кода проверки для каждого поля). Если есть какие-либо ошибки проверки, пользовательский интерфейс отображает их в верхней части формы. Если ошибок нет, форма ввода данных закрывается, а запрос сериализуется и отправляется по сети.
Что-то здесь не так?
Я чувствую, что здесь что-то не так. У меня есть несколько проблем с текущим дизайном:
Мне бы хотелось, чтобы код проверки на уровне домена указывал имя любых полей, в которых произошла ошибка, но я не хочу жестко кодировать заголовки меток пользовательского интерфейса в классах домена. Одна возможность, о которой я подумал, состояла в том, чтобы методы Validate
уровня домена генерировали сообщения с местозаполнителем, таким как "%s cannot be in the future"
, и чтобы код пользовательского интерфейса заполнял заполнитель правильной меткой.
Оба интерфейса IQueryMessage
и IQueryField
имеют метод, называемый Validate
. Я думаю, что это должно быть извлечено в отдельный интерфейс, (IValidatable
возможно), но мне интересно, если я делаю вещи излишне сложными.
Я использую VB6, поэтому я не могу использовать наследование в своих классах (VB6 поддерживает классы, но не наследование). Я могу только определять и реализовывать интерфейсы. Из-за этого и из-за того, как спроектированы мои текущие интерфейсы, я дублирую много стандартного кода в моих классах реализации. Я думаю о решении этого с помощью подхода инверсии контроля. Например, я думал об определении одного конкретного класса QueryField
, который можно инициализировать с помощью набора экземпляров IValidationRule
, определяющих, какие правила проверки использовать, а затем метод QueryField.Validate()
просто соберет результаты выполнения каждого из них. править. Таким образом, правила проверки могут быть адаптированы к каждому полю, но класс QueryField
может обрабатывать все общие связанные с полями вещи (имя поля, длина поля, обязательные / не обязательные проверки и т. Д.).
Как я могу улучшить это?
Меня интересуют любые предложения по рефакторингу и советы по улучшению текущего дизайна. Кроме того, я не обязательно связан с проверкой, ориентированной на домен; другие предложения приветствуются. Основной мотивацией для использования доменной центрированной проверки было сохранение инкапсуляции увеличения и возможность использования сообщения запроса и объектов поля в среде без графического интерфейса без необходимости переписывать всю логику проверки.