È mai accettabile che un condizionale abbia effetti collaterali? [chiuso]


10

Sto seguendo un corso intermedio sulle strutture di dati come prerequisito per l'ingresso nel programma CS MS in un'università di cui tutti in America hanno sentito parlare. Una riga di codice scritta in classe attirò la mia attenzione:

if (a > 33 | b++ < 54) {...}

Questo non passerebbe una revisione del codice sul mio posto di lavoro. Se hai scritto codice come questo in un'intervista, questo sarebbe uno sciopero significativo contro di te. (Oltre ad essere un condizionale con effetti collaterali, è intelligente a scapito della chiarezza.)

In realtà, non ho mai visto un condizionale con effetti collaterali e anche Google non si presenta molto. Anche un altro studente è rimasto indietro dopo le lezioni per chiederlo, quindi non sono l'unico a pensare che questo sia strano. Ma il professore era piuttosto irremovibile che questo era un codice accettabile e che avrebbe scritto qualcosa del genere al lavoro. (Il suo lavoro in FT è di SWE principale presso un'azienda di cui tutti avete sentito parlare.)

Non riesco a immaginare un mondo in cui questa linea di codice sia mai accettabile, tanto meno desiderabile. Ho sbagliato? Va bene? Che dire del caso più generale: i condizionali con effetti collaterali? Sono mai a posto?


7
Quella linea dovrebbe essere eliminata dall'orbita. Due volte per buona misura.
Blrfl,

8
Un nit: un singolo tubo (barra verticale) è un bit per bit o nella maggior parte delle lingue, piuttosto che un "o" logico. Non cortocircuita se il lato sinistro è vero. Dal momento che questo condizionale ha effetti collaterali sul lato destro, fa una differenza particolarmente grande nel risultato.
Jonathan Eunice,

2
Esistono modi di dire usati in varie lingue che rientrerebbero in questa categoria, ma poiché sono "ben noti" o "normali" non causano problemi. La linea nella domanda non sembra rientrare nella categoria dell'uso idiomatico, quindi la eviterei.
Jaydee,

2
@JonathanEunice, sì, alcune persone erano confuse sulla valutazione del corto circuito. Non è un errore di battitura da parte mia.
rianjs,

5
Guarda il lato positivo. Ora conosci un'altra società in cui NON vuoi intervistare.
John R. Strohm,

Risposte:


23

C'è un effetto collaterale semi-condizionale a cui riesco a pensare che va bene:while(iter.MoveNext())

Detto questo, penso che questo rientri principalmente nella categoria " non è mai un grande qualificatore". Mi vengono in mente alcuni rari casi in cui l'ho visto accettabile, ma in generale questo è vile e da evitare.

Inoltre non riesco a pensare a uno scenario in cui quella particolare linea sarebbe accettabile, ma non riesco nemmeno a pensare a uno scenario in cui quella particolare linea sarebbe utile , quindi è difficile immaginare il contesto in cui si trova.


Era solo una linea di lancio in un metodo durante la lezione. Non intendeva fare nulla di utile.
rianjs,

4
Allo stesso modo, le while(v = *p++)scansioni di stile C / C ++ attraverso un array con terminazione zero (ad es. Stringa C) sono piuttosto comuni e ampiamente accettate.
Phil Miller,

3
Ho spesso considerato i condizionali ad anello della forma while(c = input.read() != '\n')ragionevolmente idiomatici.

1
Potrebbero esserci alcuni modi di dire accettabili comuni, ma chiaramente "essere intelligenti a scapito della chiarezza" rientra nel campo MAI.
Julia Hayward,

Mi sono completamente dimenticato di iter.MoveNext (). Un caso del tutto ragionevole per un condizionale che ha un effetto collaterale. Grazie!
rianjs,

8

Nel mio mondo, una lettura dalla memoria può essere considerata un effetto collaterale (ad es. IO mappato in memoria).

Ora, considera quanto segue:

    while( ( *memory_mapped_device_status_register & READY_FLAG) == 0) {
       // Wait
    }

E confronta con:

    status = *memory_mapped_device_status_register;
    while( ( status & READY_FLAG) == 0) {
        // Wait
        status = *memory_mapped_device_status_register;
    }

Evitare l'effetto collaterale (la lettura) nella condizione aiuta la leggibilità; o ha semplicemente duplicato il codice e aggiunto disordine?

Non è OK che una condizione abbia effetti collaterali (se ciò rende il codice meno leggibile) ed è anche OK che una condizione abbia effetti collaterali (se ciò rende il codice più leggibile). Il fattore chiave è la "leggibilità". Tutto il resto sono regole create dagli sciocchi nel tentativo sbagliato di migliorare la leggibilità (pur avendo spesso l'effetto opposto).


3

Come sempre con tali domande, questa è una questione di laurea. Se ci fosse una prova inequivocabile che qualsiasi effetto collaterale all'interno di ifun'espressione portava sempre a un codice peggiore, allora non sarebbe legale creare quelle espressioni. I progettisti linguistici possono essere umani ideosincratici e fallibili, ma non sono così stupidi.

Detto questo, quali sono gli esempi di effetti collaterali giustificati all'interno di un if? Ad esempio, supponiamo che tu sia legalmente tenuto a registrare tutti e tutti gli accessi alla proprietà Pdi un'entità Ea fini di audit. (Immagina di lavorare in un impianto di arricchimento dell'uranio e che ci sono controlli legali molto severi su ciò che il tuo codice è autorizzato a fare e su come dovrebbe farlo.) Quindi chiunque ifcontrolli quella proprietà causerà l'effetto collaterale del registro di controllo in fase di estensione.

Questa è una preoccupazione trasversale piuttosto chiara, non influisce sul tuo ragionamento sullo stato del programma (molto) e puoi implementarlo in modo che sia completamente invisibile e non distratto quando rivedi la linea con if(nascosto via nell'accessorio, o ancora meglio via AOP). Direi che è un caso abbastanza chiaro di un effetto collaterale che non è un problema. Situazioni simili potrebbero essere immaginate quando si desidera solo contare le esecuzioni di rami per scopi di profilazione, ecc.

Più queste circostanze attenuanti scompaiono, più estraneo diventerà il costrutto. Se un particolare tipo di loop (ad esempio if((c = getc()) == 'x') { quit(); }è ben noto e accettato dalla comunità linguistica, allora è un problema molto meno grave rispetto a quando lo inventi spontaneamente, ecc. La tua riga di esempio non è all'altezza di quello standard, ma potrei immaginare molto, molto quelli più orribili che non scriverò nemmeno, sono così orribili.


2

Sebbene sia un codice davvero puzzolente, ha il vantaggio di essere più semplice (e forse più veloce se non si dispone di un buon compilatore di ottimizzazione) rispetto all'equivalente if (a > 33 | b < 54) {b++; ...} else b++;

ma ovviamente è possibile ottimizzarlo come segue (ma attenzione! questo ha un comportamento diverso in caso di overflow!): b++; if (a > 33 | b < 53) {...}

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.