Evgenii Legotckoi
Там. 26, 2016, 1:09 Т.Қ.

Пайдаланушы нұсқаулығы №24 - Ruby - Ерекшеліктерді өңдеу: құтқару

При выполнении программы могут возникать непредвиденные проблемы.  Файл, который нужно прочитать, может не существовать; диск может оказаться полным в момент записи данных; пользователь может некорректно ввести данные.

  1. ruby> **file = open("some_file")**
  2. **ERR: (eval):1:in `open': No such file or directory - some_file**

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

  1. FILE *file = fopen("some_file", "r");
  2. if (file == NULL) {
  3.   fprintf( stderr, "File doesn't exist.\n" );
  4.   exit(1);
  5. }
  6. bytes_read = fread( buf, 1, bytes_desired, file );
  7. if (bytes_read != bytes_desired ) {
  8.   /* do more error handling here ... */
  9. }
  10. ...

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

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

  1. begin
до тех пор, пока не происходит исключительная ситуация, которая передает управление блоку, отвечающему за ее обработку (начинается с
  1. rescue
).  Если исключения не происходит, то
  1. rescue
-блок не выполняется.  Следующий метод возвращает первую строку из текстового файла или
  1. nil
, если происходит исключение:

  1. def first_line( filename )
  2.   begin
  3.     file = open("some_file")
  4.     info = file.gets
  5.     file.close
  6.     info  # Last thing evaluated is the return value
  7.   rescue
  8.     nil   # Can't read the file? then don't return a string
  9.   end
  10. end

Иногда бывает нужна возможность обойтись с проблемой творчески.  Здесь, если требуемый файл недоступен, мы пробуем использовать стандартный поток ввода:

  1. begin
  2.   file = open("some_file")
  3. rescue
  4.   file = STDIN
  5. end
  6.  
  7. begin
  8.   # ... process the input ...
  9. rescue
  10.   # ... and deal with any other exceptions here.
  11. end

  1. retry
может быть использован внутри
  1. rescue
для запуска повторного выполнения блока с
  1. begin
.  Теперь можно переписать предыдущий пример немного компактнее:

  1. fname = "some_file"
  2. begin
  3.   file = open(fname)
  4.   # ... process the input ...
  5. rescue
  6.   fname = "STDIN"
  7.   retry
  8. end

Тем не менее, здесь есть недостаток.  Несуществующий файл может заставить этот код выполняться снова и снова.  Вы должны остерегаться подобной западни при использовании

  1. retry
для обработки исключительных ситуаций.

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

  1. raise
.  Этот оператор принимает один аргумент, который представляет из себя строку, описывающую исключение.  Аргумент не обязателен, но опускать его не стоит.  Его можно получить позже из специальной глобальной переменной
  1. $!
.

  1. ruby> **raise "test error"**
  2. **test error**
  3. ruby> **begin**
  4.     |**raise "test2"**
  5.     | **rescue**
  6.     |**print "An error occurred: ",$!, "\n"**
  7.     | **end**
  8. An error occurred: test2
  9. **nil**

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз