Un server dovrebbe "essere indulgente" in ciò che accetta e "scartare silenziosamente input difettosi"?


27

Avevo l'impressione che ormai tutti fossero d'accordo che questa massima fosse un errore. Ma recentemente ho visto questa risposta che ha un commento "be lenient" votato 137 volte (ad oggi).

A mio avviso, la clemenza in ciò che i browser accettano è stata la causa diretta del caos totale che HTML e alcuni altri standard web erano alcuni anni fa, e solo recentemente hanno iniziato a cristallizzare correttamente da quel casino. Il mio modo di vedere, di essere indulgente in ciò che accetti sarà portare a questo.

La seconda parte della massima è "elimina in modo silenzioso l'input difettoso, senza restituire un messaggio di errore, a meno che ciò non sia richiesto dalla specifica" , e questo sembra offensivo al limite. Qualsiasi programmatore che ha sbattuto la testa contro il muro quando qualcosa fallisce silenziosamente saprà cosa intendo.

Quindi, mi sbaglio completamente su questo? Il mio programma dovrebbe essere indulgente in ciò che accetta e ingoiare gli errori in silenzio? O sto interpretando male cosa dovrebbe significare?


La domanda originale diceva "programma", e prendo il punto di tutti su questo. Può avere senso che i programmi siano indulgenti. Ciò che intendevo veramente, tuttavia, sono le API: interfacce esposte ad altri programmi , piuttosto che alle persone. HTTP è un esempio. Il protocollo è un'interfaccia utilizzata solo da altri programmi. Le persone non forniscono mai direttamente le date che vanno nelle intestazioni come "If-Modified-Since".

Quindi, la domanda è: il server che implementa uno standard dovrebbe essere indulgente e consentire date in diversi altri formati, oltre a quello che è effettivamente richiesto dallo standard? Credo che si supponga che "essere indulgenti" si applichi a questa situazione, piuttosto che alle interfacce umane.

Se il server è clemente, potrebbe sembrare un miglioramento complessivo, ma penso che in pratica conduca solo a implementazioni client che finiscono per dipendere dalla clemenza e quindi non riescono a lavorare con un altro server clemente in modi leggermente diversi.

Quindi, un server che espone alcune API dovrebbe essere indulgente o è una pessima idea?


Ora su gestione indulgente dell'input dell'utente. Prendi in considerazione YouTrack (un software di tracciamento dei bug). Utilizza una lingua per l'immissione di testo che ricorda Markdown. Solo che è "indulgente". Ad esempio, scrivendo

- foo
- bar
- baz

non è un modo documentato per creare un elenco puntato, eppure ha funzionato. Di conseguenza, è stato utilizzato molto durante il nostro bugtracker interno. La prossima versione viene fuori e questa caratteristica indulgente inizia a funzionare in modo leggermente diverso, rompendo un mucchio di elenchi che (mis) hanno usato questa funzione (non). Il modo documentato per creare elenchi puntati funziona ancora, ovviamente.

Quindi, il mio software dovrebbe essere indulgente in quali input utente accetta?


4
Riguardo "elimina silenziosamente input errati", chiederei per ogni caso quello che dovrebbe essere considerato input errato. Se fai una domanda a un utente e ti aspetti che "sì" o "no", "YES" sia errato? Che ne dici di "y"? Che ne dici di "oui"? In generale, non essere timido nel dire all'utente che il suo input non è quello che ti aspetti. Tuttavia assicurati di essere stato il più inclusivo possibile - nella mia mente, questo è ciò che si intende per "essere indulgente".

3
Se stai parlando dell'input dell'utente finale - che si riferisce alle linee di amicizia dell'utente della tua applicazione, allora dovresti essere dominante; per l'input generato automaticamente dalla macchina (da un'API), dovresti essere prolisso (rigoroso).
Burhan Khalid,

2
In realtà la clemenza dell'HTML è stata la ragione per cui è diventata così popolare (e la rigidità dell'XHTML perché è stata abbandonata).
Oliver Weiler,

