È più semplice leggere e conservare il codice usando i caratteri "!", o implicando "Not" nel nome del metodo?

0

Spesso lo trovo "!" i personaggi (che significano "non" nelle lingue basate su C) sono facili da trascurare. Quindi a volte creo metodi che restituiscono il risultato inverso.

Ad esempio, invece di fare questo:

if (!dataContext.Permissions.HasAccessToFeature("FeatureX")) { ... }

... Creo un secondo metodo che è l'inverso dell'altro, facendo leggere il codice come segue:

if (dataContext.Permissions.DeniedAccessToFeature("FeatureX")) { ... }

Sento che questo rende il codice più leggibile, ma mi chiedo se gli altri sono d'accordo?

    
posta willem 21.06.2016 - 14:44
fonte

6 risposte

10

Penso che la seconda variante potrebbe portare a più confusione. true dovrebbe comportare risultati positivi e false un risultato negativo. La domanda in linguaggio naturale è di solito "Sei autorizzato ad accedere alla funzione?", Non "Non sei autorizzato ad accedere alla funzione?".

La risposta è anche coerente - "Sì, hai il permesso di accedere alla funzione" vs "Sì, non ti è permesso accedere alla funzione".

Che cosa succede nel tuo secondo caso quando vuoi verificare il risultato opposto, in cui un utente ha accesso alla funzione?

if (!dataContext.Permissions.DeniedAccessToFeature("FeatureX"))

Se l'operatore ! ti confonde davvero tanto, perché non lo fai semplicemente

if (dataContext.Permissions.HasAccessToFeature("FeatureX") == false)

Riguardo a una parte della tua domanda:

...I create a second method that is the inverse of the other

A livello meta, pensi davvero che sia saggio avere due metodi diversi che eseguono lo stesso compito? Cosa succede se la logica deve cambiare, ma viene aggiornato solo un metodo perché il metodo inverso viene utilizzato solo in alcuni punti?

    
risposta data 21.06.2016 - 14:55
fonte
9

Consideriamo sia il problema generale che il problema specifico.

In generale il consiglio è di solito di evitare i negativi nei nomi. Il motivo è: si nota che può essere fonte di confusione negare una cosa; beh, a volte devi negare una cosa, ed è molto che confonde per negare un negativo:

if (!product.NotTaxable) ...

Yuck.

Nel caso specifico menzionate c'è un consiglio specifico. La tua proposta presenta problemi di usabilità con implicazioni sulla sicurezza, in almeno due modi.

In primo luogo, nella maggior parte dei sistemi di sicurezza si desidera eseguire il default sulla modalità sicura, non sulla modalità non protetta. Cioè, tu dici "l'accesso è disabilitato di default, avere un'autorizzazione concessa è speciale e consente l'accesso". Non si dice "l'accesso è consentito per impostazione predefinita, l'autorizzazione negata è speciale e non consente l'accesso". Quindi vuoi progettare il tuo codice allo stesso modo, per enfatizzare questo.

In secondo luogo, molti sistemi di sicurezza non hanno una relazione "binaria" tra "concesso" e "negato". Cioè, solo perché un permesso particolare è concesso, non implica che non sia negato!

Immaginate per esempio un sistema di permessi che concede l'accesso alla risorsa al gruppo contabile, ma nega l'accesso ai dipendenti in vacanza. Bob è un contabile in vacanza; gli è concesso accesso e accesso non consentito, e ora devi decidere quale vincerà. Anche in questo caso, probabilmente si desidera impostare la modalità protetta in modo predefinito e non consentire l'accesso.

Oppure immagina un sistema di permessi in cui ci sono tre tipi di regole: alcuni concedono l'accesso, il periodo, alcuni negano l'accesso, il periodo e alcuni dicono "Non si applicano a questa situazione". Si crea un elenco di regole prioritarie e lo si scarica finché non si ottiene il primo sussidio, nel qual caso si è terminato, o il primo si nega, nel qual caso si è terminato. Anche qui abbiamo la proprietà che "non concesso" e "negato" sono molto diversi.

La cosa importante non è se stai evitando! s, ma piuttosto che le tue API esprimono in modo molto chiaro e corretto la logica del dominio aziendale. Questa è la vera preoccupazione per la leggibilità.

    
risposta data 21.06.2016 - 15:42
fonte
3

Secondo lo zio Bob

Negatives are just a bit harder to understand than positives. So, when possible, conditionals should be expressed as positives.
For example:
if (buffer.shouldCompact()) is preferable to if (!buffer.shouldNotCompact())

Da Clean Code Chapter 17, Item G29 "Evita condizionali negativi"

Quindi il tuo primo esempio è preferibile.

Tuttavia, lui stesso non fornisce una spiegazione, ma sono completamente d'accordo con lui qui.

    
risposta data 21.06.2016 - 16:10
fonte
1

Non vorrei creare una funzione al solo scopo di rinominare un operatore ! perché è un disastro completo quando si tratta di minimalismo dell'interfaccia e manutenzione del codice con due convenzioni diverse, ma se si ha la possibilità di scegliere dall'inizio, fare funziona nel modo più ovvio da usare. Per me, sarebbe utilizzare il secondo modulo (e solo questo), perché molto probabilmente utilizzerai ripetutamente if (PermDenied(feature)) throw ... e quasi mai dovrai negarlo.

Di nuovo, questo è solo seguendo il mio zen di combattere contro la lunghezza e gli operatori inutili; ma la denominazione dettagliata con logica semplice può essere migliore della logica dettagliata con semplice denominazione.

    
risposta data 21.06.2016 - 15:08
fonte
1

Se controlli se l'accesso è negato, non c'è molta differenza tra "! hasAccess" e "deniedAccess".

Tuttavia, se controlli di avere accesso , c'è un'enorme differenza nella leggibilità tra "hasAccess" e "! deniedAccess". È necessario prendere in considerazione entrambi i casi quando si decide come denominare un metodo o una proprietà.

    
risposta data 21.06.2016 - 22:08
fonte
1

Come altri hanno già detto, il consiglio è di evitare i negativi mentre si nomina un metodo. Dovrebbe essere facile da seguire in qualsiasi tipo di linguaggio.

Ma mi piacerebbe entrare nel "!" domanda. Hai detto che è facile trascurare e sono d'accordo e in disaccordo allo stesso tempo. Penso che per le persone nuove in C # che non sono abituate a questo tipo di sintassi si , è facile trascurare. Per le persone abituate a C # o questo tipo di sintassi, la prima cosa che noteranno è esattamente la presenza o l'assenza del "!".

Ho sviluppato C # da molti anni e non ci ho mai pensato molto fino a quando non ho letto la tua domanda e ho notato che ho immediatamente cercato l'inizio della condizione per vedere se il "!" era lì.

Il mio consiglio è di usare "!", perché a mio parere, la maggior parte degli sviluppatori di C # sono abituati. Ma alla fine ciò che conta davvero è che tu e il tuo team concordiate se dovreste usarlo o meno ed essere coerenti con tutto il codice sorgente.

    
risposta data 22.06.2016 - 00:32
fonte

Leggi altre domande sui tag