Qual è il miglior linguaggio di programmazione per scrivere un'applicazione di servizio di messaggistica?
Le applicazioni di servizio di messaggistica normalmente hanno bisogno di gestire un gran numero di richieste concorrenti/parallele. Come tale, alcuni linguaggi sono migliori di altri a causa del loro supporto incorporato per il parallelismo. Non c'è un linguaggio "migliore", comunque.
In primo luogo, ci sono alcuni linguaggi che sono intrinsecamente una 'scelta peggiore' a causa della loro mancanza di supporto nativo al parallelismo (sia nell'implementazione dell'interprete/compilatore che nelle specifiche del linguaggio). Questi sarebbero molti dei linguaggi dinamici (Ruby, Python, ecc.). La ragione è che gli interpreti di questi linguaggi girano in un singolo thread del sistema operativo, oltre al fatto che non c'è un modello di concorrenza incorporato per il linguaggio. Questi linguaggi semplicemente non sono stati progettati per la concorrenza e il parallelismo. Ora, qualcuno potrebbe dire 'ma sono stati portati alla JVM e blah blah blah', il che dà loro la capacità di utilizzare i thread della JVM, ma rimane il fatto che l'esecuzione di questi linguaggi sulla JVM non è così ben testata. Per esempio, ho avuto problemi ad usare il debugger Pry in JRuby perché JRuby è un ripensamento per quel particolare Gem (e molti altri).
Ci sono altre lingue che sono scelte che funzioneranno, ma non sono grandi scelte. Questi sono generalmente i linguaggi procedurali (la maggior parte dei quali supporta l'architettura orientata agli oggetti). Questi sono linguaggi come Java, C++, C, C#, Objective-C, Smalltalk, e simili. Ora, questi linguaggi hanno o librerie di concorrenza ben supportate che sono state aggiunte in seguito, o il supporto alla concorrenza e al parallelismo costruito direttamente nella specifica del linguaggio. In entrambi i casi, però, il modello procedurale è costruito intorno alla mutazione della memoria e dello stato e non fa nulla per scoraggiare o impedire al programmatore di farlo. Quindi ciò che rende questi linguaggi una scelta migliore di Ruby e Python è che supportano nativamente la programmazione concorrente (usando thread reali, o thread verdi, o quello che volete). La cosa che li rende cattivi è che rendono difficile scrivere codice che non si presti a condizioni di gara perché la capacità di mutare i valori a cui si accede in memoria è così facile che questi linguaggi praticamente lo incoraggiano. Ora immaginate cosa potrebbe succedere quando 2 thread di esecuzione stanno usando lo stesso valore in memoria? Cosa succede se un thread di esecuzione lo sovrascrive in un modo che gli altri non si aspettano? Questo è solo uno dei tanti problemi in cui si cacciano i linguaggi procedurali in questo dominio di problemi in cui il parallelismo è importante.
Quindi, cosa rimane? Dove, ci sono 2 famiglie di linguaggi di cui non abbiamo ancora parlato - Logica e Funzionale. Non so molto di programmazione logica, ma quello che posso dire è che molti linguaggi basati sulla logica sembrano essere ancora abbastanza immaturi/sperimentali, e questo post di StackOverflow tende ad allontanarmi da Prolog come soluzione quando ho bisogno di concorrenza: How Concurrent is Prolog?.
Quindi ci restano i linguaggi funzionali. Ora questo diventerà molto soggettivo (ma non troppo soggettivo), e sono sicuro che ci sono persone là fuori che non saranno d'accordo con me (in effetti, sono sicuro che ci sono già persone che non sono d'accordo con alcune delle cose che ho detto fino a questo punto, quindi, naturalmente, fate le vostre ricerche e traete le vostre conclusioni). Ma penso che i linguaggi funzionali siano i più adatti per la programmazione concorrente e parallela per 2 ragioni principali: 1. Immutabilità - I linguaggi funzionali sono costruiti in un modo che scoraggia (nel minimo) o rende in qualche modo impossibile (nel migliore) la mutazione delle variabili e dei valori della cache sul posto. Ciò significa che la maggior parte delle condizioni di gara a cui si finisce per dover fare attenzione nei linguaggi procedurali come Java, C, C++, ecc. spariscono semplicemente a causa del modello di programmazione. 2. Un altro vantaggio aggiunto è che l'immutabilità significa che la maggior parte del vostro programma sarà composto da 'pure' funzioni matematiche (per lo stesso input, si ottiene sempre lo stesso output), il che rende il vostro codice intrinsecamente componibile, e quindi, estendibile. Penso che questo sia ciò che ha reso facile aggiungere un modello di concorrenza a linguaggi funzionali come Haskell e Lisp, anche se alcuni sono stati progettati con la concorrenza in mente (Clojure ed Erlang, per esempio).
Ora da qui, quale sia il migliore è difficile da dire. Mi piace Haskell perché è puramente funzionale con un sistema di tipi algebrico, così in fase di compilazione sono ragionevolmente sicuro che se il mio codice viene compilato, è corretto (un vantaggio che mi piace indipendentemente dal tipo di progetto che sto costruendo). Ma anche i tipi mi diranno spesso cosa sta facendo il mio codice e come e dove può essere parallelizzato. Per di più, Haskell è un linguaggio funzionale puro, quindi non devo quasi mai pensare alle condizioni di gara. La cosa che diventa difficile è che Haskell è pigro, quindi se si ha un sacco di IO in corso, si finisce con errori come avere troppi descrittori di file aperti contemporaneamente e quel genere di cose. L'altro svantaggio è che se non avete mai usato un linguaggio con un sistema di tipi Hindley-Milner prima e non avete un background in algebra astratta e teoria delle categorie, vi ci vorrà un po' per imparare Haskell. Tuttavia, ci sono framework web Haskell che supportano un alto numero di richieste parallele molto facilmente.
Un'altra grande scelta è Erlang o uno dei linguaggi BEAM (Elixir, LFE, Joxa). Erlang ha un modello di concorrenza collaudato e testato nel settore che funziona alla grande per gestire richieste multiple in una volta sola.
Anche i linguaggi Scala e Clojure sono ottime scelte con un modello di concorrenza integrato. Scala ha il vantaggio di un sistema di tipi statico che supporta la maggior parte dei tipi di dati vantaggiosi che si possono trovare in Haskell, ma manca l'attenzione sull'applicazione dell'immutabilità che ha Clojure (anche se Scala incoraggia la programmazione immutabile in una certa misura). Se siete già a vostro agio con la JVM, questi linguaggi potrebbero essere la scelta migliore per voi.
Ci sono anche altre scelte in cui non voglio entrare (Nodejs, rust, go, ecc.) semplicemente perché devo fermarmi da qualche parte. Ma spero che questo vi dia abbastanza informazioni per restringere la vostra lista di potenziali linguaggi da usare.
Articoli simili
- È una buona idea scrivere un motore di gioco in Python? Se no, qual è il miglior linguaggio per scrivere un motore di gioco?
- Qual è la differenza tra linguaggio macchina, linguaggio assembly e linguaggio di alto livello nei computer?
- Il linguaggio assembly è considerato un linguaggio di programmazione funzionale?
- In quale linguaggio di programmazione è codificato Netflix? Come si usa questo linguaggio?