1
Penso che la chiave sia che se si tratta di uno scenario in cui si può permettere che fallisca con grazia è che almeno si registra l'evento.
Rig

2
@OliverWeiler Sento che il fallimento di XHTML ha avuto a che fare con il fatto che era del tutto inutile. HTML era già lì e un po 'ha funzionato. Inoltre, mentre l'HTML è ovviamente immensamente popolare, è un po 'triste che stiamo definendo questa tecnologia un successo. Soddisfa la domanda, ma anche Symbian ha soddisfatto la domanda di smartphone.
Roman Starkov,

Risposte:


9

Naturalmente hai perfettamente ragione. I programmi non dovrebbero mai essere "indulgenti" in quanto ciò serve solo a mascherare i problemi. I problemi dovrebbero essere evidenziati, non spazzati sotto il tappeto. Un messaggio di errore informativo è un must assoluto affinché un programma sia utile per l'utente.

Il più delle volte quando vengono forniti dati errati / non validi, il fornitore di tali dati (sia esso un utente o l'output di qualche altro programma) probabilmente non sapeva che non era valido. L'ingestione dell'errore li manterrà nella convinzione che sia (o potrebbe essere) valida, che prolifera i dati non validi.

L'unico modo per i sistemi di interoperare è che tale interoperazione sia definita in modo completo e inequivocabile. Un programma che accetta i dati al di fuori delle specifiche rende di fatto accettati tali dati anche se non sono validi per le specifiche, il che non solo rende la compatibilità un carico enorme più difficile, ma significa anche che non è più definita formalmente. Il programma stesso è ora lo standard di fatto . Pertanto, i programmi indulgenti sono impossibili da sviluppare ulteriormente o da sostituire poiché non è possibile apportare la minima modifica al modo in cui funziona.


25

Penso che tutto dipenda da chi è il tuo target demografico. Se sono programmatori, allora assolutamente no. Il tuo programma dovrebbe fallire duramente e urlare un sanguinoso omicidio. Tuttavia, se il tuo pubblico di destinazione non è programmatore, il tuo programma dovrebbe essere indulgente dove può gestire le eccezioni con garbo, altrimenti sussurrare un omicidio sanguinolento.

Come caso di studio, prendi il NPAPI Flash player. Esiste una versione di "rilascio" per coloro che non si preoccupano davvero del 99% degli errori che possono verificarsi, ma esiste anche una versione di "debug" che può essere utilizzata per urlare sanguinosi omicidi quando qualcosa va storto. Ognuno supporta la riproduzione di contenuti Flash ovviamente, ma è indirizzato a due dati demografici completamente diversi.

Alla fine, penso che l'importante sia: che cosa importa ai tuoi utenti?


4
La stragrande maggioranza degli strumenti da riga di comando Unixy che affermano di avere un pubblico di destinazione al di fuori dei programmatori sono comunque inutili per gli utenti che commettono errori. Anche se non sei un programmatore, di solito è meglio per un programma spiegare un problema piuttosto che fare qualcosa di insensato o non intenzionale.
Timwi,

2
@romkyns: Non del tutto, sto dicendo che la tua applicazione dovrebbe gestire gli errori in modo sensato per i tuoi utenti target.
Demian Brecht,

@Timwi: nel qual caso, quegli strumenti da riga di comando Unixy sono scarsamente progettati;)
Demian Brecht,

3
@romkyns - Penso che un buon esempio potrebbe essere: in modalità debug, vuoi che un programma si fermi su qualsiasi problema e ti dica cosa è andato storto. In modalità produzione si desidera che il programma continui a funzionare nel miglior modo possibile e registrare tutti i problemi che può gestire. In questo modo, i programmatori possono vedere cosa hanno fatto di sbagliato e risolverlo, ma gli utenti non saranno disturbati da cose che non possono risolvere. Alcuni problemi ovviamente non possono essere risolti, ma un buon esempio sono le regole di stile CSS, in cui è ancora possibile eseguire il rendering di un sito, anche se non si capisce una delle regole di stile.
Ripristina Monica il

