Есть ли лучший способ проверки ввода пользователя?

Есть ли лучший способ проверки ввода пользователя?

Актуальная проблема:

Пользователь дает определенные входные данные в окне. Когда он закончил с этими входами, он может нажать "Создать". Теперь должно быть отображено всплывающее сообщение со всеми неверными данными. Если нет неправильного ввода, просто продолжите.

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

Я планировал создать класс ErrorMessages, который содержит список, в который я могу поместить все сообщения об ошибках. Каждый раз, когда вводится неверный ввод, новое сообщение добавляется в список errorMessages. Поэтому, если пользователь нажимает кнопку "Создать", отображаются все сообщения в списке. Это хороший способ справиться с вещами?

Так есть ли лучший способ практики? Какие-либо шаблоны проектирования, которые обеспечивают такое решение?

Редактировать: это школьное задание. Так и с нелогичными требованиями. Я должен показать все неверные данные, когда нажимаю "создать". Я хотел бы сделать это из класса Form. (Таким образом, валидация работает даже без GUI, я даже не создавал GUI на данный момент). Сначала убедитесь, что моя функциональность работает правильно;). Я хочу, чтобы мой код был чистым, абстрактным и ООП. Так как мне показать мои сообщения об ошибках?

4 ответа

Решение

Я планировал создать класс ErrorMessages, который содержит список, в который я могу поместить все сообщения об ошибках. Каждый раз, когда вводится неверный ввод, новое сообщение добавляется в список errorMessages. Поэтому, если пользователь нажимает кнопку "Создать", отображаются все сообщения в списке. Это хороший способ справиться с вещами?

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

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

Вместо этого я рекомендую использовать ErrorProvider класс для отображения любых ошибок прямо рядом с соответствующим элементом управления. Я немного больше рассказал об этом подходе в своем ответе здесь и здесь.

Конечно, вам все равно нужно будет убедиться в окончательном представлении (нажав кнопку ОК / Отправить), что все введенные данные верны, но тогда это всего лишь простой случай проверки на наличие ошибок.

Я мог бы легко сделать это в классе Form. Но я помню лучший метод проверки входных данных в установленных свойствах.

Да, идея здесь заключается в инкапсуляции. Класс Form должен знать только материал формы. Не нужно знать, какой тип ввода / не подходит для всех ваших различных элементов управления.

Вместо этого эту логику проверки следует размещать в другом месте, например в классе, в котором хранятся ваши данные. Этот класс будет предоставлять открытые свойства для получения и установки данных, а внутри метода setter он будет проверять данные.

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

Этого не должно быть, ни один экземпляр класса не может быть создан, если ввод не действителен.

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

Такой класс, вероятно, вообще не имел бы методов установки - только методы получения.

Тем не менее, это своего рода необычное требование в мире C# (каким бы распространенным оно ни было в C++). Как правило, размещение вашего кода проверки внутри сеттеров работает просто отлично.

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

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

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

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

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

Сначала создайте пользовательские атрибуты проверки

public class ValidationAttribute : Attribute{
  public type RuleType{get;set;}
  public string Rule{get;set;}
  public string[] RuleValue{get;set;}
}

Во-вторых, создайте собственный обработчик ошибок / сообщение

public class ValidationResult{
  public bool IsSuccess{get;set;};
  public string[] ErrorMessages{get;set;};
}

Затем создайте валидатор

public class RuleValidator{
  public ValidationResult Validate(object o){
    ValidationResult result = new ValidationResult();
    List<string> validationErrors = new List<string>();
    PropertyInfo[] properties = o.GetType().GetProperties();
    foreach(PropertyInfo prop in properties){
      // validate here
      // if error occur{
        validationErrors.Add(string.Format("ErrorMessage at {0}", prop.Name));
      //}
    }

    result.ErrorMessages = validationErrors.ToArray();
  }
}

Чтобы использовать это, то вы можете сделать так:

public class Person{
  [ValidationAttribute(typeof(string), "Required", "true")]
  public string Name{get;set;}

  [ValidationAttribute(typeof(int), "Min", "1")]
  public int Age{get;set;}
}

Для вызова валидатора

public void ValidatePerson(Person person){
  RuleValidator validator = new RuleValidator();
  ValidationResult result = validator.Validate(person);
  // generate the error message here, use result.ErrorMessages as source
}

В чем преимущество:

  1. Вы можете использовать в любой платформе приложений (Winforms, Asp.Net, WCF и т. Д.)
  2. Вы можете установить правило на уровне атрибута
  3. Это может сделать автоматическую проверку
  4. Этот подход может использоваться с DependencyInjection с пользовательскими валидаторами для разделения логики валидации

Недостаток:

  1. Трудно создать валидаторы
  2. При неправильном обращении валидаторы могут стать очень большими
  3. Плохая производительность из-за использования отражения

Увидеть ErrorProvider класс (документация здесь). Он предоставляет набор стандартных визуальных индикаторов, которые можно прикрепить к большинству стандартных элементов управления WinForms.

Есть несколько возможных подходов:

  • Используйте "мгновенную" проверку.

Когда пользователь вводит значение, оно проверяется во время ввода (TextChanged) и подтверждено сразу. Создайте экземпляр нового класса, вызовите свойство / метод, что следует принять string и вернуться bool (или бросить Exception в случае собственности), на false - нарисовать специальное состояние ошибки (красная метка рядом с текстовым полем, что-то мигает, ErrorProvider или что вы можете сделать, что должно сказать пользователю "неправильно!").

Этот мне нравится использовать, но немного по-другому, обычно я проверяю только Type а затем просто пытаюсь разобрать его сразу в форме. Можно абстрагироваться больше, если форма оперирует stringи все форматирование и проверка происходит в классе (установщики свойств). Или вы можете предоставить форму с дополнительной информацией (используя методы запроса или атрибуты), чтобы она могла выполнять мгновенную проверку без необходимости создания экземпляра класса или использования установщиков. Как пример, double factor свойство может быть идентифицировано в форме (или даже элементе управления), чтобы выполнить 'double.Parseand you can have attributeЗначение по умолчаниюwhich can be used to display to the user value in the different way when it's different from default (like it is done byPropertyGrid`).

  • Используйте обычную проверку.

Когда пользователь закончил ввод, подтвердите (пытаясь установить значение и поймав исключение), если не так - пользователь не может "выйти" или "прогрессировать", пока он не нажмет ESC (чтобы отменить изменения) или исправит свой ввод, чтобы пройти проверку.

Этот мне не нравится. Идея проведения пользователя раздражает меня (и пользователя ofc). Также сложно реализовать перекрестные проверки (например, если у вас есть Min а также Max значения, затем пользователь будет вынужден сначала увеличить "право", иначе аннулирование не удастся).

  • Используйте "ОК" проверки.

Это просто означает, что пользователь может вводить все и проверять, только когда он нажимает кнопку "ОК".

Я думаю, что сочетание кнопки "ОК" и интерактивной мгновенной проверки является лучшим для пользователя. Поскольку пользователь знает, где он допустил ошибку при вводе, но он все еще свободен для просмотра и только получит "пощечину" от проверки после нажатия кнопки "ОК" (на этом шаге вы можете просто показать ему первую из ошибок, которые он сделал, не обязательно) показать им все).

Сообщения об ошибках могут быть предоставлены сеттерами по старинке LastError так или в виде текста в Exception,

Другие вопросы по тегам