it-swarm.it

Quale linguaggio di programmazione genera meno bug difficili da trovare?

Quale lingua, secondo te, consente al programmatore medio di produrre funzionalità con il minor numero di bug difficili da trovare? Questa è ovviamente una domanda molto ampia, e sono interessato a risposte e saggezza molto ampie e generali.

Personalmente trovo che passo pochissimo tempo a cercare strani bug in Java e C #, mentre il codice C++ ha il suo set distinto di bug ricorrenti e Python/simile ha il suo set di comuni e bug stupidi che sarebbero stati rilevati dal compilatore in altre lingue.

Inoltre trovo difficile considerare i linguaggi funzionali a questo proposito, perché non ho mai visto un programma grande e complesso scritto in un codice completamente funzionale. Il tuo contributo per favore.

Modifica: Chiarimento completamente arbitrario del bug difficile da trovare: occorrono più di 15 minuti per la riproduzione o più di 1 ora per trovare la causa e correggere.

Scusami se questo è un duplicato, ma non ho trovato nulla su questo argomento specifico.

54
Magnus Wolffelt

Più potente è il sistema di tipi del linguaggio, più bug verranno colti al momento della compilazione stessa.

La figura seguente confronta alcuni dei linguaggi di programmazione ben noti in termini di potenza, semplicità e sicurezza dei loro sistemi di tipi. [ Fonte ]

alt text

* Fattorizzazione nella capacità di usare costrutti non sicuri.

C # viene inserito nella riga non sicura a causa della parola chiave "non sicura" e del macchinario puntatore associato. Ma se vuoi pensare a questi come a una sorta di meccanismo di funzione estranea in linea, sentiti libero di alzare C # verso il cielo.

Ho contrassegnato Haskell '98 come puro ma GHC Haskell come non puro a causa della non sicura * famiglia di funzioni. Se disabiliti * non sicuro *, salta GHC Haskell di conseguenza.

58
missingfaktor

A mio avviso, Haskell ti aiuta a evitare alcune comuni fonti di errori:

  • è puramente funzionale: le funzioni non possono avere effetti collaterali (non intenzionali) e questo rende la programmazione multicore più semplice e meno soggetta ad errori
  • è fortemente tipizzato: non puoi ad es. mescolare accidentalmente i valori bool, char, int e float
  • è tipizzato staticamente: molti errori di programmazione vengono colti al momento della compilazione
  • null non fa parte delle definizioni del tipo di valore: in questo modo eviti errore di miliardi di dollari
  • ci sono molte funzioni di ordine superiore già pronte che puoi riutilizzare invece di scrivere le tue implementazioni, possibilmente difettose
  • ha un garbage collector: gli errori di memoria sono quasi eliminati (ad eccezione di "perdite di spazio" a causa della sua strategia di valutazione pigra)
20

Tradizionalmente i bug più difficili da trovare sono le condizioni di gara nelle applicazioni multi-thread così come sono

  • quasi impossibile da riprodurre
  • può essere molto sottile

Quindi hai bisogno di lingue che gestiscano il parallelismo per te il più possibile e in modo non intrusivo. Questi non sono ancora mainstream. Java fa un po ', ma ti lascia con la parte difficile.

A quanto ho capito, hai bisogno di un linguaggio funzionale poiché "nessun effetto collaterale" è la cosa che in primo luogo fa sparire i due punti elenco. Ho visto che sono in corso lavori per rendere trasparente Haskell un efficiente linguaggio multi-thread e credo che Fortress sia progettato da zero per essere un linguaggio parallelo efficiente.


Modifica: In Java Executors gestisce ancora più parti rigide. Devi rendere le singole attività conformi all'interfaccia Callable.

18
user1249

Ada è progettato in modo tale da catturare il più possibile in fase di compilazione anziché in fase di esecuzione. Ciò significa che spesso ci vuole circa 10 volte più tempo per compilare un programma in Ada rispetto all'equivalente in Java dire, ma quando lo compili puoi essere molto più sicuro che intere classi di bug saranno non si manifestano durante l'esecuzione del programma.

13
Mark Pim

Innanzitutto una definizione: un bug difficile da trovare, a quanto ho capito, è un bug che può essere riprodotto ma la causa è difficile da trovare.

