Esiste una correlazione tra la portata del progetto e la rigidità della lingua?


72

Spiegando la differenza tra rigore delle lingue e paradigmi a un mio collega, ho finito per affermare che:

  • I linguaggi tolleranti, come i linguaggi dinamici e interpretati, vengono utilizzati al meglio per prototipi e piccoli progetti o applicazioni Web di medie dimensioni. Quando si scelgono linguaggi dinamici eleganti come Python o JavaScript con Node.js, i vantaggi sono:

    1. Sviluppo veloce,

    2. Codice targa caldaia ridotto,

    3. Capacità di attrarre programmatori giovani e creativi che fuggono da "linguaggi aziendali"   come Java.

  • I linguaggi digitati / compilati staticamente sono i migliori per le applicazioni che richiedono un rigore più elevato, come le app business-critical o le app di medie e grandi dimensioni.

    1. Famosi paradigmi e schemi sviluppati per decenni,

    2. Facilità di controllo statico,

    3. Capacità di trovare molti sviluppatori professionisti con esperienza decennale.

  • Linguaggi rigorosi come Haskell, Ada o tecniche come i contratti di codice in C # sono migliori per i sistemi che favoriscono la sicurezza rispetto alla flessibilità (anche se Haskell può essere estremamente flessibile), come i sistemi critici per la vita e i sistemi che dovrebbero essere estremamente stabili. I vantaggi sono:

    1. Capacità di rilevare il maggior numero possibile di bug al momento della compilazione,

    2. Facilità di controllo statico,

    3. Facilità di prove formali.

Tuttavia, osservando i linguaggi e le tecnologie utilizzati per progetti su larga scala da parte di grandi società, sembra che la mia affermazione sia errata . Ad esempio, Python viene utilizzato con successo per sistemi di grandi dimensioni come YouTube o altre applicazioni Google che richiedono una notevole rigidità.

Esiste ancora una correlazione tra la portata del progetto e la rigidità del linguaggio / paradigma che dovrebbe essere usato?

C'è un terzo fattore che ho dimenticato di prendere in considerazione?

Dove sbaglio?


12
Il controllo rigoroso del tipo e il controllo statico del tipo non sono la stessa cosa. Python è tipizzato in modo dinamico, ma è più rigoroso di C. Il vantaggio del controllo statico dei tipi non è la rigidità di per sé ma che i tipi vengono controllati in fase di compilazione, non in fase di esecuzione. Ho affrontato molti problemi C / C ++ nella mia carriera a causa del casting implicito.
Gort il robot il

5
Probabilmente c'è qualcosa da dire sul ciclo di vita: il software che inizia nella tua prima categoria può evolversi in altri, "trascinando" la lingua con esso.
Mat

11
L'unica cosa elegante di javascript è che funziona nella maggior parte dei browser.
JeffO,

1
@StevenBurnap: non potrei essere più d'accordo sulla differenza tra statico e rigoroso. Java è un altro punto sullo spettro, essendo statico e troppo rigoroso. Gli sviluppatori spesso rimproverano la tipizzazione statica usando Java come esempio, ma molte di queste critiche dovrebbero essere dirette al compilatore eccessivamente rigoroso di Java , non alla tipizzazione statica in generale. Guarda Scala sullo stesso JVM, che è tipicamente statico, ma ha un codice molto meno dettagliato a causa delle fantastiche capacità di inferenza del compilatore del compilatore.
Cornel Masson,

2
"Python viene utilizzato con successo per sistemi di grandi dimensioni" - qual è la definizione di "successo" qui? Che funziona principalmente e produce qualche risultato? La quantità di test e forza lavoro richiesta è inclusa? Che dire della manutenibilità?
Den

Risposte:


39

Un interessante caso di studio sulle questioni relative al ridimensionamento di progetti che utilizzano un linguaggio dinamico e interpretato può essere trovato in Beginning Scala di David Pollak.

Ho iniziato a cercare un modo per esprimere il codice nel mio cervello in un modo più semplice e diretto. Ho trovato Ruby and Rails. Mi sono sentito liberato. Ruby mi ha permesso di esprimere concetti in molte meno righe di codice. Rails era molto più facile da usare rispetto a Spring MVC, Hibernate e agli altri framework Web Java "ottimizzati". Con Ruby e Rails, ho potuto esprimere molto di più di ciò che avevo in testa in un periodo di tempo più breve. Era simile alla liberazione che ho provato quando sono passato dal C ++ a Java ...

