Введення в обробку помилок в Swift 3

Сьогодні ми підготували переклад для тих, хто так само, як автор статті, при вивченні Документації мови програмування Swift уникає голови «Error Handling».

Зі статті ви дізнаєтеся:

  • що таке оператор if-else і що з ним не так;
  • як подружитися з Error Handling;
  • коли варто використовувати Try! і Try?


Моя історія

Коли я був молодший, я починав вивчати документацію мови Swift. Я кілька разів прочитав усі глави, крім однієї: «Error Handling». Чомусь мені здавалося, що потрібно бути професійним програмістом, щоб зрозуміти цю главу.

Я боявся обробки помилок. Такі слова, як catch, try, throw та throws, здавалися безглуздими. Вони просто лякали. Невже вони не виглядають страшними для людини, яка бачить їх в перший раз? Але не хвилюйтеся, друзі мої. Я тут, щоб допомогти вам.

Як я пояснив своєї тринадцятилітньої сестрі, обробка помилок – це всього лише ще один спосіб написати блок if-else для надсилання повідомлення про помилку.

Повідомлення про помилку від Tesla Motors

Як ви напевно знаєте, у автомобілів Tesla є функція автопілота. Але, якщо в роботі машини з будь-яких причин відбувається збій, вона просить вас взяти кермо в руки і повідомляє про помилку. У цьому уроці ми дізнаємося, як виводити таке повідомлення за допомогою Error Handling.

Ми створимо програму, яка буде розпізнавати такі об'єкти, як світлофори на вулицях. Для цього потрібно знати як мінімум машинне навчання, векторне числення, лінійну алгебру, теорію ймовірності і дискретну математику. Жарт.

Знайомство з оператором if-else

Щоб максимально оцінити Error Handling в Swift, давайте оглянемося в минуле. Ось що багато, якщо не все, початківці розробники зробили б, зіткнувшись з повідомленням про помилку:

var isInControl = true

func selfDrive() {
if isInControl {
print("You good, let me ride this car for ja")
} else {
print("Hold the handlebar RIGHT NOW, or you gone die")
}
}

selfDrive() // "You good..."

Проблема

Найбільша проблема полягає в читання коду, коли блок else стає занадто громіздким. По-перше, ви не зрозумієте, містить сама функція повідомлення про помилку, до тих пір, поки не прочитаєте функцію від початку до кінця або якщо не назвете її, наприклад, selfDriveCanCauseError, що теж спрацює.

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

З іншою проблемою можна зіткнутися при виконанні деяких складних функцій або дій всередині блоку else. Наприклад:

else {
print("Hold the handle bar Right now...")

// If handle not held within 5 seconds, car will shut down 
// Slow down the car
// More code ...
// More code ...

}

Блок else роздувається, і працювати з ним – все одно що намагатися грати в баскетбол в зимовому одязі (по правді кажучи, я так і роблю, так як в Кореї досить холодно). Ви розумієте, про що я? Це некрасиво і нечитабельне.

Тому ви просто могли б додати функцію в блок else замість прямих викликів.


else { 
slowDownTheCar()
shutDownTheEngine()
}

Однак при цьому зберігається перша з виділених мною проблем, плюс немає якогось певного способу позначити, що функція selfDrive() небезпечна і що з нею потрібно звертатися з обережністю. Тому пропоную зануритися в Error Handling, щоб писати модульні і точні повідомлення про помилки.

Знайомство з Error Handling

До цього часу ви вже знаєте про проблему If-else з повідомленнями про помилки. Наведений вище приклад був дуже простим. Давайте припустимо, що є два повідомлення про помилку:

  1. ви заблукали
  2. акумулятор автомобіля розряджається.
Я збираюся створити enum, який відповідає протоколу Error.

enum TeslaError: Error {
case lostGPS
case lowBattery 
}

Чесно кажучи, я точно не знаю, що робить Error протокол, але при обробці помилок без цього не обійдешся. Це як: «Чому ноутбук включається, коли натискаєш на кнопку? Чому екран телефону можна розблокувати, провівши по ньому пальцем?»

Розробники Swift так вирішили, і я не хочу задаватися питанням про їх мотиви. Я просто використовую те, що вони для нас зробили. Звичайно, якщо ви хочете розібратися детальніше, ви можете завантажити програмний код Swift і проаналізувати його самостійно – тобто, за нашою аналогією, розібрати ноутбук або iPhone. Я ж просто пропущу цей крок.

Якщо ви заплуталися, потерпіть ще кілька абзаців. Ви побачите, як все стане ясно, коли TeslaError перетвориться в функцію.

