Qual è il prossimo livello di astrazione? [chiuso]

15

Poiché i linguaggi di programmazione inizialmente utilizzavano solo linee di codice eseguite in sequenza, e si sono evolute in funzioni che erano uno dei primi livelli di astrazione, e quindi sono state create classi e oggetti per astrarla ulteriormente; qual è il prossimo livello di astrazione?

Cosa c'è di più astratto delle classi o ce n'è ancora?

    
posta Jordan Medlock 04.09.2012 - 20:23
fonte

10 risposte

32

Penso che tu abbia alcuni malintesi sulla storia dell'informatica.

La prima astrazione (nel 1936) era, infatti, il Lambda Calculus della Chiesa di Alonzo, che è il fondamento del concetto di funzioni di alto livello e di tutti i linguaggi funzionali che seguirono. Ha ispirato direttamente il Lisp (il secondo più antico linguaggio di programmazione ad alto livello, creato nel 1959), che a sua volta ha ispirato tutto, dalla ML a Haskell e Clojure.

La seconda astrazione era la programmazione procedurale. È venuto fuori dalle architetture di computer di von Neumann, dove sono stati scritti programmi sequenziali, un'istruzione alla volta. FORTRAN (il più antico linguaggio di programmazione di alto livello, 1958) è stato il primo linguaggio di alto livello a uscire dal paradigma procedurale.

La terza astrazione probabilmente era in realtà una programmazione dichiarativa, prima esemplificata da Absys (1967) e poi Prolog (1972). È il fondamento della programmazione logica, in cui le espressioni vengono valutate facendo corrispondere una serie di dichiarazioni o regole, piuttosto che eseguire una serie di istruzioni.

La quarta astrazione è stata quindi la programmazione orientata agli oggetti, che ha fatto la sua prima apparizione nei programmi Lisp negli anni '60, ma è stata successivamente esemplificata da Smalltalk nel 1972. (Anche se sembra esserci qualche dibattito sul fatto che lo stile di passaggio dei messaggi di Smalltalk è l'unica vera astrazione orientata agli oggetti, non la toccherò.)

Tutte le altre astrazioni, in particolare sulla tradizionale architettura di computer di von Neumann, sono variazioni su questi quattro temi. Non sono convinto che ci sia un'altra astrazione oltre a quelle quattro che non è semplicemente una variazione o una combinazione di esse.

Ma un'astrazione è, in sostanza, semplicemente un modo per modellare e descrivere un algoritmo. È possibile descrivere gli algoritmi come una serie di passaggi discreti, come un insieme di regole che devono essere rispettate, come un insieme di funzioni matematiche o come oggetti interagenti. È molto difficile concepire un altro modo per descrivere o modellare algoritmi, e anche se esiste, non sono convinto della sua utilità.

Esiste, tuttavia, il modello di calcolo quantistico. Nel calcolo quantistico, sono necessarie nuove astrazioni per modellare gli algoritmi quantistici. Essendo un neofita in quest'area, non posso commentarlo.

    
risposta data 04.09.2012 - 20:50
fonte
4

Per molti, la forma più pura di astrazione del codice nell'era corrente della programmazione binaria è la "funzione di ordine superiore". Fondamentalmente, la funzione stessa viene trattata come dati e le funzioni delle funzioni sono definite, proprio come le vedresti in equazioni matematiche con operatori che definiscono il risultato dei loro operandi e un ordine predeterminato di operazioni che definiscono il "nidificazione" di queste operazioni. La matematica ha pochissimi "comandi imperativi" nella sua struttura; i due esempi a cui posso pensare sono "lascia x avere un valore o essere qualsiasi valore conforme a qualche vincolo" e "funzioni a tratti" in cui l'input determina l'espressione necessaria per produrre l'output. Questi costrutti sono facilmente rappresentabili come proprie funzioni; la "funzione" x restituisce sempre 1 e gli "overload" delle funzioni sono definiti in termini di ciò che viene loro passato (che a differenza dei sovraccarichi orientati agli oggetti può essere definito sulla base dei valori immessi) consentendo la valutazione "a tratti" di un gruppo denominato di funzioni, anche in termini di se stessi. In quanto tale, il programma elimina la nozione di imperativi a basso livello e si concentra invece sulla "valutazione di se stessa" dati i dati di input.

