Kann zu viel Abstraktion schlecht sein?

46

Als Programmierer ist es meines Erachtens unser Ziel, gute Abstraktionen zum gegebenen Domänenmodell und der Geschäftslogik zu liefern. Aber wo soll diese Abstraktion aufhören? Wie man den Kompromiss zwischen Abstraktion und all ihren Vorteilen (Flexibilität, einfache Änderung usw.) und dem einfachen Verständnis des Codes und all seinen Vorteilen eingeht.

Ich glaube, ich neige dazu, zu abstrahierten Code zu schreiben, und ich weiß nicht, wie gut er ist. Ich neige oft dazu, es zu schreiben, als wäre es eine Art Mikro-Framework, das aus zwei Teilen besteht:

  1. Mikromodule, die in das Mikrorahmenwerk eingebunden sind: Diese Module sind leicht zu verstehen, zu entwickeln und als einzelne Einheiten zu warten. Dieser Code stellt im Wesentlichen den Code dar, der die in den Anforderungen beschriebenen Funktionen ausführt.
  2. Verbindungscode; jetzt steht hier meines erachtens das problem. Dieser Code ist in der Regel kompliziert, da er manchmal sehr abstrakt ist und am Anfang schwer zu verstehen ist. dies ergibt sich aus der Tatsache, dass es sich nur um reine Abstraktion handelt, wobei die Grundlage für die Realität und die Geschäftslogik im vorgelegten Code 1 liegt; Aus diesem Grund wird nicht erwartet, dass dieser Code nach dem Testen geändert wird.

Ist das ein guter Ansatz bei der Programmierung? Dass es, sich ändernden Code in vielen Modulen sehr fragmentiert und sehr einfach zu verstehen und sich nicht ändernden Code sehr komplex aus der Abstraktion POV? Sollte der gesamte Code einheitlich komplex sein (dh Code 1 komplexer und verknüpft und Code 2 einfacher), so dass jeder, der ihn durchschaut, ihn in angemessener Zeit verstehen kann, Änderungen jedoch teuer sind oder die oben vorgestellte Lösung gut ist, wo "Code ändern" ist sehr einfach zu verstehen, zu debuggen, zu ändern und "Code verknüpfen" ist etwas schwierig.

Hinweis: Hier geht es nicht um Codelesbarkeit! Code bei 1 und 2 ist lesbar, Code bei 2 enthält jedoch komplexere Abstraktionen, während Code 1 einfache Abstraktionen enthält.

m3th0dman
quelle
3
Kommentare und eindeutige Namen werden erfunden, um die zum Verstehen von komplexem Code erforderliche Zeit zu verkürzen. Es ist völlig in Ordnung, wenn Ihr Code auf niedrigerer Ebene komplexer ist. Auf einer bestimmten Ebene spricht man mit ziemlicher Sicherheit ohnehin von einer weitaus komplexeren und tieferen Ebene.
DougM
25
"Zu viel" ist per Definition schlecht.
Jon Purdy
@ JimmyHoffa: Muss diese Typen an ihrer Stelle behalten. Und sei nicht eifersüchtig - ich kann Haskell nicht den ganzen Tag schreiben . Eigentlich sind es hauptsächlich PHP, JavaScript und OCaml.
Jon Purdy

Antworten:

78

Die allerersten Worte von TC ++ PL4:

Alle Probleme in der Informatik können durch eine andere Indirektionsebene gelöst werden, mit Ausnahme des Problems zu vieler Indirektionsebenen. - David J. Wheeler

(David Wheeler war mein Doktorvater. Das Zitat ohne die wichtige letzte Zeile wird manchmal "Das erste Gesetz der Informatik" genannt.)

Bjarne
quelle
6
Und woher weißt du, wenn du zu viele Indirektionsebenen hast? Ich würde eher sagen, dass es mit Erfahrung einhergeht, aber ein erfahrener Programmierer versteht leicht mehr Indirektion, weshalb er bei zu vielen Ebenen kein Problem sieht.
m3th0dman,
2
@ m3th0dman - Sie haben die richtige Abstraktionsebene, wenn es einfach wird, zukünftige Änderungen vorzunehmen. Natürlich können Sie auch fragen, woher Sie wissen, wann dies geschieht, wodurch der Fragezyklus lediglich auf andere Weise wiederholt wird.
1
Diese Frage ist wie von Programmierern abhängig. Sie werden komplexe Programmierer haben, die Ihre verrückte 8-Ebenen-Architektur verstehen und sie für brillant halten, während andere einfache, aber flüssige Programmierer sie für lächerlich halten und über Ihre verrückte 8-Ebenen streiten Projekt mit mehreren Ebenen. Hier zahlt sich die Dokumentation aus. Damit können Sie nicht nur Ihren Code dokumentieren, sondern auch verteidigen
Ryan
1
verzeihen Sie meine Unwissenheit, aber ich verstehe nicht "TC ++ PL4"
LastTribunal
30

