Was ist die nächste Abstraktionsebene? [geschlossen]


15

Da in den Programmiersprachen anfangs nur Codezeilen verwendet wurden, die nacheinander ausgeführt wurden, wurden Funktionen eingeschlossen, die eine der ersten Abstraktionsebenen darstellten. Anschließend wurden Klassen und Objekte erstellt, um den Code noch weiter zu abstrahieren. Was ist die nächste Abstraktionsebene?

Was ist noch abstrakter als der Unterricht oder gibt es noch einen?


17
Sie scheinen zu glauben, dass dies ein linearer Verlauf mit einer Reihenfolge ist ("X ist abstrakter als Y ist abstrakter als Z"). Ich bin anderer Ansicht.

2
Es wäre eine ziemlich gute Idee, zu sagen, warum Sie betteln, um sich zu unterscheiden. ;) (gelesen: Ich bin interessiert!)
sergserg

3
Ich schlage die ultimative "Abstraktion" vor: Tu was ich denke, nicht was ich schreibe. ;)
Izkata

1
@Delnan: Abstraktion führt keine Gesamtordnung ein, aber man kann sagen "abstrakter", "weniger abstrakt". Beispielsweise ist eine generische Implementierung der Zusammenführungssortierung abstrakter als eine Implementierung der Zusammenführungssortierung, die nur für Ganzzahlen funktioniert.
Giorgio

2
Bros, lerne dir eine Kategorietheorie. Dann können wir diskutieren, was Abstraktion wirklich wie zivilisierte Männer bedeutet.
Davidk01

Antworten:


32

Ich denke, Sie haben einige falsche Vorstellungen über die Geschichte des Computens.

Die erste Abstraktion (1936) war tatsächlich die Lambda-Rechnung der Alonzo-Kirche, die die Grundlage für das Konzept der Funktionen höherer Ordnung und aller folgenden funktionalen Sprachen bildet. Es inspirierte direkt Lisp (die zweitälteste Programmiersprache auf hohem Niveau, die 1959 erstellt wurde), was wiederum alles von ML bis Haskell und Clojure inspirierte.

Die zweite Abstraktion war die prozedurale Programmierung. Es stammt aus den von Neumann-Computerarchitekturen, in denen sequentielle Programme geschrieben wurden, eine Anweisung nach der anderen. FORTRAN (die älteste Programmiersprache auf hoher Ebene, 1958) war die erste Hochsprache, die aus dem prozeduralen Paradigma hervorging.

Die dritte Abstraktion war wahrscheinlich deklaratives Programmieren, zuerst am Beispiel von Absys (1967) und dann von Prolog (1972). Es ist die Grundlage der Logikprogrammierung, bei der Ausdrücke durch Abgleichen einer Reihe von Deklarationen oder Regeln ausgewertet werden, anstatt eine Reihe von Anweisungen auszuführen.

Die vierte Abstraktion war dann die objektorientierte Programmierung, die in den 60er Jahren zum ersten Mal in Lisp-Programmen auftauchte, aber später von Smalltalk im Jahr 1972 veranschaulicht wurde die Eine Wahre objektorientierte Abstraktion. Ich werde das nicht anfassen.)

Alle anderen Abstraktionen, insbesondere zur traditionellen von Neumann-Computerarchitektur, sind Variationen dieser vier Themen. Ich bin nicht davon überzeugt, dass es eine andere Abstraktion gibt als diese vier, die nicht nur eine Variation oder eine Kombination davon ist.

Aber eine Abstraktion ist im Wesentlichen nur ein Weg, einen Algorithmus zu modellieren und zu beschreiben. Sie können Algorithmen als eine Reihe von diskreten Schritten, als einen Satz von Regeln, die befolgt werden müssen, als einen Satz von mathematischen Funktionen oder als interagierende Objekte beschreiben. Es ist sehr schwer, Algorithmen auf andere Weise zu beschreiben oder zu modellieren, und selbst wenn es solche gibt, bin ich von ihrer Nützlichkeit nicht überzeugt.

Es gibt jedoch das Quantenrechenmodell. Beim Quantencomputing sind neue Abstraktionen erforderlich, um Quantenalgorithmen zu modellieren. Da ich ein Neuling in diesem Bereich bin, kann ich nichts dazu sagen.


4
Könnte aspektorientierte Programmierung eine weitere Form der Abstraktion sein?
Shivan Dragon

Objektorientierte Programmierung kam in den 60er Jahren von Lisp? [Zitat benötigt], große Zeit. Alles, was ich gehört habe, besagt, dass es aus Simula in den 60er Jahren stammte , die direkt von ALGOL abstammte, einer imperativen Sprache, die nichts mit Lisp zu tun hatte. Smalltalk entstand, indem von Simula eingeführte Konzepte aufgegriffen und gedreht wurden, um sich "lispiger" zu fühlen.
Mason Wheeler

3
@ MasonWheeler: Es steht in den Handbüchern zu Lisp 1 und 1.5, und es ist üblich, dass Lispers davon spricht, objektorientierte Programme zu machen, besonders die alten Leute. Die KI-Leute waren zu der Zeit groß in der Herstellung von Objektsystemen in Lisp.
greyfade

2
@ ShivanDragon: Ich würde nein sagen. Es ist nur eine Möglichkeit, ein ansonsten prozedurales Programm mit zusätzlichen Kabelbäumen zu instrumentieren. Es modelliert weder Algorithmen, noch scheint es das Design von Datenstrukturen zu beeinflussen.
greyfade

4
Tatsächlich geht die SKI-Kombinationsrechnung sowohl der Lambda-Rechnung als auch der Turing-Maschine voraus.
Jörg W Mittag

4

Für viele ist die reinste Form der Code-Abstraktion in der gegenwärtigen Ära der binären Programmierung die "Funktion höherer Ordnung". Grundsätzlich wird die Funktion selbst als Daten behandelt und Funktionen von Funktionen werden so definiert, wie Sie es in mathematischen Gleichungen mit Operatoren sehen würden, die das Ergebnis ihrer Operanden und eine vorbestimmte Reihenfolge von Operationen definieren, die die "Verschachtelung" dieser Operationen definieren. Mathematik hat nur sehr wenige "Imperativbefehle" in ihrer Struktur. Die beiden Beispiele, an die ich denken kann, sind "lass x einen Wert haben oder sei ein beliebiger Wert, der einer bestimmten Einschränkung entspricht" und "stückweise Funktionen", bei denen die Eingabe den Ausdruck bestimmt, der zur Erzeugung der Ausgabe benötigt wird. Diese Konstrukte sind leicht als ihre eigenen Funktionen darstellbar; die "Funktion" x liefert immer 1 und "Überladungen" von Funktionen werden in Bezug auf das definiert, was an sie übergeben wird (was im Gegensatz zu objektorientierten Überladungen auf der Grundlage von eingegebenen Werten definiert werden kann), was die "stückweise" Auswertung einer benannten Gruppe von Funktionen auch in Bezug auf sich selbst ermöglicht. Als solches beseitigt das Programm die Vorstellung von Imperativen auf niedriger Ebene und konzentriert sich stattdessen darauf, gegebene Eingabedaten "selbst zu bewerten".

Diese Funktionen höherer Ordnung bilden das Rückgrat der "funktionalen Sprachen"; Was ein Programm tut, wird durch "reine Funktionen" definiert (eine oder mehrere Eingaben, eine oder mehrere Ausgaben, keine Nebenwirkungen oder "versteckter Zustand"), die ineinander verschachtelt und nach Bedarf ausgewertet werden. In solchen Fällen wird die meiste "imperative Logik" weg abstrahiert; Die Laufzeit übernimmt den eigentlichen Funktionsaufruf und alle Bedingungen, unter denen die eine oder andere Überlastung einer Funktion aufgerufen werden muss. In einem solchen Programm wird der Code nicht als "etwas tun", er wird als "etwas sein" betrachtet, und was genau es ist, wird bestimmt, wenn das Programm bei der ersten Eingabe ausgeführt wird.

