Was ist Abstraktion? [geschlossen]


38

Gibt es eine allgemein vereinbarte Definition für eine Programmierabstraktion , wie sie von Programmierern verwendet wird? [Beachten Sie, dass die Programmierabstraktion nicht mit Wörterbuchdefinitionen für das Wort "Abstraktion" zu verwechseln ist.] Gibt es eine eindeutige oder sogar mathematische Definition? Was sind einige klare Beispiele für Abstraktionen?


..und gezwungen zu beweisen, dass ich kein Roboter bin, wenn ich dies
poste, bedeutet,

8
Was meinst du mit "mathematisch"? Ich würde Abstraktion nicht wirklich als mathematischen Begriff betrachten.
Fishtoaster

2
@mlvljr: Es tut mir leid, ich bin mir immer noch nicht sicher, ob ich folge. Abstraktion ist nur die Praxis, eine einfachere Art des Umgangs mit etwas bereitzustellen. Ich verstehe nicht, wie formale Tools / Methoden damit zu tun haben.
Fishtoaster

1
@mlvljr, Möchten Sie ein mathematisches Beispiel oder eine Mathematik, die alle Programmierextraktionen abdeckt? Ich glaube nicht, dass letzteres existiert.
C. Ross

8
Perhpas cstheory.stackexchange.com ist der richtige Ort für diese Frage
Conrad Frix

Antworten:


46

Die Antwort auf "Können Sie definieren, was eine Programmierabstraktion mehr oder weniger mathematisch ist?" ist "nein". Abstraktion ist kein mathematischer Begriff. Es wäre, als würde man jemanden bitten, die Farbe einer Zitrone mathematisch zu erklären.

Wenn Sie jedoch eine gute Definition wünschen: Abstraktion ist der Übergang von einer bestimmten Idee zu einer allgemeineren. Schauen Sie sich zum Beispiel Ihre Maus an. Ist es drahtlos? Welche Art von Sensor hat es? Wie viele Knöpfe? Ergonomisch? Wie groß ist es? Die Antworten auf all diese Fragen können Ihre Maus genau beschreiben. Unabhängig von den Antworten handelt es sich jedoch weiterhin um eine Maus, da es sich um ein Zeigegerät mit Tasten handelt. Das ist alles was man braucht um eine Maus zu sein. "Silver Logitech MX518" ist ein konkretes, spezifisches Element, und "Maus" ist eine Abstraktion davon. Eine wichtige Sache, über die man nachdenken sollte, ist, dass es kein konkretes Objekt wie eine "Maus" gibt, es ist nur eine Idee. Die Maus auf Ihrem Schreibtisch ist immer etwas Spezifischeres - es '

Abstraktion kann geschichtet und so fein- oder grobkörnig sein, wie Sie möchten (eine MX518 ist eine Maus, bei der es sich um ein zeigendes Objekt handelt, bei der es sich um ein Computerperipheriegerät handelt, bei dem es sich um ein elektrisch betriebenes Objekt handelt). Sie können so weit gehen, wie Sie möchten und in praktisch jede gewünschte Richtung (meine Maus hat einen Draht, was bedeutet, dass ich ihn als Objekte mit einem Draht einstufen kann. Er ist auch flach am Boden, sodass ich ihn als Objekte einstufen kann, die nicht rollen, wenn sie nicht rollen aufrecht auf einer schiefen Ebene aufgestellt).

Objektorientierte Programmierung basiert auf dem Konzept von Abstraktionen und Familien oder Gruppen von ihnen. Gutes OOP bedeutet, gute Abstraktionen auf der entsprechenden Detailebene auszuwählen, die in der Domäne Ihres Programms sinnvoll sind und nicht "auslaufen". Ersteres bedeutet, dass die Klassifizierung einer Maus als Objekt, das nicht auf einer geneigten Ebene rollt, für eine Anwendung, die Computerausrüstung inventarisiert, keinen Sinn ergibt, für einen Physiksimulator jedoch möglicherweise Sinn ergibt. Letzteres bedeutet, dass Sie vermeiden sollten, sich in eine Hierarchie einzumischen, die für bestimmte Objekte keinen Sinn ergibt. Zum Beispiel, in meiner Hierarchie oben, sind wir sicher, dass alleComputer-Peripheriegeräte werden mit Strom versorgt? Was ist mit einem Stift? Wenn wir einen Stift in die Kategorie "Peripheriegeräte" einteilen möchten, haben wir ein Problem, da er keinen Strom verbraucht und wir Computerperipheriegeräte als Objekte definiert haben, die Strom verbrauchen. Das Kreis-Ellipse Problem ist das bekannteste Beispiel für dieses Rätsel.


2
Ich glaube ich sehe; Sie sprechen speziell von einer abstrakten Bezugnahme auf eine Methode oder Funktion, dh von ihrem Vertrag im Gegensatz zu ihrer Implementierung. Ihre Aussagen sind korrekt, und dies ist eine zutreffende Verwendung des Begriffs. Ein Methodenaufruf ist eine Abstraktion eines konkreten Verhaltens.
Nlawalker

4
@nlawalker: Sie verwechseln Abstraktion mit Generalisierung. Sie sind nicht dasselbe. Was Sie beschreiben, ist letzteres (Übergang von einer bestimmten Idee zu einer allgemeineren ). Die Abstraktion bewegt sich von konkreten Dingen zu abstrakten Dingen, z. B. mit 7 blauen und 7 roten Murmeln, und sagt: "Ich habe zwei Sets mit der gleichen Anzahl gleichfarbiger Murmeln": Hier bewege ich mich von konkreten Dingen (Murmeln) zu abstrakten Dingen (Klassen und äquivalente Mengen). Übrigens ist eine natürliche Zahl n die Klasse aller äquivalenten Mengen von Kardinalitäten n, die nicht kreisförmig sind und durch Eins-zu-Eins-Zuordnungen zwischen diesen Mengen definiert werden.
Pillmuncher

33
Die Farbe einer Zitrone ist mathematisch gesehen Licht mit einer Wellenlänge von ungefähr 570 nm.
Erik

1
@Erik Ich wollte das so schreiben. Bah!
Gary Rowe

1
@Erik Das ist Physik, nicht Mathematik :) Mathematik kennt sich mit Begriffen wie "Licht" nicht aus. Licht ist empirisch; Mathe ist nicht.
Andres F.

25

