Acabei de revisar algum código que escrevi há algum tempo e posso ver que tenho alguns métodos particulares que lançam percepções de argumentos de argumento e / ou exceções de argumento se houver problemas com os parâmetros dos métodos.
Eu acho que minha lógica é que ajuda a prova futura do aplicativo se alguém tentar "abusar" do método no futuro. No entanto, dado que é um método privado e as pessoas que provavelmente chamarão esse método podem ver os comentários e o código associados, é apenas desnecessário jogar isso. Certamente não dói tê-los, embora adicione desordem.
Meu sentimento é que essas exceções geralmente são mais úteis em algo como uma API que será exposta publicamente.
fonte
Como tudo o mais, depende ....
Se os métodos públicos forem invólucros simples que chamam o método privado (na linha de um método sobrecarregado privado), pode fazer sentido lançar uma exceção no método privado em vez de verificar cada um deles.
Geralmente, se ele não atender à definição acima, normalmente eu não verificaria os argumentos / lançaria uma exceção em um método privado. Embora existam outros casos, geralmente faço isso em um método privado antes de executar alguma operação cara que poderia falhar parcialmente se os argumentos forem inválidos.
fonte
Percebo que, embora a pergunta não tenha um rótulo de idioma, provavelmente está falando implicitamente sobre "idiomas do café". Mas apenas por uma questão de integridade, gostaria de mencionar o consenso aparente um tanto divergente no mundo C ++.
Normalmente, há três coisas em que os programadores de C ++ estarão interessados:
noexcept
?No passado, eu abordei o primeiro problema escrevendo código como este
em que d
CHECK_ARGS
é#define
uma constante em tempo de compilação para que o compilador possa eliminar completamente todo o código de verificação de argumentos em compilações otimizadas. (Não estou dizendo que compilar as verificações é uma coisa boa em geral, mas acredito que um usuário deve ter a opção de compilá-las.)Ainda gosto dessa solução: o código de verificação de argumentos é claramente visível, agrupado no
if
. No entanto, o segundo e o terceiro problema não são resolvidos por isso. Portanto, agora estou mais inclinado a usar umaassert
macro para verificação de argumentos.Os padrões de codificação Boost concordam com isso:
Houve uma palestra muito interessante proferida por John Lakos no CppCon'14 intitulada Programação Defensiva Feita Corretamente ( parte 1 , parte 2 ). Na primeira parte de sua palestra, ele discute a teoria dos contratos e o comportamento indefinido. Na segunda parte, ele apresenta o que considero uma proposta muito boa para verificação sistemática de argumentos. Em essência, ele propõe macros de asserção que permitem ao usuário selecionar quanto de orçamento (em termos de utilização da CPU) ela deseja doar à biblioteca para verificação de argumentos e fazer com que a biblioteca faça uso racional desse orçamento. Além disso, o usuário também pode instalar uma função global de tratamento de erros que será chamada caso um contrato quebrado seja detectado.
Quanto ao aspecto de uma função ser privada, não creio que isso signifique que nunca deveremos verificar se seus argumentos. Podemos confiar mais em nosso próprio código para não violar o contrato de uma função interna, mas também sabemos que também não somos perfeitos. A verificação de argumentos nas funções internas é tão útil para detectar nossos próprios erros quanto nas funções públicas para detectar erros no código do cliente.
fonte
Considere a seguinte estrutura:
Lógica interna: Esta função assume que é chamada com parâmetros corretos e, portanto, utiliza assertivas para verificar pré-condições, pós-condições e invariantes para verificar sua lógica interna.
Interface de usuário de fardos: Esta função envolve o funcionamento interno e usa InvalidArgumentExceptions para lidar com valores errados e dizer ao usuário para corrigir suas entradas:
Assert(x).hasLength(4);
,Assume(y).isAlphanumeric();
,Assert(z).isZipCode();
,Assume(mailAdress).matchesRegex(regex_MailAdress);
,Reject(x).ifEmpty();
, etc.Wrapper de interface em lote: Esta função agrupa a função interna e usa log, marcações de validade e estatísticas para manipular valores errados sem interromper alguma tarefa de longa execução. As marcações poderiam ser usadas mais tarde por alguém verificando e limpando o banco de dados de resultados.
Wrapper da interface da linha de comandos: esta função agrupa a função interna e solicita novamente a última entrada.
Você deve usar ambos - afirmações e exceções - em métodos diferentes para tarefas diferentes. Você deve separar a lógica interna da verificação de parâmetros. Compare-o com a separação de Model, View, Controller.
fonte
Existem maneiras melhores de evitar a verificação de referência nula: use o contrato de código ou uma estrutura de AOP para fazer a verificação. Google "contrato de código c #" ou "postsharp".
fonte