A che punto la brevità non è più una virtù?


102

Una recente correzione di bug mi ha richiesto di esaminare il codice scritto da altri membri del team, dove l'ho trovato (è C #):

return (decimal)CostIn > 0 && CostOut > 0 ? (((decimal)CostOut - (decimal)CostIn) / (decimal)CostOut) * 100 : 0;

Ora, ammesso che ci sia una buona ragione per tutti quei cast, questo sembra ancora molto difficile da seguire. Si è verificato un errore minore nel calcolo e ho dovuto districarlo per risolvere il problema.

Conosco lo stile di codifica di questa persona dalla revisione del codice e il suo approccio è che il più breve è quasi sempre meglio. E ovviamente c'è valore lì: abbiamo visto tutti catene di logica condizionale inutilmente complesse che potrebbero essere riordinate con pochi operatori ben posizionati. Ma è chiaramente più abile di me nel seguire catene di operatori stipate in un'unica affermazione.

Questo è, ovviamente, in definitiva una questione di stile. Ma qualcosa è stato scritto o studiato per riconoscere il punto in cui la ricerca della brevità del codice smette di essere utile e diventa una barriera alla comprensione?

Il motivo del cast è Entity Framework. Il db deve memorizzarli come tipi nullable. Decimale? non è equivalente a Decimale in C # e deve essere lanciato.


153
Quando la brevità supera la leggibilità.
Robert Harvey,

27
Guardando il tuo esempio specifico: un cast è (1) un luogo in cui lo sviluppatore conosce più del compilatore e deve dire al compilatore un fatto che non può essere dedotto, oppure (2) in cui alcuni dati vengono archiviati in "errato "digita per i tipi di operazioni che dobbiamo eseguire su di esso. Entrambi sono forti indicatori del fatto che qualcosa potrebbe essere riformulato. La soluzione migliore qui è trovare un modo per scrivere il codice senza cast.
Eric Lippert,

29
In particolare, sembra strano che sia necessario eseguire il cast di CostIn in decimale per confrontarlo con zero, ma non CostOut; perché? Cosa c'è sulla terra è il tipo di CostIn che può essere paragonato a zero solo lanciandolo in decimale? E perché CostOut non è dello stesso tipo di CostIn?
Eric Lippert,

12
Inoltre, la logica qui potrebbe effettivamente essere errata. Supponiamo che CostOutsia uguale a Double.Epsilon, e quindi sia maggiore di zero. Ma (decimal)CostOutè in questo caso zero e abbiamo una divisione per zero errori. Il primo passo dovrebbe essere quello di ottenere il codice corretto , che penso non lo sia. Ottenerlo corretto, creare casi di test e quindi renderlo elegante . Codice elegante e codice breve hanno molto in comune, ma a volte la brevità non è l'anima dell'eleganza.
Eric Lippert,

5
La brevità è sempre una virtù. Ma la nostra funzione oggettiva combina la brevità con altre virtù. Se si può essere più brevi senza danneggiare altre virtù, si dovrebbe sempre.
Solomonoff's Secret

Risposte:


163

Per rispondere alla tua domanda sulla ricerca esistente

Ma qualcosa è stato scritto o studiato per riconoscere il punto in cui la ricerca della brevità del codice smette di essere utile e diventa una barriera alla comprensione?

Sì, c'è stato lavoro in questo settore.

Per capire queste cose, devi trovare un modo per calcolare una metrica in modo che i confronti possano essere fatti su base quantitativa (piuttosto che semplicemente eseguire il confronto basato su arguzia e intuizione, come fanno le altre risposte). Una potenziale metrica che è stata esaminata è

Complessità ciclomatica ÷ Linee di codice sorgente ( SLOC )

Nel tuo esempio di codice, questo rapporto è molto alto, perché tutto è stato compresso su una riga.

Il SATC ha riscontrato che la valutazione più efficace è una combinazione di dimensioni e complessità [ciclomatica]. I moduli con elevata complessità e grandi dimensioni tendono ad avere la più bassa affidabilità. I moduli con dimensioni ridotte e alta complessità sono anche un rischio di affidabilità perché tendono ad essere un codice molto conciso, che è difficile da cambiare o modificare.