Ich stimme den meisten Antworten grundsätzlich nicht zu.

Das ist meine Antwort:

Wenn zwei Mengen G und H gegeben sind, kann eine Galois-Verbindung (Alpha, Beta) zwischen ihnen definiert werden, und eine kann als Konkretisierung der anderen bezeichnet werden. kehren Sie die Verbindung um, und einer ist eine Abstraktion des anderen. Die Funktionen sind eine Konkretisierungsfunktion und eine Abstraktionsfunktion.

Dies ergibt sich aus der Theorie der abstrakten Interpretation von Computerprogrammen, die bislang in der Regel ein statischer Analyseansatz ist.


8
OK, Sie bekommen einen goldenen Stern für Professoren :)
Mike Dunlavey

@ Mike: Ja? :-)
Paul Nathan

Ah, und kann es ein Beispiel geben?
mlvljr

2
@mlvljr: di.ens.fr/~cousot/AI astree.ens.fr bieten eine Skizze der Daten.
Paul Nathan

1
Amir: Es ist die technische Definition der Abstraktion von der statischen Analysewelt.
Paul Nathan

13

Abstraktion ist mehr Fokus auf Whatund weniger auf How. Oder Sie können sagen, Sie kennen nur die Dinge, die Sie benötigen, und vertrauen einfach dem Anbieter für alle anderen Dienste. Es verbirgt manchmal sogar die Identität des Dienstleisters.

Diese Site bietet beispielsweise ein System zum Stellen und Beantworten von Fragen. Fast jeder hier weiß, wie man auf dieser Site fragt, antwortet, abstimmt und andere Dinge erledigt. Aber nur sehr wenige wissen, welche Technologien zugrunde liegen. Zum Beispiel, ob die Site mit ASP.net mvc oder Python entwickelt wurde, ob dies auf einem Windows- oder einem Linux-Server usw. läuft. Das geht uns nichts an. Diese Site behält also eine Abstraktionsebene über dem zugrunde liegenden Mechanismus, damit wir den Service bereitstellen können.

Einige andere Beispiele:

  • Ein Auto verbirgt alle seine Mechanismen, bietet aber die Möglichkeit, es zu fahren, zu tanken und dem Besitzer zu warten.

  • Jede API verbirgt alle Implementierungsdetails, die den Dienst für andere Programmierer bereitstellen.

  • Eine Klasse in OOP versteckt ihre privaten Mitglieder und implementiert öffentliche Mitglieder, die den Dienst zum Anrufen der öffentlichen Mitglieder bereitstellen.

  • Bei der Verwendung eines Objekts vom Typ eines Interfaceoder eines abstract classin Java oder C ++ wird die eigentliche Implementierung ausgeblendet. Und nicht nur versteckt, die Implementierungen der in deklarierten Methoden Interfaceunterscheiden sich wahrscheinlich auch in verschiedenen implementierten / geerbten Klassen. Da Sie jedoch denselben Service erhalten, stören HowSie sich einfach nicht daran, dass er implementiert ist und genau Who/ Whatden Service bereitstellt.

  • Identity Hiding : Für den Satz "Ich weiß, Sam kann Computerprogramme schreiben." Die Abstraktion könnte lauten: "Sam ist ein Programmierer. Programmierer können Computerprogramme schreiben." In der zweiten Aussage ist die Person nicht wichtig. Aber seine Programmierfähigkeit ist wichtig.


Warum also nicht einfach eine "genaue Spezifikation von was" nennen?
mlvljr

+1 für das Satori-Bit, auch
mlvljr

@mlvljr Ein bisschen Howist immer hilfreich, um das Whats zu verstehen . So kann es mit Abstraktion gemischt werden.
Gulshan

7

Eine Programmierabstraktion ist ein vereinfachtes Modell eines Problems.

Beispielsweise ist eine TCP / IP-Verbindung eine Abstraktion über das Senden von Daten. Sie geben lediglich eine IP-Adresse und eine Portnummer an und senden diese an die API. Sie sind nicht mit allen Details der Drähte, Signale, Nachrichtenformate und Fehler befasst.


Aha! Was ist hier ein vereinfachtes Modell ? Erinnerst du dich an das undichte Rätsel? :)
mlvljr

7

Eine Abstraktion ist nur die Programmierversion eines Theorems.

Sie haben ein formales System, Sie schlagen einen Gedanken über dieses System vor. Sie beweisen es, und wenn es funktioniert, dann haben Sie einen Satz. Wenn Sie wissen, dass Ihr Theorem gilt, können Sie es in weiteren Beweisen über das System verwenden. Vom System bereitgestellte Primitive (wie if-Anweisungen und int-Werttypen) werden normalerweise als Axiome angesehen, obwohl dies nicht unbedingt zutrifft, da alles, was keine im Maschinencode geschriebenen CPU-Anweisungen sind, eine Art Abstraktion ist.

In der funktionalen Programmierung ist die Idee eines Programms als mathematische Aussage sehr stark ausgeprägt, und häufig kann das Typensystem (in einer starken, statisch typisierten Sprache wie Haskell, F # oder OCAML) zum Testen der Theoremität durch Beweise verwendet werden.

Beispiel: Nehmen wir an, wir haben Additions- und Gleichheitsprüfung als primitive Operationen und Ganzzahlen und Boolesche Werte als primitive Datentypen. Das sind unsere Axiome. Wir können also sagen, dass dies 1 + 3 == 2 + 2ein Theorem ist. Verwenden Sie dann die Regeln für Addition, Ganzzahlen und Gleichheit, um festzustellen, ob dies eine wahre Aussage ist.

Nehmen wir nun an, wir wollen Multiplikation, und unsere Primitive (der Kürze halber) enthalten ein Schleifenkonstrukt und ein Mittel, um symbolische Referenzen zuzuweisen. Wir könnten das vorschlagen

ref x (*) y := loop y times {x +}) 0

Ich werde so tun, als ob ich das bewiesen hätte, um zu demonstrieren, dass Multiplikation zutrifft. Jetzt kann ich Multiplikation verwenden, um mehr mit meinem System (der Programmiersprache) zu tun.