Probabilmente l'aspetto più importante è quello che definirei ristrettezza, ovvero fino a che punto può sfuggire un bug, quanto è grande l'ambito che un bug può potenzialmente influenzare. In lingue come C, un bug, ad es. un indice di array negativo o un puntatore non inizializzato, può influenzare letteralmente tutto ovunque nell'intero programma, quindi nel caso peggiore, devi controllare tutto ovunque per trovare la fonte del tuo problema.

Le buone lingue a questo proposito supportano i modificatori di accesso e li applicano in un modo che rende difficile o impossibile bypassarli. Le buone lingue ti incoraggiano a limitare l'ambito delle tue variabili, invece di rendere troppo facile avere variabili globali (ad esempio "tutto ciò che non è dichiarato esplicitamente è una variabile globale con un tipo e un valore predefiniti").

Il secondo aspetto importante è concorrenza. Le condizioni di gara sono generalmente difficili da riprodurre e quindi difficili da trovare. Buone lingue offrono meccanismi di sincronizzazione facili da usare e le loro librerie standard sono thread-safe dove necessario.

Questo completa già la mia lista; altre cose come la digitazione forte aiutano a catturare i bug in fase di compilazione, ma quei bug probabilmente non sarebbero difficili da trovare in seguito.

Considerando tutto ciò, direi che Java e C #, e molte altre lingue nel mondo JVM e .net, sono adatti per evitare bug difficili da trovare.

7
user281377

Poiché Excel è il DSL più utilizzato, vado con Excel. (escluso VBA ovviamente)

Si adatta al conto:

  • È sempre facile riprodurlo (ecco un foglio di calcolo - non funziona)
  • È abbastanza facile trovare il bug, dato che è totalmente "funzionale" - inizia con la cella che è sbagliata e rintraccia tutte le sue dipendenze.
7
Scott Whitlock

Questa è una domanda difficile perché la maggior parte dei bug non è colpa della lingua stessa - piuttosto è colpa degli sviluppatori che fanno errori nel modo in cui usano la lingua.

Credo che ci siano diversi aspetti delle caratteristiche del linguaggio che influenzano la probabilità di bug:

  • Interattività - i linguaggi dinamici con REPL incoraggiano l'interazione/sperimentazione con programmi in esecuzione e cicli di codice/test molto più piccoli. Se ritieni che l'iterazione sia un buon modo per scoprire soluzioni semplici e pulite e rilevare/eliminare i bug, questo favorirebbe le lingue interattive.

  • Espressività - se il codice è più corto e presenta una minore complessità/incidenza della caldaia, è più facile vedere bug/errori logici.

  • Digitare safety : più tempo è necessario per la compilazione, più errori verranno rilevati dal compilatore, quindi in generale la sicurezza del tipo è una buona cosa. Tuttavia questi di solito non sono difficili da trovare bug - anche in un linguaggio completamente dinamico il tipo sbagliato in una struttura di dati di solito causerà un errore di runtime molto ovvio, e TDD quasi sempre rileva questo tipo di bug.

  • Immutabilità - molti bug gravi sono dovuti a interazioni complesse di stato mutevole. Le lingue che enfatizzano l'immutabilità (Haskell, Clojure, Erlang) hanno un enorme vantaggio evitando la mutabilità

  • Programmazione funzionale - gli approcci funzionali alla scrittura del codice tendono ad essere più "dimostrabilmente corretti" del codice orientato agli oggetti con sequenze complesse di effetti/interazioni. La mia esperienza è che FP aiuta a evitare bug insidiosi - credo che ci sia qualche ricerca accademica da qualche parte che attualmente non riesco a trovare a sostegno di questo.

  • Supporto della concorrenza - i problemi di concorrenza sono particolarmente difficili da rilevare e eseguire il debug, motivo per cui questo è così importante. Tutto ciò che richiede il blocco manuale alla fine è destinato a fallire (e questo include praticamente un approccio alla concorrenza orientato agli oggetti tutti). Il miglior linguaggio che conosco a questo proposito è Clojure: ha un approccio unico alla gestione della concorrenza che combina la memoria transazionale del software con strutture di dati immutabili per ottenere un framework di concorrenza nuovo, affidabile e compostabile. Vedi http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey per ulteriori approfondimenti