Funktionen höherer Ordnung sind mittlerweile auch ein Grundnahrungsmittel vieler imperativer Sprachen. Die Lambda-Anweisungen von .NET ermöglichen im Grunde genommen eine "anonyme" funktionale Eingabe in eine andere "Funktion" (die zwingend implementiert ist, aber theoretisch nicht muss), wodurch eine hochgradig anpassbare "Verkettung" von sehr universellen "Funktionen" erzielt werden kann das gewünschte Ergebnis.

Eine andere Abstraktion, die häufig in der jüngsten Runde der Programmiersprachen zu sehen ist, ist die dynamische Variablentypisierung auf der Grundlage des Konzepts der "Ententypisierung". Wenn es aussieht wie eine Ente, schwimmt wie eine Ente, fliegt wie eine Ente und quakt wie eine Ente, können Sie es eine Ente nennen. Egal ob Stockente oder Canvasback. Es ist MÖGLICHERWEISE wichtig, ob es sich tatsächlich um eine Gans oder einen Schwan handelt, aber andererseits ist es vielleicht auch egal, ob Sie sich nur darum kümmern, dass sie schwimmt und fliegt und irgendwie wie eine Ente aussieht. Dies wird als ultimative Objektvererbung angesehen. Es ist dir egal, was es ist , außer dass du ihm einen Namen gibst. was wichtiger ist, was es tut. In solchen Sprachen gibt es grundsätzlich nur zwei Arten; das "Atom", ein einzelnes Informationselement (ein "Wert"; eine Zahl, ein Zeichen, eine Funktion, was auch immer) und das "Tupel", bestehend aus einem Atom und einem "Zeiger" auf alles andere im Tupel. Wie genau diese Typen zur Laufzeit binär implementiert werden, ist unerheblich. Mit diesen können Sie die Funktionalität von praktisch jedem Typ erreichen, den Sie sich vorstellen können, von einfachen Werttypen über Zeichenfolgen bis hin zu Auflistungen (die, da Werte von verschiedenen "Typen" sein können, "komplexe Typen" oder "Objekte" zulassen).


1
"Duck Typing" (zumindest wie Sie beschreiben) ist nicht wirklich neu oder auf dynamisch getippte Sprachen beschränkt. Es gibt es schon lange in statisch typisierten Sprachen als "strukturelle Untertypisierung", am besten in OCaml.
Tikhon Jelvis

2

Man könnte domänenspezifische Sprachen wie SQL als eine höhere Abstraktionsordnung betrachten. SQL ist eine sehr zielgerichtete Sprache, die Operationen wie das Speichern abstrahiert und Funktionen auf höherer Ebene basierend auf der Mengenlehre bietet. Bedenken Sie auch, wie viele gängige Sprachen heute nicht auf eine bestimmte Architektur abzielen, sondern auf eine virtuelle Maschine (wie die JVM oder die .NET CLR). Zum Beispiel wird C # in IL kompiliert, was von der nativen Laufzeit-Engine interpretiert wird (oder häufiger in JIT - Just In Time Compiled - für eine native Implementierung).

Das Konzept der Verwendung von DSLs zur Erstellung von Hochsprachen, die ohne große technische Erfahrung zur Erstellung eines Arbeitsprogramms verwendet werden können, hat viel Aufsehen erregt. Überlegen Sie, ob jemand in der Lage wäre, seine Entitäten und Interaktionen in einfachem Englisch zu beschreiben, und die Betriebsumgebung alles von der Präsentation einer einfachen Benutzeroberfläche bis zum Speichern von Daten in einer Datenbank erledigt. Sobald diese Operationen abstrahiert sind, können Sie sich vorstellen, wie mühelos das Programmieren werden kann.

Heutzutage gibt es einige, wie zum Beispiel JetBrains MPS (ein Toolkit zur Beschreibung von DSLs oder eines Sprachgenerators). Microsoft hatte einen kurzen (und vielversprechenden) Ausflug in diesen Raum mit seiner M-Sprache (die M-Sprache war so vollständig, dass die Sprache in M ​​definiert war).