1
Il commento di @ BrendanLong colpisce praticamente l'unghia della testa - a volte produrre risultati è più importante che essere corretti. Alcuni errori (o avvisi) possono essere recuperati con grazia, senza input da parte dell'utente; sta a te decidere cosa vuoi fare in questi casi.
Daniel B,

7

Esistono due tipi di "indulgente": uno è accettare input errati e provare a dargli un senso, e l'altro è accettare diversi tipi di input.

Generalmente, vuoi sempre il secondo quando è fattibile. Il primo è quando muori duro e veloce. Un esempio: date.

Ecco alcuni input di esempio, compresi validi, non validi e ambigui.

  • 2011-01-02
  • 01/02/2011
  • Jan 2, 2011
  • 2-Jan-2011
  • Green

C'è solo un input non valido qui: Green. Non provare nemmeno ad accettarlo come data. Dal momento che Greenovviamente non è una data, questo è un caso in cui il fallimento silenzioso è accettabile.

01/02/2011è valido, ma ambiguo. Non sai necessariamente se è stata inserita o meno come data USA (2 gennaio) o meno (1 febbraio). Qui, probabilmente è meglio fallire ad alta voce e chiedere all'utente una data inequivocabile.

2011-01-02di solito è considerato inequivocabile, quindi spesso va bene andare avanti e assumere che sia il formato "AAAA-MM-GG", e fallisce solo più in basso. È un po 'una decisione di giudizio, tuttavia, quando si tratta di input dell'utente.

Jan 2, 2011e 2-Jan-2011sono validi e inequivocabili, dovrebbero essere accettati. Tuttavia, The Second of January of the year 2011è anche valido e inequivocabile, ma andare così lontano per motivi di clemenza è eccessivo. Vai avanti e fallisci in silenzio, proprio come Green.

In breve , la risposta è "dipende". Dai un'occhiata a cosa può essere inserito e assicurati di non accettare mai tipi di input in conflitto (come DD/MM/YYYYvs MM/DD/YYYY).

Nel contesto della domanda / commento collegato , questo è un caso di 2011-01-02. L'input è simile a JSON e verrà convalidato come JSON anche se il mimetype è errato; vai avanti e prova ad usarlo anche se fallisce ad un certo punto più in basso.


1
C'è una cosa che non stai prendendo in considerazione qui. Se l' utente digitasse quella stringa, sì, dovrei accettare vari formati, senza dubbio. Ma stiamo parlando di API. I client delle API sono altri programmi. Se è clemente nel suo formato data, ogni futuro server che espone questa API dovrà essere clemente nello stesso modo o rischiare l'incompatibilità. La clemenza finisce per essere dannosa piuttosto che utile, non credi?
Roman Starkov,

1
@romkyns Penso che tu abbia frainteso la posizione della clemenza. L'API deve essere clementi in ciò che accetta (dovrebbe comprendere tutti 2011-01-02, Jan 2, 2011e 2-Jan-2011, se non è troppo difficile da implementare), non in ciò che uscite . I futuri clienti di quell'API non dovranno nemmeno conoscerne nessuno, purché ne inseriscano correttamente uno. Idealmente, il livello API convertirà tutti questi nella stessa rappresentazione interna utilizzata dal codice prima di passarlo.
Izkata,

@romkyns L' output potrebbe, ad esempio, essere sempre in 2011-01-02formato, ed è quello che avresti inserito nella tua documentazione. Non vedo alcun effetto dannoso.
Izkata,