Ja definitiv. Die Sache ist, keine Abstraktion ist perfekt. Alle Details der Ebene, auf der sich Abstraktionen befinden, sind aus einem bestimmten Grund vorhanden. Dies kann viele Dinge vereinfachen, aber wenn diese Komplexität nicht irgendwann erforderlich wäre, wäre sie wahrscheinlich gar nicht vorhanden. Und das bedeutet, dass irgendwann jede Abstraktion in irgendeiner Weise durchläuft.

Und hier liegt das eigentliche Problem. Wenn Abstraktionen fehlschlagen, ist es umso schwieriger, das Problem zu ermitteln und zu beheben, je mehr von ihnen Sie zwischen dem von Ihnen geschriebenen Code und den tatsächlichen Vorgängen geschichtet haben, da es möglicherweise mehr Stellen gibt, an denen das Problem auftritt. Und je mehr Schichten es gibt, desto mehr müssen Sie wissen, um sie aufzuspüren.

Mason Wheeler
quelle
1
"Und das bedeutet, dass irgendwann jede Abstraktion auf irgendeine Weise durchläuft.": Richtig. Eine bessere Abstraktion ist eine, die weniger häufig leckt.
Giorgio
11
In Anbetracht der Antwort von Bjarnes (und des Verweises auf die Wiki-Seite von David Wheeler ) können Sie vielleicht Ihre Zitat-Zuordnung ändern? :)
congusbongus
2
@CongXu: Übrigens habe ich vom anderen Ende aus gegoogelt: nach "Bjarne Stroustrup-Zitaten" gesucht und keinen einzigen Hinweis darauf gefunden, dass Bjarne den Satz "Hinzufügen einer weiteren Indirektionsebene" ausgesprochen hat ... Natürlich nicht schlüssig, tut es aber machen Sie es höchst unwahrscheinlich, dass er der erste war, der es aussprach.
Marjan Venema
1
Mehr Abstraktionsebenen bedeuten einfache Abstraktionen und damit weniger Leckage pro Abstraktion. In einer mathematischen Formulierung (natürlich ohne Beweise) kann die Summe der Abstraktionslecks konstant sein, wenn sich die Anzahl der Abstraktionsstufen ändert.
m3th0dman
2
Ich habe mich mal naiv an einen Senior gewandt, um dort eine Abstraktion einzufügen, wo sie nicht gebraucht wurde. Es wurde nie über das hinaus verwendet, was ich eigentlich wollte.
Cees Timmerman
15

Ja absolut.

Die Analogie, die ich gerne zur Erklärung der Programmierung verwende, ist die eines Schneiders. Bei der Anfertigung eines Anzugs hinterlässt ein guter Schneider immer eine kleine Menge Stoff an strategischen Stellen innerhalb des Kleidungsstücks, damit das Kleidungsstück ein- oder ausgezogen werden kann, ohne seine Gesamtform oder -struktur zu verändern.

Good Tailor's hinterlässt keine Stoffmengen an jeder Naht, nur für den Fall, dass Sie einen dritten Arm wachsen lassen oder schwanger werden. Zu viel Material an den falschen Stellen führt zu einer schlechten Passform und einem schlechten Tragekomfort. Der zusätzliche Stoff steht dem normalen Gebrauch im Weg. Zu wenig Stoff und das Kleidungsstück neigen zu Tränen und können nicht verändert werden, um geringfügige Veränderungen des Körperbaus des Trägers zu bewältigen, die sich auf den Sitz des Kleidungsstücks auswirken.

Vielleicht wird unser Guter Schneider eines Tages die Aufgabe haben, ein Kleid so eng zu machen, dass es eingenäht werden muss. Und vielleicht wird unser Good Tailor gebeten, Umstandsmode herzustellen, bei der Stil und Passform neben Komfort und Erweiterbarkeit an zweiter Stelle stehen. Bevor Sie jedoch eine dieser besonderen Aufgaben übernehmen, ist ein guter Schneider klug genug, um alle auf die Kompromisse aufmerksam zu machen, die zur Erreichung dieser Ziele gemacht werden.

