Esiste una correlazione tra la scala del progetto e il rigore della lingua?

69

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

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

    1. Sviluppo rapido,

    2. Codice boilerplate ridotto,

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

  • Le lingue tipizzate staticamente / compilate sono le migliori per le applicazioni che richiedono maggiore rigore, come app o app business-critical per applicazioni 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 decenni di esperienza.

  • 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 sistemi e sistemi critici che dovrebbero essere estremamente stabile. I vantaggi sono:

    1. Capacità di catturare quanti più bug possibili in fase di compilazione,

    2. Facilità di controllo statico,

    3. Facilità di prove formali.

Tuttavia, esaminando le lingue e le tecnologie utilizzate per i progetti su larga scala da parte delle 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 un'importante quantità di rigore.

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

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

Dove mi sbaglio?

    
posta Arseni Mourzenko 24.08.2013 - 19:18
fonte

5 risposte

38

Un interessante case study sulle questioni relative ai progetti di ridimensionamento che utilizzano un linguaggio dinamico e interpretato può essere trovato in Inizio Scala di David Pollak.

I started searching for a way to express the code in my brain in a simpler, more direct way. I found Ruby and Rails. I felt liberated. Ruby allowed me to express concepts in far fewer lines of code. Rails was so much easier to use than Spring MVC, Hibernate, and the other “streamlined” Java web frameworks. With Ruby and Rails, I got to express a lot more of what was in my head in a shorter period of time. It was similar to the liberation I felt when I moved from C++ to Java...

As my Ruby and Rails projects grew beyond a few thousand lines of code and as I added team members to my projects, the challenges of dynamic languages became apparent.

We were spending more than half our coding time writing tests, and much of the productivity gains we saw were lost in test writing. Most of the tests would have been unnecessary in Java because most of them were geared toward making sure that we’d updated the callers when we refactored code by changing method names or parameter counts. Also, I found that working on teams where there were mind melds between two to four team members, things went well in Ruby, but as we tried to bring new members onto the team, the mental connections were hard to transmit to new team members.

I went looking for a new language and development environment. I was looking for a language that was as expressive as Ruby but as safe and high-performance as Java...

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

In particolare, l'autore approfondisce la spiegazione delle differenze nella scrittura di prova tra le lingue digitate dinamicamente e staticamente nel Capitolo 7. Nella sezione "Coniglietti terribilmente uccisi: l'autore di Dwemthy's Stairs" discute la porta Scala di un particolare esempio di Ruby:

Why the Lucky Stiff... introduces some of Ruby’s metaprogramming concepts in Dwemthy’s Array in which a rabbit battles an array of creatures. N8han14 updated the example to work in Scala...

Compared to the Ruby code, the library parts of the Scala code were more complex. We had to do a lot of work to make sure our types were correct. We had to manually rewrite Creature’s properties in the DupMonster and the CreatureCons classes. This is more work than method_missing. We also had to do a fair amount of work to support immutability in our Creatures and Weapons.

On the other hand, the result was much more powerful than the Ruby version. If we had to write tests for our Ruby code to test what the Scala compiler assures us of, we’d need a lot more lines of code. For example, we can be sure that our Rabbit could not wield an Axe. To get this assurance in Ruby, we’d have to write a test that makes sure that invoking |^ on a Rabbit fails. Our Scala version ensures that only the Weapons defined for a given Creature can be used by that Creature, something that would require a lot of runtime reflection in Ruby...

La lettura di cui sopra può far pensare che man mano che i progetti crescono, la scrittura di test potrebbe diventare proibitiva. Questo ragionamento sarebbe sbagliato, come dimostrano esempi di progetti di grandi dimensioni di successo menzionati proprio in questa domanda ("Python è usato con successo per ... YouTube").

Il problema è che il ridimensionamento dei progetti non è molto semplice. Progetti molto ampi e di lunga durata possono "permettersi" diversi processi di sviluppo del test, con suite di test di qualità di produzione, team di sviluppo test professionale e altri materiali pesanti.

