Dal punto di vista dello sviluppo del ciclo di vita del software, il dattilografia è un vantaggio o un problema?

3

I linguaggi tipizzati in modo statico come Java offrono il vantaggio del controllo in fase di compilazione dei tipi: si garantisce che un oggetto sia di un determinato tipo, quindi:

  • non è necessario spendere tempo e risorse per studiare il TYPE di una variabile o parametro, perché non sappiamo se questo è un None , List[string] , o solo un string
  • non ci sono errori di tipo runtime di questo modulo
  • non c'è da preoccuparsi per gli errori nell'uso delle convenzioni (ad esempio intPhoneNumber modificato in una stringa, ma ha dimenticato di cambiare il nome in strPhoneNumber )

Ci sono probabilmente altri punti che non ho menzionato. Ma l'idea generale è che ci sia meno carico cognitivo sul programmatore e se ci sono ipotesi errate, il feedback viene immediatamente fornito sotto forma di una compilazione fallita - e il feedback immediato è esattamente uno dei fattori vincenti del test unitario.

Duck-typing d'altra parte non si preoccupa del tipo esplicito di un oggetto - finché l'oggetto ha gli attributi rilevanti (membri di dati e funzioni), il programma può andare avanti. Se l'oggetto ha una funzione con lo stesso nome di quanto richiesto da una parte di codice, il codice tenterà di utilizzare la funzione, anche se l'implementazione è inaspettatamente diversa. Se l'oggetto non ha gli attributi richiesti, il programma si blocca. Il vantaggio è una riduzione del codice: nessuna definizione di interfaccia è necessaria in un linguaggio di digitazione anatra.

Come descritto sopra, uno scenario così inaspettato può essere rilevato solo in fase di runtime. Ma un linguaggio tipizzato staticamente potrebbe prendere una tale discrepanza in fase di compilazione. A meno che una robusta suite di test delle unità non sia configurata con una copertura del 100% percorso , è possibile che tale errore di base (e non prevenibile) (mancata corrispondenza del tipo) non venga rispettato. E sappiamo che è molto difficile per una serie di motivi raggiungere una percentuale così alta di copertura del codice, per non parlare della copertura del codice di percorso.

Quindi:

  • Gli "svantaggi" della tipizzazione statica, ovvero il codice più dettagliato, non sarebbero superati di gran lunga dai vantaggi della sua spinta intrinseca all'affidabilità del software?
  • Da un punto di vista dell'affidabilità del software di produzione, c'è un qualsiasi vantaggio nell'uso delle lingue con tali funzioni?
  • O è semplicemente che tali linguaggi non dovrebbero essere utilizzati per la produzione (anche se sono in molti, molti casi)?
posta Ahmed Tawfik 19.03.2016 - 13:33
fonte

2 risposte

6

1. Molto di quello che hai detto è vero anche nelle lingue con tipizzazione statica.

Duck-typing on the other hand does not care about the explicit type of an object - as long as the object has the relevant attributes (data members and functions), the program can go ahead. If the object has a function with the same name as what is required by some piece of code, then the code will attempt to use the function, even if the implementation is unexpectedly different.

Se scrivi un'interfaccia IFoo, posso creare una classe BadFoo che ne derivi e ha implementazioni completamente sbagliate di tutti i metodi che causano tutti i tipi di errori di runtime nel codice che hai scritto che si basa su alcune istanze di IFoo scritte correttamente. Il compilatore non può impedirmi di farlo. Di conseguenza, questa affermazione:

Unless a robust unit testing suite is set up with 100% path code coverage, such a basic - and preventable - error (type mismatch) is liable to be missed.

è assolutamente vero nelle lingue tutte , sia che siano statiche o dinamiche e che supportino o meno una qualche forma di digitazione anatra. Nella mia esperienza gli errori di runtime di tipo tipografico che si riscontrano nei tradizionali linguaggi tipizzati staticamente sono tra gli errori più insidiosi che quelle lingue possano produrre.

2. La tipizzazione statica e la digitazione anatra non si escludono a vicenda.

In linea di principio, un compilatore può facilmente vedere che IFoo è un'interfaccia contenente il metodo foo () e MegaCorpFoo è una classe con un metodo foo (), e quindi concludere che MegaCorpFoo soddisfa l'interfaccia IFoo senza che nessun programmatore abbia per dirlo esplicitamente .

