Qual è il prossimo livello di astrazione? [chiuso]


15

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

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


17
Sembra che pensi che sia una progressione lineare, con un ordinamento ("X è più astratto di Y è più astratto di Z"). Mi permetto di dissentire.

2
Sarebbe una buona idea dire perché ti permetti di dissentire. ;) (leggi: sono interessato!)
sergserg

3
Propongo la massima "astrazione": fai quello che penso, non quello che scrivo. ;)
Izkata,

1
@Delnan: L'astrazione non introduce un ordine totale, ma è possibile dire "più astratto", "meno astratto". Ad esempio, un'implementazione generica di merge sort è più astratta di un'implementazione di merge sort che funziona solo per numeri interi.
Giorgio,

2
Bros, impara qualche teoria delle categorie. Quindi possiamo discutere di cosa significhi davvero l'astrazione come gli uomini civili.
davidk01,

Risposte:


32

Penso che tu abbia alcune idee sbagliate sulla storia dell'informatica.

La prima astrazione (nel 1936) fu, in effetti, il Lambda Calculus della Alonzo Church, che è la base del concetto di funzioni di alto ordine e di tutti i linguaggi funzionali che seguirono. Ha ispirato direttamente Lisp (il secondo linguaggio di programmazione di alto livello più antico, creato nel 1959), che a sua volta ha ispirato qualsiasi cosa, da ML a Haskell e Clojure.

La seconda astrazione era la programmazione procedurale. È uscito dalle architetture informatiche von Neumann in cui sono stati scritti programmi sequenziali, un'istruzione alla volta. FORTRAN (il più antico linguaggio di programmazione di alto livello, 1958) fu il primo linguaggio di alto livello ad uscire dal paradigma procedurale.

La terza astrazione era probabilmente una programmazione dichiarativa, esemplificata da Absys (1967), e successivamente da Prolog (1972). È il fondamento della programmazione logica, in cui le espressioni vengono valutate abbinando una serie di dichiarazioni o regole, anziché eseguire una serie di istruzioni.

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

Tutte le altre astrazioni, in particolare sulla tradizionale architettura informatica di von Neumann, sono variazioni su questi quattro temi. Non sono convinto che ci sia un'altra astrazione oltre 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 gli algoritmi e, anche se esiste, non sono convinto della sua utilità.

Vi è, tuttavia, il modello di calcolo quantistico. Nell'informatica quantistica sono necessarie nuove astrazioni per modellare gli algoritmi quantistici. Essendo un neofita in quest'area, non posso commentarlo.


4
La programmazione orientata agli aspetti potrebbe essere considerata ancora un'altra forma di astrazione?
Drago Shivan,

La programmazione orientata agli oggetti è nata da Lisp negli anni '60? [citazione necessaria], grande tempo. Tutto quello che ho sentito dire che è uscito da Simula negli anni '60, che era un diretto discendente di ALGOL, un linguaggio imperativo che non aveva nulla a che fare con Lisp. Smalltalk è nato prendendo i concetti introdotti da Simula e ruotandoli per sentirsi più "morbidi".
Mason Wheeler,

3
@MasonWheeler: è nei manuali Lisp 1 e 1.5, ed è comune ascoltare Lispers parlare di programmi orientati agli oggetti, specialmente i vecchi. All'epoca i ragazzi dell'IA erano bravi a realizzare sistemi di oggetti in Lisp.
Greyfade,

2
@ShivanDragon: direi di no. È solo un modo di strumentare un programma altrimenti procedurale con imbracature aggiuntive. In realtà non modella gli algoritmi, né sembra influenzare la progettazione delle strutture di dati.
Greyfade,

4
In realtà, il calcolo del combinatore SKI precede sia il calcolo lambda che la macchina di Turing.
Jörg W Mittag,

4