collegamento

Ecco alcuni riferimenti se sei interessato:

McCabe, T. e A. Watson (1994), Software Complexity (CrossTalk: The Journal of Defense Software Engineering).

Watson, AH e McCabe, TJ (1996). Test strutturati: una metodologia di test che utilizza la metrica della complessità ciclomatica (pubblicazione speciale NIST 500-235). Estratto il 14 maggio 2011 dal sito Web McCabe Software: http://www.mccabe.com/pdf/mccabe-nist235r.pdf

Rosenberg, L., Hammer, T., Shaw, J. (1998). Metriche e affidabilità del software (Atti del Simposio internazionale IEEE sull'ingegneria dell'affidabilità del software). Estratto il 14 maggio 2011 dal sito web della Penn State University: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.4041&rep=rep1&type=pdf

La mia opinione e soluzione

Personalmente, non ho mai apprezzato la brevità, solo la leggibilità. A volte la brevità aiuta la leggibilità, a volte no. Ciò che è più importante è che stai scrivendo il codice davvero evidente (ROC) anziché il codice di sola scrittura (WOC).

Solo per divertimento, ecco come lo scriverei e chiedere ai membri del mio team di scriverlo:

if ((costIn <= 0) || (costOut <= 0)) return 0;
decimal changeAmount = costOut - costIn;
decimal changePercent = changeAmount / costOut * 100;
return changePercent;

Nota anche l'introduzione delle variabili di lavoro ha il felice effetto collaterale di innescare l'aritmetica in virgola fissa anziché l'aritmetica intera, quindi decimalviene eliminata la necessità di tutti quei cast .


4
Mi piace molto la clausola di guardia per il caso inferiore a zero. Potrebbe essere degno di un commento: come può un costo essere inferiore a zero, che caso speciale è quello?
user949300

22
+1. Probabilmente aggiungerei qualcosa del tipoif ((costIn < 0) || (costOut < 0)) throw new Exception("costs must not be negative");
Doc Brown,

13
@DocBrown: è un buon suggerimento, ma vorrei considerare se un test di codice eccezionale può essere esercitato. Se sì, allora scrivi un test case che esercita quel percorso di codice. Se no, allora cambia il tutto in un Assert.
Eric Lippert,

12
Sebbene questi siano tutti aspetti positivi, credo che lo scopo di questa domanda sia lo stile del codice, non la logica. Il mio codice snip è uno sforzo di equivalenza funzionale dal punto di vista della scatola nera. Generare un'eccezione non equivale a restituire 0, quindi quella soluzione non sarebbe funzionalmente equivalente.
John Wu,

30
"Personalmente, non ho mai apprezzato la brevità, solo la leggibilità. A volte la brevità aiuta la leggibilità, a volte no." Punto eccellente . +1 solo per quello. Mi piace anche la tua soluzione di codice.
Wildcard il

49

La brevità è buona quando riduce il disordine attorno alle cose che contano, ma quando diventa concisa , impacchettando troppi dati rilevanti troppo densamente per seguirli facilmente, allora i dati rilevanti diventano disordinati e si ha un problema.

In questo caso particolare, i cast da decimalripetere vengono ripetuti più volte; sarebbe probabilmente meglio nel complesso riscriverlo come qualcosa del tipo:

var decIn = (decimal)CostIn;
var decOut = (decimal)CostOut;
return decIn > 0 && CostOut > 0 ? (decOut - decIn ) / decOut * 100 : 0;
//                  ^ as in the question

Improvvisamente la linea che contiene la logica è molto più corta e si adatta su una linea orizzontale, quindi puoi vedere tutto senza dover scorrere, e il significato è molto più evidente.


1
Probabilmente sarei andato più lontano e refactored ((decOut - decIn ) / decOut) * 100su un'altra variabile.
FrustratedWithFormsDesigner

9
L'assemblatore era molto più chiaro: una sola operazione per riga. Doh!

