Fiquei com a impressão de que agora todos concordam que essa máxima foi um erro. Mas eu vi recentemente essa resposta, que tem um comentário "seja branda", votada 137 vezes (até hoje).
Na minha opinião, a clemência no que os navegadores aceitam foi a causa direta da bagunça total que o HTML e alguns outros padrões da web eram há alguns anos atrás, e só recentemente começaram a se cristalizar adequadamente dessa bagunça. A forma como eu vejo, sendo branda no que você aceitar irá levar a isso.
A segunda parte da máxima é "descartar entrada defeituosa silenciosamente, sem retornar uma mensagem de erro, a menos que isso seja exigido pela especificação" , e isso parecerá ofensivo. Qualquer programador que bater a cabeça na parede quando algo falhar silenciosamente saberá o que quero dizer.
Então, eu estou completamente errado sobre isso? Meu programa deve ser tolerante com o que aceita e engolir erros silenciosamente? Ou estou interpretando mal o que isso significa?
A pergunta original dizia "programa", e eu entendo a opinião de todos sobre isso. Pode fazer sentido que os programas sejam brandos. O que eu realmente quis dizer, no entanto, são APIs: interfaces expostas a outros programas , e não a pessoas. HTTP é um exemplo. O protocolo é uma interface que somente outros programas usam. As pessoas nunca fornecem diretamente as datas que entram nos cabeçalhos como "If-Modified-Since".
Portanto, a pergunta é: o servidor que implementa um padrão deve ser branda e permitir datas em vários outros formatos, além do que é realmente exigido pelo padrão? Eu acredito que o "ser tolerante" deve se aplicar a essa situação, ao invés de interfaces humanas.
Se o servidor for indulgente, pode parecer uma melhoria geral, mas acho que na prática só leva a implementações de clientes que acabam confiando na indulgência e, portanto, deixam de trabalhar com outro servidor indiferente de maneiras ligeiramente diferentes.
Portanto, um servidor que expõe alguma API é branda ou é uma péssima ideia?
Agora, no tratamento branda da entrada do usuário. Considere o YouTrack (um software de rastreamento de bugs). Ele usa um idioma para entrada de texto que lembra o Markdown. Exceto que é "branda". Por exemplo, escrevendo
- foo
- bar
- baz
não é uma maneira documentada de criar uma lista com marcadores e, no entanto, funcionou. Consequentemente, acabou sendo muito utilizado em todo o nosso bugtracker interno. A próxima versão é lançada e esse recurso branda começa a funcionar de maneira um pouco diferente, quebrando várias listas que (mis) usavam esse (não) recurso. A maneira documentada de criar listas com marcadores ainda funciona, é claro.
Portanto, meu software deve ser indulgente em quais entradas de usuário ele aceita?
fonte
Respostas:
Claro que você está completamente certo. Os programas nunca devem ser "brandos", pois isso serve apenas para mascarar problemas. Os problemas devem ser destacados, não varridos para debaixo do tapete. Uma mensagem de erro informativa é uma necessidade absoluta para que um programa seja útil ao usuário.
Na maioria das vezes, quando dados incorretos / inválidos são fornecidos, o provedor desses dados (seja um usuário ou a saída de outro programa) provavelmente não sabia que era inválido. A ingestão do erro os manterá na crença de que é (ou pode ser) válido, o que prolifera dados inválidos.
A única maneira de os sistemas interoperarem é que essa interoperação seja definida total e inequivocamente. Um programa que aceita dados fora da especificação torna esses dados de fato aceitos, mesmo que sejam inválidos pela especificação, o que não apenas dificulta a compatibilidade de uma carga enorme, mas também significa que não é mais formalmente definido. O próprio programa é agora o padrão de fato . Portanto, é impossível desenvolver programas mais brandos ou substituí-los porque você não pode fazer a menor alteração na maneira como ele opera.
fonte
Eu acho que tudo depende de quem é o seu público-alvo. Se são programadores, absolutamente não. Seu programa deve falhar com força e gritar assassinato sangrento. No entanto, se seu público-alvo não for programador, ele deverá ser brando, onde possa lidar com as exceções com elegância; caso contrário, sussurre um doce assassinato.
Como um estudo de caso, use o NPAPI Flash player. Existe uma versão de "lançamento" para quem realmente não se importa com 99% dos erros que podem ocorrer, mas há também uma versão de "depuração" que pode ser usada e grita assassinato sangrento quando algo dá errado. Cada suporte é obviamente reproduzido em Flash, mas tem como alvo dois dados demográficos completamente diferentes.
No final, acho que o importante é: Com o que seus usuários se preocupam?
fonte
Existem dois tipos de "branda": uma é aceitar entradas incorretas e tentar entendê-las, e a outra é aceitar tipos diferentes de entradas.
Geralmente, você sempre quer o segundo quando for possível. O primeiro é quando você morre rápido e com força. Um exemplo: datas.
Aqui estão algumas entradas de exemplo, incluindo válidas, inválidas e ambíguas.
2011-01-02
01/02/2011
Jan 2, 2011
2-Jan-2011
Green
Há apenas uma entrada inválida aqui:
Green
. Nem tente aceitá-lo como uma data. Desde aGreen
obviamente não é uma data, é um caso em que falhas silenciosas são aceitáveis.01/02/2011
é válido, mas ambíguo. Você não sabe necessariamente se foi ou não inserida como uma data nos EUA (2 de janeiro) ou não (1 de fevereiro). Aqui, provavelmente é melhor falhar alto e pedir ao usuário uma data inequívoca.2011-01-02
geralmente é considerado inequívoco; portanto, geralmente é bom seguir em frente e assumir que é o formato "AAAA-MM-DD", e falhar apenas mais adiante. É um pouco de julgamento, no entanto, ao lidar com a entrada do usuário.Jan 2, 2011
e2-Jan-2011
são válidos e inequívocos, devem ser aceitos. No entanto, tambémThe Second of January of the year 2011
é válido e inequívoco, mas ir tão longe em prol da clemência é um exagero. Vá em frente e falhe silenciosamente, assim comoGreen
.Em suma , a resposta é "depende". Dê uma olhada no que pode ser inserido e verifique se você nunca aceita tipos de entrada conflitantes (como
DD/MM/YYYY
vsMM/DD/YYYY
).No contexto da pergunta / comentário vinculado , esse é um caso de
2011-01-02
. A entrada se parece com JSON e será validada como JSON, mesmo que o tipo de mimet esteja errado; vá em frente e tente usá-lo mesmo se falhar em algum momento mais abaixo na linha.fonte
2011-01-02
,Jan 2, 2011
e2-Jan-2011
, se não é muito difícil de implementar), não no que ela produz . Os futuros clientes dessa API nem precisam saber sobre nenhum, desde que estejam inserindo corretamente um deles. Idealmente, a camada da API converteria tudo isso na mesma representação interna que o código usa antes de transmiti-lo.2011-01-02
formato, e é isso que você coloca na documentação. Não vejo nenhum efeito prejudicial.Falhar silenciosamente é a pior coisa que você poderia fazer. Você tentou depurar uma API com falha silenciosa? É impossível .
Há "Faça o seu melhor para se recuperar, mas envie um erro detalhado" e há "Falha silenciosa".
fonte
Parece-me que a Lei de Postel - "Seja conservador no que faz, seja liberal no que aceita dos outros" é o que está sendo discutido para um serviço JSON. Isso geralmente é aplicado a serviços da web e não à interface do usuário.
Para obter feedback construtivo do usuário da interface do usuário e restringir a entrada do usuário, é a regra geral que usamos.
fonte
Eu acho que isso está bem coberto no capítulo 1, seção 6 da TAOUP. Especificamente, a regra de reparo , que afirma que um programa deve fazer o que pode com uma entrada, transmitir os dados corretos e, se a resposta correta falhar, faça-o o mais rápido possível.
Um conceito semelhante é a programação defensiva . Você não sabe que tipo de entrada receberá, mas seu programa deve ser robusto o suficiente para cobrir todos os casos. Isso significa que deve ser programado em casos de recuperação para problemas conhecidos, como entrada desconfigurada, e uma captura de todos os casos para lidar com incógnitas.
Portanto, descartar entradas defeituosas silenciosamente é bom, desde que você esteja manipulando essas entradas. Você nunca deve jogá-lo no chão, por assim dizer.
Para uma API, acho que ser tolerante é o mesmo que para um programa. A entrada ainda está errada , mas você está tentando reparar o máximo possível. A diferença é o que é considerado reparo válido . Como você aponta, uma API branda pode causar problemas, pois as pessoas usam "recursos" que não existem.
Obviamente, uma API é apenas uma versão de nível inferior da regra de composição . Como tal, é realmente coberto pela regra da menor surpresa , já que é uma interface.
Como observa a citação de Spencer, evite similaridades superficiais, que podem ser discutidas sobre entradas "imprecisas". Sob essas condições, eu normalmente argumentaria que tudo indica que o programa não pode pode ser reparado, porque ele não sabe o que é desejado e é menos surpreendente para a base de usuários.
No entanto, você está lidando com datas com muitos "padrões". Às vezes, eles até se misturam em um único programa (cadeia). Como você sabe que uma data é esperada, tentar reconhecê-la é apenas um bom design. Especialmente se a data vier de algum programa externo e passar sem modificação por um segundo a caminho.
fonte
Os programas implantados no servidor, na maioria das vezes, devem receber milhares de solicitações a cada minuto, ou às vezes a cada segundo. Se um programa do servidor aceitar e corrigir as entradas defeituosas dos clientes, receio que ele tenha 2 desvantagens:
Os programas de servidor não devem aceitar entrada com defeito, mas os servidores devem retornar uma mensagem de erro ao cliente, se houver uma entrada com defeito.
fonte
O comportamento ideal, conceitualmente, é fazer o que pode ser feito com segurança, garantindo simultaneamente que alguém que possa resolver algum problema seja notificado de alguma forma. Na prática, é claro, muitas vezes é impossível encontrar essa última restrição diretamente e, portanto, torna-se melhor a questão de lidar com informações duvidosas.
Uma coisa que pode ser muito útil no design de um protocolo, especificação de formatação ou "idioma" é ter um meio de distinguir quatro categorias de itens potenciais não compreendidos:
Ter uma convenção bem definida pela qual aplicativos que possam ler qualquer versão de um formato de dados poderão reconhecer qual categoria é apropriada para qualquer coisa gerada em conformidade com versões posteriores é uma abordagem muito melhor do que tentar adotar medidas de compatibilidade ad-hoc mais tarde. Por exemplo, se um formato de arquivo tiver linhas com o formato "Tag: Value", é possível especificar que o primeiro caractere de qualquer tag indique a categoria em que pertence; para tags das categorias de ignorar silenciosamente, é possível que o primeiro caractere indique também a versão do padrão para o qual a tag deve ser válida (de modo que, se uma tag "ignorar silenciosamente" afirmar estar presente na versão 3 de o padrão, um analisador para a versão ignorá-lo-ia silenciosamente, mas um analisador para a versão 3 ou posterior gritaria se não pudesse analisá-lo).
O mais importante, em qualquer caso, é evitar a conversão de dados ambíguos ou incompreendidos em dados errados. Em alguns casos, pode ser melhor recusar a propagação de dados ambíguos, embora em outros casos seja melhor propagá-los exatamente como recebidos, caso o destinatário os considere ambíguos. O que é verdadeiramente perigoso, senão o mal, é a conversão de dados usando suposições variadas, por exemplo, a conversão de uma lista de datas como:
em uma lista de datas como
Mesmo que alguém tenha uma lista com algumas datas inseridas erroneamente, pode ser possível para um ser humano, dada uma lista no formato original, determinar qual formato estava correto e sinalizar valores duvidosos para pesquisas adicionais (verificação em outros registros etc.) ) A renderização das datas no último formato, no entanto, seria irremediavelmente e irrecuperavelmente distorcida.
fonte
Minha experiência de interface do usuário vem principalmente de sistemas de desktop. Os sites são diferentes, embora eu tenha visto alguns sites que podem desafiar um sistema de desktop. Mas pelo que vale a pena:
Descobri que as mensagens de erro devem ser o último recurso; um sistema ideal não os teria. A melhor coisa a fazer é não permitir entradas inválidas: o usuário não pode inserir "verde" se estiver selecionando uma lista suspensa de meses. Ele não pode pressionar um botão acinzentado.
A próxima melhor coisa a fazer é aceitar os dados incorretos. Digamos que você esteja exibindo um histograma de vendas diárias durante um mês. Após a entrada do usuário, o gráfico abrange um século e a barra de um século é 10 vezes maior que os outros. O usuário agora sabe que fez algo errado e, além disso, sabe muito mais sobre o que fez de errado do que qualquer mensagem poderia lhe dizer. Quando a entrada é gráfica - arrastando um mouse, por exemplo - esse tipo de feedback ainda funciona e é inestimável. Muitas entradas podem ser inválidas, mas, usando esse método, o usuário recebe feedback instantâneo e detalhado sobre os resultados de cada posição do mouse.
Tudo isso dito, às vezes o usuário precisa saber por que o botão está acinzentado para que ele não possa pressioná-lo. Então não há nenhuma ajuda para ele (se não é , deixe-me saber), mas para ungray o botão e, quando ele clica sobre ele, dar-lhe uma boa explicação de por que o botão não está funcionando no momento.
fonte
A declaração é sobre o envio de informações pela Internet. Uma das coisas com o envio de informações pela Internet é que nem sempre elas chegam ao alvo ou são fragmentadas.
fonte
Algo que parece estar esquecido aqui - quais são as consequências do fracasso?
Exibir uma página da web? Você deve fazer todo o possível para tolerar informações incorretas. Suas opções são exibir o que você pode ou gerar um erro. O último curso não fornece nada ao usuário e, portanto, deve ser apenas um último recurso, pois fornece ao usuário um resultado completamente inútil; seria muito difícil que um erro fosse pior que isso.
Por outro lado, se estiver pedindo o alvo de um Minuteman III, você rejeitará "Moscou" como entrada, pois é potencialmente ambíguo.
fonte