Quale linguaggio di programmazione genera meno bug difficili da trovare? [chiuso]

54

Quale lingua, secondo lei, consente al programmatore medio di generare funzioni con la minor quantità di bug difficili da trovare? Questa è, ovviamente, una domanda molto ampia, e mi interessano risposte e saggezze molto ampie e generali.

Personalmente trovo che trascorro pochissimo tempo alla ricerca di strani bug nei programmi Java e C #, mentre il codice C ++ ha il suo insieme distinto di bug ricorrenti, e Python / similar ha il proprio set di bug comuni e sciocchi che verrebbero rilevati dal compilatore in altre lingue.

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

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

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

    
posta Magnus Wolffelt 01.12.2010 - 17:20
fonte

12 risposte

59

Più potente è il sistema di tipi del linguaggio, più bug saranno catturati al momento della compilazione stesso.

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

*Factoringnellapossibilitàdiusarecostruttinonsicuri.

C#getsstuffedintotheunsaferowbecauseofthe"unsafe" keyword and associated pointer machinery. But if you want to think of these as a kind of inline foreign function mechanism feel free to bump C# skyward.

I've marked Haskell '98 as pure but GHC Haskell as not pure due to the unsafe* family of functions. If you disable unsafe* then jump GHC Haskell up accordingly.

    
risposta data 09.03.2015 - 20:13
fonte
20

Secondo me Haskell ti aiuta a evitare alcune fonti di errore comuni:

  • è puramente funzionale: le funzioni non possono avere effetti collaterali (non intenzionali) e questo rende la programmazione multicore più semplice e meno soggetta a errori
  • è strongmente digitato: non puoi, ad es. mischia accidentalmente valori bool, char, int e float
  • è scritto in modo statico: molti errori di programmazione vengono rilevati in fase di compilazione
  • null non fa parte delle definizioni del tipo di valore: con questo eviti l'errore miliardi di dollari
  • ci sono molte funzioni di ordine superiore pronte all'uso che puoi riutilizzare invece di scrivere le tue, eventualmente errate implementazioni
  • ha un garbage collector: gli errori di memoria sono quasi eliminati (tranne che per "perdite di spazio" a causa della sua strategia di valutazione lenta)
risposta data 17.07.2016 - 03:46
fonte
18

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 linguaggi che gestiscano il parallelismo per te nel modo più semplice e meno invasivo possibile. Questi non sono ancora mainstream. Java ne fa alcuni, ma ti lascia con la parte difficile.

Per quanto ne so, 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 il lavoro è in corso in modo trasparente rendendo Haskell un linguaggio multi-thread efficiente, e credo che la Fortress sia progettata da zero per essere un linguaggio parallelo efficiente.

Modifica: in Java Executors gestisci ancora più parti difficili. Devi rendere le singole attività conformi all'interfaccia Callable .

    
risposta data 15.06.2011 - 14:58
fonte
13

Ada è progettato in modo che il più possibile venga catturato in fase di compilazione anziché in fase di esecuzione. Ciò significa che spesso occorrono circa 10 volte di più per ottenere un programma in Ada da compilare rispetto a quello che direbbe in Java, ma quando si compila puoi essere molto più sicuro che intere classi di bug non si manifestino quando il programma eseguire.

    
risposta data 01.12.2010 - 12:08
fonte
7

Prima 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 chiamerei narghilè , cioè fino a che punto può scappare 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ò influire letteralmente su tutto il resto del programma, quindi nel caso peggiore, devi controllare tutto ovunque per trovare la fonte del tuo problema.

I buoni linguaggi in questo senso supportano i modificatori di accesso e li applicano in un modo che rende difficile o impossibile aggirarli. I buoni linguaggi 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. Le 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 strong digitazione aiutano a catturare bug in fase di compilazione, ma probabilmente questi bug non sarebbero difficili da trovare più tardi.

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

    
risposta data 01.12.2010 - 12:55
fonte
7

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

Si adatta al conto:

  • È sempre facile riprodurre (ecco un foglio di calcolo - non funziona)
  • È piuttosto facile trovare il bug, poiché è totalmente "funzionale" - inizia con la cella che è sbagliata e traccia tutte le sue dipendenze.
risposta data 02.12.2010 - 12:02
fonte
7