Man mano che i miei progetti Ruby and Rails sono cresciuti oltre alcune migliaia di righe di codice e quando ho aggiunto membri del team ai miei progetti, le sfide dei linguaggi dinamici sono diventate evidenti.

Stavamo spendendo più della metà del nostro tempo di scrittura del codice per scrivere i test e gran parte dei guadagni di produttività che abbiamo visto sono stati persi nella scrittura dei test . La maggior parte dei test non sarebbe stata necessaria in Java perché la maggior parte di essi era orientata a garantire che avremmo aggiornato i chiamanti quando abbiamo refactored il codice modificando i nomi dei metodi o il conteggio dei parametri. Inoltre, ho scoperto che lavorando su team in cui c'erano combinazioni mentali tra due e quattro membri del team, le cose andavano bene in Ruby, ma mentre cercavamo di portare nuovi membri nel team, le connessioni mentali erano difficili da trasmettere ai nuovi membri del team .

Sono andato alla ricerca di un nuovo linguaggio e ambiente di sviluppo. Stavo cercando un linguaggio espressivo come Ruby ma sicuro e performante come Java ...

Come puoi vedere, le principali sfide nel ridimensionamento del progetto per l'autore si sono rivelate essere nello sviluppo di test e nel trasferimento di conoscenze.

In particolare, l'autore approfondisce i dettagli nello spiegare le differenze nella scrittura di prova tra linguaggi tipizzati dinamicamente e staticamente nel capitolo 7. Nella sezione "Poignantly Killing Bunnies: Dwemthy's Stairs" l'autore discute il porto alla Scala di un particolare esempio di Ruby:

Why the Lucky Stiff ... introduce alcuni dei concetti di metaprogrammazione di Ruby nell'array di Dwemthy in cui un coniglio combatte una serie di creature. N8han14 ha aggiornato l' esempio per lavorare in Scala ...

Rispetto al codice Ruby, le parti della libreria del codice Scala erano più complesse. Abbiamo dovuto fare molto lavoro per assicurarci che i nostri tipi fossero corretti. Abbiamo dovuto riscrivere manualmente le proprietà di Creature nelle classi DupMonster e CreatureCons. Questo è più lavoro di method_missing. Abbiamo anche dovuto fare una buona dose di lavoro per sostenere l'immutabilità nelle nostre creature e armi.

D'altra parte, il risultato è stato molto più potente della versione Ruby. Se dovessimo scrivere dei test per il nostro codice Ruby per verificare ciò che ci assicura il compilatore Scala, avremmo bisogno di molte più righe di codice. Ad esempio, possiamo essere certi che il nostro coniglio non potrebbe impugnare un'ascia. Per ottenere questa certezza in Ruby, dovremmo scrivere un test che assicuri che l'invocazione |^su un coniglio fallisca. La nostra versione Scala assicura che solo quelle Armi definite per una determinata Creatura possano essere usate da quella Creatura, qualcosa che richiederebbe molta riflessione sul runtime in Ruby ...


Leggere sopra può far pensare che, man mano che i progetti diventano ancora più grandi, la scrittura di prova potrebbe diventare proibitiva in modo ingombrante. Questo ragionamento sarebbe sbagliato, come evidenziato da esempi di progetti molto grandi di successo menzionati in questa domanda ("Python è usato con successo per ... YouTube").

Il fatto è che il ridimensionamento dei progetti non è molto semplice. I progetti di grandi dimensioni e di lunga durata possono "permettersi" diversi processi di sviluppo dei test, con suite di test di qualità di produzione, team di sviluppatori di test professionali e altre cose pesanti.

Le suite di test di Youtube o Java Compatibility Kit hanno sicuramente una vita diversa rispetto ai test in un piccolo progetto tutorial come Dwemthy's Array .



24

La tua affermazione non è sbagliata. Hai solo bisogno di scavare un po 'più a fondo.

Detto semplicemente, i grandi sistemi usano più lingue, non solo una lingua. Potrebbero esserci parti costruite usando linguaggi "rigorosi" e potrebbero esserci parti costruite usando linguaggi dinamici.

