Sii liberale in ciò che accetti ... o no?

43

[Disclaimer: questa domanda è soggettiva, ma preferirei ottenere risposte sostenute da fatti e / o riflessioni]

Penso che tutti siano a conoscenza del principio di robustezza , in genere riassunto dalla legge di Postel:

Be conservative in what you send; be liberal in what you accept.

Concordo sul fatto che per la progettazione di un protocollo di comunicazione diffuso questo abbia senso (con l'obiettivo di consentire un'estensione facile), tuttavia ho sempre pensato che la sua applicazione a HTML / CSS fosse un fallimento totale, ogni browser che implementava il suo possiede il rilevamento / comportamento di tweak silenzioso, rendendo quasi impossibile ottenere un rendering coerente su più browser.

Tuttavia noto che la RFC del protocollo TCP considera accettabile il "Silent Failure" a meno che non sia diversamente specificato ... il che è un comportamento interessante, per usare un eufemismo.

Ci sono altri esempi dell'applicazione di questo principio nel commercio del software che appaiono regolarmente perché hanno morso gli sviluppatori, dall'alto verso il basso:

  • Inserimento punto e virgola JavaScript
  • C (silent) conversioni integrate (che non sarebbero così male se non fossero troncate ...)

e ci sono strumenti per aiutare a implementare un comportamento "intelligente":

Tuttavia, trovo che questo approccio, sebbene possa essere utile quando si ha a che fare con utenti non tecnici o per aiutare gli utenti nel processo di recupero degli errori, ha alcuni svantaggi quando viene applicato alla progettazione dell'interfaccia librerie / classi:

  • è alquanto soggettivo se l'algoritmo indovina "giusto", e quindi potrebbe andare contro il principio di stordimento
  • rende l'implementazione più difficile, quindi maggiori possibilità di introdurre bug (violazione di YAGNI ?)
  • rende il comportamento più suscettibile al cambiamento, poiché qualsiasi modifica della routine "guess" potrebbe interrompere i vecchi programmi, quasi escludendo le possibilità di refactoring ... dall'inizio!

E questo è ciò che mi ha portato alla seguente domanda:

Quando progetti un'interfaccia (libreria, classe, messaggio), ti appoggi al principio di robustezza o no?

Io stesso tendo ad essere piuttosto severo, usando un'estesa validazione dell'input sulle mie interfacce, e mi chiedevo se fossi forse troppo severo.

    
posta Matthieu M. 16.10.2010 - 15:41
fonte

10 risposte

33

Direi robustezza quando non introduce ambiguità .

Ad esempio: Quando si analizza un elenco separato da virgole, se c'è o meno uno spazio prima / dopo la virgola non cambia il significato semantico.

Durante l'analisi di una stringa guid deve accettare qualsiasi numero di formati comuni (con o senza trattini, con o senza parentesi graffe circostanti).

La maggior parte dei linguaggi di programmazione è robusta con l'utilizzo dello spazio bianco. Nello specifico ovunque esso non influisce sul significato del codice. Anche in Python, dove lo spazio bianco è rilevante, è ancora flessibile quando ci si trova all'interno di una lista o di una dichiarazione del dizionario.

Sono assolutamente d'accordo sul fatto che se qualcosa può essere interpretato in più modi o se non è chiaro al 100% che cosa si intendesse allora troppa robustezza può finire per essere un dolore, ma c'è molto spazio per la robustezza senza essere ambigui.

    
risposta data 16.10.2010 - 18:25
fonte
14

Assolutamente no. Tecniche come la programmazione difensiva nasconde i bug , rendendo il loro aspetto meno probabile e più casuale, il che rende più difficile il loro rilevamento, il che rende più difficile isolarli.

Il Scrittura di codice solido ampiamente sottovalutato è stato tremendo nel sottolineare ripetutamente il bisogno e le tecniche di fare bug difficili da introdurre o nascondere. Attraverso l'applicazione dei suoi principi come "Eliminare il comportamento casuale, forzare i bug a essere riproducibili". e, "Cerca sempre ed elimina difetti nelle tue interfacce". gli sviluppatori miglioreranno notevolmente la qualità del loro software eliminando l'ambiguità e gli effetti collaterali incontrollati che sono responsabili di una grande quantità di bug.

    
risposta data 16.10.2010 - 18:14
fonte
9

Overapplication of Robustness porta a indovinare ciò che l'utente desiderava, il che va bene fino a quando non si sbaglia. Richiede inoltre la totale fiducia sbagliata che i tuoi clienti non abusino della tua fiducia e creino parole senza senso casuali che semplicemente funzionano, ma che non sarai in grado di supportare nella versione 2.

Overapplication of Correctness ti porta a negare ai tuoi clienti il diritto di commettere errori minori, il che va bene fino a quando non si lamentano che le loro cose funzionano bene sul prodotto della concorrenza e ti dicono che cosa puoi fare con il tuo standard di 5.000 pagine che la parola "DRAFT" è ancora scarabocchiata sulla copertina a pastello, e almeno 3 esperti sostengono che sia fondamentalmente difettosa, e altri 200 esperti onesti affermano di non comprendere appieno.