Ich kann auch mein Typensystem überprüfen. (*) hat eine Art von int -> int -> int. Es dauert 2 Ints und gibt ein Int aus. Die Addition hat einen Typ von int -> int -> int, so dass die 0 + (Rest) gilt, solange (Rest) zu einem int führt. Meine Schleife könnte alles Mögliche tun, aber ich sage, sie gibt eine Kette von Curry-Funktionen aus, so dass (x + (x + (x ... + 0))) das Ergebnis ist. Die Form dieser Additionskette ist einfach (int -> (int -> (int ... -> int))), daher weiß ich, dass meine endgültige Ausgabe ein int sein wird. Mein Typensystem hat also die Ergebnisse meines anderen Beweises aufgehalten!

Kombinieren Sie diese Art von Idee über viele Jahre, viele Programmierer und viele Codezeilen, und Sie haben moderne Programmiersprachen: eine herzhafte Menge von Primitiven und riesige Bibliotheken von "bewährten" Code-Abstraktionen.


4

Wäre die Antwort von Wikipedia gut genug? http://en.wikipedia.org/wiki/Abstraction_%28programming%29

In der Informatik werden durch den Mechanismus und die Praxis der Abstraktion Details reduziert und herausgerechnet, so dass man sich jeweils auf wenige Konzepte konzentrieren kann.


Und was wäre dann ein Beispiel für eine abstrahierte Sache?
mlvljr

3
@mlvljr: Wenn Sie den Wikipedia-Artikel lesen, sehen Sie einige.
John Fisher

Leider bin ich mir ziemlich sicher, dass sie viel zu abstrakt sein werden.
mlvljr

4

Nun, mathematisch gesehen ist "Integer" eine Abstraktion. Und wenn Sie formale Beweise wie x + y = y + x für alle ganzen Zahlen erstellen, arbeiten Sie mit der Abstraktion "Ganzzahl" und nicht mit bestimmten Zahlen wie 3 oder 4. Dasselbe passiert in der Softwareentwicklung, wenn Sie mit der interagieren Maschine auf einer Ebene über Registern und Speicherplätzen. In den meisten Fällen können Sie auf einer abstrakteren Ebene kraftvollere Gedanken denken.


Wird nicht mit und IInt add(IInt a, IInt b);Unterprogramm in einem Programm, wo Sie vorher wissen, dass aund bwerden, sagen wir Int128: IIntein mehr oder weniger gutes Beispiel? - Wenn Sie Ihr Codestück dazu bringen, das zu tun, was es tun soll, wissen (können), dass es das tut, was Sie brauchen, und gleichzeitig (und auf der anderen Seite) lassen Sie es genau das tun , was Sie wollen brauchen, ohne es jemals zu wissen (mit der Fähigkeit, das Ding auch in anderen Kontexten zu verwenden)?
mlvljr

1
Entschuldigung, aber ich kann Ihre Frage nicht verstehen.
Kate Gregory

Angenommen, Sie schreiben ein Programm, das 2 zu 3 addieren muss. Dazu rufen Sie eine add(int, int)Subroutine / Funktion auf. Es wird ausreichen, es nur return 2 + 3;in diesem Fall zu haben. Und warum sollte man eine "universellere" Routine verwenden ( return a + b;dh mit den gelieferten Istwerten a und bParametern arbeiten und damit wirklich von ihren Werten abstrahieren ) - das war meine (rhetorische) Frage oben. Hoffe, es wurde jetzt etwas klarer.
mlvljr

Mein erster Kommentar ist ziemlich "selbstverschleiert", ich stimme zu :)
mlvljr

4

Sie bekommen hier gute Antworten. Ich würde nur zur Vorsicht raten - die Leute denken, Abstraktion ist irgendwie diese wunderbare Sache, die auf einen Sockel gestellt werden muss und von der man nicht genug bekommen kann. Es ist nicht. Es ist nur gesunder Menschenverstand. Sie erkennen lediglich die Ähnlichkeiten zwischen den Dingen, sodass Sie eine Problemlösung auf eine Reihe von Problemen anwenden können.

Erlauben Sie mir einen Ärger ...

Ganz oben auf meiner Liste der Ärger steht, wenn die Leute von "Abstraktionsebenen" sprechen, als wäre das eine gute Sache. Sie machen "Wrapper" um Klassen oder Routinen, die sie nicht mögen, und nennen sie "abstrakter", als würden sie dadurch besser. Erinnern Sie sich an die Fabel von der "Prinzessin und der Erbse"? Die Prinzessin war so zart, dass sie nicht schlafen konnte, wenn sich unter ihrer Matratze eine Erbse befand, und das Hinzufügen weiterer Matratzenschichten würde nicht helfen. Die Idee, dass das Hinzufügen weiterer "Abstraktionsebenen" hilft, ist einfach so - normalerweise nicht. Dies bedeutet lediglich, dass jede Änderung an der Basisentität durch mehrere Codeebenen erfolgen muss.


Wenn man sich die Abstraktion als etwas vorstellt, das "zu schön ist, um klar wahrgenommen (oder noch mehr in trockenen (mathematischen) Begriffen beschrieben) zu werden", hilft das nicht, (erstens und zumindest) zu verstehen, was es ist, und (zweitens) Techniken zu entwickeln Anwendung und (Horror!) Beurteilung [wie und auf welche Weise der angegebene Code abstrakt ist]
mlvljr

3
Wenn eine Änderung an einem Ort dazu führt, dass Sie an einem anderen Ort mehrere Änderungen vornehmen müssen, sind Ihre Abstraktionen schlecht. Im Wesentlichen werde ich nicht sagen, dass ich oder jemand anderes nie zu viel Abstraktion falsch gemacht hat, aber es gibt eine Methode für diesen Wahnsinn. Gute Abstraktionen sind der Grundstein für lose gekoppelten Code. Mit der richtigen Abstraktion werden Änderungen lächerlich einfach. Ja, ich stelle Abstraktionen auf ein Podest und verbringe übermäßig viel Zeit damit, die richtigen zu finden.
Jason Baker

@ Jason Baker Lassen Sie unsere Abstraktionstechniken nur konkret genug sein, um sie effektiv zu nutzen ...
mlvljr

1
@Jason: "Wenn eine Änderung an einem Ort dazu führt, dass Sie an einem anderen Ort mehrere Änderungen vornehmen müssen, sind Ihre Abstraktionen schlecht." Ich bin mit dir da. Ich scheine von schlechten umgeben zu sein.
Mike Dunlavey

