Вы не думаете на достаточно высоком уровне. ОК, строитель терпит неудачу. Атрибут остается неопределенным. Но что вы делаете с кодом, вызывающим метод доступа? Контракт класса указал, что вызов метода всегда будет возвращать IO :: File. Но сейчас возвращается undef. (Контракт был IO::File
, а не Maybe[IO::File]
, верно?)
Таким образом, на следующей строке кода вызывающий объект умрет («Не удается вызвать метод readline» для неопределенного значения в строке 42__caller.pl), поскольку он ожидает, что ваш класс будет следовать контракту что это определено. Ваш класс не должен был терпеть неудачу, но теперь это произошло. Как звонящий может что-то сделать, чтобы исправить эту проблему?
Если он может обрабатывать undef
, вызывающему на самом деле не нужен файловый дескриптор для начала ... так почему он запросил ваш объект для него?
Учитывая это, единственное разумное решение - умереть. Вы не можете выполнить договор, с которым согласились, и die
- единственный выход из этой ситуации. Так что просто сделай это; смерть - это факт жизни.
Теперь, если вы не готовы умереть во время работы компоновщика, вам нужно измениться, когда код, который может дать сбой, запускается. Вы можете сделать это во время создания объекта, сделав его не ленивым или явно оживив атрибут в BUILD (BUILD { $self->file_name }
).
Лучший вариант - вообще не открывать дескриптор файла для внешнего мира, а вместо этого делать что-то вроде:
# dies when it can't write to the log file
method write_log {
use autodie ':file'; # you want "say" to die when the disk runs out of space, right?
my $fh = $self->file_handle;
say {$fh} $_ for $self->log_messages;
}
Теперь вы знаете, когда программа умрет; в new
или write_log
. Вы знаете, потому что документы так говорят.
Второй способ делает ваш код намного чище; потребителю не нужно знать о реализации вашего класса, ему просто нужно знать, что он может сказать ему написать несколько сообщений журнала. Теперь вызывающая сторона не имеет отношения к деталям вашей реализации; он просто говорит классу, чего он действительно хотел.
И смерть в write_log
может даже быть чем-то, что вы можете восстановить (в блоке улова), тогда как "не может открыть эту случайную непрозрачную вещь, о которой вы не должны знать в любом случае", вызывающему абоненту гораздо сложнее оправиться от.
По сути, разрабатывайте свой код разумно, и исключения - единственный ответ.
(В любом случае, я не понимаю, что это за «они»). Они точно так же работают в C ++ и очень похожи в Java, Haskell и во всех других языках. Действительно ли слово die
действительно страшно или что-то в этом роде? ?)