La mia soluzione personale è sempre stata una deprecazione. Li sostieni, ma di 'loro che stanno sbagliando e (se possibile) il percorso più facile per la correttezza. In questo modo, quando disattivi la funzione bug entro 10 anni, hai almeno la traccia cartacea per affermare che "ti abbiamo avvertito che questo potrebbe accadere".

    
risposta data 15.11.2011 - 12:09
fonte
9

Sfortunatamente il cosiddetto "principio di robustezza" non porta alla robustezza. Prendi HTML come esempio. Molti problemi, lacrime, spreco di tempo ed energia avrebbero potuto essere evitati se i browser avessero analizzato rigorosamente l'HTML dall'inizio invece di cercare di indovinare il significato di contenuti malformati.

Il browser dovrebbe semplicemente aver visualizzato un messaggio di errore invece di provare a ripararlo sotto le copertine. Ciò avrebbe costretto tutti i pasticceri a sistemare il loro casino.

    
risposta data 15.11.2011 - 13:50
fonte
6

Io divido le interfacce in diversi gruppi (aggiungi di più se vuoi):

  1. quelli che sono sotto il tuo controllo dovrebbero essere severi (tipicamente le classi)
  2. API della libreria, che dovrebbero essere anche rigorose, ma è consigliata una validazione aggiuntiva
  3. interfacce pubbliche che devono gestire ogni tipo di abuso (in genere protocolli, input dell'utente, ecc.). Qui la robustezza sull'input è davvero redditizia, non ci si può aspettare che tutti possano sistemare le proprie cose. E ricorda per l'utente che sarà colpa tua se l'applicazione non funziona, non la parte che ha inviato alcune schifezze mal formattate.

L'output deve essere sempre rigoroso.

    
risposta data 15.11.2011 - 18:11
fonte
5

Penso che l'HTML e il World Wide Web abbiano fornito una prova su vasta scala del vero Principio del Robustness Principle e lo abbiano dimostrato come un enorme fallimento. È direttamente responsabile del caos confusionario dei quasi-standard HTML in concorrenza che rende la vita miserabile agli sviluppatori Web (e ai loro utenti) e peggiora con ogni nuova versione di Internet Explorer.

Sappiamo dagli anni '50 come convalidare il codice correttamente. Eseguirlo con un parser rigoroso e se qualcosa non è sintatticamente corretto, lanciare un errore e interrompere. Non passare, non raccogliere $ 200, e per l'amore di tutto ciò che è binario non lasciare che qualche programma del computer tenti di leggere la mente del programmatore se commette un errore!

HTML e JavaScript ci hanno mostrato esattamente cosa succede quando quei principi vengono ignorati. La migliore linea d'azione è imparare dai loro errori e non ripeterli.

    
risposta data 16.10.2010 - 15:52
fonte
3

Come contrappunto all'esempio di Mason, la mia esperienza con il Protocollo di avvio di sessione era quella mentre i diversi stack interpretavano il relativo RFC in modo diverso (e sospetto che ciò avvenga con lo standard ogni mai scritto), essere (moderatamente) liberale in ciò che accetti significa che puoi effettivamente effettuare chiamate tra due dispositivi. Poiché questi dispositivi sono soliti elementi fisici rispetto ai software su un desktop, devi semplicemente essere liberale in ciò che accetti, oppure il tuo telefono non può chiamare un altro telefono di un particolare marchio. Ciò non rende il tuo telefono un bell'aspetto!

Ma se stai scrivendo una libreria, probabilmente non hai il problema di più parti che interpretano uno standard comune in modi reciprocamente incompatibili. In tal caso, direi che è rigoroso in ciò che accetti, perché rimuove le ambiguità.

Il file Jargon ha anche una storia dell'orrore su "indovinare" l'utente intento.

    
risposta data 16.10.2010 - 16:50
fonte
3

Hai ragione, la regola si applica ai protocolli e non alla programmazione. Se digiti un errore durante la programmazione, riceverai un errore non appena esegui la compilazione (o l'esecuzione, se sei uno di quei tipi dinamici). Non c'è niente da guadagnare lasciando che il computer indovini per te. A differenza della gente comune, siamo ingegneri e capaci di dire esattamente cosa intendo. ;)

Quindi, quando si progetta un'API, direi non seguire il principio di robustezza. Se lo sviluppatore commette un errore, dovrebbe scoprirlo subito. Naturalmente, se la tua API utilizza dati da una fonte esterna, come un file, dovresti essere indulgente. L'utente della tua biblioteca dovrebbe scoprire i propri errori, ma non quelli di nessuno.

Per inciso, suppongo che "l'errore silenzioso" sia permesso nel protocollo TCP perché altrimenti, se le persone lanciassero pacchetti malformati, verrebbero bombardati con messaggi di errore. Questa è la semplice protezione DoS.

    
risposta data 16.10.2010 - 17:31
fonte
1

IMO, la robustezza è un aspetto di un compromesso progettuale e non un principio di "preferenza". Come molti hanno sottolineato, niente puzza come soffiare quattro ore cercando di capire dove il tuo JS è andato storto solo per scoprire il vero problema era solo un browser ha fatto la cosa giusta con XHTML Strict. Lascia che la pagina vada in pezzi quando una parte dell'HTML pubblicato è stato un disastro completo.

D'altra parte, chi vuole cercare la documentazione per un metodo che accetta 20 argomenti e insiste che siano nello stesso ordine con i segnaposti a valore vuoto o nullo per quelli che si desidera saltare? Il modo altrettanto terribile di affrontare quel metodo sarebbe quello di controllare ogni argomento e provare a indovinare quale era per ciò che si basava su posizioni e tipi relativi e poi fallire in silenzio o cercare di "arrangiarsi" con argille prive di significato.

Oppure puoi infondere flessibilità nel processo passando una lista di coppie letterale / dizionario / valore-chiave di un oggetto e gestendo l'esistenza di ogni argomento man mano che ci arrivi. Per il compromesso perfissimo, è una torta e mangia anche lo scenario.

Sovraccaricare args in modi intelligenti e coerenti all'interfaccia è un modo intelligente per essere solidi riguardo alle cose. Pertanto, la ridondanza in cottura è un sistema in cui si presume che la consegna dei pacchetti non venga regolarmente consegnata in una rete estremamente complessa posseduta e gestita da tutti in un campo tecnologico emergente con un'ampia varietà di potenziali mezzi di trasmissione.

Tollerare i fallimenti abietti, tuttavia, specialmente all'interno di un sistema che controlli, non è mai un buon compromesso. Per esempio, ho dovuto prendere una pausa per evitare di lanciarmi in un'altra domanda su come mettere JS in cima o in fondo alla pagina. Diverse persone hanno insistito sul fatto che fosse meglio mettere JS in cima perché, se la pagina non si caricava completamente, avresti comunque qualche funzionalità. Le pagine half-working sono peggiori di quelle complete. Nella migliore delle ipotesi, determinano un numero maggiore di visitatori del tuo sito presumendo che tu sia incompetente prima di scoprirlo, piuttosto che se la pagina busted up viene semplicemente rimandata a una pagina di errore in caso di mancata verifica di convalida seguita da un'e-mail automatica a qualcuno che può fare qualcosa al riguardo. Ti sentiresti a tuo agio a consegnare le informazioni della tua carta di credito a un sito che è stato per metà licenziato tutto il tempo?

Il tentativo di fornire funzionalità 2010 su un browser del 1999 quando si poteva semplicemente consegnare una pagina di tecnologia inferiore è un altro esempio di un fallito compromesso progettuale. Le opportunità esplose e il denaro che ho visto sprecare per il tempo impiegato dagli sviluppatori in soluzioni alternative corrette solo per ottenere angoli arrotondati su un elemento che si libra sopra uno sfondo sfumato! @ # $, Ad esempio, mi hanno completamente spazzato via. E per cosa? Fornire pagine tecnologicamente avanzate che offrono prestazioni scadenti a tecnici collaudati limitando nel contempo le scelte sui browser di fascia più alta.

Affinché sia la scelta giusta, la scelta di gestire l'input in maniera solida dovrebbe sempre semplificare la vita su entrambi i lati del problema, nel breve e lungo termine IMO.

    
risposta data 06.04.2012 - 03:53
fonte
1

Non fallire mai in silenzio . A parte questo, cercare di indovinare ciò che l'utente di un'API / libreria voleva, non sembra una cattiva idea. Non lo seguirò comunque; avendo un severo requisito, può esporre bug nel codice chiamante e / o interpretazioni errate sulla tua API / libreria.

Inoltre, come è stato già sottolineato, dipende da quanto sia difficile indovinare effettivamente cosa l'utente si aspettava. Se è molto semplice, hai due casi:

  1. La tua libreria dovrebbe essere progettata diversamente (rinominare alcune funzioni o dividerle in due), in modo che l'utente possa aspettarsi ciò che effettivamente fornisci.
  2. Se ritieni che la tua libreria sia progettata correttamente, il che significa denominazione chiara / diretta, puoi provare a dedurre ciò che l'utente desiderava.

In ogni caso non è ovvio e deterministico al 100% che un input debba essere convertito in un altro, non si dovrebbero fare le conversioni, per un numero di ragioni già citate (rottura della compatibilità con il refactoring, meno stupore degli utenti) .

Quando si ha a che fare con un utente finale, provare a correggere il proprio input / guess è molto gradito. È previsto per inserire informazioni non valide; questo caso è completamente non eccezionale. Tuttavia, un altro sviluppatore non è un semplice utente non tecnico. Ha l'esperienza per capire un errore e l'errore può avere un significato / essere vantaggioso per lui. Pertanto, sono d'accordo con te sulla progettazione di API rigorose, mentre, naturalmente, la severità è accompagnata da chiarezza e semplicità.

Ti consiglio di leggere questa mia domanda , di un caso simile.

    
risposta data 12.04.2016 - 10:41
fonte

Leggi altre domande sui tag