1
Es hört sich so an, als hätten Sie an einem Ort gearbeitet, an dem die Entwickler großartige Visionen hatten, und es gab keinen starken Chef, der das Team fokussierte. Wenn ich mich in einem solchen Umfeld befinde, beginne ich, nach einem anderen Job zu suchen (Projektbudget immer überschritten oder Unternehmen klein genug => bankrott). Kürzlich habe ich einen Tweet gesehen: 'Spaghetti Code' vs. 'Lasagne Code', letzterer ist, wenn es zu viele Schichten gibt.
Yzorg

4

Ich denke, Sie könnten einen Blog-Beitrag von mir über undichte Abstraktionen nützlich finden. Hier ist der relevante Hintergrund:

Die Abstraktion ist ein Mechanismus, der dabei hilft, die Gemeinsamkeiten einer Reihe verwandter Programmfragmente zu erkennen, ihre Unterschiede zu beseitigen und es Programmierern zu ermöglichen, direkt mit einem Konstrukt zu arbeiten, das dieses abstrakte Konzept darstellt. Dieses neue Konstrukt weist (praktisch) immer Parametrisierungen auf : eine Möglichkeit, die Verwendung des Konstrukts an Ihre spezifischen Anforderungen anzupassen.

Eine ListKlasse kann beispielsweise die Details einer Implementierung mit verknüpften Listen abstrahieren. Anstatt über Manipulationen nextund previousZeiger nachzudenken, können Sie überlegen , ob einer Sequenz Werte hinzugefügt oder daraus entfernt werden sollen. Abstraktion ist ein wesentliches Werkzeug, um nützliche, reichhaltige und manchmal komplexe Merkmale aus einer viel kleineren Menge primitiverer Konzepte zu erstellen.

Abstraktion ist mit Kapselung und Modularität verbunden, und diese Konzepte werden oft missverstanden.

In diesem ListBeispiel kann die Kapselung verwendet werden, um die Implementierungsdetails einer verknüpften Liste auszublenden. In einer objektorientierten Sprache können Sie beispielsweise den Zeiger nextund als previousprivat kennzeichnen, wobei nur die List-Implementierung Zugriff auf diese Felder hat.

Die Verkapselung reicht für die Abstraktion nicht aus, da dies nicht unbedingt impliziert, dass Sie eine neue oder andere Konzeption der Konstrukte haben. Wenn eine ListKlasse nur Zugriffsmethoden im ' getNext' / ' setNext' - Stil zur Verfügung stellen würde, würde sie die Implementierungsdetails von Ihnen kapseln (z. B. haben Sie das Feld ' prev' oder ' previous' benannt? Welchen statischen Typ hat es?), Aber es hätte einen sehr geringen Abstraktionsgrad.

Die Modularität betrifft das Ausblenden von Informationen : In einer Schnittstelle werden stabile Eigenschaften angegeben, und ein Modul implementiert diese Schnittstelle, wobei alle Implementierungsdetails innerhalb des Moduls erhalten bleiben. Die Modularität hilft Programmierern, mit Veränderungen umzugehen, da andere Module nur von der stabilen Schnittstelle abhängen.

Das Ausblenden von Informationen wird durch die Kapselung unterstützt (sodass Ihr Code nicht von instabilen Implementierungsdetails abhängt), die Kapselung ist jedoch aus Gründen der Modularität nicht erforderlich. Zum Beispiel können Sie eine Implementierung ListStruktur in C, das Aussetzen der ‚ next‘ und ‚ prev‘ Zeiger auf die Welt, sondern auch eine Schnittstelle bereitstellen, enthält initList(), addToList()undremoveFromList()funktionen. Unter der Voraussetzung, dass die Regeln der Schnittstelle eingehalten werden, können Sie sicherstellen, dass bestimmte Eigenschaften immer gültig sind, beispielsweise, dass die Datenstruktur immer gültig ist. [Parnas 'klassisches Papier über Modularität wurde zum Beispiel mit einem Beispiel in der Montage geschrieben. Die Schnittstelle ist ein Vertrag und eine Form der Kommunikation über das Design, sie muss nicht unbedingt mechanisch überprüft werden, obwohl wir uns heute darauf verlassen.]

Obwohl Begriffe wie abstrakt, modular und gekapselt als positive Designbeschreibungen verwendet werden, ist es wichtig zu wissen, dass das Vorhandensein einer dieser Eigenschaften nicht automatisch zu einem guten Design führt:

  • Wenn ein n ^ 3-Algorithmus "gut gekapselt" ist, arbeitet er immer noch schlechter als ein verbesserter n log n-Algorithmus.

  • Wenn eine Schnittstelle für ein bestimmtes Betriebssystem festgeschrieben ist, wird keiner der Vorteile eines modularen Designs realisiert, wenn beispielsweise ein Videospiel von Windows auf das iPad portiert werden muss.

  • Wenn die erstellte Abstraktion zu viele unwesentliche Details enthält, kann sie kein neues Konstrukt mit eigenen Operationen erstellen: Es wird einfach ein anderer Name für dieselbe Sache sein.


Nun, das scheint ungefähr das zu sein, was ich eigentlich wollte (ein paar gemeine / beispielsichere "Beschimpfungen" zu "modular == abstrakt == gut == man kann-nie-abschätzen-es-nur-kämpfen" -Ansicht). , danke (noch zu lesen)
mlvljr

Und hier ist ein provokatives Motto aus meiner bevorstehenden Antwort (auf meine eigene Frage) "Abstraktionen lecken, wenn der Geist schwach wird";)
mlvljr

2

Ok, ich denke, ich habe herausgefunden, was Sie fragen: "Was ist eine mathematisch strenge Definition von 'Eine Abstraktion'."

Wenn das der Fall ist, haben Sie wahrscheinlich kein Glück - "Abstraktion" ist ein Begriff für Softwarearchitektur / -design und hat meines Wissens keine mathematische Grundlage (vielleicht kann mich jemand korrigieren, der sich mit theoretischem CS besser auskennt hier) haben nicht mehr als "Koppeln" oder "Verbergen von Informationen" mathematische Definitionen.


2

Abstraktion ist, wenn Sie als irrelevant erachtete Details zu Gunsten der als relevant erachteten ignorieren.

Die Abstraktion umfasst die Kapselung, das Verbergen von Informationen und die Verallgemeinerung. Es umfasst keine Analogien, Metaphern oder Heuristiken.