4
@Izkata: hai frainteso. Immagina che esistesse un vecchio programma disponibile solo come binario. Devi scrivere un nuovo programma che accetta gli stessi input del vecchio. Se il vecchio programma era ben definito in ciò che accetta, il tuo lavoro è ben definito. Se è indulgente, il tuo lavoro è impossibile.
Timwi,

1
Un forte disaccordo. a meno che non sia un input inserito dall'utente, sii sempre rigoroso sia sull'input che sull'output. Cosa succede quando è necessario implementare nuovamente il servizio? Hai documentato tutti i possibili formati di data? Dovrai implementarli tutti, poiché non vuoi che i vecchi clienti si rompano. Utilizzare ISO 8601 per tutte le istanze e i periodi di data generati dalla macchina: è ben specificato e ampiamente disponibile nelle librerie. A proposito, cosa significa in realtà 2011-01-02? Il periodo di tempo dalle 00:00 del 2 alle 00:00 del 3? In quale fuso orario?
Dibbeke,

6

Fallire in silenzio è la cosa peggiore che tu possa mai fare. Hai provato a eseguire il debug di un'API con errore silenzioso? È impossibile .

C'è "Fai del tuo meglio per recuperare ma invia errori dettagliati" e c'è "Errore silenzioso".


3

Mi sembra che la Legge di Postel - "Sii prudente in ciò che fai, sii liberale in ciò che accetti dagli altri" è ciò che viene discusso per un servizio JSON. Questo di solito viene applicato ai servizi Web e non all'interfaccia utente.

Per un'interfaccia utente costruttiva il feedback e la contrapposizione dell'utente è la regola empirica che utilizziamo.


Ma se guardi le risposte qui, tutti sembrano concordare sul fatto che abbia sempre senso solo per le UI, cioè l'opposto della legge originale.
Roman Starkov,

Vedo ciò che dici e concordo con i poster che l'obiettivo è un servizio / API pulito e rigoroso, ma nel bene o nel male so di aver aggiunto "robustezza" in un modo o nell'altro ai miei servizi. Di solito una traduzione di valore o due al limite. Finché il significato è chiaro, l'app sa come elaborare il messaggio e nessuna regola aziendale viene violata, quindi l'aggiunta di robustezza aiuterà l'interoperabilità.
MarcLawrence,

Fino a quando qualcun altro non andrà a implementare le tue specifiche, solo per scoprire che la "robustezza", su cui centinaia di clienti hanno fatto affidamento, non era in realtà nelle specifiche e deve essere retroingegnerizzata ...
Roman Starkov

3

Penso che questo sia ben trattato nel capitolo 1, sezione 6 di TAOUP. In particolare, la regola di riparazione , che afferma che un programma dovrebbe fare ciò che può con un input, inoltrare i dati corretti e, se la risposta corretta è un errore, farlo al più presto.

Un concetto simile è la programmazione difensiva . Voi non sapete che tipo di ingresso che si riceverà, ma il programma dovrebbe essere sufficientemente robuste per coprire tutti i casi. Ciò significa che dovrebbe essere programmato in casi di recupero per problemi noti come l'input mangled e una cattura di tutti i casi per gestire incognite.

Quindi scartare silenziosamente l'input difettoso va bene, purché tu stia gestendo quell'input. Non dovresti mai lasciarlo cadere sul pavimento, per così dire.


Per un'API, penso che essere indulgenti sia lo stesso di un programma. L'input è ancora errato , ma stai tentando di riparare il più possibile. La differenza è ciò che è considerato riparazione valida . Come sottolineato, un'API indulgente può causare problemi poiché le persone utilizzano "funzionalità" che non esistono.

Naturalmente, un'API è solo una versione di livello inferiore della regola di composizione . Come tale, è davvero coperto dalla regola della minima sorpresa , dal momento che è un'interfaccia.

Come osserva la citazione di Spencer, evita la somiglianza superficiale, che può essere discussa su input "fuzzy". In queste condizioni, normalmente direi che tutto indica che il programma non è in grado di riparare, perché non saprà cosa è desiderato ed è meno sorprendente per la base utenti.

