Рубрика «exception»

Почему я предпочитаю исключения, а не значения ошибок - 1


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

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

Давайте рассмотрим пример, в котором применено защищённое от ошибок целочисленное деление:

int safeDiv(int a, int b) {
   if (b == 0)
      throw Div0(); // Исключения передаются особым образом
   return a / b; // Теперь-то всё абсолютно безопасно, ведь так?
}

Новые языки программирования склонны применять сообщения об ошибках в функциональном стиле и кодировать ошибки в возвращаемый тип. Например, Go кодирует ошибку в возвращаемый тип при помощи кортежа (res, err), а Rust возвращает Result<T, E> — тип-сумму результата и ошибки.
Читать полностью »

C++23 — финал, C++26 — начало - 1

С момента моей прошлой публикации состоялось уже две встречи международного комитета по стандартизации C++.

Комитет занимался полировкой C++23:

  • static operator[];
  • static constexpr в constexpr-функциях;
  • безопасный range-based for;
  • взаимодействие std::print с другими консольными выводами;
  • монадический интерфейс для std::expected;
  • static_assert(false) и прочее.

И прорабатывал новые фичи C++26:

  • std::get и std::tuple_size для агрегатов;
  • #embed;
  • получение std::stacktrace из исключений;
  • stackful-корутины.

Читать полностью »

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

Один из наиболее распространённых неудачных подходов — это использование исключений для контроля потока выполнения. Этого следует избегать по двум причинам:

  1. Это снижает производительность и быстродействие вашего кода
  2. Это делает ваш код менее читаемым

Читать полностью »

Существуют различные способы обработки ошибок в языках программирования:

  • стандартные для многих языков исключения (Java, Scala и прочий JVM, python и многие другие)
  • коды статуса или флаги (Go, bash)
  • различные алгебраические структуры данных, значениями которых могут быть как успешные результаты так и описания ошибок (Scala, haskell и другие функциональные языки)

Исключения используются очень широко, с другой стороны о них часто говорят, что они медленные. Но и противники функционального подхода часто апеллируют к производительности.

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

Сразу отбросим использование кодов и флагов, так как этот подход не принят в JVM языках и по моему мнению слишком подвержен ошибкам (прошу прощения за каламбур). Поэтому будем сравнивать исключения и разные виды АТД. Кроме того АТД можно рассматривать как использование кодов ошибок в функциональном стиле.

UPDATE: к сравнению добавлены исключения без стек-трейсов

Читать полностью »

[DotNetBook] Время занимательных историй: исключительно исключительные ситуации - 1

Существует ряд исключительных ситуаций, которые скажем так… Несколько более исключительны чем другие. Причем если попытаться их классифицировать, то как и было сказано в самом начале главы, есть исключения родом из самого .NET приложения, а есть исключения родом из unsafe мира. Их в свою очередь можно разделить на две подкатегории: иcключительные ситуации ядра CLR (которое по своей сути — unsafe) и любой unsafe код внешних библиотек.

Давайте поговорим про эти особые исключительные ситуации.

ThreadAbortException

Вообще, это может показаться не очевидным, но существует четыре типа Thread Abort.

Данная статья — третья из четырех в цикле статей про исключения. Полный цикл:
Архитектура системы типов
Cобытия об исключительных ситуациях
Виды исключительных ситуаций (эта статья)
— Сериализация и блоки обработки

Читать полностью »

[DotNetBook] События об исключительных ситуациях и как на пустом месте получить StackOverflow и ExecutionEngineException - 1 С этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом. За ссылками — добро пожаловать по кат.

События об исключительных ситуациях

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

    try {
        // ...
    } catch {
        // do nothing, just to make code call more safe
    }

В такой ситуации может оказаться что выполнение кода уже не так безопасно как выглядит, но сообщений о том что произошли какие-то проблемы мы не имеем. Второй вариант — когда приложение глушит некоторое, пусть даже легальное, исключение. А результат — следующее исключение в случайном месте вызовет падение приложения в некотором будущем от случайной казалось бы ошибки. Тут хотелось бы иметь представление, какая была предыстория этой ошибки. Каков ход событий привел к такой ситуации. И один из способов сделать это возможным — использовать дополнительные события, которые относятся к исключительным ситуациям: AppDomain.FirstChanceException и AppDomain.UnhandledException.