Per quanto riguarda il tuo esempio di Google e YouTube, ho sentito che usano Python principalmente come "colla" tra vari sistemi. Solo Google sa con cosa sono costruiti quei sistemi, ma scommetto che molti dei sistemi critici di Google sono costruiti usando linguaggi rigorosi e "aziendali" come C ++ o Java, o forse qualcosa che essi stessi hanno creato come Go.

Non è che non si possano usare linguaggi tolleranti per sistemi su larga scala. Molte persone affermano che Facebook utilizza PHP, ma dimenticano di menzionare che Facebook ha dovuto creare linee guida di programmazione estremamente rigide per utilizzarlo in modo efficiente su questa scala.

Quindi sì, è necessario un certo livello di rigore per progetti su larga scala. Ciò può derivare dalla rigidità del linguaggio o della struttura o dalle linee guida di programmazione e dalle convenzioni sul codice. Non puoi semplicemente prendere pochi laureati, dare loro Python / Ruby / JavaScript e aspettarti che scrivano software che si ridimensiona su milioni di utenti.


"Non puoi semplicemente prendere pochi laureati" ... "e aspettarti che scrivano software che si ridimensiona su milioni di utenti." probabilmente sarebbe stato abbastanza.
coloranti

Vale la pena notare che, come con Google e Python, l'uso di PHP da parte di Facebook è in gran parte come colla ... La mia comprensione è che per la maggior parte delle funzioni, il PHP è principalmente usato come client relativamente semplice su un sistema server più complesso che viene tipicamente implementato in un linguaggio "tradizionale" più pesante, come Java, C ++, Haskell, OCaML, ecc.
Jules

"Solo Google sa con cosa sono costruiti questi sistemi" .. Ne ho anche qualche dubbio :) Nella mia esperienza, nessuna singola entità (persona o altro) può elencare tutte le parti di un sistema molto grande. In molti casi, seppellito nelle ciotole di alcuni server è un pezzo dimenticato di Perl, Fortran o KSH che esegue "Magic".
Mattnz,

3