Queste funzioni di ordine superiore formano la spina dorsale dei "linguaggi funzionali"; ciò che un programma fa è definito in termini di "pure funzioni" (uno o più input, uno o più output, nessun effetto collaterale o "stato nascosto"), che sono annidati l'uno nell'altro e valutati come necessario. In questi casi, la maggior parte della "logica imperativa" viene sottratta; il runtime gestisce l'effettiva chiamata di funzioni e qualsiasi condizione in cui l'uno o l'altro sovraccarico di una funzione possa aver bisogno di essere chiamato. In tale programma, il codice non è pensato come "facendo" qualcosa, è pensato come "essere" qualcosa, e ciò che è esattamente è determinato mentre il programma viene eseguito dato l'input iniziale.

Le funzioni di ordine superiore sono ora un punto fermo di molte lingue imperative; Le dichiarazioni lambda di .NET consentono fondamentalmente l'input funzionale "anonimo" in un'altra "funzione" (implementata imperativamente ma teoricamente non deve essere), consentendo così un "concatenamento" altamente personalizzabile di "funzioni" molto generali da raggiungere il risultato desiderato.

Un'altra astrazione comunemente vista nell'ultimo round di linguaggi di programmazione è la tipizzazione dinamica delle variabili basata sul concetto di "tipizzazione"; se sembra un'anatra, nuota come un'anatra, vola come un'anatra e fa la cacca come un'anatra, puoi chiamarla un'anatra. Non importa se è in realtà un germano reale o un tascabile. Potrebbe essere importante se è in realtà un'oca o un cigno, ma di nuovo potrebbe non avere importanza se tutto quello che ti interessa è che nuota e vola, e kinda sembra un'anatra. Questo è considerato il massimo nell'ereditarietà degli oggetti; non ti importa cosa sia , tranne che per dargli un nome; la cosa più importante è ciò che fa . In tali lingue ci sono fondamentalmente solo due tipi; l '"atomo", un singolo elemento di informazione (un "valore", un numero, un carattere, una funzione, qualsiasi cosa) e la "tupla", composta da un atomo e un "puntatore" a tutto il resto nella tupla. Il modo esatto in cui questi tipi sono implementati in binario dal runtime è irrilevante; utilizzando questi, è possibile ottenere la funzionalità di praticamente ogni tipo che si può pensare, dai semplici tipi di valore alle stringhe alle raccolte (che, poiché i valori possono essere di diversi "tipi", consente "tipi complessi" o "oggetti").

    
risposta data 04.09.2012 - 20:30
fonte
2

Si potrebbero considerare i linguaggi specifici del dominio come SQL come un ordine superiore di astrazione. SQL è un linguaggio molto mirato che astrae operazioni come la memorizzazione e fornisce funzioni di livello superiore basate sulla teoria degli insiemi. Considera anche quanti linguaggi mainstream oggi non hanno come target un'architettura specifica, ma piuttosto una macchina virtuale (come la JVM o il CLR .NET). Ad esempio C # è compilato in IL che viene interpretato (o più frequentemente JIT - Just In Time Compiled - in un'implementazione nativa) dal motore di runtime nativo.

Il concetto di DSL è stato usato per creare linguaggi di altissimo livello che possono essere utilizzati senza molta esperienza tecnica per creare un programma funzionante. Pensa se qualcuno fosse in grado di descrivere le loro entità e le loro interazioni in un inglese chiaro e semplice e l'ambiente operativo gestisse qualsiasi cosa, dalla presentazione di un'interfaccia utente semplice, alla memorizzazione di dati in un database di qualche tipo. Una volta che queste operazioni sono state sottratte, puoi immaginare come può diventare una programmazione semplice.

Ne esistono alcuni oggi come JetBrains MPS (che è un kit di strumenti per la descrizione di DSL o un generatore di lingue). Microsoft ha avuto una breve incursione (e molto promettente potrei aggiungere) in questo spazio con la sua lingua M (la Il linguaggio M era così completo che la lingua era definita in M).

I critici del concetto puntano a precedenti tentativi falliti di rimuovere i programmatori dal lavoro di sviluppo di programmi, la differenza con i workbench DSL (come li chiama Fowler) è che gli sviluppatori sarebbero ancora coinvolti nella codifica di concetti che gli esperti di dominio potrebbero utilizzare per esprimere le esigenze del proprio dominio. Proprio come i fornitori di OS e Language creano strumenti che usiamo per la programmazione, utilizzeremmo le DSL per fornire strumenti per gli utenti aziendali. Si potrebbero immaginare DSL che descrivono i dati e la logica, mentre gli sviluppatori creano interpreti che archiviano e recuperano dati e applicano la logica espressa nella DSL.

    
risposta data 12.03.2013 - 09:42
fonte
1

