Quando è giustificato scrivere condizioni implicite? [duplicare]

1

Come programmatore principiante, ho iniziato a scavare solo di recente nel benchmarking e ho confrontato vari modi per realizzare lo stesso compito in termini di velocità.

Il più delle volte, il risultato è che la differenza di velocità è trascurabile o che è talmente grande che utilizzerò sicuramente l'opzione più veloce.

Questo lascia le casse nel mezzo. Se capisco correttamente dalla lettura di domande e risposte simili, il consenso degli ingegneri del software è che eventuali ottimizzazioni che comprimono la leggibilità del codice o che ti fanno perdere tempo prezioso dovrebbero essere lasciate fino a quando non hai incontrato un problema di prestazioni e identificato quale codice è il collo di bottiglia. Mi sembra del tutto ragionevole.

Tuttavia, che cosa è "leggibile" e cosa no? Ho un esempio molto concreto in mente. Dai un'occhiata a questo benchmark in JavaScript: link . Confronta l'uso del condizionamento implicito attraverso la moltiplicazione con un valore booleano con un condizionale esplicito utilizzando l'operatore ternario ? . Ora, mi è costato poco tempo o sforzo per scrivere semplicemente la versione più veloce in tutti i casi, quindi l'unica preoccupazione nella mia mente è la leggibilità.

La mia opinione dopo aver letto i commenti e amp; risposte

Non sono d'accordo con il voto di duplicazione. Capisco quanto questo sia notevolmente simile alla domanda collegata, ma si trattava principalmente della leggibilità di un condizionale implicito. Puoi rispondere alla domanda collegata con una risposta come "l'operatore ternario è molto più facile da leggere rispetto all'aggiunta di un prodotto con un valore booleano"? No, ma puoi farlo.

potrebbe - ma non è ancora stato - una risposta di fondo a entrambe le domande. Questo dovrebbe invocare l'idea di segnalazione, come fatto da parole chiave come if o funzioni quasi universali come strlen . Allontanarsi da questi metodi universali di fare qualcosa verso un metodo specifico della lingua o addirittura specifico per l'implementazione è destinato ad essere meno leggibile, costituendo quindi una micro-ottimizzazione, sulla quale il consenso è chiaro. Tuttavia, così com'è, le risposte hanno solo concluso che l'operatore ternario è più leggibile e quindi è stato unico per questa domanda. La discussione di fondo sulla micro-ottimizzazione, come ho cercato di chiarire menzionando questo nella mia domanda, non era l'argomento principale della domanda. Adatterò il testo della domanda per evidenziarlo. Quindi davvero non considero la mia domanda una duplicazione a quella collegata.

    
posta RalphD 29.09.2017 - 13:39
fonte

4 risposte

3

Credo che tu abbia risposto alla tua stessa domanda. Si afferma che è ragionevole preferire la leggibilità rispetto alle prestazioni a meno che non vi sia un problema di prestazioni. Inoltre, è implicito (implicitamente) che il metodo più veloce nell'esempio è più veloce e meno leggibile. Pertanto, utilizzare il metodo più veloce e meno leggibile se le prestazioni rappresentano un problema. Se non lo è, slow (er) 1 e leggibile è la strada da percorrere.

1 Siamo onesti. La differenza qui è piuttosto trascurabile,  soprattutto nel codice giorno per giorno. A meno che non stiate elaborando un sacco di cose, non farà la differenza. E se lo sei, beh, allora le prestazioni probabilmente contano e quindi l'uso del metodo più veloce è giustificato.

    
risposta data 29.09.2017 - 14:52
fonte
4

Spazzare la polvere sotto il tappeto

Quando hai a che fare con micro-ottimizzazioni per migliorare la velocità del tuo programma (riscrivendo le operazioni di O (1) per sovraperformare le loro controparti tradizionali), c'è qualcosa di altro che deve essere affrontato seriamente sul tuo programma più spesso. Non puoi sistemare una casa sul punto di crollare su se stessa spazzando la polvere sotto il tappeto. In altre parole, se il tuo programma è già veloce, le micro-ottimizzazioni possono migliorarlo ulteriormente, ma senza grandi vantaggi e se il tuo programma è lento, le micro-ottimizzazioni non sono il problema. Per lo meno, non dovresti essere in grado di giustificare la possibilità di rendere il tuo programma meno leggibile a scapito delle micro-ottimizzazioni a causa del piccolo vantaggio che ottieni guadagnando.

Tranne ...

Tranne che cosa? Hai appena detto che non dovresti essere in grado di giustificare la realizzazione di micro-ottimizzazioni. Sì, mentre questo è vero, ci sono casi limite quando le micro-ottimizzazioni come quando la tua piccola insignificante operazione O (1) viene avvolta in un ciclo annidato inevitabile che viene chiamato ad ogni frame di disegno. Se fate i conti, per qualcosa che potenzialmente viene chiamato 100.000 volte al secondo, ciò fa sì che la piccola operazione O (1) che impiega 1 microsecondo prenda all'improvviso un decimo di secondo. Esegui cinque operazioni come questa e la frequenza fotogrammi è scesa da 60 fotogrammi al secondo a soli 2.

