Представление бизнес-правил с исключениями

16

Я знаю, что это дорого, но (ИМО) я считаю, что это очень хорошая практика. Я говорю о таких правилах, как, скажем, вы не можете сохранить счет-фактуру, если вы не являетесь продавцом ... так что в этом случае выдается исключение, говорящее «вы не авторизованы» или что-то подобное ...

Другой подход - объекты со статусом или что-то в этом роде.

Есть ли другой подход? Что ты думаешь на этот счет?

sebagomez
источник

Ответы:

15

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

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

Матяш
источник
1
Именно так я и поступаю в своих приложениях. Использование FluentValidation для облегчения моей жизни, а метод ValidateAndThrow экономит мой день.
Маттео Моска
В приложении с пользовательским интерфейсом я полностью согласен, но в приложении уровня обслуживания я бы сгенерировал исключение, если бы мне передали объект, который не соответствует бизнес-правилам. Если вы используете оба в комбинации, то иногда вы добавляете функцию проверки или сложную ошибку, как описано в последнем предложении.
Билл
8
Брось исключение для конкретного домена . Это позволяет вам разделить между нашими и не нашими выше.
@ Thorbjørn Ravn Andersen +1 «специфичное для домена» отличное дополнение
Джастин Омс
1
@JamesPoulson может быть достаточно создать JamesPoulsonExceptionкак подкласс RuntimeExceptionи затем предоставить исходное исключение как cause. Затем вы можете просто сказать, if (exception instanceof JamesPoulsonException)... чтобы дифференцировать. Используйте getCause()метод для достижения исходного исключения.
9

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

Использование исключений для обеспечения соблюдения бизнес-правил не является хорошим дизайном.

Вальтер
источник
Я понимаю, что вы сказали, что вы не согласны с пользовательским интерфейсом. Я в порядке с этим. Я согласен с вами, что более дружественный пользовательский интерфейс не позволит вам обновить то, что вам запрещено. Но это не означает, что проверка и проверка исключений в бизнес-ядре не нужны. Наоборот, я считаю, что они необходимы. Они нужны вам для того, чтобы плохо запрограммированный пользовательский интерфейс не допускал злоупотребления BL.
Фед
8
@Fede: это вопрос разделения интересов. Пользовательский интерфейс отвечает за сбор информации о намерениях пользователя и предоставление обратной связи от бизнес-уровня. Работа бизнес-уровня заключается в анализе информации, собранной пользовательским интерфейсом, ее анализе и либо в представлении отчета в пользовательский интерфейс, и / или в запросе уровня данных сохранить некоторые данные. Между этими слоями должна быть только слабая связь. Исключением является плохой, плохой подход к слабой связи. Это означает не только совместное использование реальных классов между слоями, но также вызывает механизм, предназначенный для обработки непредвиденных сбоев.
Адам Кроссленд
@ Адам - ​​Хорошо сказано и точно в точку.
Уолтер
1
@ Адам - ​​Не следуйте за вами с разделением проблем. Я не ожидаю, что кто-либо в пользовательском интерфейсе обработает исключение CustomerNameInLowercaseException (пожалуйста, я также надеюсь, что исключение даже не существует!). Вы можете просто обработать универсальное исключение ValidationException. Кроме того, я на 100% уверен, что пользовательский интерфейс должен собирать только информацию и все такое. Я уже говорил, что независимо от того, что вы делаете в пользовательском интерфейсе, BL не должен предполагать, что все входные данные в порядке. Это просто какое-то защитное программирование.
Фед
@Fede: работа бизнес-уровня состоит в том, чтобы гарантировать, что каждый вход в порядке. Если пользовательский интерфейс делает это, то он реализует бизнес-логику. Теперь, если это тот случай, когда поле ввода ограничиваются цифрами и BL видит буквенные символы, по всем средствам бросить в исключении . Всякий раз, когда компонент получает недопустимые входные данные от другого компонента, создание исключения является логичным и правильным. Интерфейс был сломан, и система сломана. Однако проверка входных данных сильно отличается от выполнения бизнес-логики. Две очень разные вещи.
Адам Кроссленд
5

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

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

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

Адам Кроссленд
источник
1
Я согласен, исключения называются исключениями, потому что они не ожидаются. С другой стороны, соблюдение бизнес-правил на уровне обслуживания с исключением не обязательно является неправильным. Вы не ожидаете, что он будет использоваться, вы ожидаете, что клиент будет только вызывать операции и отправлять только данные, которые соответствуют действительным условиям; но вы хотите встроить слой защиты, потому что знаете, что ошибки могут происходить и в кодировании клиента. Вроде как с использованием ограничений внешнего ключа в базе данных: вы ожидаете, что люди вставят и обновят данные правильно, но знают, что они могут потерпеть неудачу из-за ошибки программирования.
Джереми
2

Выражение бизнес-правил - это одно, а их реализация - другое.

думать о пользовательском опыте; если пользователь не продавец, поэтому дать им кнопку с надписью «Создать счет» вообще ?

Стивен А. Лоу
источник
1
То, что вы не даете кнопку, не означает, что они все равно не отправят вам сообщение, чтобы что-то сделать. Подумайте, насколько простыми были бы правила безопасности, если бы это было все, что потребовалось ..
jmoreno
Если пользователю не разрешено делать X, не давайте ему кнопку с надписью «Do X». Лучшая защита - это невежество - не говорите пользователю о том, чего он не может;)
Стивен А. Лоу,
1

Это полностью зависит от того, что делается.

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

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

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

Дэвид Торнли
источник
0

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

Это означает, что простые правила, которые можно описать в одном предложении, как правило, должны быть реализованы в превентивном или авторитетном порядке, в зависимости от того, что это такое. Однако, если у вас есть многомерное правило, требующее более трех или четырех факторов (особенно если выбор этих факторов основан на одном или нескольких других факторах), кодирование исключений может быть более приемлемым. Часто в этих случаях логический путь будет иметь много исключений предшественников, которые должны быть выброшены ((проверяет, почему действие не может быть выполнено), а затем (или наоборот) происходит сбой безопасности (чтобы проверить, разрешено ли действие ), иногда возникает некоторая авторитетная логика накопления, которую необходимо проверить (доступность потомка / предка, предшественник заявляет, что объекты должны быть помещены и т. д.)

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

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

Джастин ом
источник