All mathematischer Formalismus für den Begriff der Abstraktion würde ich sein eine Abstraktion, wie sie notwendigerweise die zugrunde liegende Sache verlangen würden, in eine Reihe von mathematischen Eigenschaften abstrahiert werden! Der kategorietheoretische Begriff eines Morphismus kommt dem, wonach Sie suchen, wahrscheinlich am nächsten.

Abstraktion ist nichts, was Sie deklarieren, sondern etwas, was Sie tun .


+1, "Ich abstrahiere!" wird für ein T-Shirt schön sein;) Danke für den Link zu Morphism (obwohl er nicht direkt die Poly - one unter den Dutzenden anderen erwähnt;)) auch.
mlvljr

2

Um es einer anderen Person zu erklären, würde ich von den Ergebnissen her umgekehrt vorgehen:

Abstraktion in der Computerprogrammierung ist die Verallgemeinerung von etwas bis zu dem Punkt, dass mehr als eine ähnliche Sache im Allgemeinen als dieselbe behandelt und gleich behandelt werden kann.

Wenn Sie das erweitern möchten, können Sie Folgendes hinzufügen:

Manchmal geschieht dies, um ein polymorphes Verhalten (Schnittstellen und Vererbung) zu erzielen, um den repetitiven Code von vornherein zu reduzieren, manchmal, um das Innenleben von etwas zu einem späteren Zeitpunkt durch eine ähnliche Lösung zu ersetzen, ohne dass dies geändert werden muss Code auf der anderen Seite des abstrahierten Containers oder Wrappers, um hoffentlich in Zukunft weniger Nacharbeit zu leisten.

Darüber hinaus denke ich, dass Sie mit Beispielen beginnen müssen ...


1

Vielleicht möchten Sie einige der Metriken von Bob Martin überprüfen

http://en.wikipedia.org/wiki/Software_package_metrics

Das heißt, ich denke nicht, dass seine "Abstraktheit" die gleiche ist wie deine. Sein ist eher ein Maß für "fehlende Implementierung in einer Klasse", was die Verwendung von Schnittstellen / abstrakten Klassen bedeutet. Instabilität und Entfernung von der Hauptsequenz spielen wahrscheinlich mehr in das hinein, wonach Sie suchen.


Ja, erinnere dich an dieses Papier. Onkel Bob ist brillant darin, die Menge mit Energie zu versorgen und Menschen für die Mechanik von OO zu interessieren.
mlvljr

Seltsamerweise habe ich vergessen (sofort) zu upvoten :)
mlvljr

1

Merriam-webster definiert abstrakt als ein Adjektiv, das von einer bestimmten Instanz getrennt ist.

Eine Abstraktion ist ein Modell eines Systems. Sie listen häufig eine Gruppe von Annahmen auf, die erfüllt sein müssen, damit ein reales System durch die Abstraktion modelliert werden kann, und sie werden häufig verwendet, um uns die Konzeption immer komplexerer Systeme zu ermöglichen. Um von einem realen System zu einer Abstraktion zu gelangen, gibt es keine formale mathematische Methode. Es liegt an der Entscheidung, wer die Abstraktion definiert und was der Zweck der Abstraktion ist.

Oft werden Abstraktionen jedoch als mathematische Konstrukte definiert. Das liegt wahrscheinlich daran, dass sie in Wissenschaft und Technik so häufig eingesetzt werden.

Ein Beispiel ist die Newtonsche Mechanik. Es wird angenommen, dass alles unendlich klein ist und die gesamte Energie erhalten bleibt. Die Wechselwirkungen zwischen Objekten werden durch mathematische Formeln klar definiert. Nun, wie wir wissen, funktioniert das Universum nicht so, und in vielen Situationen tritt die Abstraktion durch. Aber in vielen Situationen funktioniert es sehr gut.

Ein weiteres abstraktes Modell sind typische lineare Schaltungselemente, Widerstände, Kondensatoren und Induktivitäten. Auch hier sind die Wechselwirkungen durch mathematische Formeln klar definiert. Bei Niederfrequenzschaltungen, einfachen Relaistreibern und anderen Dingen funktioniert die RLC-Analyse gut und liefert sehr gute Ergebnisse. In anderen Situationen, wie bei Mikrowellen-Funkkreisen, sind die Elemente zu groß und die Interaktionen sind feiner, und die einfachen RLC-Abstraktionen halten nicht stand. Was zu diesem Zeitpunkt zu tun ist, liegt im Ermessen des Ingenieurs. Einige Ingenieure haben darüber hinaus eine weitere Abstraktion erstellt, wobei einige die idealen Operationsverstärker durch neue mathematische Formeln ersetzen, andere die idealen Operationsverstärker durch simulierte reale Operationsverstärker ersetzen, die wiederum mit einem komplexen Netzwerk aus kleineren simuliert werden ideale Elemente.

Wie andere gesagt haben, ist es ein vereinfachtes Modell. Es ist ein Werkzeug, um komplexe Systeme besser zu verstehen.


Ich hätte dies wahrscheinlich besser betonen sollen, aber ich interessiere mich nicht für die Art von Abstraktionen, denen unnötige Details ihrer realen Prototypen fehlen, sondern gebe daher einige hilfreiche Hinweise zum Entwurf von Systemen, die sich mit den oben genannten realen Objekten befassen sollten (Ein Beispiel ist das Erstellen einer Employee-Klasse mit einigen realen Employee-Eigenschaften, die möglicherweise in einer Geschäftsanwendung nützlich sind.) Was mich interessiert, ist die Art der Abstraktion, die eine Software-Entität von anderen solchen Entitäten "abschirmt", die sich damit befassen (Beispiel: EmployerAnnahmen von Employee).
mlvljr

1
Du machst keinen Sinn. Hinweise zum Entwurf eines realen Systems zu geben, ist kein Zweck für eine Abstraktion. Wenn Sie nicht wissen, was modelliert wird, ist dies kein Problem für eine Abstraktion.
Whatsisname

Ich sprach über das Abstrahieren von Details der realen Objekte, mit denen sich die Software befassen wird - beim Erstellen dieser Software. Verwenden einer (Software-) Abstraktion einer realen Entität, um diese reale Sache (neu) zu entwerfen, war nicht gemeint (es handelt sich um "Softwaresysteme" als "Systeme" in ", bietet jedoch einige hilfreiche Hinweise zum Entwurf von Systemen in" mein Kommentar oben).
mlvljr

1