2
@FrustratedWithFormsDesigner Vorrei fare un ulteriore passo avanti e racchiudere il controllo condizionale tra parentesi.
Chris Cirefice,

1
@FrustratedWithFormsDesigner: l'estrazione di questo prima del condizionale ignorerebbe il controllo divison-by-zero ( CostOut > 0), quindi dovresti espandere il condizionale in uno ifstato. Non che ci sia qualcosa di sbagliato in questo, ma aggiunge più verbosità della semplice introduzione di un locale.
wchargin,

1
A dire il vero, solo sbarazzarsi delle caste sembra che tu abbia trasmesso abbastanza IMO, se qualcuno trova difficile da leggere perché non riesce a riconoscere un semplice calcolo della frequenza di base, questo è il suo problema, non il mio.
Walfrat,

7

Anche se non posso citare alcuna ricerca particolare sull'argomento, suggerirei che tutti quei cast nel tuo codice violino il principio Non ripetere te stesso. Ciò che il codice sembra tentare di fare è convertire il costIne costOutin digitare Decimal, quindi eseguire alcuni controlli di integrità sui risultati di tali conversioni e l'esecuzione di ulteriori operazioni su quei valori convertiti se i controlli passano. In effetti, il codice esegue uno dei controlli di integrità su un valore non convertito, aumentando la possibilità che costOut possa contenere un valore maggiore di zero, ma inferiore alla metà della dimensione del minimo diverso da zero che Decimalpuò rappresentare. Il codice sarebbe molto più chiaro se definisse variabili di tipo Decimalper contenere i valori convertiti e quindi agisse su quelli.

Sembra curioso che tu sia più interessato al rapporto tra le Decimalrappresentazioni di costIne costOutrispetto al rapporto tra i valori effettivi di costIne costOut, a meno che il codice non utilizzi anche le rappresentazioni decimali per qualche altro scopo. Se il codice farà ulteriore uso di quelle rappresentazioni, questo sarebbe un ulteriore argomento per creare variabili per contenere quelle rappresentazioni, piuttosto che avere una sequenza continua di cast in tutto il codice.