Kritiker des Konzepts verweisen auf frühere gescheiterte Versuche, Programmierer von der Arbeit bei der Programmentwicklung auszuschließen. Der Unterschied zu den DSL-Workbenches (wie Fowler sie nennt) besteht darin, dass Entwickler weiterhin an der Codierung von Konzepten beteiligt sind, die die Domain-Experten verwenden könnten, um diese auszudrücken die Bedürfnisse ihrer Domain. So wie Anbieter von Betriebssystemen und Sprachen Tools erstellen, die wir für die Programmierung verwenden, verwenden wir DSLs, um Tools für Geschäftsanwender bereitzustellen. Man kann sich DSLs vorstellen, die Daten und Logik beschreiben, während Entwickler Interpreter erstellen, die Daten speichern und abrufen und die in der DSL ausgedrückte Logik anwenden.


1

Ich würde argumentieren, dass Metastrukturen, Module, Frameworks, Plattformen und Services alle übergeordnete Feature-Gruppierungen als Klassen sind. Meine Hierarchie der Abstraktionen von Programmiersystemen:

  • Dienstleistungen
  • Plattformen, Lösungsstapel
  • Frameworks
  • Module, Pakete
  • Metastrukturen: Metaklassen, Funktionen höherer Ordnung, Generika, Vorlagen, Merkmale, Aspekte, Dekoratoren
  • Objekte, Klassen, Datentypen
  • Funktionen, Prozeduren, Unterprogramme
  • Kontrollstrukturen
  • Zeilen von Code

Metastrukturen wie Metaklassen , Funktionen höherer Ordnung und Generika verleihen Basisklassen, Funktionen, Datentypen und Dateninstanzen eine klare Abstraktion. Merkmale, Aspekte und Dekoratoren sind neuere Mechanismen zum Kombinieren von Code-Features und zum "Beschleunigen" anderer Klassen und Funktionen.

Sogar Vor-Objekt-Sprachen hatten Module und Pakete, so dass es fraglich sein könnte, sie über Klassen zu setzen. Weil sie diese Klassen und Metastrukturen enthalten, rangiere ich sie höher.

Frameworks sind die beste Antwort - sie orchestrieren mehrere Klassen, Metastrukturen, Module, Funktionen usw., um anspruchsvolle Abstraktionen auf hoher Ebene bereitzustellen. Und doch arbeiten Frameworks fast ausschließlich im Bereich der Programmierung.

Lösungsstacks oder -plattformen kombinieren im Allgemeinen mehrere Frameworks, Subsysteme oder Komponenten in einer Umgebung, um mehrere Probleme zu lösen.

Schließlich gibt es Dienste, die häufig als Web- oder Netzwerkdienste bereitgestellt werden. Hierbei handelt es sich um Architekturen, Frameworks, Lösungsstacks oder Anwendungsfunktionen, die als vollständige Bundles bereitgestellt werden. Ihre Interna sind oft undurchsichtig und legen in erster Linie Administrator-, Programmier- und Benutzeroberflächen offen. PaaS und SaaS sind gängige Beispiele.

Nun, diese Entwicklung ist aus einigen Gründen möglicherweise nicht ganz zufriedenstellend. Erstens macht es eine ordentliche lineare Abfolge oder Hierarchie von Dingen, die nicht perfekt linear oder hierarchisch sind. Es behandelt einige Abstraktionen wie "Stacks" und Service, die nicht vollständig unter der Kontrolle des Entwicklers stehen. Und es setzt keinen neuen magischen Elfenstaub fest. (Spoiler: Es gibt keinen magischen Elfenstaub. )

Ich denke , dass es ein Fehler ist nur für neue Abstraktion aussehen Ebene . Alle, die ich oben aufgeführt habe, gibt es schon seit Jahren , auch wenn sie nicht alle so prominent oder populär waren, wie sie jetzt sind. Und im Laufe der Jahre haben sich die Abstraktionen auf allen Codierungsebenen verbessert. Wir haben jetzt allgemeine, generische Sammlungen, nicht nur Arrays. Wir durchlaufen Sammlungen, nicht nur Indexbereiche. Wir haben Listenverständnisse und Listenfilter- und Kartenoperationen. Viele Sprachfunktionen können eine variable Anzahl von Argumenten und / oder Standardargumenten haben. Und so weiter. Wir erhöhen die Abstraktion auf jeder Ebene, daher ist das Hinzufügen weiterer Ebenen keine Voraussetzung für die Erhöhung der gesamten Abstraktionsebene.


