Дизайн исключений: пользовательские исключения, считывающие данные из файла? - PullRequest
1 голос
/ 31 марта 2010

У меня есть метод, который читает данные из текстового файла, разделенного запятыми, и создает список объектов сущностей, скажем, клиентов.

Так, например, читается:

Name
Age
Weight

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

Теперь мой вопрос, должен ли я генерировать исключение, такое как InvalidAgeException, из метода, считывающего данные файла? И предположим, что есть ограничение длины для поля «Имя», поэтому, если длина больше, чем максимальные символы, я выбрасываю исключение NameTooLongException или просто InvalidNameException, или я просто принимаю его и жду, пока бизнес-уровень не получит его и не выдаст исключения оттуда?

(Если вы можете указать мне хороший ресурс, который тоже был бы хорош)

Ответы [ 5 ]

3 голосов
/ 31 марта 2010

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

  • Назовите пользовательские классы исключений как можно более «раскрывающими намерения». Поэтому исключение NameTooLongException лучше, чем исключение InvalidNameException
  • Также исключение должно быть таким же полезным для клиента, чтобы решить проблему. (Ах, мне нужно сократить имя в файле, а не копаться в исключении / коде, чтобы узнать, почему Имя неверно.) Сократить обнаружение и разрешение цикла времени для ваших клиентов.
1 голос
/ 31 марта 2010

Похоже, что вы делаете несколько вещей в вашем методе:

  1. Чтение внешнего источника данных (файла)
  2. Создание объектов из прочитанных данных.
  3. Передача объектов в другую часть приложения (для дальнейшей обработки).

Я бы ограничил валидацию следующими случаями:

  1. Если вы не можете прочитать файл throw здесь (нет файла, файл в неправильном формате).
  2. Если вы не можете создавать объекты из-за сброса данных здесь («возраст» не может быть проанализирован из-за нечисловых символов).
  3. Проверка Бизнес-логика (имя слишком длинное или слишком маленькое, вес слишком большой или слишком маленький) в Бизнес-уровень .
1 голос
/ 31 марта 2010

Зависит от того, как настроена ваша логика. Если ваша логика чтения файлов является универсальной (не универсальной в C #, а универсальной в том смысле, что она не специфична), то было бы лучше поместить исключение в значение чуть выше.

Например, если так было настроено:

// just an example
FileContents ReadFile(string path)
{
   // Don't necessarily throw exceptions related to data validity
}

SomeObject FromFile(string path)
{
   FileContents contents = ReadFile(path);
   // Do throw exceptions related to data validity

   // construct your object
}

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

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

Пример иерархии наследования может быть:

  • System.Exception
    • DataLoadException
      • NameException
        • NameTooLongException
        • InvalidNameException
      • AgeException
      • ...

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

1 голос
/ 31 марта 2010

Если данные непригодны, вероятно, лучше всего выдать исключение во время чтения записи. Например, если вы знаете, что символьные данные в поле возраста могут быть возможны, только если пользователь испортил файл за пределами вашего приложения. Это то, что произойдет, если вы попытаетесь сериализовать объект, испортить сериализованные данные, а затем попытаться десериализовать его.

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

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

0 голосов
/ 31 марта 2010

Лучше всего подходит для пакетной обработки, я бы сказал, создания класса проверки и ErrorData. Класс данных будет иметь Linenumber (CSV linenumber), Message и, если вы считаете, какие-либо свойства подходят

Прочитайте файл и передайте всю коллекцию в класс проверки, чтобы проверить и получить ошибки в коллекции класса ErrorData.

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

Кто-нибудь может открыть журнал / или сообщение об ошибке, чтобы исправить данные.

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