Eine Abstraktion repräsentiert etwas (zB ein Konzept, eine Datenstruktur, eine Funktion) in Bezug auf etwas anderes. Zum Beispiel verwenden wir Wörter, um zu kommunizieren. Ein Wort ist eine abstrakte Entität, die in Form von Lauten (Sprache) oder in Form von grafischen Symbolen (Schrift) dargestellt werden kann. Die Schlüsselidee einer Abstraktion besteht darin, dass sich die betreffende Entität von der zugrunde liegenden Darstellung unterscheidet, genauso wie ein Wort nicht die Laute sind, mit denen es ausgesprochen wird, oder die Buchstaben, mit denen es geschrieben wird.

Somit kann zumindest theoretisch die zugrunde liegende Darstellung einer Abstraktion durch eine andere Darstellung ersetzt werden. In der Praxis unterscheidet sich die Abstraktion jedoch selten gänzlich von der zugrunde liegenden Darstellung, und manchmal " leckt " die Darstellung durch. Zum Beispiel enthält Sprache emotionale Untertöne, die beim Schreiben nur sehr schwer zu vermitteln sind. Aus diesem Grund können eine Audioaufnahme und eine Abschrift der gleichen Wörter sehr unterschiedliche Auswirkungen auf das Publikum haben. Mit anderen Worten, die Abstraktion von Wörtern leckt oft.

Abstraktionen erfolgen normalerweise in Schichten. Wörter sind Abstraktionen, die durch Buchstaben dargestellt werden können, die wiederum selbst Abstraktionen von Tönen sind, die wiederum Abstraktionen des Bewegungsmusters der Luftpartikel sind, die durch die Stimmbänder erzeugt und von den Trommeln des Ohrs erfasst werden .

In der Informatik sind Bits typischerweise die niedrigste Repräsentationsebene. Bytes, Speicherorte, Assembler-Anweisungen und CPU-Register bilden die nächste Abstraktionsebene. Dann haben wir primitive Datentypen und Anweisungen einer höheren Sprache, die in Bezug auf Bytes, Speicherorte und Assembler-Anweisungen implementiert sind. Dann Funktionen und Klassen (unter der Annahme einer OO-Sprache), die in Form von primitiven Datentypen und eingebauten Sprachanweisungen implementiert sind. Dann werden komplexere Funktionen und Klassen in Bezug auf die einfacheren implementiert. Einige dieser Funktionen und Klassen implementieren Datenstrukturen wie Listen, Stapel, Warteschlangen usw. Diese werden wiederum verwendet, um spezifischere Entitäten wie eine Warteschlange von Prozessen oder eine Liste von Mitarbeitern oder eine Hash-Tabelle von Buchtiteln darzustellen .


1
Wenn es undicht ist, dann ist es offensichtlich keine Abstraktion ... genug, seien wir ehrlich.
mlvljr

2
@mlvljr Computer sind leider keine mathematischen Probleme, daher müssen Sie ein gewisses Maß an Leckage berücksichtigen. Wenn nicht anders angegeben, impliziert die Tatsache, dass Berechnungen auf einem physischen Gerät durchgeführt werden, bestimmte Einschränkungen hinsichtlich des Umfangs der Probleme, die modelliert werden können. Technisch gesehen implizieren die Unvollständigkeitssätze, dass bestimmte Dinge über mathematische Systeme nicht intern bewiesen werden können, sodass selbst Mathematik "undichte Abstraktionen" aufweist.
CodexArcanum

2
Sie können immer eine Situation finden, in der eine Abstraktion ausläuft. Es gibt keine perfekte Abstraktion. Es ist einfach eine Frage, wie viel es leckt und ob Sie damit leben können.
Dima

@CodexArcanum 1. Eine Routine, die ein intkleineres als (MAX_INT_SIZE / 2-1) nimmt und ein anderes zurückgibt, das doppelt so viel ist: int f(int a) { return a*2; }2. ein "Handler" mit einem Prototyp void (*) (void), der aufgerufen werden soll, wenn ... uhmm es laut aufgerufen werden soll Der Vertrag des Aufrufers - beide stellen Abstraktionen dar (1 - über die Details seiner Implementierung (die wir zur Verfügung gestellt haben, die aber für diejenigen, die keinen Zugriff auf den Quellcode haben, nicht zugänglich sind), 2-- über was genau der Behandler tut (beachten Sie jedoch, dass dies der Person bekannt ist, die den Handler zugewiesen hat) und nicht auslaufen
mlvljr

Die Einschränkung von MAX_INT_SIZE wird an keiner Stelle in der Signatur Ihrer Methode klargestellt. Wenn Sie keine Sprache verwenden, die eine vertragsbasierte Programmierung ermöglicht (wie Eiffel), liegt ein Leck vor. Das Erwähnen von Einschränkungen in der Dokumentation zählt nicht, da sich die Dokumentation außerhalb des Systems befindet. Und wenn der Strom während einer Operation ausfällt? Was ist, wenn Sie Daten über ein Netzwerk übertragen müssen und Latenz besteht? Kein Programmierparadigma kann die Physikalität der Systemhardware abstrahieren.
CodexArcanum

1

Ein Weg, den ich versuche, es den Leuten zu beschreiben, ist vielleicht nicht der beste Weg

Stellen Sie sich ein Programm vor, das 2 + 2 addiert und 4 ausgibt

Stellen Sie sich ein Programm vor, das zwei von einem Benutzer eingegebene Zahlen hinzufügt: x + y = z

Was ist nützlicher und allgemeiner?


Darum ging es in meinem Kommentar zu Kate Gregorys Antwort. ;) Das Interessante ist, dass, während das weniger allgemeine Programm das allgemeinere verwenden kann, es wahrscheinlich kontraproduktiv wäre, wenn ein Benutzer, der das erste angefordert hat, das zweite
anfordert

1

Ich würde argumentieren, dass eine Abstraktion etwas ist, das unnötige Details verbirgt. Eine der grundlegendsten Abstraktionseinheiten ist das Verfahren. Ich möchte mich beispielsweise nicht darum kümmern, wie ich Daten in der Datenbank speichere, wenn ich diese Daten aus einer Datei einlese. Also erstelle ich eine Funktion save_to_database.

Abstraktionen können auch zu größeren Abstraktionen zusammengefügt werden. Zum Beispiel können Funktionen in einer Klasse zusammengestellt werden, Klassen können zusammengestellt werden, um ein Programm zu bilden, Programme können zusammengestellt werden, um ein verteiltes System zu bilden, usw.