Per molti, la forma più pura di astrazione del codice nell'era attuale 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 si vedrebbero in equazioni matematiche con gli operatori che definiscono il risultato dei loro operandi e un ordine predeterminato di operazioni che definiscono il "annidamento" di queste operazioni. La matematica ha pochissimi "comandi imperativi" nella sua struttura; i due esempi a cui riesco a pensare sono "lascia che x abbia un valore o sia un valore conforme a un 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 "sovraccarichi" di funzioni sono definite in termini di ciò che viene loro passato (che a differenza dei sovraccarichi orientati agli oggetti possono essere definiti in base ai valori immessi) consentendo una valutazione "a tratti" di un gruppo di funzioni denominato, anche in termini di se stessi. Come tale, il programma elimina la nozione di imperativi a basso livello e si concentra invece sulla "valutazione di se stesso" dati di input dati.

Queste funzioni di ordine superiore costituiscono la spina dorsale dei "linguaggi funzionali"; ciò che fa un programma è definito in termini di "funzioni pure" (uno o più input, uno o più output, senza effetti collaterali o "stato nascosto"), che sono nidificati l'uno nell'altro e valutati se necessario. In tali casi, la maggior parte della "logica imperativa" viene sottratta; il runtime gestisce l'effettiva chiamata di funzioni e può essere necessario chiamare qualsiasi condizione in cui l'uno o l'altro sovraccarico di una funzione. In un tale programma, il codice non è pensato come "fare" qualcosa, è pensato come "essere" qualcosa e ciò che è esattamente determinato quando il programma viene eseguito con l'input iniziale.

Le funzioni di ordine superiore sono ora un punto fermo anche di molte lingue imperative; Le istruzioni lambda di .NET consentono fondamentalmente un input funzionale "anonimo" in un'altra "funzione" (implementata in modo imperativo ma teoricamente non deve essere), consentendo in tal modo "concatenamento" altamente personalizzabile di "funzioni" di uso molto generale il risultato desiderato.

Un'altra astrazione che si vede comunemente nell'ultimo giro di linguaggi di programmazione è la tipizzazione variabile dinamica basata sul concetto di "tipizzazione anatra"; se sembra un'anatra, nuota come un'anatra, vola come un'anatra e cigola come un'anatra, puoi chiamarla anatra. Non importa se in realtà è un germano reale o un canvasback. Potrebbe importare se in realtà è un'oca o un cigno, ma poi potrebbe non importare se tutto ciò che ti interessa è che nuota e vola, e un po ' sembra un'anatra. Questo è considerato il massimo dell'eredità degli oggetti; non ti importa di cosa si tratti , tranne che per dargli un nome; ciò che è 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, carattere, funzione, qualunque cosa) e la "tupla", composta da un atomo e un "puntatore" a tutto il resto della tupla. Il modo esatto in cui questi tipi vengono implementati in binario dal runtime è irrilevante; usando questi, puoi ottenere la funzionalità praticamente di ogni tipo a cui riesci a pensare, dai tipi di valore semplici alle stringhe alle raccolte (che, dato che i valori possono essere di "tipi" diversi, consente "tipi complessi" noti anche come "oggetti").


1
"Duck typing" (almeno come descritto) non è realmente nuovo o limitato ai linguaggi tipizzati dinamicamente; è in circolazione da molto tempo nei linguaggi tipicamente statici come "sotto-tipizzazione strutturale", meglio visibile in OCaml.
Tikhon Jelvis,

2

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

Il concetto di DSL utilizzato per creare linguaggi di altissimo livello che possono essere utilizzati senza molta esperienza tecnica per creare un programma di lavoro è stato molto diffuso. Pensa se qualcuno fosse in grado di descrivere le proprie entità e interazioni in un inglese quasi semplice e l'ambiente operativo gestisse tutto, dalla presentazione di una semplice interfaccia utente, alla memorizzazione dei dati in un database di qualche tipo. Una volta che tali operazioni vengono astratte, puoi immaginare come può diventare semplice la programmazione.

Esistono oggi alcuni come JetBrains MPS (che è un toolkit per la descrizione di DSL o un generatore di linguaggio). Microsoft ha avuto una breve incursione (e molto promettente potrei aggiungere) in questo spazio con il suo linguaggio M (il linguaggio M era così completo che il linguaggio è stato definito in M).

