JavaRush /Java Blog /Random-IT /Livelli dei linguaggi di programmazione
Marat Sadykov
Livello 41

Livelli dei linguaggi di programmazione

Pubblicato nel gruppo Random-IT

introduzione

Quali sono i diversi linguaggi di programmazione? Che tipo di concetti sono racchiusi in essi? Come si sono sviluppati? In questo articolo esamineremo i tipi di linguaggi di programmazione basati sui cosiddetti livelli: dai codici macchina (basso livello, vicino all'hardware del computer) fino a linguaggi come Java o C# (alto livello). Meno trasformazioni subisce l'elenco testuale del programma nel processo di trasformazione in un insieme di zeri e uno, più basso è il livello.
Livelli dei linguaggi di programmazione - 1
Successivamente esamineremo:
  1. Linguaggi di basso livello (codici macchina e assembly)
  2. Livello intermedio (C, Fortran….)
  3. Alto livello (C++, Java, Python, Ruby, JavaScript...)
Il livello caratterizza anche il livello di dettaglio che l'elenco del futuro programma deve essere dettagliato per attuare l'attuazione. Quanto è semplice questo processo per gli esseri umani? Il livello di una lingua non dovrebbe essere considerato un indicatore inequivocabile delle sue capacità. Un linguaggio di programmazione è uno strumento efficace in un'area e meno utile in altre. Sia il falegname che il falegname lavorano con il legno. Il primo ha lo strumento principale: un set di scalpelli, il secondo un'ascia. Tuttavia, un falegname renderà più elegante un mobile intagliato e un falegname costruirà una casa più velocemente. Sebbene ciascuno sia in grado di svolgere il lavoro dell'altro, lo faranno in modo molto meno efficiente. Vari dati in un computer sono rappresentati come insiemi di zeri e uno. I comandi di controllo per la sua elaborazione sono gli stessi dati contenenti istruzioni che determinano la posizione delle informazioni necessarie e il metodo di modifica.

Linguaggi macchina (livello più basso)

Dovremo fare una breve visita dall'area Software all'area Hardware. Consideriamolo in forma semplificata. Il processore è il “cervello” principale del computer. La scheda madre su cui è installato contiene controller che vengono utilizzati per interagire con altri dispositivi tramite bus (canali dati per la comunicazione).
Livelli dei linguaggi di programmazione - 2
Alcuni funzionano ad alta velocità (frecce rosse): il processore trae comandi dalla memoria e manipola i dati, la scheda video, soprattutto nei giochi 3D, consuma enormi quantità di texture, forme, coordinate pixel e altri oggetti per costruire un'immagine sullo schermo del monitor . Altri (a causa delle limitazioni nella velocità dello scambio di informazioni) non necessitano di indicatori così elevati. Vari dispositivi interni ed esterni sono collegati nello schema con frecce verdi.

Il mondo interiore del processore

Tutti i comandi del processore provengono dalla memoria per l'esecuzione in forma binaria. Il formato, il numero, il sottoinsieme delle istruzioni dipendono dalla sua architettura. La maggior parte di loro sono incompatibili tra loro e seguono ideologie diverse. Ed anche il tipo di comando dipende fortemente dalla modalità (8/16/32... profondità di bit) e dalla sorgente dati (memoria, registro, stack...) con cui lavora il processore. La stessa azione può essere rappresentata da istruzioni diverse. Il processore ha istruzioni per aggiungere due operandi (ADD X,Y) e aggiungerne uno a quello specificato (INC X). L'aggiunta di una tripla a un operando può essere eseguita come ADD X,3 o chiamando tre volte INC X. E, per processori diversi, è impossibile prevedere quale di questi metodi sarà ottimale in termini di velocità o utilizzo della memoria. Per comodità, le informazioni binarie sono scritte in formato esadecimale. Consideriamo parte di un programma familiare (linguaggio C, la cui sintassi è simile a Java)
int func() {
    int i = getData("7") ;
    return ++i;
   ...
}
Codice che implementa le stesse azioni sotto forma di una sequenza di istruzioni per il processore: ... 48 83 ec 08 bf bc 05 20 00 31 c0 e8 e8 fe ff ff 48 83 c4 08 83 c0 01 ... ecco come appare effettivamente il linguaggio di programmazione di basso livello per il processore Intel. Un frammento che chiama un metodo con un argomento e restituisce il risultato incrementato di uno. Questo è il linguaggio macchina (codice), che viene trasferito direttamente, senza trasformazioni, al processore per l'esecuzione. Professionisti:
  • Siamo completamente padroni della situazione, abbiamo le più ampie possibilità di utilizzo del processore e dell'hardware del computer.
  • Abbiamo a disposizione tutte le opzioni per organizzare e ottimizzare il codice.
Aspetti negativi:
  • È necessario avere una conoscenza approfondita del funzionamento dei processori e tenere conto di un gran numero di fattori hardware durante l'esecuzione del codice.
  • La creazione di programmi leggermente più complessi rispetto all'esempio fornito comporta un notevole aumento del tempo impiegato nella scrittura del codice e nel debugging.
  • Dipendenza dalla piattaforma: un programma creato per un processore generalmente non funzionerà su altri. È possibile che per questo processore, in altre modalità di funzionamento, sia richiesta la modifica del codice.
I codici macchina erano ampiamente utilizzati agli albori dei computer; non esistevano altri metodi di programmazione nell’era dei pionieri dei computer. Attualmente vengono utilizzati occasionalmente dagli ingegneri microelettronici durante lo sviluppo o il test di basso livello dei processori.

Linguaggio assembly (basso livello)

A differenza di un computer, tu ed io percepiamo meglio le informazioni in forma testuale/semantica piuttosto che in forma digitale. Puoi facilmente nominare cinquanta nomi di contatti sul tuo smartphone, ma difficilmente sarai in grado di scrivere a memoria i numeri di telefono corrispondenti. È lo stesso con la programmazione. Saliamo la scala dei tipi effettuando tre passaggi fondamentali:
  • Associamo un'istruzione simbolica a gruppi di istruzioni del processore digitale che eseguono azioni corrispondenti.
  • Evidenziamo separatamente gli argomenti delle istruzioni del processore.
  • Introduciamo la possibilità di nominare aree di memoria, variabili e posizione dei singoli comandi.
Confrontiamo i frammenti del programma precedente in codice macchina (al centro) e in linguaggio assembly (a destra):
2004b0     48 83 ec 08      sub    $0x8,%rsp
2004b4     bf bc 05 20 00   mov    $0x2005bc,%edi
2004b9     31 c0            xor    %eax,%eax
2004bb     e8 e8 fe ff ff   callq  getData
2004c0     48 83 c4 08      add    $0x8,%rsp
2004c4     83 c0 01         add    $0x1,%eax
Come puoi vedere, il processo di scrittura di un programma è stato semplificato: non è necessario utilizzare libri di riferimento per generare valori di comando digitali, calcolare le lunghezze di transizione, distribuire i dati in memoria tra le sue celle e altre funzionalità del processore. Descriviamo l'azione richiesta da una serie di comandi simbolici e gli argomenti necessari per la logica di esecuzione, quindi il programma traduttore traduce il file di testo in una serie di zero e uno comprensibili al processore. Professionisti:
  • Il processo di scrittura e modifica del codice è stato semplificato.
  • È stato mantenuto il controllo su tutte le risorse hardware.
  • È relativamente più semplice portare il programma su altre piattaforme, ma richiedono modifiche a seconda della compatibilità hardware.
Aspetti negativi:
  • Il linguaggio assembly è un linguaggio di programmazione di basso livello. Creare anche piccole sezioni di codice è difficile. Inoltre, è anche necessario tenere conto del funzionamento specifico dell'apparecchiatura.
  • Dipendenza dalla piattaforma.
L'esempio demo Java più popolare:
public static void main(String[] args) {
    System.out.println("Hello World!");
}
apparirà (sintassi NASM, utilizzando l'API di Windows e kernel32.lib) come segue:
global _main
	extern  _GetStdHandle@4
	extern  _WriteFile@20
	extern  _ExitProcess@4

	section .text
_main:
	; DWORD  bytes;
	mov 	ebp, esp
	sub 	esp, 4

	; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
	push	-11
	call	_GetStdHandle@4
	mov 	ebx, eax

	; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push	0
	lea 	eax, [ebp-4]
	push	eax
	push	(message_end - message)
	push	message
	push	ebx
	call	_WriteFile@20

	; ExitProcess(0)
	push	0
	call	_ExitProcess@4

	; never here
	hlt
message:
	db  	'Hello, World', 10
message_end:
Come i codici macchina, il linguaggio assembly è più spesso utilizzato da ingegneri e programmatori di sistemi. Viene utilizzato per scrivere parti dipendenti dall'hardware del kernel del sistema operativo che sono critiche in termini di tempo o critiche per le funzionalità di implementazione dei driver per vari dispositivi periferici. Ma ultimamente vi ricorrono sempre meno, poiché il suo utilizzo riduce notevolmente la portabilità dei programmi su altre piattaforme. A volte utilizzano il processo di disassemblaggio: creano un elenco assembler di un programma da codici digitali per analizzare la logica per l'esecuzione di piccoli frammenti. In rari casi, se il codice originale di alto livello non è disponibile: analisi dei virus per combatterli o perdita del codice sorgente. Il linguaggio assembly è considerato di prima/seconda generazione (non considereremo separatamente gli pseudocodici prima della comparsa dell'assemblatore e la loro differenza rispetto ai comandi simbolici). Vorrei evidenziare l'uso dell'assemblatore in Demo Scene: una fusione di arte, matematica e codifica di basso livello, che incarna le idee artistiche dei loro creatori sotto forma di programmi che generano videoclip con limitazioni di risorse. Spesso la dimensione totale del programma e del file di dati non deve superare i 256 byte (è popolare anche il formato 4/64 kilobyte). Ecco un esempio di un programma da 4 KB:

Lingue del gruppo C/Fortran (livello intermedio/alto)

Con lo sviluppo delle capacità della tecnologia informatica, la quantità di funzionalità e i tempi di implementazione del codice nell'assemblatore non erano più soddisfacenti. I costi di scrittura, test e manutenzione dei programmi sono cresciuti molto più velocemente delle loro capacità. Era necessario ridurre le esigenze del programmatore in termini di conoscenza del funzionamento delle apparecchiature, per dotarlo di uno strumento che gli permettesse di scrivere in linguaggi vicini alla logica umana. Passa a un nuovo livello di tipi di linguaggio di programmazione. Fornire la possibilità di suddivisione in vari moduli con ulteriori chiamate sequenziali (paradigma di programmazione procedurale), fornire vari tipi di dati con la possibilità di costruirli, ecc. Inoltre, queste misure hanno portato una migliore portabilità del codice su altre piattaforme, un'organizzazione più comoda dei lavoro di squadra. Uno dei primi linguaggi a supportare tutto quanto sopra è stato il Fortran, sviluppato negli anni '50 del secolo scorso . La capacità di creare in forma testuale con una descrizione della logica di esecuzione utilizzando loop, rami, subroutine e operando con array e presentando dati sotto forma di numeri reali, interi e complessi ha deliziato ingegneri e scienziati. In breve tempo furono creati “quadri” e biblioteche scientifiche. Tutto ciò è stato una conseguenza del fatto che Fortran è ancora attuale, anche se in un ambiente scientifico ristretto, e si sta sviluppando, poiché il bagaglio di sviluppi è molto ampio, solo la libreria IMSL si è sviluppata attivamente dal 1970 (!), come ricordi molti software simili simili? -veterani? Un altro ramo dello sviluppo dei linguaggi a questo livello è il C. Se Fortran è diventato uno strumento per scienziati, allora C è stato creato per aiutare i programmatori a creare software applicativo: sistemi operativi, driver, ecc. Il linguaggio consente di controllare manualmente l'allocazione della memoria e fornisce accesso diretto alle risorse hardware. I programmatori C devono controllare entità di basso livello, quindi molti sono dell'opinione che il C sia un linguaggio assembly avanzato e spesso viene chiamato linguaggio di “medio livello”. Avendo introdotto la digitazione dei dati nell'assembler, elementi di programmazione procedurale e modulare, il linguaggio C è ancora uno dei principali linguaggi per la programmazione di sistema, facilitata anche dal rapido sviluppo della microelettronica negli ultimi tempi. Tutti i tipi di gadget, controller, reti e altri dispositivi necessitano di driver, implementazione di protocolli di collaborazione e altri software di livello relativamente basso per implementare l'interazione con le apparecchiature. Tutto quanto sopra contribuisce alla domanda della lingua oggi. I principi funzionali e orientati agli oggetti sono stati ulteriormente sviluppati sotto forma di C++, C#, Java, prendendo molto dalla sintassi C.
  • Semplificazione del processo di creazione del codice: introduzione di tipologie, divisione in moduli, riduzione dei listati dei programmi.
  • Logica trasparente dell'algoritmo sottostante dovuta al passaggio dai codici macchina a comandi più leggibili dall'uomo in uno stile semanticamente descrittivo.
  • Portabilità. È bastato ricompilare il testo del programma per l'esecuzione su un'altra piattaforma (possibilmente con una leggera modifica).
  • Velocità dei programmi compilati.
Aspetti negativi:
  • Mancanza di gestione automatica della memoria e necessità di monitoraggio costante.
  • Mancanza di implementazione di concetti di programmazione orientata agli oggetti e funzionale.

Sviluppo di linguaggi di alto livello

I linguaggi di programmazione di alto livello, in termini di creazione di software, hanno iniziato sempre più ad allontanarsi dai codici macchina e ad implementare vari paradigmi di programmazione oltre a quelli procedurali. Tra questi rientra anche l'implementazione dei principi orientati agli oggetti. C++, Java, Python, JavaScript, Ruby... - la gamma di linguaggi di questo tipo è oggi la più popolare e richiesta. Offrono maggiori opportunità per implementare una varietà di software ed è impossibile determinare chiaramente la "specializzazione" di ciascuno di essi. Ma la popolarità dell'applicazione in aree rilevanti è dovuta alle librerie/framework per lavorare con essi, ad esempio: JavaScript - Frontend. Il linguaggio è stato progettato per l'interazione tra un browser Web client, un utente e un server remoto. Le librerie più popolari sono Angular, React e VUE. Attualmente viene utilizzato in modo relativamente attivo sul web e su altri server (backend), Node.js è particolarmente popolare. Ruby : backend. Viene utilizzato per creare script (file di servizio) e su server web. Il framework principale è Ruby On Rails. Python è un dominio scientifico e ingegneristico (oltre al dominio web). È un'alternativa ai pacchetti informatici e matematici standard (Mathematica, Octave, MatLab...), ma ha la consueta semantica del linguaggio e un gran numero di librerie. Ha molti appassionati nel campo dei sistemi di apprendimento automatico, della statistica e dell'intelligenza artificiale. Le librerie utilizzate di frequente includono Django, Numpy, Pandas e tensorflow. C++ – Sviluppo universale ed evolutivo del linguaggio C. Fornisce funzionalità di programmazione funzionale e orientata agli oggetti senza perdere la capacità di interagire con hardware di basso livello. In questo modo si ottengono produttività e flessibilità durante la creazione del software, ma anche il prezzo corrisponde: un'elevata barriera all'ingresso a causa della complessa specificazione del linguaggio, la necessità di un controllo indipendente sulle risorse durante l'esecuzione del programma. Molti software monoutente e di sistema vengono scritti utilizzandolo: moduli del sistema operativo (Windows, Symbian...), giochi, editor (Adobe Photoshop, Autodesk Maya...), database (MSSQL, Oracle...), lettori ( WinAmp...), ecc. Va notato che il software moderno è un prodotto complesso, il cui sviluppo utilizza più linguaggi di programmazione contemporaneamente e può essere molto difficile determinare il grado di partecipazione di ciascuno di essi nel il risultato complessivo.

Ulteriori progressi

Recentemente ha guadagnato popolarità un altro tipo di programmazione: funzionale (ulteriore sviluppo del livello linguistico) . Ecco un altro tipo di astrazione per i calcoli: funzioni che accettano un insieme di funzioni come argomenti e ne restituiscono un altro. Il ruolo delle variabili è svolto dalle stesse funzioni (le variabili che ci sono familiari sono semplicemente espressioni costanti, simili a final prima di una dichiarazione di tipo in Java). La funzione stessa è chiusa nel suo ambito, il risultato della sua operazione dipende solo dagli argomenti passati. Da ciò conseguono due notevoli proprietà:
  • Per i test abbiamo bisogno solo degli argomenti della funzione (il risultato del lavoro non dipende da variabili esterne, ecc.).
  • Un programma in stile funzionale è miracolosamente pronto per la concorrenza: chiamate di funzioni sequenziali possono essere eseguite in thread vicini (poiché non sono influenzate da fattori esterni) e non richiedono lock (ovvero non ci sono problemi di sincronizzazione). Un buon incentivo per dedicare tempo a questo argomento, vista la diffusa adozione di processori multi-core.
Tuttavia, la soglia di ingresso è più alta rispetto all'OOP: per un codice efficace è necessario costruire un programma, descrivendo l'algoritmo di esecuzione sotto forma di funzioni. Ma anche per uno stile puramente funzionale sarebbe bello conoscere le basi della logica e della teoria delle categorie. I più popolari sono Haskell, Scala, Fa#. Ma non temere, in Java (così come in altri linguaggi moderni di terza generazione) sono comparsi elementi di programmazione funzionale e possono essere combinati con l'OOP. Conoscerai tutti questi dettagli in modo più dettagliato durante lo stage online JavaRush. Il campo della programmazione logica (il livello successivo dei linguaggi) non ha ancora trovato ampia applicazione pratica a causa della sua scarsa domanda. La creazione di programmi richiede la conoscenza dei fondamenti della matematica discreta, della logica dei predicati, degli strumenti di vincolo e di altri rami della logica matematica. Il linguaggio attivo più popolare è Prolog.

Conclusione

Attualmente, le lingue più comuni sono OOP. Java, sin dal suo inizio, è sempre stato tra i primi, di solito tra i primi tre, linguaggi popolari. Oltre all'OOP, contiene elementi di programmazione funzionale e puoi combinare diversi stili di scrittura dei tuoi programmi. La gamma di applicazioni di Java è molto ampia: si tratta di attività aziendali, implementazione di server Web (backend), il linguaggio principale per la creazione di applicazioni Android, ambienti di programmazione e luoghi di lavoro multipiattaforma (IDE/AWM) e modellazione e molto altro ancora . La posizione di Java è particolarmente forte nel settore Enterprise, un'area del software aziendale che richiede codice di alta qualità e di lunga durata e l'implementazione della logica aziendale più complessa.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION