По крайней мере, на ранних стадиях производства, мне нравится иметь много бросков исключений (умереть рано девизом). Так что я могу быстро уловить любую ошибку (и сэкономить много времени, избегая размышлений в логике и отслеживания кодов возврата). Затем в каждой итерации выпуска я могу уменьшить серьезность бросков, связывая их с состоянием $ o-> debug. Поэтому, когда вы запускаете свои тесты, умираете во всем, но когда вы запускаете свой код для настоящего хруста, вместо этого в журнал и умираете только тогда, когда происходят неизбежные фатальные условия. По моему скромному мнению, это более гибко, чем коды возврата, которые я использовал в старые времена.
Также простое исключение 'die' иногда не очень полезно, поэтому лучше иметь функцию throw, которая печатает всю трассировку стека вызовов (например, Carp-> confess () | cluck ()).
И хороший механизм ловли также удобен. используйте Try :: Tiny или TryCatch .
PD: нить perlmonk, на которую указывает Адриан, - классика.