Em um novo emprego, tenho sido sinalizado em revisões de código para códigos como este:
PowerManager::PowerManager(IMsgSender* msgSender)
: msgSender_(msgSender) { }
void PowerManager::SignalShutdown()
{
msgSender_->sendMsg("shutdown()");
}
Disseram-me que o último método deveria ser:
void PowerManager::SignalShutdown()
{
if (msgSender_) {
msgSender_->sendMsg("shutdown()");
}
}
ou seja, I deve colocar um NULLguarda em torno da msgSender_variável, mesmo que seja um membro de dados privados. É difícil para mim me impedir de usar palavrões para descrever como me sinto sobre esse pedaço de 'sabedoria'. Quando peço uma explicação, recebo uma ladainha de histórias de horror sobre como algum programador júnior, durante um ano, ficou confuso sobre como uma classe deveria funcionar e excluiu acidentalmente um membro que ele não deveria ter (e a definiu NULLposteriormente) , aparentemente), e as coisas explodiram em campo logo após o lançamento do produto, e "aprendemos da maneira mais difícil, confie em nós" que é melhor NULLverificar tudo .
Para mim, isso parece uma programação de culto de carga , pura e simples. Alguns colegas bem-intencionados estão sinceramente tentando me ajudar a 'entender' e ver como isso me ajudará a escrever um código mais robusto, mas ... Não posso deixar de sentir que eles não entendem. .
É razoável que um padrão de codificação exija que cada ponteiro não referenciado em uma função seja verificado NULLprimeiro - mesmo membros de dados privados? (Nota: para contextualizar, fabricamos um dispositivo de eletrônicos de consumo, não um sistema de controle de tráfego aéreo ou outro produto 'falha-igual-morre-de-pessoas'.)
EDIT : No exemplo acima, o msgSender_colaborador não é opcional. Se for o caso NULL, indica um erro. A única razão pela qual ele é passado para o construtor é que PowerManagerpode ser testado com uma IMsgSendersubclasse simulada .
RESUMO : Houve ótimas respostas para essa pergunta, obrigado a todos. Aceitei o @aaronps principalmente devido à sua brevidade. Parece haver um consenso geral bastante amplo de que:
- A
NULLproteção obrigatória para cada ponteiro não referenciado é um exagero, mas - Você pode contornar o debate inteiro usando uma referência (se possível) ou um
constponteiro, e assertAs instruções são uma alternativa mais esclarecida aosNULLguardas para verificar se as pré-condições de uma função são atendidas.
nulle não fazer nada é apenas uma maneira de mover o erro para baixo na execução, tornando muito mais difícil rastrear de volta à fonte.