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?
programming-languages
object-oriented
language-agnostic
abstraction
Jordan Medlock
quelle
quelle
Antworten:
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.
quelle
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).
quelle
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.
quelle
Ich würde argumentieren, dass Metastrukturen, Module, Frameworks, Plattformen und Services alle übergeordnete Feature-Gruppierungen als Klassen sind. Meine Hierarchie der Abstraktionen von Programmiersystemen:
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.
quelle
Die nächste Abstraktion nach Klassen sind Metaklassen . So einfach ist das;)
quelle
Type
die reflektierende Fähigkeiten bietet, aber keine Mutation (Sie können keine neue Methode hinzufügen,MyType
indem Sie sagen,typeof(MyType).Methods += new Method ( "Foo", (int x)=>x*x )
wie Sie es in CLOS können)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.
quelle
Ich denke, das Schauspielermodell fehlt in der Kandidatenliste.
Das meine ich mit Schauspielern:
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
quelle
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
String
Klasse oder alle gängigen mathematischen Operationen unter demMath
Modul (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.
quelle
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.
quelle
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.
quelle