Tuttavia, hai a che fare con date che hanno molti "standard". A volte anche questi vengono mescolati in un singolo programma (catena). Dato che sai che è prevista una data, tentare di riconoscerla è solo un buon progetto. Soprattutto se la data proviene da un programma esterno e viene superata non modificata per un secondo sulla sua strada.


2

I programmi distribuiti sul server, la maggior parte delle volte, dovrebbero ricevere migliaia di richieste ogni minuto, o talvolta ogni secondo. Se un programma server accetta e corregge input errati dai client, temo che presenterà 2 svantaggi:

  1. Perdita di tempo prezioso per il server. Con oltre 1000 richieste al secondo, il controllo degli errori in ciascuna richiesta può riflettere una risposta lenta per ciascun client.
  2. Ingiusto nei confronti dei client / programmi client che forniscono input corretti. Oltre a ciò, quando un programmatore lato server si trova sul codice del server, deve pensare ai vari casi di ciò che possono essere input errati. Chi lo deciderà?

I programmi server non devono accettare input errati, ma i server devono restituire un messaggio di errore al client, se è presente un input errato.


2

Il comportamento ideale, concettualmente, è quello di fare ciò che può essere fatto in modo sicuro, garantendo allo stesso tempo che qualcuno in grado di risolvere eventuali problemi venga in qualche modo informato di loro. In pratica, ovviamente, quest'ultimo vincolo è spesso impossibile da soddisfare direttamente, e quindi la domanda diventa la migliore per gestire input dubbi.

Una cosa che può essere molto utile nella progettazione di un protocollo, specifiche di formattazione o "linguaggio" è quella di avere un mezzo per distinguere quattro categorie di potenziali elementi non compresi:

  1. Cose che dovrebbero essere filtrate se non comprese.
  2. Cose che dovrebbero essere ignorate se non comprese, ma comunque conservate se i dati devono essere trasmessi (forse in una sorta di wrapper per indicare che è passato attraverso almeno una fase che non li ha capiti)
  3. Le cose che dovrebbero generare un avviso se non comprese, ma non dovrebbero impedire un tentativo di recupero dei dati (ad es. All'interno di una pagina Web, un oggetto il cui tipo è sconosciuto, ma la cui fine all'interno del file è ben definita, potrebbe essere visualizzato in rosso "X" senza impedire il rendering del resto della pagina.)
  4. Cose che indicherebbero che qualsiasi cosa che non sia in grado di capirle potrebbe avere problemi gravi e irrecuperabili altrove (ad es. Un indicatore che i dati rimanenti sono compressi e che qualsiasi cosa possa essere compresa da qualsiasi cosa che possa eseguire la decompressione richiesta).

Avere una convenzione ben definita in base alla quale le app in grado di leggere qualsiasi versione di un formato di dati sarà in grado di riconoscere quale categoria è appropriata per qualsiasi cosa generata in conformità con le versioni successive è un approccio molto migliore rispetto al tentativo di incastrare misure di compatibilità ad hoc più tardi. Ad esempio, se un formato di file ha righe del formato "Tag: Value", si potrebbe specificare che il primo carattere di qualsiasi tag indicherà la categoria a cui appartiene; per i tag delle categorie silent-ignore, è possibile che il primo carattere indichi anche la versione dello standard per cui il tag dovrebbe essere valido (in modo che se un tag "silent-ignore" afferma di essere presente nella versione 3 di lo standard, un parser per la versione lo ignorerebbe silenziosamente, ma un parser per la versione 3 o successive lo squawk se non potesse analizzarlo).

La cosa più importante in ogni caso è evitare la conversione di dati ambigui o incompresi in dati errati. In alcuni casi, potrebbe essere meglio rifiutare di propagare dati ambigui, sebbene in altri casi potrebbe essere meglio propagarli esattamente come ricevuti nel caso in cui il destinatario lo consideri inequivocabile. Ciò che è veramente pericoloso se non addirittura malvagio è la conversione dei dati utilizzando ipotesi diverse, ad esempio la conversione di un elenco di date come:

