Никаких исключений: буквально

Рассмотрим другой подход к обработке исключений.

Разве вы не ненавидите, когда статьи начинаются так? Есть два типа людей. Ну, есть два вида. Есть те, кто застилает постель после того, как просыпаются, и есть те, кто оставляет все это в связке.
Имеет ли значение, складываю ли я одеяла, взбиваю подушку и оставляю их аккуратно сложенными? Возможно нет. Но я предпочитаю думать, что становлюсь лучше или, по крайней мере, лучше справляюсь с трудностями более трудного дня; Сходить в спортзал, сделать презентацию или написать сообщение в блоге.

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

С тех пор я узнал, что есть ленивый-хороший и ленивый-плохой. Хорошие разработчики ленивы, они пишут код, который позволяет им меньше работать; или лучше сказать: более эффективно. Но эта лень хороша лишь до некоторой степени, и ее преодоление приводит только к плохому коду. Тем не менее, ни один разработчик внезапно не станет ленивым. Это спираль: мы просто отказываемся от плохого кода, а затем создаем еще один.

Поэтому я настаиваю на том, чтобы заправить постель.

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

Мой любимый подход к обработке исключений - использование нескольких возвращаемых значений. У вас есть это на языке Go, а также в ES6 через деструктуризацию.

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

package main
import "fmt"
import "errors"
func divide(a int, b int) (error, int) {
  if b == 0.0 {
    return errors.New("Division by zero"), 0.0
  } else {
    return nil, (a/b);
  }
}
func main() {
  err1, result1 := divide(8,4)
  if err1 == nil {
    fmt.Printf("Result == %d.\n", result1)
  } else {
    fmt.Println(err1)
  }
  err2, result2 := divide(8,0)
  if err2 == nil {
    fmt.Printf("Result == %d.\n", result2)
  } else {
    fmt.Println(err2)
  }
}

ES6 также предоставляет такую ​​возможность посредством деструктуризации, и я мог бы добавить еще один фрагмент того же решения, написанного на ES6, но я бы предпочел поговорить о async / await.
С async / await, вы можете нарушить синтаксис then / catch, который вы пишете для Promises, и получить код с аккуратным отступом и более читабельным потоком; ну, если вам не нужно что-то ловить.

function findAndPrintUser(id) {
  users.findById(id)
    .then((user) => console.log(user.name))
    .catch((err) => console.error(err));
}
async function findAndPrintUserAsync(id) {
  try {
    const user = await users.findById(id)
    console.log(user.name);
  } catch (err) {
    console.error(err);
  }
}

Во фрагменте кода после замены then на await остается использовать блок try / catch, позволяющий обрабатывать возможность отказа от обещания. Это как бы портит всю аккуратную выемку, о которой мы мечтали. Здесь на помощь приходит деструктуризация.

Следующий фрагмент, который, как мне кажется, я изначально видел в await-to-js, просто состоит из функции, которая принимает обещание, выполняет then / catch и возвращает массив, который можно деструктурировать и никогда бы вы больше не написали в своем коде другое выражение then / catch.

function to(promise) {
  return promise
    .then(data => [null, data])
    .catch(err => [err, null])
}
async function findAndPrintUserAsync(id) {
  const [err, user] = await to(users.findById(id))
  if (err) {
    console.error(err);
  } else {
    console.log(user.name);
  }
}

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

В конце концов, разве не здорово вернуться домой на аккуратно сложенную кровать?

✉️ Подпишитесь на рассылку еженедельно Email Blast от CodeBurst 🐦 Подпишитесь на CodeBurst на Twitter , просмотрите 🗺️ Дорожная карта веб-разработчиков на 2018 год и 🕸️ Изучите веб-разработку с полным стеком .