I cast (decimali) devono probabilmente soddisfare alcuni requisiti delle regole aziendali. Quando hai a che fare con i contabili a volte devi saltare attraverso stupidi cerchi. Pensavo che il CFO avrebbe avuto un attacco di cuore quando ha scoperto che la linea "Usa correzione di arrotondamenti fiscali - $ 0,01" era inevitabile data la funzionalità richiesta. (Fornito: prezzo al netto delle imposte. Devo calcolare il prezzo al lordo delle imposte. Le probabilità che non ci sia risposta è uguale all'aliquota fiscale.)
Loren Pechtel,

@LorenPechtel: Dato che la precisione con cui un Decimalcast ruoterà dipende dalla grandezza del valore in questione, trovo difficile immaginare regole commerciali che richiederebbero il modo in cui i cast si comporteranno.
supercat

1
Un buon punto: avevo dimenticato i dettagli del tipo decimale perché non ho mai avuto occasione di desiderare qualcosa del genere. Ora penso che questa sia l'obbedienza del culto del carico alle regole aziendali - in particolare, il denaro non deve essere in virgola mobile.
Loren Pechtel,

1
@LorenPechtel: per chiarire il mio ultimo punto: un tipo a virgola fissa può garantire che x + yy traboccerà o genererà y. Il Decimaltipo non lo fa. Il valore 1.0d / 3.0 avrà più cifre a destra del decimale di quante possano essere mantenute quando si usano numeri più grandi. Quindi l'aggiunta e la sottrazione dello stesso numero maggiore causerà una perdita di precisione. I tipi a virgola fissa possono perdere precisione con la moltiplicazione o divisione frazionaria, ma non con addizione, sottrazione, moltiplicazione o divisione con resto (ad esempio 1.00 / 7 è 0.14 resto 0.2; 1.00 div 0.15 è 6 resto 0.10).
supercat

1
@Hulk: Sì, certo. Stavo discutendo se usare x + yy cedendo x, x + yx cedendo y, o x + yxy, e alla fine ho finito per fare i primi due. L'importante è che i tipi a virgola fissa possano garantire che molte sequenze di operazioni non causino mai errori di arrotondamento non rilevati di qualsiasi entità. Se il codice aggiunge elementi in modi diversi per verificare che i totali corrispondano (ad esempio confrontando la somma dei subtotali di riga con la somma dei subtotali di colonna), avere risultati esattamente uguali è molto meglio che farli uscire "vicini".
supercat

5

Guardo quel codice e chiedo "come può un costo essere 0 (o meno)?". Quale caso speciale indica? Il codice dovrebbe essere

bool BothCostsAreValidProducts = (CostIn > 0) && (CostOut > 0);
if (!BothCostsAreValidProducts)
  return NO_PROFIT;
else {
   // that calculation here...
}

Sto indovinando i nomi qui: cambia BothCostsAreValidProductse NO_PROFITcome appropriato.


Certo, i costi possono essere zero (pensa ai regali di Natale). E in tempi di tassi di interesse negativi i costi negativi non dovrebbero essere neanche troppo sorprendenti e almeno il codice dovrebbe essere preparato per affrontarlo (ed essere lanciando errori)
Hagen von Eitzen,

Sei sulla strada giusta.
danny117,

È sciocco. if (CostIn <= 0 || CostOut <= 0)va completamente bene.
Miles Rout,

Molto meno leggibile. Il nome della variabile è orribile (BothCostsAreValid sarebbe meglio. Non c'è nulla qui sui prodotti). Ma anche questo non aggiunge nulla alla leggibilità, perché solo controllando CostIn, CostOut va bene. Inseriresti una variabile aggiuntiva con un nome significativo se il significato dell'espressione che viene testato non è ovvio.
gnasher729,

5

La brevità smette di essere una virtù quando dimentichiamo che è un mezzo per un fine piuttosto che una virtù in sé. Ci piace la brevità perché si correla con la semplicità e ci piace la semplicità perché il codice più semplice è più facile da capire e più facile da modificare e contiene meno bug. Alla fine vogliamo che il codice raggiunga questi obiettivi:

  1. Soddisfa i requisiti aziendali con la minima quantità di lavoro

  2. Evita i bug

  3. Consentiteci di apportare modifiche in futuro che continuano a soddisfare 1 e 2

Questi sono gli obiettivi. Qualsiasi principio o metodo di progettazione (che si tratti di KISS, YAGNI, TDD, SOLID, prove, sistemi di tipi, metaprogrammazione dinamica ecc.) È virtuoso solo nella misura in cui ci aiutano a raggiungere questi obiettivi.

La linea in questione sembra aver perso di vista l'obiettivo finale. Mentre è breve, non è semplice. In realtà contiene ridondanza inutile ripetendo la stessa operazione di fusione più volte. La ripetizione del codice aumenta la complessità e la probabilità di bug. La miscelazione del casting con il calcolo effettivo rende anche il codice difficile da seguire.

La linea ha tre preoccupazioni: Guardie (involucro speciale 0), tipo casting e calcolo. Ogni preoccupazione è piuttosto semplice se presa in isolamento, ma poiché è stata mescolata tutta nella stessa espressione, diventa difficile seguirla.

Non è chiaro il motivo per cui CostOutnon viene lanciato la prima volta che viene usato mentre lo CostInè. Potrebbe esserci una buona ragione, ma l'intenzione non è chiara (almeno non senza contesto), il che significa che un manutentore starebbe attento a cambiare questo codice perché potrebbero esserci delle ipotesi nascoste. E questo è un anatema per la manutenibilità.

Dato che CostInviene lanciato prima del confronto con 0, suppongo che sia un valore in virgola mobile. (Se fosse un int non ci sarebbe motivo di lanciare). Ma se CostOutè un float, il codice potrebbe nascondere un oscuro bug di divisione per zero, dal momento che un valore in virgola mobile potrebbe essere piccolo ma diverso da zero, ma zero se impostato su un valore decimale (almeno credo che ciò sia possibile).

Quindi il problema non è la brevità o la mancanza di esso, il problema è la logica e la conflazione ripetute delle preoccupazioni che portano a un codice difficile da mantenere.

L'introduzione di variabili per contenere i valori espressi aumenterebbe probabilmente la dimensione del codice conteggiato in numero di toke, ma ridurrà la complessità, separa le preoccupazioni e migliora la chiarezza, il che ci avvicina all'obiettivo del codice che è più facile da capire e mantenere.


1
Un punto importante: lanciare CostIn una volta anziché due lo rende illeggibile, perché il lettore non ha idea se si tratta di un bug sottile con una correzione ovvia o se ciò viene fatto intenzionalmente. Chiaramente se non posso dire con certezza cosa intendesse lo scrittore con una frase, allora non è leggibile. Dovrebbero esserci due cast o un commento che spiega perché il primo utilizzo di CostIn non richiede o non dovrebbe avere un cast.
gnasher729,

3

La brevità non è affatto una virtù. La leggibilità è LA virtù.

La brevità può essere uno strumento per raggiungere la virtù o, come nel tuo esempio, può essere uno strumento per ottenere qualcosa di esattamente opposto. In un modo o nell'altro, non ha quasi alcun valore. La regola secondo cui il codice dovrebbe essere "il più breve possibile" può essere sostituita con "il più osceno possibile" altrettanto bene - sono tutti ugualmente insignificanti e potenzialmente dannosi se non servono a uno scopo più grande.

Inoltre, il codice che hai pubblicato non segue nemmeno la regola della brevità. Erano le costanti essere dichiarato con il suffisso M, la maggior parte delle orribili (decimal)calchi potrebbero essere evitati, come il compilatore promuoverebbe rimanendo inta decimal. Credo che la persona che stai descrivendo stia semplicemente usando la brevità come scusa. Molto probabilmente non deliberatamente, ma comunque.


2

Nei miei anni di esperienza, sono arrivato a credere che la massima brevità sia quella del tempo - il tempo domina tutto il resto. Ciò include sia il tempo di esecuzione - quanto tempo impiega un programma a svolgere un lavoro - sia il tempo di manutenzione - quanto tempo impiega per aggiungere funzionalità o correggere bug. (Il modo in cui bilanci questi due dipende dalla frequenza con cui il codice in questione viene eseguito rispetto al miglioramento - ricorda che l'ottimizzazione prematura è ancora la radice di tutti i mali .) La brevità del codice è al fine di migliorare la brevità di entrambi; il codice più corto di solito viene eseguito più velocemente ed è generalmente più facile da capire e quindi da mantenere. Se neanche lo fa, allora è un netto negativo.

Nel caso mostrato qui, penso che la brevità del testo sia stata erroneamente interpretata come brevità del conteggio delle righe, a scapito della leggibilità, che può aumentare i tempi di manutenzione. (Potrebbe anche richiedere più tempo, a seconda di come viene eseguito il casting, ma a meno che la riga sopra non venga eseguita milioni di volte, probabilmente non è un problema.) In questo caso, i cast decimali ripetitivi riducono la leggibilità, poiché è più difficile guarda qual è il calcolo più importante. Avrei scritto come segue:

decimal dIn = (decimal)CostIn;
decimal dOut = (decimal)CostOut;
return dIn > 0 && CostOut > 0 ? ((dOut - dIn) / dOut) * 100 : 0;

(Modifica: questo è lo stesso codice dell'altra risposta, quindi eccoti.)

Sono un fan dell'operatore ternario ? :, quindi lo lascerei entrare.


5
I ternari sono difficili da leggere, in particolare se ci sono espressioni oltre un singolo valore o variabile nei valori di ritorno.
Almo,

Mi chiedo se questo è ciò che guida i voti negativi. Tranne quello che ho scritto è molto d'accordo con Mason Wheeler, attualmente con 10 voti. Ha lasciato anche il ternario. Non so perché così tante persone abbiano un problema ? :- penso che l'esempio sopra sia sufficientemente compatto, esp. rispetto a un if-then-else.
Paul Brinkley,

1
Davvero non sono sicuro. Non ti ho votato. Non mi piacciono i ternari perché non è chiaro cosa c'è su entrambi i lati del :. if-elselegge come l'inglese: non può mancare ciò che significa.
Almo,

FWIW Ho il sospetto che stai ricevendo voti perché questa è una risposta molto simile a Mason Wheeler, ma la sua è stata la prima.
Bob Tway,

1
Morte all'operatore ternario !! (inoltre, death to tab, né spazi e qualsiasi modello di bracketing e indentazione eccetto Allman (in realtà, The Donald (tm) ha twittato che queste saranno le prime tre leggi che emana il 20)
Mawg

2

Come quasi tutte le risposte sopra la leggibilità dovrebbe essere sempre il tuo obiettivo principale. Tuttavia, penso anche che la formattazione possa essere un modo più efficace per raggiungere questo obiettivo rispetto alla creazione di variabili e nuove righe.

return ((decimal)CostIn > 0 && CostOut > 0) ?
       100 * ( (decimal)CostOut - (decimal)CostIn ) / (decimal)CostOut:
       0;

Concordo pienamente con l'argomento della complessità ciclomatica nella maggior parte dei casi, tuttavia la tua funzione sembra essere abbastanza piccola e semplice da affrontare meglio con un buon caso di test. Per curiosità, perché è necessario eseguire il decimale?


4
Il motivo del cast è Entity Framework. Il db deve memorizzarli come tipi nullable. Doppio? non equivale a raddoppiare in C # e deve essere lanciato.
Bob Tway,

2
@MattThrower Intendi decimal, vero? double! = decimal, c'è una grande differenza.
pinkfloydx33

1
@ pinkfloydx33 sì! Digitando su un telefono con solo mezzo cervello impegnato :)
Bob Tway,

Devo spiegare ai miei studenti che i tipi di dati SQL sono stranamente diversi dai tipi utilizzati nei linguaggi di programmazione. Non sono stato in grado di spiegare loro perché, comunque. "Non lo so!" "Piccolo endian!"

3
Non lo trovo affatto leggibile.
Almo,

1

Per me, sembra che un grosso problema con la leggibilità qui risieda nella completa mancanza di formattazione.

Lo scriverei così:

return (decimal)CostIn > 0 && CostOut > 0 
            ? (((decimal)CostOut - (decimal)CostIn) / (decimal)CostOut) * 100 
            : 0;

A seconda che il tipo di CostIne CostOutsia un tipo a virgola mobile o un tipo integrale, alcuni dei cast possono anche non essere necessari. A differenza di floate double, i valori integrali vengono implicitamente promossi decimal.


Mi dispiace vedere che questo è stato sottoposto a downgrade senza alcuna spiegazione, ma mi sembra identico alla risposta di backpackcode meno alcune delle sue osservazioni, quindi suppongo che fosse giustificato.
PJTraill

@PJTraill Devo averlo perso, è davvero quasi identico. Tuttavia, preferisco fortemente avere gli operatori sulle nuove linee, motivo per cui lascerò stare la mia versione.
Felix Dombek,

Concordo con gli operatori, come ho osservato in un commento sull'altra risposta: non avevo notato che l'avevi fatto come preferivo.
PJTraill

0

Il codice può essere scritto in fretta, ma nel mio mondo il codice sopra dovrebbe essere scritto con nomi di variabili molto migliori.

E se leggo correttamente il codice, allora sta cercando di fare un calcolo grossmargin.

var totalSales = CostOut;
var totalCost = CostIn;
var profit = (decimal)(CostOut - CostIn);
var grossMargin = 0m; //profit expressed as percentage of totalSales

if(profit > 0)
{
    grossMargin = profit/totalSales*100
}

3
Hai perso la divisione per zero restituisce zero.
danny117,

1
ed è per questo che è difficile riformattare il codice di qualcun altro che è massimizzato per brevità e perché è bene avere commenti extra per spiegare perché / come funzionano le cose
Rudolf Olah

0

Sto assumendo CostIn * CostOut sono numeri interi
Ecco come lo scriverei
M (Money) è decimale

return CostIn > 0 && CostOut > 0 ? 100M * (CostOut - CostIn) / CostOut : 0M;

1
sperando che non siano entrambi pensieri negativi: p
Walfrat

2
Il diviso per zero è ancora lì?
danny117,

@ danny117 Quando la brevità dà la risposta sbagliata, è andata molto lontano.
paparazzo,

Non voglio aggiornare la domanda e renderla attiva. 100M e 0M impongono il decimale. Penso che (CostOut - CostIn) verrà eseguito come valore matematico intero e quindi la differenza verrà convertita in decimale.
paparazzo,

0

Il codice è scritto per essere compreso dalle persone; la brevità in questo caso non compra molto e aumenta l'onere per il manutentore. Per questa brevità, dovresti assolutamente estenderlo o rendendo il codice più autocompattante (nomi di variabili migliori) o aggiungendo più commenti che spiegano perché funziona in questo modo.

Quando scrivi codice per risolvere un problema oggi, quel codice potrebbe essere un problema domani quando cambiano i requisiti. La manutenzione deve sempre essere presa in considerazione ed è essenziale migliorare la comprensibilità del codice.


1
È qui che entrano in gioco le pratiche e i principi dell'ingegneria del software. Requisiti non funzionali
hanzolo

0

La brevità non è più una virtù quando

  • C'è divisione senza un controllo preventivo per zero.
  • Non è presente alcun controllo per null.
  • Non c'è pulizia.
  • TRY CATCH contro lancia la catena alimentare dove l'errore può essere gestito.
  • Ipotesi sono fatte sull'ordine di completamento delle attività asincrone
  • Attività che utilizzano il ritardo anziché riprogrammare in futuro
  • Inutile IO viene utilizzato
  • Non usando l'aggiornamento ottimistico

Quando non c'è una risposta abbastanza lunga.

1
Ok, questo avrebbe dovuto essere un commento, non una risposta. Ma è un ragazzo nuovo, quindi almeno spiegalo; non limitarti a votare e scappare! Benvenuto a bordo, Danny. Ho cancellato un
voto negativo

2
Ok ho esteso la risposta per includere alcune cose più complesse che ho imparato nel modo più duro e nel modo più semplice scrivendo un breve codice.
danny117,

Grazie per il benvenuto @Mawg Voglio sottolineare che il controllo per null è ciò che riscontro i problemi più gravi nel breve codice.
danny117,

Ho appena modificato tramite Android e non ha richiesto una descrizione della modifica. Ho aggiunto un aggiornamento ottimistico (rileva i cambiamenti e avvisa)
danny117,

0

Se questo stava superando i test delle unità di convalida, allora andrebbe bene, se fosse stata aggiunta una nuova specifica, fosse richiesto un nuovo test o un'implementazione migliorata, e fosse richiesto di "districare" la terseness del codice, cioè quando sorgerebbe un problema.

Ovviamente un bug nel codice mostra che c'è un altro problema con Q / A che era una svista, quindi il fatto che ci fosse un bug che non è stato rilevato è motivo di preoccupazione.

Quando si tratta di requisiti non funzionali come la "leggibilità" del codice, deve essere definito dal responsabile dello sviluppo e gestito dallo sviluppatore principale e rispettato dagli sviluppatori per garantire implementazioni adeguate.

Cercare di garantire un'implementazione standardizzata del codice (standard e convenzioni) per garantire la "leggibilità" e la facilità di "manutenibilità". Ma se questi attributi di qualità non sono definiti e applicati, finirai con il codice come nell'esempio sopra.

Se non ti piace vedere questo tipo di codice, prova a far concordare al team gli standard e le convenzioni di implementazione e scriverlo e fare revisioni casuali del codice o controlli a campione per convalidare la convenzione.

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.