È più facile scrivere codice robusto in linguaggi compilati e rigorosamente tipizzati? [chiuso]

6

Mi piacerebbe leggere l'opinione degli esperti sul fatto che i linguaggi compilati e rigorosamente tipizzati aiutino i programmatori a scrivere codice robusto più facile, con le spalle, verificando la mancata corrispondenza dei tipi e, in generale, i difetti in fase di compilazione che altrimenti sarebbero scoperto in runtime?

I test unitari nei linguaggi generici e interpretati in modo approssimativo devono essere più accurati perché i casi di test devono valutare cose che in un linguaggio compilato non sarebbero semplicemente compilate?

È necessario che il programmatore sia compilato, scritto rigorosamente per scrivere meno codice poiché non deve controllare costantemente i tipi corretti (istanza di operatore) dal momento che il compilatore intercetta queste cose (lo stesso vale per i nomi delle variabili errati o non iniziate le variabili)?

NOTA: per linguaggio rigorosamente tipizzato intendo le lingue che ti obbligano a dichiarare le variabili e ad assegnare loro un tipo per poterle usare, e una volta dichiarata una variabile, non puoi cambiarne il tipo o assegnare valori di tipo incompatibili.

int myInt = 0;
String myString = "";
myInt = myString; // this will not fly in a strictly typed language
myInte = 10;   // neither will this ( myInte variable doesn't exist )
    
posta Tulains Córdova 22.08.2012 - 03:23
fonte

3 risposte

11

I'd like to read the opinion of experts on whether compiled, strictly-typed languages help programmers write robust code easier, having their backs, checking for type mismatches, and in general, catching flaws in compile time that otherwise would be discovered in runtime ?

Per alcuni programmi che fanno.
Per alcuni programmi ti richiedono di fare cose che non sono realmente necessarie per abilitare i controlli statici che non catturano nulla.

Gli esperti non hanno consenso. Personalmente, preferisco le lingue tradizionali tipizzate staticamente per la maggior parte delle cose.

Has unit testing in loosely typed, interpreted languages need to be more thorough because test cases need to assess things that in a compiled languages wouldn't simply compile ?

Non necessariamente. Il consenso generale è che i test unitari sono il modo più semplice e veloce per farlo, ma c'è un po 'di dibattito se hai bisogno di qualche più unit test per catturare in modo efficace quegli errori o se i normali test potresti scrivere per testare la funzionalità lo prenderebbe.

Need the programer in compiled, strictly-typed need to write less code since he/she doesn't have to constantly check for correct types ( instance of operator ) since the compiler catches those things ( the same applying to misspelled variable names or uninitiated variables ) ?

Se stai facendo l'instanceof nei linguaggi dinamici, questo è un odore di codice (imo). Quindi se consideri le annotazioni di tipo, le dichiarazioni di tipo o le dichiarazioni di variabili come "codice", allora sì, dovrai scrivere più codice per fare il sovraccarico. Se no, allora è discutibile.


La cosa principale è che non è mai così chiaro. Gli strumenti sono generalmente più facili per le lingue tipizzate in modo statico. Le annotazioni di tipo aiutano la leggibilità del codice (quindi alcuni sostengono). Non avere annotazioni di tipo aiuta la leggibilità del codice (quindi alcuni sostengono). Non c'è una buona misurazione quantitativa per aiutare. Nessun consenso.

    
risposta data 22.08.2012 - 03:51
fonte
7

Sì, la sicurezza del tipo porta a un codice più robusto. Ma a quale costo?

Non trovi mai tutti i bug nei test. Prima si trova un bug, meno costoso è da risolvere (meno persone coinvolte, meno comunicazioni, ecc.). Il modo più economico per correggere un bug è far sì che la lingua o il compilatore impediscano che accada.

Ho avuto un cliente che aveva una scommessa permanente da oltre un anno, offrendo un hamburger gratuito per trovare un bug reale nel mio codice. La sicurezza del tipo ha contribuito a rendere possibile ciò.

In generale, compilatori o linguaggi che impediscono bug sono una buona cosa, ma può essere portata all'estremo. XSLT non ti consente di aggiornare il valore di una variabile. Di conseguenza, devi ricorrere alla ricorsione per creare un ciclo semplice (sto scrivendo questo in pig-java / pig-C perché XSLT ha una sintassi terribile che non riesco a ricordare):

function sumList(x) {
    if (x.length > 1) {
        return sumList(x.tail) + x.head;
    } else {
        return x.head;
    }
}

Ci sono vantaggi a questo approccio (pochi effetti collaterali), ma ciò impone anche la frammentazione del codice in cui tutti i tipi di cose sono stati suddivisi in piccole funzioni separate. È stato difficile evitare di fare cose più volte, e questo ha portato a tutti i tipi di altri bug e alle prestazioni lente che erano peggiori di una modifica accidentale del valore di una variabile.