Per quanto ne so, Go è l'unico linguaggio che fa chiaramente questo. I modelli di C ++ lo realizzano probabilmente, ma in modo fragile e criptico. Probabilmente puoi anche hackerare un equivalente di questo in Java o C # con le loro API di reflection.

3. I linguaggi tipicamente statici tradizionali presentano errori di runtime relativi al tipo

C ++, Java e C # consentono tutte diverse forme di casting, molte delle quali sono intrinsecamente "non sicure" nel senso che possono portare a errori di runtime.

La differenza effettiva tra digitazione statica (nei tradizionali linguaggi OOP) e digitazione anatra non è che la digitazione anatra sia meno sicura, ma piuttosto che MyFoo deve dichiarare esplicitamente che soddisfa l'interfaccia IFoo, e ci deve essere un'interfaccia IFoo esplicitamente definita da qualche parte per cominciare.

Quindi il vero compromesso non è necessariamente di sicurezza, ma semplicemente di verbosità.

Il vantaggio di questa verbosità è che, poiché il compilatore riceve da me istruzioni più dettagliate, può controllare più cose per me al momento della compilazione. Questo tende anche ad abilitare strumenti di analisi statica più potenti che possono trovare perdite di memoria e condizioni di gara e altri problemi sottili che potresti non scoprire mai da soli.

Il rovescio della medaglia è che quelle istruzioni più dettagliate distraggono dal "codice reale" che implementa la logica a cui tieni realmente, rendendola un po 'più difficile da capire e forse più facile da interrompere quando le persone devono cambiarlo più tardi. Un sistema di tipo più rigoroso è anche in grado di intralciarti e ti aiuta, ad esempio quando devi scrivere una classe wrapper attorno ad alcune classi di terze parti solo per poter aggiungere una dichiarazione che soddisfi un'interfaccia il la terza parte non aveva modo di saperlo.

La mia opinione personale è che un'applicazione che deve cambiare molto frequentemente e abbia molte dipendenze (come molte app web) è spesso meglio con linguaggi meno prolissi in cui il programmatore che fa le modifiche può concentrarsi esclusivamente sul "vero codice" "fare la cosa giusta e superare una serie di test, invece di combattere il sistema di tipi sui casi d'angolo che probabilmente non si presenteranno prima che il codice debba essere cambiato di nuovo. D'altra parte, un'applicazione che dovrebbe cambiare raramente, ha poche dipendenze e ha bisogno di essere estremamente affidabile e coerente per lunghi periodi di tempo (come un database o un server Web) trae vantaggio dal prendere tempo per definire esplicitamente tutte le sue tipi e per ottenere più controlli in fase di compilazione e un compilatore di analisi statica, verificare che molte classi di bug siano dimostrabilmente impossibili.

Idealmente, alla fine avremo un linguaggio che combina la digitazione statica come predefinita con più funzioni di riduzione della verbosità come la digitazione anatra in modo da ottenere il meglio da entrambi i mondi e questo intero dibattito diventa un non-standard problema.

    
risposta data 19.03.2016 - 14:35
fonte
6

Hai un'assunzione errata lì. La tipizzazione di anatra può essere controllata staticamente. Poiché il compilatore sa quale tipo viene passato alla funzione e sa quali operazioni richiede quella funzione, può rilevare gli errori in caso di mancata corrispondenza.

Allo stesso modo, il tuo secondo proiettile è un po 'ottimista. Lingue come Java hanno type cast, il che significa che può ottenere errori di runtime a causa del tentativo di eseguire operazioni su cose che non le supportano.

Tutto ciò che ho detto, l'argomento per le lingue senza annotazioni di tipo è che sono più facili da leggere. Non hai il "rumore" delle annotazioni di tipo che ingombrano il tuo codice, quindi puoi leggere cosa sta effettivamente accadendo. Allo stesso modo, per i linguaggi dinamici, una discussione è che tu farai comunque test delle unità , quindi non è un peso eccessivo.

Personalmente, non sono d'accordo con questi argomenti, ma i miei bisogni sono diversi dagli altri.

    
risposta data 19.03.2016 - 13:51
fonte

Leggi altre domande sui tag