1

Die nächste Abstraktion nach Klassen sind Metaklassen . So einfach ist das;)

eine Klasse, deren Instanzen Klassen sind. So wie eine gewöhnliche Klasse das Verhalten bestimmter Objekte definiert, definiert eine Metaklasse das Verhalten bestimmter Klassen und ihrer Instanzen. Nicht alle objektorientierten Programmiersprachen unterstützen Metaklassen. Unter denen, die dies tun, variiert das Ausmaß, in dem Metaklassen einen bestimmten Aspekt des Klassenverhaltens außer Kraft setzen können. Jede Sprache hat ein eigenes Metaobjektprotokoll, eine Reihe von Regeln, die bestimmen, wie Objekte, Klassen und Metaklassen interagieren ...


1
Metaklassen sind die Stammobjekte der Vererbungshierarchie (n) der Sprache. .NET ist Objekt. Sie können sich Schnittstellen auch als Metaklassen vorstellen. Sie definieren die Schnittstelle ihrer Erben unabhängig von der eigentlichen "Eltern" -Klasse des Erben.
KeithS

1
@KeithS das ist nicht das, was das Wort in irgendeinem Zusammenhang bedeutet, den ich gesehen habe - von CLOS über UML bis C #. Eine Metaklasse ist eine Klasse, deren Instanzen Klassen sind - eine schwache Implementierung ist C #, Typedie reflektierende Fähigkeiten bietet, aber keine Mutation (Sie können keine neue Methode hinzufügen, MyTypeindem Sie sagen, typeof(MyType).Methods += new Method ( "Foo", (int x)=>x*x )wie Sie es in CLOS können)
Pete Kirkham

1

Ich bin überrascht, dass niemand die Kategorietheorie erwähnt hat.

Die grundlegendste Einheit der Programmierung ist die Funktion, die auf Typen basiert. Funktionen werden normalerweise mit f: A -> B bezeichnet, wobei A und B Typen sind. Wenn Sie diese Dinge, die ich als Typen und Funktionen bezeichne, richtig zusammenfassen, erhalten Sie eine Kategorie. Sie müssen an dieser Stelle nicht aufhören.

Nehmen Sie diese Dinge, Kategorien und fragen Sie sich, wie Sie sie richtig zueinander in Beziehung setzen können. Wenn du es richtig machst, bekommst du einen sogenannten Funktor, der zwischen zwei Kategorien geht und normalerweise als F: C -> B bezeichnet wird. Auch hier musst du nicht aufhören.

Sie können alle Funktoren nehmen und auf die richtige Weise zusammensetzen. Wenn Sie die Dinge richtig machen, fragen Sie sich, wie Sie zwei Funktoren miteinander in Beziehung setzen können. Zu diesem Zeitpunkt erhalten Sie eine sogenannte natürliche Transformation, mu: F -> G, wobei F und G Funktoren sind.

Mein Wissen an diesem Punkt wird unklar, aber Sie können dies weiterhin tun und die Leiter der Abstraktion weiter erklimmen. Objekte und Klassen beschreiben nicht annähernd, wie hoch Sie die Abstraktionsleiter erklimmen können. Es gibt viele Sprachen, die die obigen Konzepte rechnerisch ausdrücken können, und die bekannteste dieser Sprachen ist Haskell. Wenn du also wirklich wissen willst, worum es bei der Abstraktion wirklich geht, dann lerne etwas über Haskell oder Agda oder HOL oder ML.


1

Ich denke, das Schauspielermodell fehlt in der Kandidatenliste.

Das meine ich mit Schauspielern:

  • unabhängige Einheiten
  • die Nachrichten empfangen, und wenn sie eine Nachricht empfangen, können
  • neue schauspieler schaffen,
  • Aktualisieren Sie einen internen Status für die nächste Nachricht.
  • und senden Sie Nachrichten

Dieses Modell ist etwas jenseits der deterministischen Turing-Maschinen und kommt unserer realen Hardware bei gleichzeitigen Programmen tatsächlich näher. Wenn Sie nicht zusätzliche (kostspielige) Synchronisationsschritte ausführen, hat sich dieser Wert heutzutage, wenn Ihr Code Daten empfängt, möglicherweise bereits auf der anderen Seite desselben Chips geändert, möglicherweise sogar innerhalb desselben Kerns.