Данная статья — первая из четырех в цикле статей про исключения. Полный цикл:
Архитектура системы типов
Cобытия об исключительных ситуациях (эта статья)
— Виды исключительных ситуаций
— Сериализация и блоки обработки

Читать полностью »

[DotNetBook] Исключения: архитектура системы типов - 1 С этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом. За ссылками — добро пожаловать по кат.

Архитектура исключительной ситуации

Наверное, один из самых важных вопросов, который касается темы исключений — это вопрос построения архитектуры исключений в вашем приложении. Этот вопрос интересен по многим причинам. Как по мне так основная — это видимая простота, с которой не всегда очевидно, что делать. Это свойство присуще всем базовым конструкциям, которые используются повсеместно: это и IEnumerable, и IDisposable и IObservable и прочие-прочие. С одной стороны, своей простотой они манят, вовлекают в использование себя в самых разных ситуациях. А с другой стороны, они полны омутов и бродов, из которых, не зная, как иной раз и не выбраться вовсе. И, возможно, глядя на будущий объем у вас созрел вопрос: так что же такого в исключительных ситуациях?

Читать полностью »

Как известно из функциональных интерфейсов в Stream API нельзя выбрасывать контролируемые исключения. Если по каким-то причинам это необходимо (например, работа с файлами, базами данных или по сети), приходится оборачивать их в RuntimeException. Это неплохо работает если ошибки игнорируются, но если их необходимо обрабатывать, то код получается громоздкий и трудночитаемый. Я заинтересовался можно ли объявлять интерфейсы и методы с generic исключениями и неожиданно для себя узнал, что можно.

Зададим такой функциональный интерфейс, от стандартного интерфейса Function<A, B> он отличается только наличием третьего generic-типа для бросаемого исключения.

public interface ThrowableFunction<A, B, T extends Throwable>{
	B apply(A a) throws T;
}

И объявим простенький метод, который преобразует коллекцию используя этот интерфейс, у этого метода также объявлен generic-тип для бросаемого исключения (совпадающий с типом исключения которое может выбросить функциональный интерфейс).

public static <A, B, T extends Throwable> Collection<B> map(Collection<A> source, ThrowableFunction<A, B, T> function) throws T {
	Collection<B> result = new ArrayList<>();
	for (A a : source) {
		result.add(function.apply(a));
	}
	return result;
}

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

image

Предлагаю вашему вниманию перевод оригинальной статьи Роберта С. Мартина.

За последние несколько месяцев я попробовал два новых языка. Swift и Kotlin. У этих двух языков есть ряд общих особенностей. Действительно, сходство настолько сильное, что мне стало интересно, не является ли это новой тенденцией в нашей языкомешалке. Если это действительно так, то это тёмный путь.

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

Проблема в том, что оба языка сделали ставку на сильную статическую типизацию. Кажется, оба намерены заткнуть каждую дыру в своём родном языке. В случае со Swift – это странный гибрид C и Smalltalk, который называется Objective-C; поэтому, возможно, упор на типизацию понятен. Что касается Kotlin – его предком является уже довольно строго типизированная Java.

Я не хочу, чтобы вы думали, что я против статически типизированных языков. Я не против. Есть определенные преимущества как для динамических, так и для статических языков; и я с удовольствием пользуюсь обоими видами. Я предпочитаю динамическую типизацию, и поэтому я иногда использую Clojure. С другой стороны, я, вероятно, пишу больше Java, чем Clojure. Поэтому вы можете считать меня би-типичным. Я иду по обеим сторонам улицы — если так можно выразиться.

Дело не в том, что меня беспокоит, что Swift и Kotlin статически типизированы. Скорее меня беспокоит глубина статической типизации.Читать полностью »

Продолжаем перевод серии статей об обработки исключений в C++

1 часть
2 часть

C++ exceptions под капотом: поиск верного landing pad

Это уже 15-я глава в нашей длинной истории. Мы уже изучили достаточно много о том, как работают исключения, и даже имеем написанную работающую собственную персональную функцию с небольшим количеством рефлексии, определяющей где находится catch-блок (landing pad в терминах исключений). В прошлой главе мы написали персональную функцию, которая может обрабатывать исключения, но она всегда подставляет только первый landing pad (т.е. первый же catch-блок). Давай те улучшим нашу персональную функцию, добавив возможность выбирать правильный landing pad в функции с несколькими catch-блоками.
Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js