Questa è una domanda difficile perché la maggior parte dei bug non è colpa del linguaggio stesso, ma è colpa degli sviluppatori che commettono 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 chiare e rilevare / eliminare i bug, allora questo tende a favorire i linguaggi interattivi.

  • Espressività - se il codice è più corto e ha meno complessità di plotplate / incidentale, allora è più facile vedere errori di bug / logica.

  • Digita sicurezza - maggiore è il tempo di compilazione, più bug verranno catturati dal compilatore, quindi in genere la sicurezza di sicurezza è 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 dati di solito causa un ovvio errore di runtime, e TDD preleva quasi sempre questo tipo di bug .

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

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

  • Supporto per la concorrenza : i problemi di concorrenza sono particolarmente difficili da rilevare e eseguire il debug, motivo per cui è così importante. Tutto ciò che richiede il blocco manuale è in ultima analisi destinato a fallire (e questo include quasi tutti gli ogni approccio orientato agli oggetti alla concorrenza). Il linguaggio migliore 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 quadro di concorrenza nuovo, affidabile e componibile. Vedi link per ulteriori approfondimenti

risposta data 05.06.2015 - 07:53
fonte
5

Meno il linguaggio è potente, meno opzioni ti danno per sparare il tuo piede.

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

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

    
risposta data 01.12.2010 - 14:55
fonte
3

What language, in your opinion, allows the average programmer to output features with the least amount of hard-to-find bugs?

Secondo me, Delfi. Essendo basato su Pascal, il linguaggio è abbastanza semplice e intuitivo per il programmatore medio (o anche inesperto i programmatori) da raccogliere facilmente, e il suo ricco supporto di strumenti e librerie rende la maggior parte dei bug facili da trovare.

  • strong tipizzazione e un compilatore rigoroso che cattura molti errori comuni.
  • Sintassi intuitiva che non incoraggia errori comuni. ("L'ultimo bug del mondo", if (alert = RED) {LaunchNukes;} , non verrà compilato, ad esempio.)
  • Un modello di oggetto ben progettato che elimina molti degli errori comuni di C ++ OOP.
  • Limita il controllo e il controllo dell'intervallo integrato nella lingua, riducendo drasticamente le possibilità di sicurezza problemi.
  • Probabilmente il compilatore più veloce conosciuto dall'uomo, che aumenta la tua produttività e rende più difficile perdere il filo del tuo pensiero mentre aspetti su una build.
  • Il debugger di Visual Studio del debugger vuole essere come quando cresce.
  • Monitoraggio delle perdite integrato direttamente nel gestore della memoria, rendendo banale la ricerca e il fissaggio delle perdite di memoria.
  • Una libreria standard ampia e matura che fornisce metodi precostituiti e pre-testati per eseguire attività comuni senza dover creare implementazioni personalizzate, magari con errori.
  • Viene fornito con strumenti utili, come un potente sistema di registrazione e un profiler, per semplificare il rintracciamento dei problemi.
  • strong supporto della community per problemi comuni non presenti nella libreria standard, tra cui una potente libreria di concorrenti di terze parti .
risposta data 01.12.2010 - 14:49
fonte
2

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

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 e Moose).

Sono molto più produttivo in Perl di quanto lo fossi in Java.

Non è necessario compilare e distribuire (a caldo), è una delle ragioni. Trovo anche che scrivere casi d'uso è più facile, in quanto 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 codice Java, potrebbe anche essere più alto. Ma trovo che sia più facile e veloce trovare e correggere questi bug.

    
risposta data 02.12.2010 - 10:12
fonte
1

Forse il rilevamento del 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 sono in grado di convincere Google a indicarmi uno studio su questo argomento. Va inoltre notato che alcune lingue come C possono essere utilizzate per aggirare i bug dell'hardware sottostante e per aggirare l'usura dell'hardware man mano che invecchia.

    
risposta data 01.12.2010 - 12:41
fonte
1

Invece di parlare di lingue e parlare di funzionalità linguistiche

  • java ti costringe a pensare alle eccezioni (genera ...) e devi pubblicare o gestire queste eccezioni. Questo mi impedisce davvero di dimenticare errori o sto usando più eccezioni derivate da SystemException che non richiedono questa gestione?
  • che dire di "design by contract" (http://en.wikipedia.org/wiki/Design_by_contract) che mi costringe a pensare a pre e post-condizioni. Ho letto che ora è possibile con c # -4.0.
risposta data 03.12.2010 - 12:25
fonte