En un nuevo trabajo, me han marcado en revisiones de código para código como este:
PowerManager::PowerManager(IMsgSender* msgSender)
: msgSender_(msgSender) { }
void PowerManager::SignalShutdown()
{
msgSender_->sendMsg("shutdown()");
}
Me dijeron que el último método debería leer:
void PowerManager::SignalShutdown()
{
if (msgSender_) {
msgSender_->sendMsg("shutdown()");
}
}
es decir, que debe poner un NULL
guardia alrededor de la msgSender_
variables, a pesar de que es un miembro de datos privados. Es difícil para mí contenerme del uso de improperios para describir cómo me siento acerca de esta 'sabiduría'. Cuando solicito una explicación, recibo una letanía de historias de terror sobre cómo un programador junior, algún año, se confundió acerca de cómo se suponía que debía funcionar una clase y eliminó accidentalmente a un miembro que no debería tener (y lo configuró NULL
después) , aparentemente), y las cosas explotaron en el campo justo después del lanzamiento de un producto, y hemos "aprendido por las malas, confía en nosotros" que es mejor simplemente NULL
verificar todo .
Para mí, esto se siente como una programación de culto de carga , simple y llanamente. Algunos colegas bien intencionados están tratando de ayudarme a "entenderlo" y ver cómo esto me ayudará a escribir código más robusto, pero ... no puedo evitar sentir que son ellos los que no lo entienden .
¿Es razonable que un estándar de codificación requiera que cada puntero desreferenciado en una función se verifique NULL
primero, incluso los miembros de datos privados? (Nota: para dar un poco de contexto, creamos un dispositivo de electrónica de consumo, no un sistema de control de tráfico aéreo o algún otro producto de 'falla-igual-muere gente').
EDITAR : en el ejemplo anterior, el msgSender_
colaborador no es opcional. Si alguna vez NULL
, indica un error. La única razón por la que se pasa al constructor es porque PowerManager
puede probarse con una IMsgSender
subclase simulada .
RESUMEN : Hubo algunas respuestas realmente buenas a esta pregunta, gracias a todos. Acepté el de @aaronps principalmente debido a su brevedad. Parece haber un acuerdo general bastante amplio de que:
- Los
NULL
guardias obligatorios para cada puntero desreferenciado son excesivos, pero - Puede esquivar todo el debate utilizando una referencia en su lugar (si es posible) o un
const
puntero, y assert
Las declaraciones son una alternativa más ilustrada que losNULL
guardias para verificar que se cumplen las condiciones previas de una función.
null
y no hacer nada es solo una forma de mover el error hacia abajo en la ejecución, lo que hace que sea mucho más difícil rastrear hasta la fuente.