I critici del concetto indicano precedenti tentativi falliti di rimuovere i programmatori dal lavoro di sviluppo di programmi, la differenza con i banchi di lavoro DSL (come li chiama Fowler) è che, gli sviluppatori sarebbero ancora coinvolti nella codificazione di concetti che gli esperti di dominio potrebbero usare per esprimere le esigenze del loro dominio. Proprio come i fornitori di sistemi operativi e lingue creano strumenti che utilizziamo per la programmazione, utilizzeremmo DSL per fornire strumenti agli utenti aziendali. Si potrebbero immaginare DSL che descrivono i dati e la logica, mentre gli sviluppatori creano interpreti che archiviano e recuperano i dati e applicano la logica espressa nel DSL.


1

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

  • Servizi
  • piattaforme, stack di soluzioni
  • quadri
  • 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
  • righe di codice

Meta-strutture come metaclassi , funzioni di ordine superiore e generici aggiungono chiaramente astrazione a classi, funzioni, tipi di dati e 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 i linguaggi 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.

Quadri sono la risposta più carnoso - essi orchestrare più classi, meta-strutture, moduli, funzioni e quali, al fine di fornire sofisticate astrazioni ad alto livello. Eppure i framework funzionano ancora quasi interamente nel regno della programmazione.

Gli stack o le piattaforme delle soluzioni generalmente combinano più framework, sottosistemi o componenti in un ambiente per risolvere molteplici problemi.

Infine, ci sono servizi, spesso distribuiti come servizi Web o di rete. Si tratta di architetture, framework, stack di soluzioni o funzionalità dell'applicazione fornite come bundle completi. I loro interni sono spesso opachi, esponendo principalmente le interfacce amministratore, programmazione e utente. PaaS e SaaS sono esempi comuni.

