Я думаю, что все ответы, которые объясняют, что у вас не должно быть флага, который контролирует, выбрасывается исключение или нет, являются хорошими. Их совет будет моим советом любому, кто чувствует необходимость задать этот вопрос.
Однако я хотел отметить, что есть существенное исключение из этого правила. Как только вы достаточно продвинулись, чтобы начать разработку API-интерфейсов, которые будут использовать сотни других людей, в некоторых случаях вы можете захотеть предоставить такой флаг. Когда вы пишете API, вы не просто пишете пуристам. Вы пишете реальным клиентам, у которых есть реальные желания. Часть вашей работы состоит в том, чтобы сделать их довольными вашим API. Это становится социальной проблемой, а не проблемой программирования, и иногда социальные проблемы диктуют решения, которые были бы далеко не идеальными в качестве самостоятельных программных решений.
Вы можете обнаружить, что у вас есть два разных пользователя вашего API, один из которых хочет исключений, а другой нет. В реальной жизни это может произойти с библиотекой, которая используется как в разработке, так и во встроенной системе. В средах разработки пользователи, вероятно, захотят иметь исключения везде. Исключения очень популярны для обработки неожиданных ситуаций. Тем не менее, они запрещены во многих встроенных ситуациях, потому что они слишком сложны для анализа ограничений в реальном времени. Когда вы на самом деле заботитесь не только о среднем времени, которое требуется для выполнения вашей функции, но и о времени, которое требуется для какого-то отдельного развлечения, идея разматывать стек в любом произвольном месте очень нежелательна.
Пример из реальной жизни для меня: математическая библиотека. Если в вашей математической библиотеке есть Vector
класс, который поддерживает получение единичного вектора в одном и том же направлении, вы должны иметь возможность делить на величину. Если величина равна 0, у вас есть ситуация деления на ноль. В разработке вы хотите поймать это . Вы действительно не хотите удивительного деления на 0, торчащие вокруг. Бросок исключения - очень популярное решение для этого. Это почти никогда не происходит (это действительно исключительное поведение), но когда это происходит, вы хотите знать это.
На встроенной платформе вы не хотите этих исключений. Было бы больше смысла сделать проверку if (this->mag() == 0) return Vector(0, 0, 0);
. На самом деле, я вижу это в реальном коде.
Теперь подумайте с точки зрения бизнеса. Вы можете попытаться научить двум различным способам использования API:
// Development version - exceptions // Embeded version - return 0s
Vector right = forward.cross(up); Vector right = forward.cross(up);
Vector localUp = right.cross(forward); Vector localUp = right.cross(forward);
Vector forwardHat = forward.unit(); Vector forwardHat = forward.tryUnit();
Vector rightHat = right.unit(); Vector rightHat = right.tryUnit();
Vector localUpHat = localUp.unit() Vector localUpHat = localUp.tryUnit();
Это удовлетворяет мнениям большинства ответов здесь, но с точки зрения компании это нежелательно. Разработчики встраиваемых систем должны изучить один стиль кодирования, а разработчики - другой. Это может быть довольно неприятно, и заставляет людей думать одним образом. Потенциально хуже: как вы можете доказать, что встроенная версия не содержит кода, генерирующего исключения? Броская версия может легко вписаться, прячась где-то в вашем коде, пока дорогая комиссия по проверке ошибок не найдет ее.
Если, с другой стороны, у вас есть флаг, который включает или отключает обработку исключений, обе группы могут изучить один и тот же стиль кодирования. Фактически, во многих случаях вы можете даже использовать код одной группы в проектах другой группы. В случае использования этого кода unit()
, если вы действительно заботитесь о том, что происходит в случае деления на 0, вы должны были написать тест самостоятельно. Таким образом, если вы перемещаете его во встроенную систему, где вы просто получаете плохие результаты, такое поведение является «нормальным». Теперь, с точки зрения бизнеса, я обучаю своих программистов один раз, и они используют одни и те же API и одинаковые стили во всех частях моего бизнеса.
В подавляющем большинстве случаев вы хотите следовать советам других: используйте идиомы, подобные tryGetUnit()
или похожие, для функций, которые не генерируют исключения, и вместо этого возвращайте значение часового типа, например, null. Если вы думаете, что пользователи могут захотеть использовать как обработку исключений, так и код обработки не исключений бок о бок в одной программе, придерживайтесь tryGetUnit()
обозначений. Тем не менее, есть угловой случай, когда реальность бизнеса может сделать использование флага лучше. Если вы окажетесь в этом угловом деле, не бойтесь отбросить «правила» на второй план. Вот для чего нужны правила!