Continua me surpreendendo que, atualmente, produtos com anos de uso, criados por equipes de profissionais, ainda hoje - falhem em fornecer mensagens de erro úteis ao usuário. Em alguns casos, a adição de apenas um pequeno pedaço de informação extra pode economizar horas de problemas para o usuário.
Um programa que gera um erro, gerou por um motivo. Ele tem tudo a sua disposição para informar ao usuário o máximo possível, por que algo falhou. E, no entanto, parece que fornecer informações para ajudar o usuário é de baixa prioridade. Eu acho que isso é uma falha enorme.
Um exemplo é do SQL Server. Quando você tenta restaurar um banco de dados que está em uso, ele não o deixa com razão. O SQL Server sabe quais processos e aplicativos estão acessando. Por que não pode incluir informações sobre os processos que estão usando o banco de dados? Eu sei que nem todo mundo passa um Applicatio_Name
atributo em sua cadeia de conexão, mas mesmo uma dica sobre a máquina em questão pode ser útil.
Outro candidato, também o SQL Server (e o mySQL), é a adorável string or binary data would be truncated
mensagem de erro e equivalentes. Muitas vezes, uma simples leitura da instrução SQL que foi gerada e a tabela mostra qual coluna é a culpada. Isso nem sempre é o caso, e se o mecanismo de banco de dados detectou o erro, por que ele não pode nos poupar esse tempo e apenas nos diz qual coluna danificada era? Neste exemplo, você pode argumentar que pode haver um impacto no desempenho ao verificá-lo e que isso impediria o escritor. Tudo bem, eu vou comprar isso. Que tal, uma vez que o mecanismo do banco de dados saiba que há um erro, ele faz uma rápida comparação após o fato, entre os valores que seriam armazenados, e os comprimentos das colunas. Em seguida, exiba isso para o usuário.
Os horríveis adaptadores de tabela do ASP.NET também são culpados. As consultas podem ser executadas e uma mensagem de erro pode ser informada que uma restrição em algum lugar está sendo violada. Obrigado por isso. Hora de comparar meu modelo de dados com o banco de dados, porque os desenvolvedores estão com preguiça de fornecer até um número de linha ou dados de exemplo. (Para o registro, eu nunca usaria esse método de acesso a dados por opção , é apenas um projeto que herdei!).
Sempre que eu lançar uma exceção do meu código C # ou C ++, forneço tudo o que tenho em mãos para o usuário. Foi tomada a decisão de lançá-lo, para que quanto mais informações eu possa fornecer, melhor. Por que minha função lançou uma exceção? O que foi repassado e o que era esperado? Demoro um pouco mais para colocar algo significativo no corpo de uma mensagem de exceção. Inferno, isso não ajuda em nada enquanto eu desenvolvo, porque eu sei que meu código lança coisas que são significativas.
Pode-se argumentar que mensagens de exceção complicadas não devem ser exibidas ao usuário. Embora eu discorde disso, é um argumento que pode ser facilmente aplacado por se ter um nível de verbosidade diferente, dependendo da sua compilação. Mesmo assim, os usuários do ASP.NET e do SQL Server não são seus usuários comuns e preferem algo cheio de informações detalhadas e deliciosas, porque podem rastrear seus problemas mais rapidamente.
Por que os desenvolvedores acham que é bom, atualmente, fornecer a quantidade mínima de informações quando ocorre um erro?
É 2011 pessoal, vamos lá .
fonte
Respostas:
Embora existam muitos exemplos de mensagens de erro incorretas que simplesmente não deveriam ser, lembre-se de que nem sempre é possível fornecer as informações que você deseja ver.
Também existe a preocupação de expor muitas informações, o que pode levar os desenvolvedores a erros por precaução. (Prometo que o trocadilho não foi planejado, mas não o estou removendo agora que o notei.)
Às vezes, também há o fato de que uma mensagem de erro complexa é inútil para o usuário final. O acompanhamento da sobrecarga de informações não é necessariamente uma boa abordagem para mensagens de erro. (Isso pode ser melhor guardado para o log.)
fonte
For further information, see log20111701.txt
. Este seria um passo na direção certa.Os desenvolvedores não são as pessoas certas para escrever mensagens de erro.
Eles veem a aplicação do ângulo errado. Eles estão extremamente conscientes do que deu errado dentro do código, mas geralmente não abordam o software do ponto de vista de tentar realizar algo. Como resultado, as informações importantes para o desenvolvedor não são necessariamente informações importantes para o usuário.
fonte
A visão de caridade:
O desenvolvedor trabalhou em estreita colaboração com o código e se esforçou para compreender alguém que não tinha seu entendimento trabalhando com ele. Como resultado, eles acham que as mensagens de erro são boas, simplesmente não têm um bom quadro de referência para julgá-las.
Mensagens de erro inteligentes são realmente difíceis de fazer. Não apenas escrevendo-os, mas você precisa descobrir tudo o que pode dar errado, avaliar a probabilidade e fornecer informações úteis (que quase certamente variam de acordo com o contexto) de volta para a pessoa que está lendo a mensagem para permitir que ela seja corrigida.
Para a maioria dos aplicativos, é difícil justificar a hora de fazer esse tipo de coisa, assim como o próximo desenvolvedor gostaria, porque os erros não ocorrem com tanta frequência. Além disso, se você tivesse esse tempo extra, não deveria gastá-lo parando os erros em vez de reportá-los?
A visão não caridosa:
A realidade provavelmente está em algum lugar no meio, embora minha experiência realmente me diga que é muito mais antiga do que posterior - basicamente, é realmente muito difícil e exige bastante esforço para lidar com algo que provavelmente não acontecerá.
fonte
Process Handle Raped By Spawned Injector, Quitting SYstem.
.... user: "wtf eu fiz`) Mas no caso do SQL Server / ASP.NET, acho que mais esforço poderia ter sido feito :)?.string/binary data
erro que extrai todas as informações da coluna da tabela, examina os valores passados e mostra quais colunas estariam violando. Isso foi trivial. Talvez eu esteja reclamando demais porque meus exemplos de casos são triviais, mas eu entendo perfeitamente que nem sempre é esse o caso. Como paramos injetores gerado a partir de estuprar processos pode muito bem ser difícil :)Infelizmente, mensagens de erro mais úteis custam tempo ao desenvolvedor, que é igual ao dinheiro da empresa. Os produtos são caros o suficiente para serem construídos como estão. Sim, seria incrível ter mensagens de erro mais úteis, e eu concordo que deve haver outras mais úteis. No entanto, é apenas um fato da vida que, quando você está dentro de um prazo, e o dinheiro está em jogo, você precisa cortar algo. "Mensagens de erro mais bonitas", como os gerentes podem ver, provavelmente serão a primeira coisa a ser feita.
fonte
Concordo que as mensagens de erro devem ser o mais específicas possível.
Uma razão para mensagens de erro genéricas é provavelmente o uso de códigos de erro. Ao usar exceções, você pode passar tudo o que precisa na mensagem de erro. Usando códigos de retorno, não há espaço para codificar um nome de coluna. Talvez o erro seja tratado por uma função genérica que não conhece o contexto e simplesmente converte o código do erro em uma string.
fonte
fonte
Como aviso geral, você deve considerar que qualquer erro ou situação excepcional é - exatamente isso: excepcional. Ele cruza o procedimento planejado e projetado. É incompatível com o modo como as coisas planejavam funcionar. Se não fosse esse o caso, não haveria necessidade de resgatar um erro de abortamento.
Nós programadores somos treinados para cuidar da autoproteção deste procedimento planejado. Assim, incluímos rotineiramente algumas verificações de sanidade para verificar nossas suposições. Quando essas verificações de sanidade falham, sabemos que o plano falhou de alguma forma ...
Sua demanda - pode parecer senso comum da perspectiva do usuário - é impossível de ser atendida, se você considerar a realidade de como esse sistema funciona. Você pede uma declaração ordenada com informações bem organizadas e adequadas adicionadas. Além disso, você ainda solicita que esta apresentação ocorra de uma maneira que se encaixe no design geral de aplicação / manuseio. Obviamente, esta informação existe em algum lugar do sistema. Obviamente, ele existe até lá de uma maneira ordenada e bem organizada (esperemos que sim). MAS, no momento em que o erro ocorre, ninguém jamais planejou disponibilizar essas informações. Um erro sempre é uma perda parcial de controle.Essa perda de controle pode ocorrer em vários níveis. Pode ser que o sistema esteja se comportando em tempo de execução diferente do planejado. Mas também pode ser que a implementação real tenha se mostrado muito mais difícil e diferente nos detalhes planejados, e não havia provisão para lidar com essa situação de maneira satisfatória. Isso também é uma perda parcial de controle.
Para relacionar isso ao exemplo concreto que você forneceu: Se, no ponto do erro, o nome e o tipo da coluna da tabela fossem conhecidos e, além do comprimento do espaço necessário, não haveria motivo para levantando um erro, não é? Poderíamos apenas consertar a situação e prosseguir como planejado. O próprio fato de sermos forçados a cometer um erro mostra que as coisas se perderam. O simples fato de essas informações não estarem disponíveis é a exceção .
O que estou escrevendo aqui pode parecer óbvio e mero senso comum. Mas, na realidade, é extremamente difícil de entender. Tentamos constantemente entendê-lo aplicando categorias morais - como deve haver um culpado, deve haver uma pessoa preguiçosa que não se importa com o usuário pobre, deve haver empresários gananciosos que fizeram um caminho para cálculos baratos. Tudo isso está além do ponto
A possibilidade de perda de controle decorre do fato de estarmos fazendo as coisas de maneira planejada e ordenada .
fonte
Eu trabalho como engenheiro de suporte de uma empresa de software e frequentemente vemos mensagens de erro novas para nós. Freqüentemente, quando as refiro à nossa equipe de desenvolvimento, elas precisam procurar a mensagem na fonte do aplicativo.
Parece-me que, mesmo que não fosse apresentado aos usuários, seria muito seguro para nós se a equipe de desenvolvimento adicionasse uma nota a um documento ou banco de dados do índice de mensagens de erro sempre que adicionassem um novo. muito mais rápido para encontrar a causa dos problemas dos clientes e economizar tempo também ...
fonte
O problema que você está vendo é, na verdade, um dos efeitos colaterais do encapsulamento adequado e ocultação de informações.
Os sistemas modernos são extremamente complicados. Há poucas chances de que o desenvolvedor médio consiga manter, em sua cabeça, um modelo mental de todo o sistema, da interface do usuário ao binário bruto, enquanto codifica qualquer tarefa em particular.
Assim, enquanto um desenvolvedor está sentado e codificando, digamos, o bit que restaura um arquivo de banco de dados, seu modelo mental é preenchido inteiramente com os bits que cercam o ato de restaurar um arquivo de banco de dados. Ele precisa (e suponho, ainda não escrevi esse código) ler um arquivo, verificar propriedades, ler versões, fazer backup de dados existentes, escolher uma estratégia de mesclagem / substituição, etc. É bem provável que exista uma passagem. consideração à interface do usuário, está na sequência de erros que ele escreve em um manipulador de exceções. Algo como:
Neste exemplo, as informações úteis sobre as quais você está perguntando em termos de processos que podem estar usando o arquivo, ou mesmo outros encadeamentos no banco de dados, estão completamente fora do escopo (programaticamente). Pode haver centenas de classes que lidam com arquivos de banco de dados; importar para essas classes informações sobre todos os outros processos que usam os arquivos ou funcionalidade para acessar o sistema de arquivos e observar os outros processos em execução (supondo que esses processos estejam nesta máquina) resultaria no que é conhecido como abstração com vazamento ; há um custo direto em produtividade.
É assim que esses tipos de erros podem persistir nos dias modernos. Obviamente, todos eles poderiam ser consertados; mas, em muitos casos, há muito mais custos indiretos envolvidos do que se imagina (nesse caso, por exemplo, talvez seja necessário que essa função percorra a enumeração de conexões e compartilhamentos de rede para ver se uma máquina remota está usando esse arquivo de banco de dados para alguns razão) e o custo está longe de ser trivial.
fonte
GenericException
, eu poderia 1) Pedir aoProcesses
Subsistema uma lista de processos. 2) Pergunte a cada processo que banco de dados eles estão usando. 3) Associe o processo ao banco de dados atribuído àquele que estou tentando substituir; 4) lance umaDatabaseInUse(dbName, processName, applicationName
exceção. :)Meu favorito era (no final dos anos 70) o compilador Univac Fortran IV, ao ler sem dígitos, anunciado fielmente
fonte
Acredito que a maioria das mensagens de erro seja realmente um código de depuração glorificado (auto) orientado a programadores / instruções printf.
Escrever mensagens de erro orientadas ao usuário significa saber quem é o usuário e antecipar o que ele deseja saber. No meio da escrita do código, um desenvolvedor está mais apto a escrever uma mensagem de erro útil para si, para depurar o código que está escrevendo no momento ou útil para os Casos de Uso conhecidos ou predominantes.
Mudar de escrever código para projetar uma parte textual da interface do usuário (ou experiência do usuário) é uma opção de contexto. Em aplicativos grandes, como aplicativos multilíngues, que podem significar que são entregues a uma pessoa ou equipe diferente (UI, tradução), em vez de serem totalmente manipulados pelo desenvolvedor, portanto, a menos que o desenvolvedor explique cuidadosamente o contexto da mensagem, detalhes importantes podem ser facilmente perdido.
Obviamente, verificar e verificar o tratamento de erros é frequentemente considerado de baixa prioridade, desde que sejam tratados erros e exceções (ou seja, capturados), mas não é dada muita ênfase a ele. É um local mentalmente não recompensador da base de código para os desenvolvedores ou o controle de qualidade avaliarem, pois as condições de erro geralmente têm uma conotação negativa (ou seja, erro ou falha) associada a eles.
fonte
Eu acho que a razão é que o relatório / tratamento de erros sempre é feito como uma reflexão posterior . Mesmo quando não são totalmente pensados, são principalmente cidadãos de segunda classe no design geral.
O software moderno geralmente consiste em várias camadas. Quando sua lógica de relatório de erros é estabelecida rapidamente, sem muita reflexão, geralmente é difícil reunir todas as informações necessárias para apresentar mensagens de erro úteis.
Por exemplo, o erro é detectado no back-end, mas ele precisa de algumas informações das camadas superiores para compor uma mensagem de erro abrangente. A maioria das boas mensagens de erro precisa de informações de quase todas as camadas (para nos dar uma visão abrangente do que aconteceu no sistema). A mensagem de erro ideal seria "OK, primeiro recebemos uma string e, em seguida, ela passou pelo analisador, o que deu algo engraçado, você pode procurar lá. De qualquer forma, a coisa foi passada mais adiante ..."
Para isso, seria necessário um acoplamento desnecessário se o mecanismo de relatório de erros não fosse cidadão de primeira classe durante a fase de projeto. Acho que a maioria das pessoas acha muito trabalho para algo que não parece impressionante (quem gosta de dizer "Viu? Meu programa travou e a mensagem de erro é útil!").
fonte