Esistono due tipi di errori da verificare: errori di tipo (concatenare un numero intero + elenco di float) ed errori di logica aziendale (trasferire denaro su un conto bancario, verificare se l'account di origine ha denaro).

La parte "dinamica" di un linguaggio di programmazione dinamico è solo il luogo in cui si svolge la verifica del tipo. In un linguaggio di programmazione "tipizzato dinamicamente", il controllo del tipo viene eseguito durante l'esecuzione di ciascuna istruzione, mentre in un linguaggio "programmato tipicamente" viene eseguito al momento della compilazione. E puoi scrivere un interprete per un linguaggio di programmazione statico (come emscriptem fa), e puoi anche scrivere un compilatore statico per un linguaggio di programmazione dinamico (come fa gcc-python o shed-skin ).

In un linguaggio di programmazione dinamico come Python e Javascript è necessario scrivere unit test non solo per la logica aziendale del programma, ma anche per verificare se il programma non presenta errori di sintassi o di tipo. Ad esempio, se si aggiunge "+" un numero intero a un elenco di float (che non ha senso e genererà un errore), in un linguaggio dinamico l'errore verrà generato durante l'esecuzione durante il tentativo di eseguire l'istruzione. In un linguaggio di programmazione statico come C ++, Haskell e Java, questo tipo di errore di tipo verrà rilevato dal compilatore.

Una piccola base di codice in un linguaggio di programmazione controllato dinamicamente è più facile da cercare errori di tipo perché è più facile avere una copertura del 100% del codice sorgente. Ecco fatto, esegui il codice a mano alcune volte con valori diversi e il gioco è fatto. Avere una copertura del 100% del codice sorgente ti dà un chiaro suggerimento che il tuo programma potrebbe non avere errori di tipo .

Con una base di codice di grandi dimensioni in un linguaggio di programmazione controllato dinamicamente, è più difficile testare ogni istruzione con ogni possibile combinazione di tipi, specialmente se sei incurante e scrivi una funzione che può restituire una stringa, un elenco o un oggetto personalizzato a seconda dei suoi argomenti.

In un linguaggio di programmazione controllato staticamente il compilatore rileverà la maggior parte degli errori di tipo al momento della compilazione. Dico di più perché anche una divisione per errore zero o un errore fuori campo dell'array sono errori di tipo.

Il più delle volte la vera discussione non riguarda i linguaggi di programmazione ma le persone che usano quei linguaggi. E questo è vero perché, ad esempio, il linguaggio assembly è potente come qualsiasi altro linguaggio di programmazione, eppure stiamo scrivendo codice su JavaScript. Perché? Perché siamo umani. Innanzitutto, tutti commettiamo errori ed è più facile e meno soggetto a errori utilizzare uno strumento dedicato specializzato per un'attività specifica. In secondo luogo, esiste un vincolo di risorse. Il nostro tempo è limitato e la scrittura di pagine Web sull'assemblaggio richiederebbe anni per terminare.


3

La mia esperienza con sistemi di grandi dimensioni è che resistono o non dipendono dalla scelta della lingua, ma da problemi di progettazione / architettura o copertura dei test . Preferirei avere un talentuoso team Python nel mio grande progetto aziendale, piuttosto che un mediocre Java.

Detto questo, vale la pena guardare qualsiasi linguaggio che ti permetta di scrivere molto meno codice (ad esempio Python vs Java). Forse il futuro è in linguaggi intelligenti e tipicamente statici con un'inferenza di tipo avanzata (ad esempio nello stampo Scala). O ibrido, come C # sta tentando con il suo dynamicqualificatore ...?

E non dimentichiamoci dell'altro "vantaggio" della digitazione statica: il corretto completamento del codice IDE / intellisense, che a mio avviso è una caratteristica essenziale, non piacevole.


1
"completamento del codice / intellisense" - anche il refactoring automatizzato è abbastanza importante.
Den

@Den Assolutamente. I linguaggi dinamici potrebbero aiutarti a scrivere versioni iniziali molto rapidamente (più facile, meno codice da scrivere), ma impantanarsi più tardi, poiché diventa sempre più difficile valutare l'impatto del cambiamento o eseguire il refactoring (senza strumenti di refactoring automatizzato)?
Cornel Masson,

0

Un'altra considerazione è chi sta dietro la scrittura di applicazioni su larga scala. Ho lavorato in molti luoghi che desiderano utilizzare Ruby o Python in alcuni grandi progetti di tipo aziendale, ma sono costantemente "abbattuti" dai responsabili IT e dai team di sicurezza aziendale proprio a causa della natura open source dei progetti.

Mi è stato detto, "Non possiamo usare Ruby on Rails perché è open source e qualcuno potrebbe mettere degli hack lì che rubano informazioni critiche o protette". Mi dispiace, ma una volta che qualcuno ha quella mentalità che open source == male, è quasi impossibile cambiarlo. Quella linea di pensiero è una malattia aziendale.

C # e Java sono fidati lingue con fiducia piattaforme. Ruby e Python non sono lingue affidabili.


2
Non sono d'accordo con l'ultima riga. Java si trova in uno dei suoi punti di fiducia più bassi di sempre. C # è considerato diffidente da tutta la comunità open source. Ruby è considerato solido ma lento (anche se non lo è più) e Python è il figlio fidato del cavallo da lavoro di tutte le industrie (machine learning e data science chiunque?).
CodeBeard,

1
I linguaggi dinamici fanno male alla sicurezza, ma "open source" non è una buona ragione. Forse intendevano "è facile influenzare una parte del codice da una parte completamente diversa del codice". Vedi programmers.stackexchange.com/questions/206558/…
Euforico

1
Si noti che in effetti "open sourceness" è uno degli aspetti della scelta di una lingua. Questo è ad esempio uno dei tre motivi forniti da Jeff Atwood per spiegare perché Discourse usa Ruby.
Arseni Mourzenko

C # è completamente open-source ora, ma è ancora curato, pianificato e sviluppato da sviluppatori professionisti, il che è bello immagino. Speriamo che il genere di cose "Python 3 vs 2" non accada qui.
Den,

Bug e falle di sicurezza sono introdotti dai programmatori e non dalle lingue, e per la cronaca ho contribuito a una serie di correzioni di sicurezza ai progetti open source. Quanti progetti chiusi ho aiutato ??? zero!
Reactgular,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.