Kurze Diskussion / Einführung: http://youtube.com/watch?v=7erJ1DV_Tlo


Ihr Beitrag ist ziemlich schwer zu lesen (Textwand). Hätten Sie etwas dagegen bearbeiten sie in eine bessere Form ing?
gnat

0

Wenn ich Sie richtig verstehe, können Sie sich Ihre "aufsteigenden Abstraktionen" als immer umfangreichere Verkapselungen von Logik vorstellen, die sich hauptsächlich auf die Wiederverwendung von Code beziehen.

Von bestimmten Befehlen, die nacheinander ausgeführt werden, gehen wir zu Funktionen / Unterprogrammen über , die eine logische Gruppierung von Befehlen in einem einzelnen Element kapseln oder abstrahieren. Dann haben wir Objekte oder Module , die Unterprogramme in Bezug auf eine bestimmte logische Entität oder Kategorie kapseln, sodass ich alle Zeichenfolgenoperationen unter der StringKlasse oder alle gängigen mathematischen Operationen unter dem MathModul (oder der statischen Klasse, in Sprachen wie C #) gruppieren kann. .

Also, wenn das unser Fortschritt ist, was kommt als nächstes? Nun, ich glaube nicht, dass Sie einen klaren nächsten Schritt haben. Wie andere geantwortet haben, gilt Ihr Fortschritt nur für imperative / prozedurale Programmierstile, und andere Paradigmen teilen Ihre Konzepte der Abstraktion nicht. Aber wenn ich etwas finde, das Ihre Metapher logisch erweitern kann, dann sind es Dienste .

Ein Service ist einer Klasse in dem Sinne ähnlich, dass er eine Entität ist, die Funktionalität verfügbar macht, aber eine viel strengere Trennung von Bedenken impliziert als das Hin und Her mit Objekten, die Sie selbst instanziiert haben. Sie stellen eine begrenzte Anzahl von Vorgängen zur Verfügung, verbergen die interne Logik und laufen nicht unbedingt auf demselben Computer.

Auch hier gibt es eine feine Unterscheidung. In den meisten Fällen verwenden Sie ein Objekt , das als Proxy für einen Dienst fungiert , und die beiden Objekte sind sich sehr ähnlich. Als Architektur unterscheiden sich die beiden Objekte jedoch.


0

Neue Formen der Abstraktion verbergen Arbeit auf niedriger Ebene vor Ihnen. Durch benannte Prozeduren und Funktionen werden Programmadressen vor Ihnen verborgen. Objekte verbergen die dynamische Speicherverwaltung und einige typabhängige "if-Anweisungen".

Ich würde vorschlagen, dass die nächste Ebene praktischer Abstraktionen, die die Plackerei auf niedriger Ebene vor Ihnen verbergen, die funktionale reaktive Programmierung ist . Schauen Sie sich "signals" in etwas wie http://elm-lang.org/ an, das die Rückrufe und Aktualisierungsabhängigkeiten verbirgt, die Sie explizit in Javascript verwalten müssten. FRP kann einen Großteil der Komplexität der Kommunikation zwischen Prozessen und Maschinen verbergen, die auch in umfangreichen Internetanwendungen und bei Hochleistungsparallelität erforderlich ist.

Ich bin mir ziemlich sicher, dass wir uns in den nächsten 5 Jahren alle darauf freuen werden.


1
FRP ist großartig, aber es handelt sich um eine ziemlich spezielle Art der Programmierung (nämlich reaktive Programmierung). Es ist nicht sehr gut für die Modellierung anderer Arten von Programmen. Die allgemeinere Art der Programmierung - das Schreiben Ihres Codes in Form von Algebren - ist jedoch ein guter Kandidat für eine neue Abstraktionsebene.
Tikhon Jelvis

0

Mengenlehre - wie sie teilweise in relationalen Datenbanken, aber auch in Statistiksprachen wie SAS und R implementiert ist - bietet eine andere, aber möglicherweise höhere Abstraktionsebene als OO.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.