Direi che le meta-strutture, i moduli, i framework, le piattaforme e i servizi sono tutti raggruppamenti di funzionalità di livello superiore rispetto alle classi. La mia gerarchia delle astrazioni del sistema di programmazione:

  • servizi
  • piattaforme, stack di soluzioni
  • framework
  • moduli, pacchetti
  • meta strutture: metaclassi, funzioni di ordine superiore, generici, modelli, tratti, aspetti, decoratori
  • oggetti, classi, tipi di dati
  • funzioni, procedure, subroutine
  • strutture di controllo
  • linee di codice

Meta-strutture come metaclasses , funzioni di ordine superiore e generici aggiungere chiaramente l'astrazione alle classi, alle funzioni, ai tipi di dati e alle istanze di dati di base. Tratti, aspetti e decoratori sono meccanismi più recenti per combinare le caratteristiche del codice e allo stesso modo "accelerare" altre classi e funzioni.

Anche le lingue pre-oggetto avevano moduli e pacchetti, quindi metterli sopra le classi potrebbe essere discutibile. Ma contengono quelle classi e meta-strutture, quindi le classifico più in alto.

I Framework sono la risposta più semplice: orchestrano più classi, meta-strutture, moduli, funzioni e così via per fornire sofisticate astrazioni di alto livello. Eppure i quadri funzionano ancora quasi interamente nel campo della programmazione.

Stack di soluzioni o piattaforme generalmente combinano più framework, sottosistemi o componenti in un ambiente per risolvere più problemi.

Infine, ci sono servizi - spesso distribuiti come Web o servizi di rete. Si tratta di architetture, strutture, stack di soluzioni o funzionalità applicative fornite come pacchetti completi. I loro interni sono spesso opachi, esponendo principalmente l'amministratore, la programmazione e le interfacce utente. PaaS e SaaS sono esempi comuni.

Ora, questa progressione potrebbe non essere del tutto soddisfacente, per alcune ragioni. Innanzitutto, crea una progressione lineare o gerarchia delle cose che non sono perfettamente lineari o gerarchici. Copre alcune astrazioni come "stack" e servizi che non sono interamente sotto il controllo degli sviluppatori. E non pone alcuna nuova polvere magica da folletto. (Spoiler: Non c'è polvere magica per i folletti. )

Penso che sia un errore cercare solo nuovi livelli di astrazione . Tutti quelli che ho elencato sopra sono esistiti per anni , anche se non tutti sono stati così importanti o popolari come lo sono ora. E in quegli anni, le astrazioni possibili a ogni livello di codifica sono migliorate. Ora abbiamo collezioni generiche e generiche, non solo array. Effettuiamo un ciclo su raccolte, non solo su intervalli indice. Abbiamo una lista di comprensione e un elenco di filtri e operazioni sulla mappa. Molte funzioni della lingua possono avere un numero variabile di argomenti e / o argomenti predefiniti. E così via. Stiamo aumentando l'astrazione a livello ogni , quindi aggiungere più livelli non è un requisito per aumentare il livello generale di astrazione.

    
risposta data 04.09.2012 - 22:01
fonte
1

La prossima astrazione dopo le lezioni è metates . È così semplice;)

a class whose instances are classes. Just as an ordinary class defines the behavior of certain objects, a metaclass defines the behavior of certain classes and their instances. Not all object-oriented programming languages support metaclasses. Among those that do, the extent to which metaclasses can override any given aspect of class behavior varies. Each language has its own metaobject protocol, a set of rules that govern how objects, classes, and metaclasses interact...

    
risposta data 04.09.2012 - 21:49
fonte
1

Sono sorpreso che nessuno abbia menzionato la teoria delle categorie.

L'unità di programmazione più fondamentale è la funzione basata sui tipi. Le funzioni sono generalmente indicate come f: A - > B, dove A e B sono tipi. Se metti queste cose, che chiamo tipi e funzioni, insieme nel modo giusto ottieni qualcosa chiamato una categoria. Non devi fermarti a questo punto.

Prendi queste cose, categorie e chiediti quale sarebbe il modo corretto di metterle in relazione tra loro. Se lo fai bene, ottieni qualcosa chiamato functor che va tra due categorie e viene solitamente indicato come F: C - > B. Ancora una volta non devi fermarti.