Suite di test di YouTube o Kit di compatibilità Java sicuro vivi un diverso life di test in un piccolo progetto tutorial come Dwemthy's Array .

    
risposta data 24.08.2013 - 23:10
fonte
24

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

Detto semplicemente, i grandi sistemi usano più lingue, non solo una lingua. Potrebbero esserci parti costruite usando linguaggi "stretti" 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 questi 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 loro stessi hanno creato come Go.

Non è che non si possano usare linguaggi tolleranti per sistemi su larga scala. Molte persone dicono che Facebook usi PHP, ma dimenticano di menzionare che Facebook ha dovuto creare linee guida di programmazione estremamente rigide per usarlo efficientemente su questa scala.

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

    
risposta data 24.08.2013 - 21:10
fonte
3

Ci sono due tipi di errori da verificare: digitare errori (concatenare un numero intero + elenco di float) e errori di logica aziendale (trasferire denaro su un conto bancario, controllare se l'account di origine ha denaro).

La parte "dinamica" di un linguaggio di programmazione dinamico è solo il luogo in cui avviene il controllo del tipo. In un linguaggio di programmazione "tipizzato dinamicamente", il controllo di tipo viene eseguito mentre si esegue ciascuna istruzione, mentre in un "tipo di linguaggio tipizzato staticamente" il controllo viene eseguito in fase di compilazione. E puoi scrivere un interprete per un linguaggio di programmazione statico (come emscriptem fa), e puoi anche scrivere un compilatore statico per una dinamica linguaggio di programmazione (come gcc-python o shed-skin fa).

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

Una piccola base di codice in un linguaggio di programmazione controllato dinamicamente è più facile cercare errori di tipo perché è più facile avere una copertura al 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 grande base di codice in un linguaggio di programmazione controllato dinamicamente è più difficile testare ogni affermazione con ogni combinazione possibile di tipi, specialmente se si è negligenti e si scrive 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 catturerà la maggior parte degli errori di tipo in fase di compilazione. Dico di più perché un errore di divisione per zero o un errore di matrice fuori limite sono anche errori di tipo.

Molto spesso la vera discussione non riguarda i linguaggi di programmazione, ma le persone che usano quelle lingue. 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, commettiamo tutti degli errori, è più facile e meno incline agli errori utilizzare uno strumento dedicato specializzato per un'attività specifica. Secondo, c'è un vincolo di risorse. Il nostro tempo è limitato e scrivere pagine web sull'assemblaggio richiederebbe anni.

    
risposta data 30.06.2014 - 09:56
fonte
3

La mia esperienza con i sistemi di grandi dimensioni è che stanno in piedi o non rientrano per scelta della lingua, ma per problemi di progettazione / architettura o copertura del test . Preferirei avere un talentuoso team Python sul mio grande progetto di impresa, piuttosto che un mediocre Java.

Detto questo, qualsiasi linguaggio che ti permetta di scrivere in modo significativo meno codice , merita di essere visto (ad esempio Python vs Java). Forse il futuro è in linguaggi intelligenti, tipizzati staticamente con un'inferenza di tipo avanzata (ad esempio nello stampo Scala). O ibrido, come C # sta tentando con il suo dynamic qualificatore ...?

E non dimentichiamo l '"altro" vantaggio statico di digitazione: corretto codice IDEcompleto / intellisense, che a mio avviso è una caratteristica essenziale, non un bello da avere.

    
risposta data 25.03.2015 - 14:26
fonte
0

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

Mi è stato detto, "Non possiamo usare Ruby on Rails perché è open source e qualcuno potrebbe inserire hacker 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 attendibili lingue con piattaforme attendibili . Ruby e Python non sono lingue attendibili.

    
risposta data 24.08.2013 - 21:41
fonte