Conclusione

Pertanto, se ti accorgo di ottimizzare parti del tuo codice sensibili alla velocità, cercherò di non giudicare troppo duramente. Anche se sarebbe utile ricordare che puoi sempre commentare sul tuo codice sia con la versione più leggibile di quella linea sia con una breve spiegazione di ciò che realizza. Esistono anche altri modi per accelerare il codice, ad esempio l'utilizzo di thread, se esiste un lavoro che può essere realizzato in parallelo. Semplicemente non eseguire micro-ottimizzazioni a meno che non si possa veramente giustificare tale ottimizzazione in termini di tempo risparmiato nel programma che lo esegue.

    
risposta data 29.09.2017 - 15:41
fonte
1

Tuttavia, che cosa è "leggibile" e cosa no?

Questo è molto soggettivo. La leggibilità non è un tratto binario, è uno spettro . Non possiamo chiamare in modo definitivo qualcosa (non leggibile) senza definire anche un quadro di riferimento.

Sono d'accordo che bool1 ? num1 : num2 è più leggibile di bool1 * num1 + !bool1 * num2 . È molto più facile dedurre l'intenzione del codice quando si vede un operatore ternario, rispetto a un'equazione matematica forzata che finisce per funzionare esattamente come un'istruzione if .

Sono d'accordo che gli sviluppatori dovrebbero sforzarsi di mantenere il loro codice il più leggibile possibile. Tuttavia, questo non significa che dovresti quindi usare la versione leggibile su quella performante.

Perché evitiamo codice illeggibile?

Perché non possiamo facilmente dedurre l'intenzione del codice.

Come possiamo evitare il codice illeggibile?

Qui ci sono due approcci diversi:

1. Cambia il codice

Questa è spesso la soluzione migliore, perché gli sviluppatori prima cercano di "valutare rapidamente" il codice, cioè provare a capire l'intenzione dalla sua struttura di base.
Per esempio. Quando elaboro il codice, sono in grado di individuare un blocco if/else molto tempo prima che abbia effettivamente letto quali valori vengono valutati e restituiti.

Questo vale non solo per la struttura del codice, ma anche per gli operatori che vengono utilizzati. Come ho detto prima, sono d'accordo che bool1 ? num1 : num2 è più leggibile di bool1 * num1 + !bool1 * num2 , perché l' operatore ternario rivela rapidamente che questo codice sta cercando di funzionare come un blocco if/else .

Tuttavia, se ci sono differenze di rendimento significative , in cui una variante più leggibile è notevolmente meno performante della sua controparte meno leggibile, dovremmo prendere in considerazione l'opzione 2:

2. Rendi il codice esistente più leggibile ma funzionalmente invariato .

Questo può essere fatto attraverso la ridenominazione delle variabili, ad es. trasformando c = b * a in surfaceArea = width * height o totalPrice = unitCost * unitQuantity . Questa è la stessa operazione, non può essere meno performante della sua controparte più concisa, ma è comunque considerevolmente più leggibile per uno sviluppatore.

Ma un altro modo per farlo è attraverso commentare . I commenti sono un ottimo strumento qui, perché ti consentono di aggiungere informazioni per uno sviluppatore senza influire sul flusso / sulle prestazioni del codice in fase di runtime .

res = bool1 * num1 + !bool1 * num2;
    //this is the functional equivalent of "bool1 ? num1 : num2"
    //but its performance is significantly higher

Problem solved! The code is focusing on performance, but the comments enhance the readability of an otherwise fairly unreadable code snippet.

Now we have the best of both worlds.

Quando apporto un miglioramento al mio codice in base a qualcosa che ho trovato online, probabilmente aggiungo anche l'URL:

res = bool1 * num1 + !bool1 * num2;
    //this is the functional equivalent of "bool1 ? num1 : num2"
    //but its performance is significantly higher
    //See: https://jsperf.com/cond-vs-mult

Ci sono molti link MSDN / StackOverflow nel mio codice (o riferimenti ad esempio all'analisi funzionale), semplicemente perché è il modo più semplice per fornire informazioni senza dover scrivere tutto nei commenti.

    
risposta data 29.09.2017 - 14:22
fonte
0

La tua domanda non avrà una risposta concreta, perché la "leggibilità" è basata su uno stile individuale. Per me personalmente, userei il ternario nell'istanza che hai evidenziato sopra semplicemente perché bool1 è un booleano e mi piace usarlo in un test vero / falso e moltiplicarlo. se il nome della variabile non fosse così descrittivo come hai fatto nel tuo esempio, diciamo che un programmatore pigro lo ha appena chiamato "a", quindi supponevo che stavo moltiplicando due numeri e avrei dovuto cercare ulteriormente nel codice per vedere che in effetti è un booleano. Ma sono solo io.

    
risposta data 29.09.2017 - 14:01
fonte

Leggi altre domande sui tag