¿Debería un constructor de Perl devolver un undef o un objeto "no válido"?

Pregunta:

Lo que se considera "mejor práctica" -y por qué - ¿De errores de manejo en un constructor?

"Best Practice" puede ser una cita de Schwartz, o el 50% de los módulos CPAN lo utilizan, etc ...; pero estoy contento con la opinión bien razonada de cualquiera, incluso si explica por qué la mejor práctica común no es realmente el mejor enfoque.

En lo que respecta a mi punto de vista del tema (informado por el desarrollo de software en Perl durante muchos años), he visto tres enfoques principales para el manejo de errores en un módulo de Perl (enumerados de mejor a peor en mi opinión):

Construye un objeto, establece una bandera inválida (usualmente "is_valid"método). A menudo, junto con la configuración del mensaje de error a través del manejo de errores de su clase.

Pros:

Permite el manejo de errores estándar (en comparación con otras llamadas a métodos) ya que permite su uso$obj->errors() Escriba llamadas después de un constructor incorrecto, como después de cualquier otra llamada de método.

Permite que se pase información adicional (por ejemplo,> 1 error, advertencias, etc.)

Permite una funcionalidad ligera de "rehacer" / "fixme". En otras palabras, si el objeto que se construye es muy pesado, con muchos atributos complejos que son 100% correctos, y la única razón por la que no es válido es porque alguien ingresó un fecha incorrecta, simplemente puedes hacerlo "$obj->setDate()"en lugar de la sobrecarga de volver a ejecutar todo el constructor. Este patrón no siempre es necesario, pero puede ser enormemente útil en el diseño correcto.

Contras: Ninguno que yo sepa.

Regreso "undef".

Contras: No se puede lograr ninguna de las ventajas de la primera solución (mensajes de error por objeto fuera de las variables globales y capacidad "fixme" ligera para objetos pesados).

Muere dentro del constructor. Fuera de algunos casos de borde muy estrecho, personalmente considero que esta es una elección horrible por demasiados motivos para enumerar al margen de esta pregunta.

ACTUALIZACIÓN: Solo para ser claros, considero que la solución (de lo contrario es muy valiosa y un gran diseño) de tener un constructor muy simple que no puede fallar en absoluto y un método de inicialización pesado en el que toda la comprobación de errores se produce simplemente como un subconjunto de cualquiera caso # 1 (si el inicializador establece indicadores de error) o caso # 3 (si el inicializador muere) para los propósitos de esta pregunta. Obviamente, al elegir un diseño de este tipo, rechazará automáticamente la opción # 2.

Respuestas a la pregunta(4)

Su respuesta a la pregunta