Der Code-Aufruf save_to_databasesollte sich keine Gedanken darüber machen, wie genau die Daten gespeichert werden, solange / weil Sie die Implementierung gewählt haben, die Sie benötigen ! Dh es wird ohnehin einen Ort geben, an dem die (abstrahierten "Relativen" zu einigen Codeteilen) Details bereitgestellt werden können. Es geht nur darum, sie mit
Bedacht auszuwählen

1

Ich stelle mir Abstraktion in der Programmierung immer vor, indem ich Details verstecke und eine vereinfachte Oberfläche bereitstelle. Dies ist der Hauptgrund, warum Programmierer monumentale Aufgaben in überschaubare Teile zerlegen können. Mit Abstraction können Sie die Lösung für einen Teil des Problems erstellen, einschließlich aller wichtigen Details, und anschließend eine einfache Benutzeroberfläche bereitstellen, um die Lösung zu verwenden. Dann können Sie praktisch die Details "vergessen". Dies ist wichtig, da eine Person auf keinen Fall alle Details eines überkomplexen Systems auf einmal im Kopf behalten kann. Das soll nicht heißen, dass die Details unter der Abstraktion niemals überarbeitet werden müssen, aber vorerst muss nur die Schnittstelle in Erinnerung bleiben.

Bei der Programmierung kann diese vereinfachte Schnittstelle von einer Variablen (die eine Gruppe von Bits abstrahiert und eine einfachere mathematische Schnittstelle bereitstellt) bis zu einer Funktion (die einen beliebigen Verarbeitungsaufwand in einem einzelnen Zeilenaufruf abstrahiert) bis zu einer Klasse und darüber hinaus reichen.

Letztendlich besteht die Hauptaufgabe der Programmierer darin, alle rechnerischen Details zu abstrahieren und eine einfache Oberfläche wie eine grafische Benutzeroberfläche bereitzustellen, von der jemand, der sich mit der Funktionsweise von Computern nicht auskennt, Gebrauch machen kann.

Einige der Vorteile der Abstraktion sind:

  • Ermöglicht es, ein großes Problem in handliche Teile zu zerlegen. Wenn Sie die Datensätze einer Person zu einer Datenbank hinzufügen, müssen Sie sich nicht mit dem Einfügen und Ausgleichen von Indexbäumen in der Datenbank herumschlagen. Diese Arbeit mag irgendwann erledigt worden sein, aber jetzt wurde sie entfernt und Sie müssen sich nicht mehr darum kümmern.

  • Ermöglicht es mehreren Personen, bei einem Projekt gut zusammenzuarbeiten. Ich möchte nicht alle Einzelheiten des Codes meines Kollegen kennen müssen. Ich möchte nur wissen, wie man es benutzt, was es macht und wie man es mit meiner Arbeit (der Schnittstelle) zusammenfügt.

  • Ermöglicht es Personen, die nicht über die erforderlichen Kenntnisse verfügen, eine komplexe Aufgabe auszuführen. Meine Mutter kann ihr Facebook aktualisieren und Leute, die sie im ganzen Land kennt, können es sehen. Ohne die Abstraktion eines wahnsinnig komplexen Systems auf ein einfaches Webinterface wäre sie auf keinen Fall in der Lage, etwas Ähnliches zu tun (und ich auch nicht).

Abstraktion kann jedoch den umgekehrten Effekt haben, Dinge weniger handhabbar zu machen, wenn sie überbeansprucht werden. Wenn Sie ein Problem in zu viele kleine Teile aufteilen, steigt die Anzahl der Schnittstellen, an die Sie sich erinnern müssen, und es wird schwieriger zu verstehen, was wirklich vor sich geht. Wie bei den meisten Dingen muss ein Gleichgewicht gefunden werden.


1

Ein zusätzliches Maß an Indirektion.

Sie möchten sich nicht darum kümmern, ob es sich bei dem von Ihnen verwendeten Objekt um ein Objekt Catoder um ein Objekt handelt. Durchsuchen DogSie daher eine virtuelle Funktionstabelle, um die richtige makeNoise()Funktion zu finden .

Ich bin mir sicher, dass dies auch auf 'niedrigere' und 'höhere' Ebenen angewendet werden könnte - stellen Sie sich einen Compiler vor, der die richtigen Anweisungen für einen bestimmten Prozessor sucht, oder Haskells MonadAbstract über Recheneffekte, indem Sie alles returnund aufrufen >>=.


1

Dies ist etwas, worüber ich eigentlich eine längere Zeit bloggen wollte, aber ich bin nie dazu gekommen. Zum Glück bin ich ein Repräsentant und es gibt sogar ein Kopfgeld. Mein Beitrag fiel ziemlich lang aus , aber hier ist das Wesentliche:

Bei der Abstraktion in der Programmierung geht es darum, die Essenz eines Objekts in einem gegebenen Kontext zu verstehen.

[...]

Abstraktion wird nicht nur mit Verallgemeinerung, sondern auch mit Verkapselung verwechselt, sondern dies sind die beiden orthogonalen Teile des Versteckens von Informationen: Das Servicemodul entscheidet, was es zeigen möchte, und das Client-Modul entscheidet, was es sehen möchte. Kapselung ist der erste Teil und Abstraktion der letztere. Nur beide zusammen ergeben ein vollständiges Informationsversteck.

Hoffentlich hilft das.


+1, Ja, das Thema scheint viele von uns wirklich zu beschäftigen;) Ich hoffe, Ihre Antwort (endlich) mit einigen eigenen Punkten zu ergänzen, um mehr Interesse an der Diskussion zu wecken.
mlvljr

0

Hier eine unmathematische Antwort:

Sich in der Programmierung zurückzuziehen, bedeutet, dass Sie sich jetzt nicht um die Details kümmern, wohingegen Sie dies tun und sich die ganze Zeit um sie kümmern sollten. Es ist im Grunde so zu tun.


1
+1, aber nicht immer denke ich (denke an wirklich unnötige Details :)). Die anfängliche Frage lautet: "Geht es darum, Details für immer zu entfernen, sie vorübergehend zu vergessen oder sie in irgendeiner Weise zu nutzen, ohne das zu wissen?"
mlvljr

1
Es ist mir egal, wie viele Photonen meine Kunden heute getroffen haben.
Flamingpenguin