Manchmal sind diese Kompromisse der richtige Weg und die Menschen sind bereit, ihre Konsequenzen zu akzeptieren. In den meisten Fällen überwiegt jedoch der Ansatz, ein wenig dort zu lassen, wo er am meisten zählt, den wahrgenommenen Nutzen.

Also, dies wieder mit Abstraktion in Verbindung bringen. Es ist absolut möglich, viel zu viele Abstraktionsebenen zu haben, genauso wie es möglich ist, viel zu wenig zu haben. Die wahre Kunst des Programmierers ist, wie unsere Schneiderfreunde, ein wenig dort zu lassen, wo es am meisten zählt.

Zurück zum Thema.

Das Problem mit Code ist normalerweise keine Abstraktion, sondern Abhängigkeiten. Wie Sie bereits betont haben, ist der Code, der diskrete Objekte verbindet, ein Problem, da eine implizite Abhängigkeit zwischen ihnen besteht. Irgendwann muss die Kommunikation zwischen den Dingen nur noch konkret sein, aber um zu beurteilen, wo dieser Punkt normalerweise liegt, muss man raten.

Das heißt "Micro" ist normalerweise ein Hinweis darauf, dass Sie Ihr Objektlayout übergranuliert haben und wahrscheinlich Type als Synonym für das verwenden, was Data sein soll . Weniger Dinge zu haben, bedeutet auch, dass weniger Abhängigkeiten erforderlich sind, um zwischen ihnen zu kommunizieren.

Aus diesem Grund bin ich ein großer Fan von asynchronem Messaging zwischen Systemen. Sie haben am Ende zwei Systeme, die von der Nachricht abhängig sind und nicht voneinander. Sie erhalten eine weniger enge Kopplung zwischen kommunizierenden Systemen. Wenn Sie zu diesem Zeitpunkt eine Abhängigkeit zwischen Systemen benötigen, müssen Sie prüfen, ob Sie die Bits haben, die an den richtigen Stellen abhängig sind. Und es ist oft der Fall, dass Sie nicht.

Schließlich wird komplizierter Code kompliziert. Daran führt oft kein Weg vorbei. Code, der weniger Abhängigkeiten aufweist, ist jedoch weitaus einfacher zu verstehen als ein Code, der auf verschiedenen externen Zuständen beruht.

Matt D
quelle
2
+1 für "Good Tailor's hinterlässt keine Stoffmengen an jeder Naht, nur für den Fall, dass Sie zufällig einen dritten Arm wachsen lassen oder schwanger werden". Leider neigen wir oft dazu, Software auf diese Weise zu entwerfen.
Kemoda
Zusammen mit der Verständlichkeit kann man Abstraktion auch nützlich finden, wenn man eine gekrümmte Linie in eine gerade biegt. Das heißt, Sie reduzieren die Komplexität und / oder Entropie mit der Abstraktion. Vielleicht so etwas wie ein Curry-Daten-Handler, bei dem das Fett, das Sie rasieren, später noch nützlich ist.
Cody
13

Meines Erachtens ist es unser Ziel, gute Abstraktionen zum gegebenen Domänenmodell und der Geschäftslogik zu liefern.

Ich sehe das anders: Unser Ziel ist es, ein Geschäftsproblem zu lösen. Abstraktionen sind nur eine Technik, um eine Lösung zu organisieren. Eine andere Antwort verwendet die Analogie eines Schneiders, der Kleidung herstellt. Ich denke an eine andere Analogie: ein Skelett. Der Code ist wie ein Skelett, und Abstraktionen sind die Verbindungen zwischen Knochen. Wenn Sie keine Gelenke haben, haben Sie nur einen einzigen Knochen, der sich überhaupt nicht bewegen kann und nutzlos ist. Aber wenn du zu viele Gelenke hast, bekommst du einen Haufen schlampiges Gelee, das nicht alleine stehen kann. Der Trick besteht darin, das richtige Gleichgewicht zu finden - genügend Gelenke, um Bewegung zuzulassen, aber nicht so sehr, dass es keine tatsächlich definierte Form oder Struktur gibt.

Jordan Lev
quelle