Superata la goffaggine nella scrittura del codice

7

Credo che questo sia un po 'correlato a questa domanda: Come essere un programmatore di bug zero? . Ma credo che questo riguardi maggiormente la goffaggine nella programmazione perché so che è impossibile diventare un programmatore di bug zero.

Spesso, scrivo un codice molto buggy causato dalla mia goffaggine. Ad esempio, scrivendo una funzione di conversione del tasso di cambio, una funzione banale. Posso codificare la funzione che funziona bene dato il valore corretto. Ma a volte ho dimenticato di convalidare alcuni valori inaspettati ma ragionevoli.

Quindi ci sono modi per i programmatori maldestri come me di scrivere e testare il codice in modo più approfondito?

Ulteriori Vedo un sacco di persone che suggeriscono di scrivere un test unitario o un approccio TDD. Ma scrivere unit-test non va sempre bene a causa della goffaggine, vero? Non lo faccio perché una volta ho provato a scrivere unit-test, ma ancora spesso ho problemi con bug.

    
posta junxiong 03.01.2012 - 15:48
fonte

10 risposte

18

Prova un approccio di sviluppo diverso: Sviluppo basato sui test (TDD).

a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards...

Test-driven development is related to the test-first programming concepts of extreme programming, begun in 1999, but more recently has created more general interest in its own right.

Programmers also apply the concept to improving and debugging legacy code developed with older techniques...

Scrivi casi di test e usa test unitari per impedire che i bug si materializzino.

    
risposta data 03.01.2012 - 15:54
fonte
7

Trascorri un po 'di tempo come tester - ti insegnerà ad entrare nella mentalità del "caso limite"

Quindi metti tutti i tuoi casi limite in test unitari per un approccio TDD ..

Oltre a TDD, penso che sarebbe utile leggere anche la Programmazione difensiva . Imparare ad affermare le tue precondizioni e postconditions in ogni metodo è una buona pratica ed essere severi! :)

    
risposta data 03.01.2012 - 15:57
fonte
5

Pensa di più sui requisiti. Poche persone sono davvero goffe o incapaci di pensare ai bug; la maggior parte non si prende il tempo per pensare agli aspetti appropriati. Se ti concedi un po 'di tempo e pensi solo ai requisiti di una funzione, scoprirai la maggior parte degli aspetti necessari.

Lo sviluppo orientato ai test è un approccio alla moda e ben documentato che ti consente di concentrarti innanzitutto sui requisiti di basso livello.

    
risposta data 03.01.2012 - 15:52
fonte
5

Oltre a TDD, suggerirei di tornare al codice un giorno o due dopo averlo scritto, e dare un'occhiata a ciò che i test controllano e a cosa controlla la funzione stessa. Durante la codifica, potresti avere un'idea molto precisa di come verrà chiamata la funzione, che potrebbe diventare più vaga se ti prendi un po 'di tempo. Inoltre, questa è una buona occasione per dare un'occhiata a quanto ben documentata è la funzione, e aggiungere commenti se non capisci perché funziona.

Potresti provare anche a codificare con un Design by Contract framework, che può aiutarti a individuare alcuni errori - nel tuo esempio , forse controllando che il segno del risultato sia uguale al segno dell'input e che il risultato (se è un float) non sia NaN o infinito.

    
risposta data 03.01.2012 - 17:01
fonte
4

Impara altre lingue, preferibilmente di paradigmi diversi.

Ad esempio, se hai utilizzato un linguaggio imperativo / OOP come Java / C # / C ++, prova un linguaggio funzionale come Scala / Haskell / F # . (Suggerisco Haskell per il tuo scopo poiché è il più fedele al paradigma.)

Il vantaggio di apprendere una nuova lingua o un nuovo paradigma è che inizierai a vedere schemi concettuali che questi altri linguaggi avrebbero definito rigorosamente, e poi quando torni a lavorare nella tua lingua preferita, puoi applicare questi modelli a il tuo codice e quindi evitare bug che in passato erano comuni.

Il TDD non è la stessa cosa del test delle unità. In effetti, molti praticanti di TDD insisteranno sul fatto che TDD dovrebbe non essere usato per catturare bug o regressioni - e che se stai scrivendo i test TDD per catturare bug, stai perdendo i benefici del design di TDD.

Se vuoi fare test per migliorare la qualità del codice, fai test unitari e test di integrazione - non TDD. Sicuramente con TDD svilupperai l'abitudine di individuare gli errori in primo piano, ma questo aspetto di TDD non è molto diverso dai normali test di unità.

    
risposta data 04.01.2012 - 02:25
fonte
3

Il test è importante ma il test stesso richiederà pazienza e attenzione ai dettagli e quindi non va bene con la goffaggine, tanto per cominciare. Preferirei suggerire l'uso di lingue con sistemi di tipi più severi (oltre al testing, non al posto di esso).

Errori di codifica stupidi sono molto rari anche per le lingue come Haskell - se si compila del tutto, è probabile che funzioni come previsto. E tali errori sono quasi impossibili per le lingue con sistemi di tipi più severi, come Agda o Coq.

    
risposta data 03.01.2012 - 16:09
fonte
3

