Tutti gli argomenti booleani indicano argomenti e quindi un odore di codice?

1

Martin Fowler descrive l'odore del codice Flag come un "tipo di argomento della funzione che indica alla funzione di eseguire un operazione diversa a seconda del suo valore ".

Risposte a È sbagliato usare un argomento booleano per determinare il comportamento? sembra confondere tutti gli argomenti booleani con gli argomenti flag. Penso che la domanda non esplori completamente il problema degli argomenti booleani.

Tuttavia, ho la sensazione che non tutti gli argomenti booleani siano uguali.

Un caso d'uso per argomenti booleani

Immagina un popup che mostri un messaggio che dipende in parte dalla presenza o meno di un utente. Definiremmo un metodo

show(boolean isLoggedIn)

Il metodo verrebbe chiamato in questo modo:

popup.show(session.isLoggedIn())

Mi sembra che in questo esempio la leggibilità e la coesione non siano influenzate negativamente. Inoltre, non penso che questo sia un argomento di bandiera. Non dice al metodo come esattamente comportarsi, ma trasmette le informazioni necessarie al metodo per prendere quella decisione.

Alternative

Non riesco a pensare a un modo per migliorare questo metodo utilizzando le soluzioni proposte nella discussione sopra.

Enum sarebbe simile a questo:

popup.show(session.isUserLoggedIn()
    ? Popup.ContentType.LoggedIn
    : Popup.ContentType.LoggedOut);

La divisione del metodo sarebbe simile a questa:

if (session.isUserLoggedIn()) {
    popup.showLoggedInMessage();
} else {
    popup.showLoggedOutMessage();
}

Questo sembra più lungo e porta anche alla duplicazione del codice se hanno parametri comuni:

if (session.isUserLoggedIn) {
    popup.showLoggedInMessage(commonIntro);
} else {
    popup.showLoggedOutMessage(commonIntro);
}

Secondo me, usare un argomento booleano è meglio di entrambi questi approcci.

Quindi, tutti gli argomenti booleani hanno un odore del codice o possono essere una tecnica valida?

    
posta sbichenko 29.06.2016 - 15:09
fonte

4 risposte

2

Nessuna regola è assoluta nello sviluppo del software e tutto dipende dal contesto.

Detto questo, non considererei il tuo esempio necessariamente un buon argomento per gli argomenti booleani. Un'API come show(bool isLoggedIn) non mi dice cosa accadrà senza che io legga documentazione o codice, mentre la funzionalità di show(string messageToDisplay) sarebbe piuttosto ovvia dalla firma.

Gli argomenti booleani sono un codice olfattivo? Sì. Poiché è qualcosa di "che probabilmente indica un problema più profondo" . Ciò non significa che non dovrebbero mai essere usati, solo che dovresti prendere in considerazione due volte prima di usarli.

    
risposta data 29.06.2016 - 19:02
fonte
1

Il possibile problema di avere un flag bool è che può essere facilmente abusato (e non intenzionalmente).

Consideriamo un esempio di giocattolo. Supponiamo che tu abbia un'applicazione di disegno di immagini che tutti amano, ma è solo in grado di salvare le immagini in bmp. Il CEO arriva in un giorno e dice che gli utenti vorrebbero avere anche un'opzione di salvataggio su jpeg. Ovviamente, accetti di farlo e decidi di farlo nel modo più semplice possibile - aggiungendo un flag bool al metodo SavePicture (). Perché? Beh, probabilmente perché il metodo SavePicture fa molte cose - raccoglie i valori dei pixel, legge il nome del file che l'utente ha inserito, codifica l'immagine per ottenere una matrice di byte e infine scrive tutto sul disco. 3 di 4 di queste attività di salvataggio non hanno nulla a che fare con i formati di immagine, solo la fase di codifica lo fa, quindi è molto più facile mettere un'istruzione if nel mezzo che controlla nuovamente un bool invece di refactoring del metodo. E questo va bene fino a quando il CEO non chiederà di inserire un nuovo formato PNG 3 mesi dopo.

Questo è il punto in cui il bool inizia a mordere. Anziché suddividere il codice in 4 funzioni separate in anticipo e utilizzandole laddove appropriato, è stata aumentata la complessità del metodo SavePicture (asJpeg) con ifs intrecciati. Cosa c'è di peggio, l'amministratore delegato potrebbe chiedere ad un'altra persona di implementare la nuova funzionalità, qualcuno che non ha mai visto come SavePicture si biforca. Ora, con il bool aggiunto, sarà più difficile per lui svelare la logica al refactoring, quindi probabilmente cambierà il tuo bool in enum o aggiungerà un secondo bool.

Tutto sommato, un bool di solito è un odore di odori. Se è più semplice aggiungere un bool, probabilmente è perché il metodo è lungo centinaia di righe e le parti del tuo sistema non compongono bene e non possono essere facilmente riorganizzate.

    
risposta data 23.01.2018 - 21:58
fonte
1

In primo luogo, Martin sembra distinguere tra flag, o variabili booleane che cambiano il modo in cui una funzione si comporta e le variabili booleane che vengono semplicemente impostate o passate da una funzione.

Interpreto l'argomentazione di Martin Fowler contro gli argomenti dei flag come un equilibrio tra la scrittura di due funzioni separate per ogni caso d'uso che sono essenzialmente le stesse e una funzione per due casi d'uso molto diversi. Non si desidera controllare costantemente il flag nella propria funzione o fare in modo che la stessa funzione si comporti in modo completamente diverso quando viene modificato un input flag, ma è necessario anche fare eccezioni quando la suddivisione in due funzioni comporterebbe una duplicazione non necessaria. Troppi argomenti di flag possono portare a preoccuparsi costantemente del fatto che la funzione stia gestendo correttamente tutti i suoi stati e della mancanza di chiarezza sul suo comportamento e scopo, mentre l'eliminazione degli argomenti dei flag in modo eccessivo può portare a duplicazioni inutili.

Ad esempio, se il tuo codice per show(boolean isLoggedIn) è il seguente:

if (isLoggedIn) {
    updateBar();
} else {
    updateFoo();
}

createWindow();

if (isLoggedIn) {
    addModal()
}

fillInRestOfWindow()

Quindi probabilmente dovresti dividerlo in due funzioni. Certo, il chiamante è più complicato perché ora deve includere un'istruzione if, ma hai cancellato diverse istruzioni if e rimosso la complessità dalla funzione non dovendo destreggiarsi tra più stati contemporaneamente.

Come tutti gli odori del codice, indica semplicemente un pattern, che se usato eccessivamente porterà a una programmazione soggetta a bug. Eppure l'uso giudizioso, con la consapevolezza dell'odore del codice, è ok.

    
risposta data 23.01.2018 - 21:04
fonte
1

In Clean Code di Robert Martin, vediamo che in generale quando abbiamo un valore booleano come argomento, di solito indica che il tuo metodo sta facendo più di una cosa. Con questo, voglio dire, stai andando contro il Principio di Responsabilità Unica.

Se il lavoro del tuo metodo è controllare il flag ed eseguire un'operazione in base al suo valore, allora il tuo codice dovrebbe essere considerato pulito.

Mentre pensi agli odori del codice e al codice pulito, dovresti sempre pensare ai principi SOLID. Sono una buona guida per decidere quale design o come dovrebbe essere il tuo codice.

    
risposta data 24.01.2018 - 00:51
fonte

Leggi altre domande sui tag