Torna a digitare sicurezza. Di solito, se ho una funzione washFabric (Fabric f) e ho passato una Cat invece che una Fabric, questo è un semplice errore da parte mia. Quando hai questo nascosto in strati di chiamate di funzione, un tale errore è molto facile da fare e difficile da testare. Quando il mio codice viene compilato in un linguaggio sicuro per il tipo, so che non ho fatto questo tipo di errore. Per questo motivo, trovo che la sicurezza del tipo sia un buon compromesso tra la velocità di dare uno schiaffo a qualcosa che funziona e che non si romperà.

La sicurezza del tipo ti rallenta. In Ruby o perl, puoi creare un metodo di lavaggio (f) e gettare un gatto nel lavaggio e il gatto esce pulito, o morto, o ancora sporco. Ma in Java, devi creare un'interfaccia Washable e definire meticolosamente metodi come soak (), addSoap (), agitate (), spin () e risciacquo () e pensare a cosa significa essere lavabile in modo che qualcuno possa creare un gatto la classe può studiare l'interfaccia Washable e decidere se un gatto dovrebbe essere lavabile o meno. Ciò richiede molto tempo e impegno.

Se vuoi un rapporto di utilizzo singolo scritto in un'ora, digita la sicurezza ti rallenterà. Ma se hai un gruppo di programmatori che lavorano su un enorme sistema che durerà per anni e deve essere molto tollerante ai guasti, allora puoi fare leva sulla sicurezza del tipo dalle mie fredde mani. : -)

    
risposta data 22.08.2012 - 17:53
fonte
4

Need the programer in compiled, strictly-typed need to write less code since he/she doesn't have to constantly check for correct types ( instance of operator ) since the compiler catches those things ( the same applying to misspelled variable names or uninitiated variables ) ?

Scrivo quasi esclusivamente in lingue digitate dinamicamente e non ho quasi mai bisogno di verificare i tipi corretti. In primo luogo, il programma genererà un errore di tipo o nessun metodo se uso il tipo sbagliato da qualche parte, e in secondo luogo, tendo ad usare i tipi che intendo usare dove intendo utilizzarli.

Una modifica su quel primo punto basato su un commento qui sotto: sì, il programma genererà quell'errore "in fase di esecuzione". Ma dal momento che eseguo porzioni del programma con la stessa facilità con cui vorrei compilarlo in un linguaggio tipizzato staticamente (possibilmente più spesso), questo non è particolarmente rilevante. "Runtime" non significa "produzione", significa "quando eseguo i miei test unitari". Quando eseguo i miei test di unità, se chiamo un metodo che non esiste su un tipo, otterrò un errore di metodo.

Mentre è vero che le persone commettono errori e talvolta scrivono un codice che divide un carattere in un array, questo è meno comune di quanto si pensi. La maggior parte del codice è abbastanza sicuro per tipo di progettazione ... se non fosse per lo più di tipo coerente, non funzionerebbe e non supererebbe i test unitari.

Allo stesso modo, nella mia esperienza, il test unitario non ha bisogno di essere più approfondito, per esempio, in Ruby che in Java ... Uso i test unitari per testare il comportamento di metodi e classi, non per il controllo dei tipi. Il controllo del tipo è implicito ... le mancate corrispondenze di tipo generano errori che indicano errori nel mio codice che dovrebbero essere risolti da un codice migliore, non aggiungendo controlli di tipo.

Un'ulteriore modifica basata su un altro commento - no, il mio test di unità non deve essere più esteso e non devo scrivere altro codice per assicurarmi di non aver sbagliato l'ortografia di un nome di variabile all'interno di un condizionale annidato.

Se avessi bisogno di una variabile per cambiare i valori in base ad un ramo logico e non perché ho dichiarato accidentalmente una nuova variabile, la prenderò mentre il test dell'unità comportamento , non la variabile di test dell'unità nomi e controllo del tipo. Scriverò lo stesso test di unità in un linguaggio esplicito statico, e mentre potrei ottenere un errore di compilazione invece di un test fallito il risultato finale è lo stesso: vedrò l'errore e correggerò il codice quando eseguirò l'unit test Questo significa che ho il giusto comportamento , non che sto usando i giusti tipi e variabili.

Se sto scrivendo un codice in cui quel tipo di errore potrebbe passare attraverso i miei test unitari, il mio problema non è che sto usando un linguaggio implicito dinamico, è che sto scrivendo codice cattivo con effetti collaterali non tracciati. L'utilizzo di un linguaggio esplicito statico non mi aiuterà in questo modo, mi darà solo un falso senso di sicurezza riguardo al mio codice errato.

    
risposta data 22.08.2012 - 06:03
fonte

Leggi altre domande sui tag