Давайте спершу надішлемо повідомлення про помилку без використання Error Handling.

var lostGPS: Bool = true
var lowBattery: Bool = false

func autoDriveTesla() {
if lostGPS {
print("i'm lost, bruh. Hold me tight")
// A lot more code

}
if lowBattery {
print("HURRY! ")
// Loads of code 
}
}

Отже, якщо б я запустив це:


autoDriveTesla() // "HURRY! " 

Але давайте використаємо Error Handling. В першу чергу ви повинні явно вказати, що функція небезпечна і може видавати помилки. Ми додамо до функції ключове слово throws.


func autoDriveTesla() throws { ... }

Тепер функція автоматично каже вашим товаришам по команді, що autoDriveTesla – особливий випадок, і їм не потрібно читати весь блок.

Звучить непогано? Чудово, тепер настав час видавати ці помилки, коли водій стикається з lostGPA або lowBattery всередині блоку Else-If. Пам'ятайте про enum TeslaError?

func autoDriveTesla() throws {
if lostGPS {
throw TeslaError.lostGPS

}
if lowBattery {
throw TeslaError.lowBattery
}

Я вас всіх зловлю

Якщо lostGPS одно true, то функція відправить TeslaError.lostGPS. Але що робити потім? Куди ми будемо вставляти це повідомлення про помилку і додавати код для блоку else?

print("Bruh, i'm lost. Hold me tight")

Окей, я не хочу завалювати вас інформацією, тому давайте почнемо з того, як виконати функцію, коли в ній є ключове слово throws.

Так як це особливий випадок, вам необхідно додавати try всередину блоку do при роботі з цією функцією. Ви такі: «Що?». Просто постежите за ходом моїх думок ще трохи.

do {
try autoDriveTesla() 
}

Я знаю, що ви зараз думаєте: «Я дуже хочу вивести на екран моє повідомлення про помилку, інакше водій помре».

Отже, куди ми вставимо це повідомлення про помилку? Ми знаємо, що функція здатна відправляти 2 можливих повідомлення про помилку:

  1. TeslaError.lowBattery
  2. TeslaError.lostGPS.
Коли функція видає помилку, вам необхідно її «зловити» і, як тільки ви це зробите, вивести на екран відповідне повідомлення. Звучить трохи заплутано, тому давайте подивимося.

var lostGPS: Bool = false
var lowBattery: Bool = true

do {
try autoDriveTesla() 
} catch TeslaError.lostGPS {
print("Bruh, i'm lost. Hold me tight")
} catch TeslaError.lowBattery {
print("HURRY! ")
}
}

// Results: "HURRY! "

Тепер все має бути зрозуміло. Якщо зрозуміло не всі, ви завжди можете подивитися моє відео на YouTube.

Обробка помилок з Init

Обробка помилок може застосовуватися не тільки до функцій, але і тоді, коли вам потрібно ініціалізувати об'єкт. Припустимо, якщо ви не задали ім'я курсу, то потрібно видавати помилку.



Якщо ви введете tryUdemyCourse(name: ""), з'явиться повідомлення про помилку.

Коли використовувати Try! і Try?

Добре. Try використовується тільки тоді, коли ви виконуєте функцію/ініціалізацію всередині блоку do-catch. Проте якщо у вас немає мети попередити користувача про те, що відбувається, виводячи повідомлення про помилку на екран, або як-то виправити її, вам не потрібен блок catch.

try?– що це?

Давайте почнемо з try? Хоча це не рекомендується,

let newCourse = try? UdemyCourse("Functional Programming")

try? завжди повертає опціональний об'єкт, тому необхідно витягти newCourse

if let newCourse = newCourse { ... }

Якщо метод init викидає помилку, як, наприклад,

let myCourse = try? UdemyCourse("") // throw NameError.noName

то myCourse буде дорівнює nil.

try! – що це?

На відміну від try? воно повертає не опціональне значення, а звичайне. Наприклад,

let bobCourse = try! UdemyCourse("Practical POP")

bobCourse не опціонально. Однак, якщо при методі ініціалізації видається помилка начебто,

let noCourseName = try! UdemyCourse("") // throw NameError.noName

додаток впаде. Так само як і у випадку з примусовим вилученням з допомогою !, ніколи не використовуйте його, якщо ви не впевнені на 101% в тому, що відбувається.

Ну ось і все. Тепер ви разом зі мною зрозуміли концепцію Error Handling. Легко і просто! І не потрібно ставати професійним програмістом.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.