0

Für mich ist Abstraktion etwas, das "buchstäblich" nicht existiert, es ist so etwas wie eine Idee. Wenn Sie es mathematisch ausdrücken, ist es nicht mehr abstrakt, weil Mathematik eine Sprache ist, um auszudrücken, was in Ihrem Gehirn passiert, damit es von einem anderen Gehirn verstanden werden kann. Sie können Ihre Ideen also nicht strukturieren, denn wenn Sie dies tun, ist es keine Idee mehr noch: Sie müssten verstehen, wie ein Gehirn funktioniert, um ein Ideenmodell auszudrücken.

Abstraktion ist etwas, mit dem Sie die Realität in etwas interpretieren können, das von ihr unabhängig sein kann. Sie können einen Strand und einen Traum abstrahieren, aber der Strand existiert, aber der Traum nicht. Man könnte aber sagen, dass beide existieren, aber es ist nicht wahr.

Das Schwierigste an der Abstraktion ist es, einen Weg zu finden, sie auszudrücken, damit andere Menschen sie verstehen und sie in die Realität umsetzen können. Das ist die härteste Aufgabe und kann nicht alleine erledigt werden: Sie müssen ein relatives Modell erfinden, das auf Ihren Ideen basiert und von jemand anderem verstanden werden kann.

Für mich sollte die Abstraktion in der Computersprache den Namen "mathematisch" für das Modell haben, es geht um die Wiederverwendung von Ideen, die kommuniziert werden können, und es ist eine enorme Einschränkung im Vergleich zu dem, was abstrakt erreicht werden kann.

Einfach gesagt, Atome sind nebeneinander, aber es ist ihnen egal. Eine große Menge von Molekülen, die in einem Menschen organisiert sind, kann verstehen, dass er neben jemandem ist, aber es kann nicht verstehen, wie, es ist nur, wie sich die Atome in einem Muster positioniert haben.

Ein Objekt, das im Allgemeinen von einem Konzept beherrscht wird, kann sich selbst nicht "verstehen". Deshalb versuchen wir, an Gott zu glauben, und warum es uns schwer fällt, unser Gehirn zu verstehen.

Kann ich jetzt meine Medaille haben?


0

Interessante Frage. Ich kenne keine einzige Definition von Abstraktion, die als maßgeblich für die Programmierung angesehen wird. Obwohl andere Leute Links zu einigen Definitionen aus verschiedenen Zweigen der CS-Theorie oder Mathematik bereitgestellt haben; Ich mag es, ähnlich wie bei "supervenience" zu denken, siehe http://en.wikipedia.org/wiki/Supervenience

Wenn wir über Abstraktion in der Programmierung sprechen, vergleichen wir im Wesentlichen zwei Beschreibungen eines Systems. Ihr Code ist eine Beschreibung eines Programms. Eine Abstraktion Ihres Codes wäre auch eine Beschreibung dieses Programms, jedoch auf einer "höheren" Ebene. Natürlich könnten Sie eine noch höhere Abstraktionsebene Ihrer ursprünglichen Abstraktion haben (z. B. eine Beschreibung des Programms in einer übergeordneten Systemarchitektur im Vergleich zu der Beschreibung des Programms in seinem detaillierten Entwurf).

Was macht nun eine Beschreibung "übergeordneter" als eine andere? Der Schlüssel ist "multiple Realisierbarkeit" - Ihre Abstraktion des Programms könnte auf viele Arten in vielen Sprachen realisiert werden. Nun könnte man sagen, dass man auch mehrere Entwürfe für ein einziges Programm erstellen könnte - zwei Personen könnten zwei verschiedene übergeordnete Entwürfe erstellen, die beide das Programm genau beschreiben. Die Äquivalenz der Erkenntnisse macht den Unterschied.

Wenn Sie Programme oder Designs vergleichen, müssen Sie dies so tun, dass Sie die wichtigsten Eigenschaften der Beschreibung auf dieser Ebene identifizieren können. Man kann sich auf komplizierte Weise erklären, dass ein Entwurf einem anderen entspricht, aber die einfachste Möglichkeit, darüber nachzudenken, ist die folgende: Kann ein einzelnes Binärprogramm die Einschränkungen beider Beschreibungen erfüllen?

Was macht also eine Beschreibungsebene höher als die andere? Angenommen, wir haben eine Beschreibungsebene A (z. B. Konstruktionsdokumente) und eine andere Beschreibungsebene B (z. B. Quellcode). A ist höher als B , weil , wenn A1 und A2 zwei nicht äquivalente Beschreibungen auf der Ebene A sind, dann Realisierungen dieser Beschreibungen, B1 und B2 müssen aber auch auf der Ebene B. nicht-äquivalent sein, wird die umgekehrte nicht unbedingt zutreffen , .

Wenn ich also kein einziges Binärprogramm erstellen kann, das zwei unterschiedliche Designdokumente erfüllt (dh, die Einschränkungen dieser Entwürfe würden sich widersprechen), muss der Quellcode, der diese Entwürfe implementiert, unterschiedlich sein. Wenn ich jedoch zwei Sätze von Quellcode nehme, die möglicherweise nicht in dasselbe Binärprogramm kompiliert werden konnten, kann es dennoch vorkommen, dass die Binärdateien, die aus dem Kompilieren dieser beiden Sätze von Quellcode resultieren, dasselbe Design aufweisen dokumentieren. Somit ist das Designdokument eine "Abstraktion" des Quellcodes.


0

Programmierabstraktionen sind Abstraktionen, die von jemandem auf einem programmatischen Element erstellt wurden. Nehmen wir an, Sie wissen, wie man ein Menü aus Elementen und Dingen zusammensetzt. Dann sah jemand dieses Stück Code und dachte, hey, das in anderen hireachy-ähnlichen Strukturen nützlich sein könnte, und definierte das Component Design Pattern mit einer Abstraktion des ersten Stück Codes.

Objektorientierte Entwurfsmuster sind ein gutes Beispiel für Abstraktion, und damit meine ich nicht die tatsächliche Implementierung, sondern die Art und Weise, wie wir uns einer Lösung nähern sollten.

Zusammenfassend lässt sich sagen, dass die Programmierabstraktion ein Ansatz ist, der es uns ermöglicht, ein Problem zu verstehen. Sie ist das Mittel, um etwas zu bekommen, aber es ist nicht die Realität

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.