# Разделяйте технические и логические исключения

(В оригинале - Distinguish Business Exceptions from Technical)

В большинстве случаев есть лишь две причины, из-за которых что-то может пойти не так во время выполнения программы. Это технические проблемы, мешающие работе приложения, и бизнес-логика, не дающая нам использовать приложение неправильно. В большинстве современных языков программирования, таких как LISP, Java, Smalltalk, и C#, для обеих ситуаций используется механизм исключений. Однако эти две ситуации столь различны, что их стоит аккуратно разделять и не смешивать. Если для обеих ситуаций использовать одну и ту же иерархию исключений (не говоря уже о том, чтобы использовать одни и те же классы), то это может стать источником серьезной путаницы.

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

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

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

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

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

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

Автор оригинала - [Dan Bergh Johnsson](http://programmer.97things.oreilly.com/wiki/index.php/Dan_Bergh_Johnsson)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://97-things-every-x-should-know.gitbook.io/97-things-every-programmer-should-know/ru/thing_74.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
