Правильно ли выбрасывать исключения в бизнес логике?
Я считаю это хорошей практикой. Исключительная ситуация - это та, при которой программа выполняется не так, как ожидалось. Но, позвольте, я ожидаю, что заказ пройдет валидацию. Я ожидаю, что заказ завершится успехом. Поэтому OrderValidationException, OrderException - исключительные ситуации. Исключительной ситуацией не является, например, отмена пользователем заказа - глупо выбрасывать исключение по клику на Cancel.

Исключения гораздо глубже, чем просто "исключительная ситуация". Они помогают развести обработку ошибок по разным уровням абстракции, а использование разных типов исключений позволяет обрабатывать конкретные ошибки там, где их нужно обработать (на нужном слое). Исключения очень помогают в локализации ошибки в дальнейшем, они позволяют избавиться от простыни If .. else, проверок на null, false и прочей ереси. Они, чаще всего, делают код чище.

Но пользоваться ими стоит аккуратно, все-таки стоит разделять исключительную ситуацию и вполне нормальную, штатную ветку исполнения. Так, если заказов нет - это НЕ исключение, тут можно вернуть null - допустимо (хотя некоторые и тут выбрасывают исключение, потому что очень соблазнительно привязать код исключения к HTTP кодам). А если у вас аплоад документов, и юзер пытается загрузить файл слишком большой, то это уже исключение.
может интересно будет
https://github.com/adelf/acwa_book_ru/blob/master/...