Va sempre bene che un condizionale abbia degli effetti collaterali? [chiuso]

10

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

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

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

In effetti, non ho mai visto un condizionale con effetti collaterali e Googling non si presenta molto. Un altro studente è rimasto indietro dopo le lezioni per chiederglielo, quindi non sono l'unico a pensare che fosse strano. Ma il professore era piuttosto irremovibile sul fatto che fosse un codice accettabile e che avrebbe scritto qualcosa del genere al lavoro. (Il suo incarico con FT è come SWE principale presso una società di cui hai sentito parlare.)

Non riesco a immaginare un mondo in cui questa linea di codice sarebbe mai accettabile, per non dire desiderabile. Ho sbagliato? Va bene? Che dire del caso più generale: condizionali con effetti collaterali? Sono sempre OK?

    
posta rianjs 10.09.2014 - 04:45
fonte

4 risposte

23

C'è un effetto collaterale semi-condizionale uno posso pensare che sia okay: while(iter.MoveNext())

Detto questo, penso che questo rientri principalmente nella categoria " mai è una categoria molto grande". Posso pensare ad alcuni casi rari in cui l'ho visto accettabile, ma in generale questo è vile e da evitare.

Non riesco nemmeno a pensare a uno scenario in cui quella particolare riga sarebbe accettabile, ma non riesco nemmeno a pensare a uno scenario in cui quella particolare riga sarebbe utile , quindi è difficile immaginare il contesto è in.

    
risposta data 10.09.2014 - 05:07
fonte
8

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

Ora, considera quanto segue:

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

E confronta:

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

Evitare l'effetto collaterale (la lettura) nelle condizioni aiuta a migliorare la leggibilità; o ha appena duplicato il codice e aggiunto ingombri?

Non è corretto che una condizione abbia effetti collaterali (se questo rende il codice meno leggibile) ed è anche OK se una condizione ha effetti collaterali (se questo rende il codice più leggibile). Il fattore chiave è la "leggibilità". Tutto il resto sono regole create dagli sciocchi in un tentativo errato di migliorare la leggibilità (mentre spesso ha l'effetto opposto).

    
risposta data 10.09.2014 - 10:20
fonte
3

Come sempre con tali domande, questa è una questione di laurea. Se ci fosse una prova inequivocabile che qualsiasi effetto collaterale all'interno di un'espressione if sempre ha portato a un codice peggiore, allora non sarebbe legale creare tali espressioni. I progettisti di linguaggi possono essere uomini ideosincratici e fallibili, ma non sono che stupidi.

Detto questo, quali sono gli esempi di effetti collaterali giustificati in un if ? Ad esempio, supponiamo di essere legalmente obbligato a registrare tutti gli accessi alla proprietà P di un'entità E a fini di controllo. (Immagina di lavorare in un impianto di arricchimento dell'uranio e ci sono controlli legali molto severi su cosa il tuo codice è autorizzato a fare e su come dovrebbe farlo.) Quindi qualsiasi if che controlla quella proprietà causerà il lato effetto del registro di controllo esteso.

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

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

    
risposta data 10.09.2014 - 08:20
fonte
2

Sebbene sia un codice molto 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 al seguente (ma attenzione! questo ha un comportamento diverso in caso di overflow!): b++; if (a > 33 | b < 53) {...}

    
risposta data 11.09.2014 - 09:34
fonte

Leggi altre domande sui tag