01/12/12
13/12/12
99/12/12

in un elenco di date come

2012-01-12
2012/12/13
1999/12/12

Anche se uno avesse un elenco con poche date inserite erroneamente, potrebbe essere possibile per un essere umano fornito un elenco nel formato originale per determinare quale formato era corretto e contrassegnare i valori dubbi per ulteriori ricerche (controllo contro altri record, ecc. ) Rendere le date in quest'ultimo formato, tuttavia, le danneggerebbe irrimediabilmente e irrimediabilmente.


Ben detto. Mi piace come la tua risposta sia un po 'più profonda. Sono tentato di accettarlo, ma dato l'interesse generale che questa domanda ha ricevuto, penso che lo lascerò in giro per un po '.
Roman Starkov,

1

La mia esperienza con l'interfaccia utente proviene principalmente da sistemi desktop. I siti Web sono diversi, anche se ho visto alcuni siti che potrebbero sfidare un sistema desktop. Ma per quello che vale:

Ho scoperto che i messaggi di errore dovrebbero essere l'ultima risorsa; un sistema ideale non li avrebbe affatto. La cosa migliore da fare è non consentire voci errate in primo luogo: l'utente non può inserire "verde" se sta selezionando da un elenco a discesa di mesi. Non può premere un pulsante in grigio.

La prossima cosa migliore da fare è accettare i dati errati. Supponi di visualizzare un istogramma delle vendite giornaliere per un mese. Dopo l'input dell'utente, il grafico copre un secolo e la barra di un secolo è 10 volte più alta delle altre. L'utente ora sa che ha fatto qualcosa di sbagliato e, inoltre, sa molto di più su ciò che ha fatto di sbagliato di quanto qualsiasi messaggio possa dirgli. Quando l'immissione è grafica, ad esempio trascinando un mouse, questo tipo di feedback funziona ancora ed è prezioso. Un gruppo di input potrebbe non essere valido, ma utilizzando questo metodo l'utente ottiene un feedback immediato e dettagliato sui risultati di ciascuna posizione del mouse.

Detto questo, a volte l'utente deve sapere perché il pulsante è disattivato in modo da non poterlo premere. Poi c'è niente da fare (se non v'è , fatemelo sapere), ma per ungray il pulsante e, quando si fa clic su di esso, dargli una buona spiegazione del motivo per cui il pulsante non funziona in questo momento.


0

La dichiarazione riguarda l'invio di informazioni su Internet. Una delle cose con l'invio di informazioni su Internet è che non sempre raggiungeranno l'obiettivo o saranno frammentati.


0

Qualcosa che sembra mancare qui - quali sono le conseguenze del fallimento?

Visualizza una pagina web? Dovresti fare tutto il possibile per tollerare input errati. Le tue scelte sono mostrare ciò che puoi o lanciare un errore. Quest'ultimo corso non dà nulla all'utente e quindi dovrebbe essere solo l'ultima risorsa in quanto fornisce all'utente un risultato completamente inutile, sarebbe piuttosto difficile per un errore essere peggio di così.

D'altra parte, se sta chiedendo il bersaglio di un Minuteman III, rifiuti "Mosca" come input in quanto potenzialmente ambiguo.


Quindi, anche se sei un programmatore e hai scritto un codice stupido, il sistema dovrebbe andare avanti e fare del suo meglio per mostrare qualcosa, invece di fermarti e urlare "oi, hai rovinato qui (numero di riga)"? Non pensi che sia esattamente ciò che porta a un codice incredibilmente cattivo?
Roman Starkov,

@romkyns: hai delle modalità di debug per quel genere di cose che sono rigorose riguardo a scricchiolare sugli errori.
Loren Pechtel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.