Ora, questa progressione potrebbe non essere del tutto soddisfacente, per alcuni motivi. In primo luogo, crea una graduale progressione lineare o una gerarchia di cose che non sono perfettamente lineari o gerarchiche. Copre alcune astrazioni come "stack" e servizi che non sono interamente sotto il controllo degli sviluppatori. E non contiene alcuna nuova polvere magica di folletto. (Spoiler: non c'è polvere magica di folletto. )

Penso che sia un errore cercare solo nuovi livelli di astrazione . Tutti quelli che ho elencato sopra esistono da anni , anche se non sono stati tutti così importanti o popolari come lo sono ora. E in quegli anni, le astrazioni possibili ad ogni livello di codifica sono migliorate. Ora disponiamo di raccolte generiche e generiche, non solo di array. Passiamo in rassegna le raccolte, non solo gli intervalli di indice. Abbiamo comprensione dell'elenco e operazioni di filtro e mappa dell'elenco. Molte funzioni del linguaggio possono avere un numero variabile di argomenti e / o argomenti predefiniti. E così via. Stiamo aumentando l'astrazione a tutti i livelli, quindi aggiungere più livelli non è un requisito per aumentare il livello complessivo di astrazione.


1

L'astrazione successiva dopo le lezioni sono le metaclasse . È così semplice ;)

una classe le cui istanze sono classi. Proprio come una classe ordinaria definisce il comportamento di determinati oggetti, una metaclasse definisce il comportamento di determinate classi e le loro istanze. Non tutti i linguaggi di programmazione orientati agli oggetti supportano metaclass. Tra quelli che lo fanno, la misura in cui i metaclassi possono prevalere su un dato aspetto del comportamento di classe varia. Ogni lingua ha il suo protocollo metaoggetto, un insieme di regole che regolano il modo in cui oggetti, classi e metaclassi interagiscono ...


1
Le metaclasse sono gli oggetti radice della gerarchia ereditaria (e) del linguaggio. .NET è Object. Puoi anche pensare alle interfacce come metaclassi; definiscono l'interfaccia dei loro eredi indipendentemente dalla classe "genitore" effettiva dell'erede.
KeithS,

1
@KeithS non è quello che significa la parola in qualsiasi contesto l'ho vista - da CLOS a UML a C #. Una metaclasse è una classe le cui istanze sono classi - un'implementazione debole è quella di C # Typeche offre capacità riflessive ma non mutazione (non è possibile aggiungere un nuovo metodo MyTypedicendo typeof(MyType).Methods += new Method ( "Foo", (int x)=>x*x )come si può fare in CLOS)
Pete Kirkham

1

Sono sorpreso che nessuno abbia menzionato la teoria delle categorie.

L'unità di programmazione più fondamentale è la funzione che si basa 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 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 un funzione che va tra due categorie ed è generalmente indicato come F: C -> B. Ancora una volta non devi fermarti.

Puoi prendere tutti i funzioni e metterle insieme nel modo giusto e se fai le cose nel modo giusto inizi a chiederti come mettere in relazione due funzioni tra loro. A questo punto ottieni qualcosa chiamato trasformazione naturale, mu: F -> G, dove F e G sono funzioni.

La mia conoscenza a questo punto diventa confusa ma puoi continuare a farlo e continuare a salire la scala dell'astrazione. Gli oggetti e le classi non si avvicinano nemmeno a descrivere quanto in alto puoi salire sulla scala dell'astrazione. Esistono molte lingue in grado di esprimere computazionalmente i concetti di cui sopra e la più importante di queste lingue è Haskell. Quindi, se vuoi davvero sapere di cosa si tratta in realtà, allora impara qualche Haskell o Agda o HOL o ML.


1

Penso che il modello dell'attore non sia presente nell'elenco dei candidati.

Ecco cosa intendo per attori:

  • entità indipendenti
  • che ricevono messaggi e quando ricevono un messaggio, possono
  • creare nuovi attori,
  • aggiorna lo stato interno per il messaggio successivo,
  • e inviare messaggi

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

Breve discussione / introduzione: http://youtube.com/watch?v=7erJ1DV_Tlo


il tuo post è piuttosto difficile da leggere (wall of text). Ti dispiacerebbe modificarlo in una forma migliore?
moscerino del

0

Se ti capisco correttamente, le tue "astrazioni ascendenti" possono essere pensate come incapsulamenti della logica sempre più grandi, principalmente legati al riutilizzo del codice.

Da istruzioni specifiche eseguite una dopo l'altra, passiamo alle funzioni / subroutine , che incapsulano, o astraggono, un raggruppamento logico di istruzioni in un singolo elemento. Quindi abbiamo oggetti o moduli che incapsulano i sottoprogrammi relativi a una certa entità o categoria logica, in modo da poter raggruppare tutte le operazioni di stringa sotto la Stringclasse o tutte le operazioni matematiche comuni sotto il Mathmodulo (o classe statica, in linguaggi come C #) .

Quindi se questa è la nostra progressione, cosa verrà dopo? Beh, non credo che tu abbia un passo chiaro e preciso. Come altri hanno risposto, la tua progressione si applica solo agli stili di programmazione imperativa / procedurale e altri paradigmi non condividono i tuoi concetti di astrazione. Ma se ho qualcosa che può logicamente estendere la tua metafora, sono i servizi .

Un servizio è simile a una classe, nel senso che è un'entità che espone funzionalità, ma implica una separazione molto più rigorosa delle preoccupazioni rispetto all'andare avanti e indietro con gli oggetti che hai istanziato. Espongono un insieme limitato di operazioni, nascondono la logica interna e non sono 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.


0

Nuove forme di astrazione ti nascondono un lavoro di basso livello. Le procedure e le funzioni denominate ti nascondono gli indirizzi dei programmi. Gli oggetti nascondono la gestione dinamica della memoria e alcune "istruzioni if" dipendenti dal tipo.

Suggerirei che il prossimo livello di astrazioni pratiche che ti nasconderà la fatica di basso livello sono quelli della programmazione reattiva funzionale . Guarda i "segnali" in qualcosa come http://elm-lang.org/ che nascondono i callback e aggiornano le dipendenze che dovresti gestire esplicitamente in javascript. FRP può nascondere la complessità della comunicazione tra processi e tra macchine necessaria nelle applicazioni Internet su larga scala e nel parallelismo ad alte prestazioni.

Sono abbastanza sicuro che questo è ciò di cui saremo tutti entusiasti nei prossimi 5 anni circa.


1
FRP è eccezionale, ma si occupa di un tipo di programmazione abbastanza specifico (vale a dire la programmazione reattiva ). Non è molto utile per modellare altri tipi di programmi. Tuttavia, il tipo più generale di programmazione che rappresenta - scrivere il codice in termini di algebre - è un buon candidato per un nuovo livello di astrazione.
Tikhon Jelvis,

0

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.

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.