Puoi prendere tutti i funtori e metterli insieme nel modo giusto e se fai le cose giuste inizi a chiedermi come mettere in relazione due funtori l'uno con l'altro. A questo punto ottieni qualcosa chiamato trasformazione naturale, mu: F - > G, dove F e G sono funtori.

La mia conoscenza a questo punto diventa confusa, ma puoi continuare a farlo e continuare a scalare la scala dell'astrazione. Gli oggetti e le classi non si avvicinano nemmeno a descrivere quanto in alto puoi salire la scala dell'astrazione. Ci sono molte lingue che possono esprimere i concetti sopra computazionalmente e la più importante di quelle lingue è Haskell. Quindi se vuoi davvero sapere di cosa tratta l'astrazione, allora impara ad usare Haskell o Agda o HOL o ML.

    
risposta data 04.05.2013 - 09:35
fonte
1

Penso che il modello dell'attore manchi dalla lista dei candidati.

Ecco cosa intendo per attori:

  • entità indipendenti
  • che riceve messaggi e quando riceve un messaggio può
  • crea nuovi attori,
  • aggiorna alcuni stati interni per il messaggio successivo,
  • e invia messaggi

Questo modello è qualcosa che va oltre le macchine deterministiche di Turing, ed è in realtà più vicino al nostro hardware del mondo reale quando si guardano programmi concorrenti. A meno che non utilizzi passaggi di sincronizzazione aggiuntivi (costosi), in questi giorni, quando il tuo codice riceve dati, quel valore potrebbe già essere cambiato sull'altro lato dello stesso dado, forse anche all'interno dello stesso core.

Breve discussione / introduzione: link

    
risposta data 04.05.2013 - 11:51
fonte
0

Se ti capisco bene, le tue "astrazioni ascendenti" possono essere pensate come incapsulamenti di logica sempre più grandi, per lo più legati al riutilizzo del codice.

Da specifiche istruzioni eseguite una dopo l'altra, passiamo a funzioni / subroutine , che incapsulano, o astraggono, un raggruppamento logico di istruzioni in un singolo elemento. Poi abbiamo objects , o modules , che incapsulano subroutine relative a una certa entità o categoria logica, quindi posso raggruppare tutte le operazioni stringa sotto la classe String , o tutte operazioni matematiche comuni nel modulo Math (o classe statica, in lingue come C #).

Quindi, se questa è la nostra progressione, cosa verrà dopo? Bene, non penso che tu abbia un passo successivo ben definito. Come altri hanno risposto, il tuo progresso si applica solo agli stili di programmazione imperativo / procedurale e altri paradigmi non condividono i tuoi concetti di astrazione. Ma se ho qualcosa che può estendere logicamente la tua metafora, è servizi .

Un servizio è simile a una classe nel senso che è un'entità che espone funzionalità, ma implica una separazione delle preoccupazioni molto più severa rispetto all'offset con gli oggetti che hai istanziato. Espongono un insieme limitato di operazioni, nascondono la logica interna e non sono nemmeno necessariamente in esecuzione sulla stessa macchina.

Ancora una volta, c'è una bella distinzione. Nella maggior parte dei casi, utilizzerai un oggetto che funge da proxy per un servizio , e i due saranno molto simili, ma come architettura, i due sono distinti.

    
risposta data 04.09.2012 - 21:07
fonte
0

Nuove forme di astrazione nascondono il lavoro a basso livello da te. Le procedure e le funzioni con nome nascondono gli indirizzi dei programmi da te. Gli oggetti nascondono la gestione dinamica della memoria e alcune "istruzioni if" dipendenti dal tipo.

Suggerirei che il prossimo livello di astrazioni pratiche che nascondono faticosezze a basso livello da parte tua sono quelle di programmazione reattiva funzionale . Guarda i "segnali" in qualcosa come link che nasconde i callback e aggiorna le dipendenze che dovresti gestire esplicitamente in javascript. FRP può nascondere molta della complessità dell'inter-processo e delle comunicazioni tra macchine necessarie nelle applicazioni Internet su larga scala e nel parallelismo ad alte prestazioni.

Sono abbastanza sicuro che questo è ciò che ci entusiasmeremo nei prossimi 5 anni.

    
risposta data 20.03.2013 - 03:05
fonte
0

La teoria degli insiemi - come parzialmente implementata nei database relazionali, ma anche in linguaggi statistici come SAS e R, fornisce un livello di astrazione diverso ma probabilmente più alto di OO.

    
risposta data 20.03.2013 - 04:35
fonte