7
mikera

Meno una lingua è potente, meno opzioni ti dà per sparare al tuo piede.

Linguaggi di alto livello come Java e C # produrranno meno bug rispetto ai linguaggi di basso livello come C++.

Detto questo, credo Java è più sicuro di C #. Java è artificialmente limitato in modo che un programmatore medio senza conoscenze avanzate possa dominarlo e produrre programmi stabili.

5
user8685

Quale lingua, secondo te, consente al programmatore medio di produrre funzionalità con il minor numero di bug difficili da trovare?

Secondo me, Delphi. Essendo basato su Pascal, il linguaggio è abbastanza semplice e intuitivo da consentire al programmatore medio (o anche programmatori inesperti) di imparare facilmente, e il suo ricco supporto di strumenti e librerie facilita la ricerca della maggior parte dei bug.

  • Digitazione forte e un compilatore rigoroso che rileva molti errori comuni.
  • Sintassi intuitiva che non incoraggia errori comuni. ("L'ultimo bug del mondo", ad esempio if (alert = RED) {LaunchNukes;}, non verrà compilato.)
  • Un modello a oggetti ben progettato che elimina molti degli errori C++ OOP comuni).
  • Verifica dei limiti e controllo della portata integrati nella lingua, riducendo drasticamente le possibilità di problemi di sicurezza.
  • Probabilmente il compilatore più veloce conosciuto dall'uomo, che aumenta la tua produttività e rende più difficile perdere il filo del pensiero mentre aspetti una costruzione.
  • Il debugger Il debugger di Visual Studio vuole essere come quando cresce.
  • Tracciamento delle perdite incorporato direttamente nel gestore della memoria, rendendo banale la ricerca e la correzione di perdite di memoria.
  • Una libreria standard ampia e matura che fornisce modi precompilati e pre-testati per eseguire attività comuni senza dover costruire implementazioni personalizzate, probabilmente errate.
  • Fornito con strumenti utili, come un potente sistema di registrazione e un profiler, per facilitare la localizzazione dei problemi.
  • Forte supporto della comunità per problemi comuni che non si trovano nella libreria standard, incluso na potente libreria di concorrenza di terze parti .
3
Mason Wheeler

Una cosa da tenere in considerazione è il tempo di inversione.

Negli ultimi cinque anni ho sviluppato principalmente applicazioni web in Java (JSF, Seam, ecc.) Recentemente ho ottenuto un nuovo lavoro e stiamo usando Perl (con Catalyst and Moose).

Sono molto più produttivo in Perl, rispetto a Java.

Non è necessario compilare e distribuire (a caldo), è uno dei motivi. Trovo anche che scrivere casi d'uso sia più semplice, poiché può essere fatto in modo più iterativo. E i framework in Java sembrano essere inutili complessi, almeno per i progetti in cui sono stato coinvolto.

Immagino che il numero di bug nel mio codice Perl sia più o meno lo stesso del numero di bug nel mio Java, potrebbe anche essere superiore. Ma trovo che sia più facile e veloce trova e correggi questi bug.

2
slu

Forse sondare il numero di strumenti disponibili per l'analisi del codice statico e dinamico per ogni linguaggio di programmazione potrebbe dare un'idea. Più strumenti per una lingua, è più probabile che la lingua sia molto popolare tra gli utenti o molto popolare nel generare bug difficili da trovare. Ma non riesco a convincere Google a indicarmi qualsiasi studio fatto sull'argomento. Va anche notato che alcuni linguaggi come C possono essere utilizzati per aggirare i bug hardware sottostanti e per aggirare l'usura dell'hardware nel tempo.

1
vpit3833

Invece di parlare di lingue, parlare di funzionalità linguistiche

  • Java ti costringe a pensare alle eccezioni (genera ...) e devi pubblicare o gestire queste eccezioni. Ciò mi impedisce davvero di dimenticare gli errori o sto usando più eccezioni derivate da SystemException che non necessitano di questa gestione?
  • che dire di "design by contract" (http://en.wikipedia.org/wiki/Design_by_contract) che mi costringe a pensare a pre e postcondizioni. Ho letto che ora è possibile con c # -4.0.
1
k3b