Fermati e leggi il tuo codice molto attentamente prima di compilarlo. Pensa come il compilatore: trova gli errori di sintassi (una volta che hai ottenuto buoni risultati, il compilatore non dovrebbe mai trovare un errore di sintassi). Inoltre, esegui il codice nella tua testa molto attentamente, gioca al computer. Visualizzalo come se avessi solo una possibilità di eseguire la compilazione, e tutto funziona meglio (in altre parole, stai molto attento a ciò che fai, non schiacciare il comando di build e quindi aggiustare ciò che viene fuori). Questa è una tecnica semplice che è sorprendentemente efficace.

    
risposta data 04.01.2012 - 01:26
fonte
1

Ci sono pochissime persone che possono scrivere il codice senza errori da zero. Personalmente mi sento sempre a disagio se compila un pezzo piuttosto lungo del mio codice e viene eseguito immediatamente e la mia intuizione si interrompe solo raramente.

Finché accetti questi che non puoi scrivere direttamente il codice senza errori è più facile trovare un compromesso tra gli sforzi che investi nel tuo codice e la (potenziale) frequenza di bug in esso.

Un ottimo approccio per ridurre al minimo i bug nel tuo codice è il già citato Sviluppo basato sui test . Lo uso spesso quando parlo in pubblico adattandolo nel modo seguente.

Ogni pezzo di codice indipendente viene scritto e riscritto in diverse iterazioni costituite da quanto segue:

  1. Progetta l'idea principale di ciò che il tuo codice dovrebbe fare.
  2. Annota la rappresentazione schematica del tuo algoritmo.
  3. Riscrivi la rappresentazione schematica in modo che sia sintatticamente corretta.
  4. Scrivi alcuni test unitari più importanti per il tuo codice (ad esempio, smoke test ).
  5. Implementa l'algoritmo per soddisfare i tuoi test esistenti.
  6. Rifatta il tuo codice per migliorarlo.
  7. Ripeti da 1 a 4 (in base alla maturità del codice) per ogni iterazione e ogni nuova funzione.

Ecco alcuni esempi.

(1) Comincio con qualcosa di simile

I want to calculate pi, so I will simulate a target being a circle with diameter d and use random numbers to cast arrows to it. I will then use the proportion of circle area to the total target size to calculate pi.

(2) Poi passo a

Request size of the target.
Request number of arrows. Cast arrows randomly to the target.
Calculate the arrows that met the target.
Calculate the pi value.

(3) Lo riscrivo in C # (solo un esempio):

var Radius = RequestFromUser<double>("Radius of Target");
var NumberOfShots = RequestFromUser<long>("Number of shots");
long GoodShots = 0; long TotalShots = NumberOfShots;
while (--NumberofShots > 0)
{
  if (ShootTarget(Radius)) GoodShots++;
}
Output(CalculatePi(GoodShots, TotalShots));

(4) Creo tutti gli stub del metodo in IDE (automaticamente). Questo mi consente di scrivere i miei test unitari in modo semi-automatico (ottieni alcuni modelli creati automaticamente per loro)
(5) Disegno il test del fumo:

var computed = ComputerPi(Radius: 10.0, NumberOfShots: 10000);
Assert.IsTrue(computed > 3.0 && computed < 3.5);

(6) I rapidamente (che significa senza lucidare il codice) implementa tutti gli stub per iniziare il test.
(7) Fintanto che i miei test mostreranno il verde, rifletto sulla mia implementazione cercando di renderla più "carina".
(8) Ripeto da (5) se la mia implementazione non è completa, o da un passaggio precedente se voglio estenderlo.

Questo mi aiuta a mantenere il mio codice piuttosto pulito e i test delle unità lentamente emergenti servono come test di regressione se lo faccio modifiche troppo drastiche al mio codice.

    
risposta data 04.01.2012 - 01:20
fonte
0

Ecco alcune buone pratiche:

  1. Esci dal sistema
  2. Enumera tutte le alternative
  3. Trova il bordo del sistema
  4. Valuta lo spazio degli stati interi
  5. Precisione nei tipi di decisione: consente solo esattamente ciò che è stato richiesto
  6. Considera il percorso dall'input all'output - non interrompere il percorso.
risposta data 03.01.2012 - 16:51
fonte
0

La vera risposta è molto semplice e noiosa e non comporta tonnellate di elenchi e istruzioni.

Codice ogni giorno per 10 anni e sarai bravissimo a farlo. Questo è tutto. Finirai per cercare di capire tutto lungo la strada, rifatti e perfeziona te stesso. È la natura del cervello umano.

Bruce Lee ha finito per capire che non esiste uno stile di combattimento, devi adattarti al tuo avversario.

Nella programmazione, non esiste uno stile, ti adatti al tuo problema. Ma devi averlo fatto per molto tempo per diventare un maestro.

Questo è tutto.

    
risposta data 04.01.2012 - 09:10
fonte

Leggi altre domande sui tag