Ultimamente, tenho me esforçado para entender qual é a quantidade certa de verificação e quais são os métodos adequados.
Eu tenho algumas perguntas sobre isso:
Qual é a maneira correta de verificar se há erros (entrada incorreta, estados incorretos etc.)? É melhor verificar explicitamente se há erros ou usar funções como declarações que podem ser otimizadas em seu código final? Sinto que a verificação explícita desorganiza um programa com muito código extra que não deve ser executado na maioria das situações - e sem mencionar que a maioria dos erros acaba com uma falha de abortar / sair. Por que desorganizar uma função com verificações explícitas apenas para abortar? Procurei afirmações versus verificação explícita de erros e encontrei pouco para realmente explicar quando fazê-lo.
A maioria diz 'use asserts para verificar erros de lógica e use verificações explícitas para verificar outras falhas'. Isso não parece nos levar muito longe. Diríamos que isso é possível:
Malloc returning null, check explictly
API user inserting odd input for functions, use asserts
Isso me tornaria melhor na verificação de erros? O que mais eu posso fazer? Eu realmente quero melhorar e escrever melhor, código 'profissional'.
fonte
setjmp
/longjmp
estão disponíveis em C, então você não precisa de um novo idioma.Respostas:
A maneira mais fácil de dizer a diferença é determinar se a condição de erro é introduzida no tempo de compilação ou no tempo de execução. Se o problema for um programador que está usando a função de alguma maneira errada, faça com que seja necessário chamar a atenção para o problema, mas depois que a correção for compilada no código de chamada, você não precisará mais se preocupar em procurar por ela. Problemas como falta de memória ou entrada incorreta do usuário final não podem ser resolvidos em tempo de compilação; portanto, você deixa as verificações.
fonte
Verifique qualquer coisa a qualquer momento (pode ter sido alterada após sua última verificação) que não esteja 100% sob seu comando. E também: Durante o desenvolvimento, mesmo não confie em si mesmo! ;-)
Okokok ... "qualquer coisa" deve ser lido como uma verificação de coisas que causariam um cancelamento anormal ou qualquer coisa que pudesse fazer seu aplicativo / sistema fazer coisas que não deveria .
Para ser sério, a última parte da última frase é essencial porque aponta para a questão principal:
Se você quer construir um sistema estável a preocupação principal não sobre o que o sistema deve fazer, mas para que seja capaz de fazer tais coisas obrigatórias, é preciso tomar cuidado com o que ele deve não fazer, mesmo se ele "tumultua o seu código".
fonte
O cerne da manipulação de erros não é se e como você captura o problema. É mais do que você faz depois de aprender sobre isso .
Primeiramente - eu diria que não há razão para que um único erro retornado pelo método subordinado esteja retornando não deva ser tratado. E erros e exceções são apenas mais do que os valores de retorno ou todos try / catch.
Apenas jogar e pegar não é suficiente.
Veja isto : onde o autor explica que apenas capturar mas não fazer nada potencialmente suprime a exceção e, a menos que seja feito o suficiente para desfazer o dano - é pior do que deixar o código continuar assim. Da mesma forma, apenas escrever a instrução "log" quando houver um erro de abertura ou leitura de arquivo pode ajudar a encontrar o motivo - mas quando o programa termina, isso pode causar danos aos dados! Não basta dizer que tenho muitas tentativas / capturas - é mais importante saber o que elas realmente fazem!
Não abuse da tentativa e captura.
Algumas vezes - programadores preguiçosos ou ingênuos pensam que, depois de escrever try / catch suficiente, seu trabalho acaba e é fácil. Muitas vezes, é melhor aplicar a ação corretiva e retomar, em vez de simplesmente despejar tudo. Se isso não puder ser feito, é preciso decidir em que nível você precisa voltar. Dependendo do contexto e da gravidade, tente criar um aninhamento preciso de um design cuidadoso. Por exemplo - Veja isto e isto
Defina quem é responsável:
Uma das primeiras coisas que você deve fazer é definir se a entrada fornecida à rotina em si é apenas um cenário inaceitável (ou não tratado até o momento) ou se é a exceção devido ao ambiente (como problema no sistema, problema de memória) ou essa situação é um resultado completamente interno do resultado do algoritmo. Em todos os casos - o nível em que você pode querer voltar ou a ação que deseja executar difere significativamente. Sob essa luz, eu gostaria de dizer - que quando você executa o código em produção - fazer abort () para sair do programa é bom - mas não para todas as pequenas coisas. Se você detectar corrupção ou falta de memória, é definitivo que, mesmo depois de fazer o seu melhor - as coisas vão morrer. Mas se você receber um ponteiro NULL na entrada - eu não
Defina qual é o melhor resultado possível:
tudo o que deve ser feito com exceção é muito crítico. Por exemplo, se em um de nossos casos - um media player descobre que não possui dados completos a serem reproduzidos pelo usuário - o que deve fazer?
Tudo isso é subjetivo - e talvez haja mais maneiras de lidar com problemas do que pensamos trivialmente. Tudo o que foi dito acima exige que você crie e compreenda a profundidade da exceção e que também faça com que diferentes cenários possam evoluir.
Às vezes, precisamos verificar as exceções antes que elas surjam. O exemplo mais comum é o erro de divisão por zero. Idealmente, é preciso testar isso antes que essa exceção seja lançada - e se for esse o caso - tente colocar o valor diferente de zero mais apropriado e seguir em frente, em vez de se suicidar!
Limpar. Pelo menos é isso que você deve fazer! Se uma função abrir 3 arquivos e o quarto não abrir - é desnecessário dizer que os 3 primeiros deveriam ter sido fechados. Delegar esse trabalho para uma camada acima é uma má ideia. se você decidir não sair sem limpar a memória. E o mais importante - mesmo que você tenha sobrevivido à exceção, informe ao mais alto que as coisas não seguiram o curso normal.
A maneira como vemos a funcionalidade (normal) do software em termos de várias hierarquias ou camadas ou abstrações, da mesma forma que devemos categorizar as exceções com base em sua gravidade, bem como no escopo em que elas surgem e estão afetando outras partes do sistema - que define como lidar com exceções tão diferentes da melhor maneira possível.
Melhor referência: Code Craft capítulo 6 - disponível para download
fonte
A verificação de erros apenas nas compilações de depuração é uma BAD IDEA (tm), compilando sob sobreposições de variáveis reutilizáveis na pilha, remove páginas de proteção, faz truques duvidosos com cálculos, substitui artríticas pesadas por turnos pré-computados e assim por diante.
Use a verificação de erros na versão também, você pode recorrer a algo tão simples como:
Isso também tem um efeito colateral muito bom, que você definitivamente não ignorará o bug quando o aplicativo começar a falhar no PC dos betta testers.
Os visualizadores e logs de eventos são completamente inúteis em comparação com
abort()
quem os verifica mesmo assim?fonte
abort
invade o depurador / cria um despejo.exit
é ruim sim Embora eu prefira__asm int 3
mais.As várias coisas que você pode fazer são:
1.Ler e assimilar muito código on-line e ver como isso é feito;
2.Utilizar algumas ferramentas de depuração para ajudá-lo a localizar regiões de erros
; erros de sintaxe.
4. Alguns erros piores aparecem devido a erros lógicos no programa que são mais difíceis de encontrar. Para isso, você pode descobrir e encontrar ou, para os mais complicados, tentar falar com pessoas ou usar recursos como Stackoverflow , Wikipedia , google para obter ajuda de pessoas.
fonte