2010-04-19 4 views
59

In einem objektorientierten Programm: Wie viel Abstraktion ist zu viel? Wie viel ist genau richtig?Wie viel Abstraktion ist zu viel?

Ich war schon immer eine Art Schraubenzieher. Ich habe das Konzept verstanden, das hinter einem hohen Maß an Verkapselung und Abstraktion steht, aber habe immer instinktiv gespürt, dass das Hinzufügen von zu viel das Programm nur verwirren würde.

Ich habe immer versucht, für eine Menge an Abstraktion zu schießen, die keine leeren Klassen oder Ebenen übrig ließ. Und im Zweifelsfall würde ich, anstatt der Hierarchie eine neue Ebene hinzuzufügen, versuchen, etwas in die vorhandenen Ebenen einzupassen.

Allerdings traf ich in letzter Zeit stärker abstrahierte Systeme. Systeme, bei denen alles, was später eine Darstellung in der Hierarchie erfordern könnte, im Vordergrund steht. Dies führt zu vielen leeren Schichten, die zunächst als schlechtes Design erscheinen. Ich bin mir jedoch bei der Überlegung bewusst geworden, dass das Verlassen dieser leeren Schichten Ihnen mehr Orte bietet, an die Sie sich in der Zukunft ohne viel Refactoring anpassen können. Dadurch können Sie neue Funktionen auf die alten hinzufügen, ohne dass Sie so viel Arbeit aufwenden müssen, um die alten anzupassen.

Die zwei Risiken davon scheinen zu sein, dass Sie die Schichten bekommen könnten, die Sie falsch brauchen. In diesem Fall würde man immer noch aufwändige Refactoring durchführen müssen, um den Code zu erweitern und würde immer noch eine Tonne nie genutzter Layer haben. Aber abhängig davon, wie viel Zeit Sie damit verbringen, die ersten Abstraktionen zu erstellen, die Chance, es zu vermasseln, und die Zeit, die später eingespart werden könnte, wenn Sie es richtig machen - es könnte sich immer noch lohnen, es zu versuchen.

Das andere Risiko, das ich mir vorstellen kann, ist das Risiko, es zu überholen und nie alle zusätzlichen Schichten zu benötigen. Aber ist das wirklich so schlimm? Sind Extraklassen-Schichten wirklich so teuer, dass sie sehr verlustreich sind, wenn sie nie benutzt werden? Der größte Aufwand und Verlust wäre hier die Zeit, die im Vorfeld der Schichten verloren geht. Ein großer Teil dieser Zeit kann jedoch später gespeichert werden, wenn man mit dem abstrahierten Code arbeiten kann, anstatt mit Code auf niedrigerer Ebene.

Also wann ist es zu viel? An welchem ​​Punkt werden die leeren Schichten und die zusätzlichen "möglicherweise" Abstraktionen übertrieben? Wie wenig ist zu wenig? Wo ist der Lieblingsplatz?

Gibt es irgendwelche verlässlichen Faustregeln, die Sie im Laufe Ihrer Karriere gefunden haben und die Ihnen helfen, die benötigte Abstraktion zu beurteilen?

+6

Wie lange ein Stück Schnur ist ??? ;) – Goz

+2

Sollte CW IMHO sein, da es keine ** an ** Antwort –

+0

@Binary Worrier Done hat. –

Antwort

16

Also wann ist es zu viel? An welchem ​​Punkt tun die leeren Schichten und zusätzliche "könnte brauchen" Abstraktionen werden Overkill? Wie wenig ist zu wenig? Wo ist der Sweet Spot?

Ich glaube nicht, dass es eine definitive Antwort auf diese Fragen gibt. Erfahrung ist notwendig, um ein Gefühl dafür zu entwickeln, was "zu viel" und "zu wenig" ist. Vielleicht kann die Verwendung einiger Metrik- oder Qualitätskontroll-Tools helfen, aber es ist schwer zu verallgemeinern. Es hängt meistens von jedem Fall ab.

Hier sind ein paar Links, die Sie auf der Suche nach Antworten ergeben könnten:

Entwicklung dreht sich alles um die Suche nach richtiges Gleichgewicht zwischen den verschiedenen Tensio ns, die in einem Softwareentwicklungsprozess vorhanden sind.

+6

+1 Jedes Mal, wenn Sie eine Abstraktionsebene hinzufügen, sollten Sie die Vorteile in Betracht ziehen. Es gibt keinen Sinn in Abstraktion nur für Abstraktionen Willen. – CiscoIPPhone

+1

Dies ist ein beliebter über die Gefahren von Frameworks zu allgemein. Witziges Zeug! http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12 –

2

Die Realität hängt davon ab, wie gut Sie in die Zukunft blicken können. Sie möchten Änderungen planen, die Sie vorhersehen können, ohne zu viele zusätzliche Layer zu erstellen. Wenn Sie ein Design haben, das Daten zwischen Systemen überträgt, können Sie eine Schnittstelle erstellen und die geplante Implementierung als Standard verwenden. Beispielsweise verwenden Sie FTP, um Dateien zu verschieben, aber Sie wissen, dass der Standard im nächsten Jahr nachrichtenbasiert (oder was auch immer) sein wird.

Wie bei Layern innerhalb des Designs erleichtern manchmal die hinzugefügten Layer das Schreiben kleinerer Klassen. Es ist in Ordnung, konzeptuelle Ebenen hinzuzufügen, wenn dies bedeutet, dass die konkreten Klassen einfach werden.

6

Einfach gesagt, es gibt zu viel Abstraktion, wenn der Code schwer zu verstehen ist.

Das heißt jetzt nicht, dass Sie alles hart programmieren sollten, denn das ist der einfachste Code zum Schreiben und Lesen.

Der einfachste Test ist, es entweder für ein paar Tage hinzustellen, es wieder aufzunehmen und sich zu fragen, ob das Sinn macht. Ein besserer Ansatz ist es, es jemand anderem zu geben und zu sehen, ob sie Kopf oder Zahl davon machen können.

+2

"Es gibt zu viel Abstraktion, wenn der Code schwer zu verstehen ist" für wen? Ich habe angefangen, an horrend komplizierten Code-Basen zu arbeiten, und kann mich nach ein paar Monaten/Jahren leicht zurechtfinden. Außerdem habe ich mit hart codierten Sachen gearbeitet, die ohne ein paar sinnvolle Abstraktionen nicht zu verstehen waren. –

+1

Was ich meine ist, dass, wenn der Code wegen der Abstraktion schwierig ist, dann ist es zu viel. Ich sage nicht, dass Code ohne Abstraktion schwer zu lesen ist, aber Sie sollten in der Lage sein, sich den Code anzuschauen und zu sagen: "Ok Punkt A geht zu Punkt B. Das macht Sinn." – kemiller2002

+0

Ich stimme Kevin zu. Zum Beispiel erstelle ich manchmal ein Shell-Skript, um sich wiederholend zu arbeiten, aber dann vergesse ich, wie EXAKT das Skript funktioniert, und benutze nur die zugrunde liegenden Befehle. Zum Beispiel mit 'du'-Skripten: In welches Verzeichnis muss ich mich zur Ausführung des Skripts begeben? Wird die Ausgabedatei im aktuellen Verzeichnis abgelegt? Ist das Skript asynchron oder blockiert? (das genaue Skript, das ich habe, heißt disk_usage ist im Grunde "nohup du> disk_usage_recursive.txt &" aber ich am Ende nur diesen Befehl eingeben jeden Typ). –

0

Siehe Artikel (6a) von RFC 1925 und wissen, dass es in der Tat wahr ist. Die einzigen Probleme, die Sie nicht durch Hinzufügen von Abstraktionsschichten beheben können, sind die, die durch zu viele Abstraktionsebenen verursacht werden. (Insbesondere jedes Stück Abstraktion macht das ganze Ding schwerer zu verstehen.)

9

Theoretisch es sollte eine Frage der einfachen mathematischen nur drei (ziemlich einfach) Variablen sein:

  • S = Einsparungen durch den Einsatz
  • C = Kosten der zusätzlich Abstraktionen
  • P = Wahrscheinlichkeit der Verwendung

Wenn S * P> C, dann ist der Code gut. Wenn S * P < C, dann ist es schlecht.

Der Grund, der rein theoretisch ist, ist jedoch, dass Sie im Allgemeinen die Wahrscheinlichkeit des Gebrauches oder der Ersparnisse nicht erraten können, die Sie davon erhalten, es zu verwenden. Schlimmer noch, Sie können nicht oder in der Regel Maßnahme die Kosten seiner Anwesenheit erraten.

Zumindest einige Leute haben daraus eine Schlussfolgerung gezogen. In TDD lautet das Standardmantra "Du wirst es nicht brauchen" (YAGNI). Einfach gesagt, alles, was nicht direkt zu dem Code beiträgt, der seine aktuellen Anforderungen erfüllt, wird als schlecht angesehen. Im Wesentlichen sind sie zu dem Schluss gekommen, dass die Wahrscheinlichkeit der Verwendung so gering ist, dass ein solcher zusätzlicher Code niemals gerechtfertigt ist.

Einiges davon kommt zurück zu "Bottom-up" versus "top-down" Entwicklung. Ich tendiere dazu, die Bottom-Up-Entwicklung als "Bibliotheksentwicklung" zu betrachten - z. Anstatt eine bestimmte Anwendung zu entwickeln, entwickeln Sie Bibliotheken für die Dinge, die Sie in der Anwendung benötigen. Das Denken ist, dass mit einer gut genug Bibliothek, können Sie fast jede Anwendung dieser allgemeinen Art relativ leicht entwickeln.

Ziemlich hängt auch von der Größe des Projekts ab.Riesige Projekte, die jahrzehntelang in Gebrauch sind, rechtfertigen viel mehr langfristige Investitionen als kleinere Projekte, die viel schneller verworfen und ersetzt werden. Dies hat auch im wirklichen Leben offensichtliche Analoga. Sie machen sich nicht annähernd so viele Gedanken über die Passform, das Finish oder die Verarbeitung eines Einwegrasierers, den Sie in weniger als einer Woche wegschmeißen, wie Sie es in einem neuen Auto tun, das Sie in den nächsten paar Jahren benutzen werden .

2

Jede Abstraktion, die nicht wirklich verwendet wird, ist zu viel. Je einfacher ein System ist, desto einfacher ist es zu ändern. Abstraktionsschichten machen Systeme fast immer komplizierter.

OTOH, es ist sicherlich möglich, ein komplexes, unüberschaubares Chaos ohne jede Art von Abstraktion zu programmieren, und manchmal können "standardisierte" Abstraktionsschichten dazu beitragen, ein System besser zu strukturieren, als die meisten Menschen es könnten.

20

Wie wenig ist zu wenig?

Wenn Sie mit „niedrigem Niveau“ Elemente auf einer Routinebasis arbeiten weiter und man ständig das Gefühl, dass Sie don '; t wollen, dies zu tun. Abstrakt sie weg.

Also wann ist es zu viel?

Wenn Sie einige Codeteile nicht regelmäßig bearbeiten können, müssen Sie sie auf die vorherige Ebene debuggen. Sie fühlen, dass diese bestimmte Schicht nichts beiträgt, nur ein Hindernis. Lass es fallen.

Wo ist der Sweet Spot?

Ich mag es, den pragmatischen Ansatz anzuwenden. Wenn Sie ein Abstraktionsbedürfnis sehen und verstehen, wie es Ihr Leben verbessert, gehen Sie darauf ein. Wenn Sie gehört haben, dass es "offiziell" eine zusätzliche Ebene der Abstraktion geben sollte, aber Sie nicht klar sind, warum, tun Sie es nicht, sondern erforschen Sie zuerst. Wenn jemand darauf besteht, etwas zu abstrahieren, aber nicht klar erklären kann, was es bringt, sagen Sie ihm, dass er weggehen soll.

25

Der Punkt der Abstraktionen sind Faktor aus gemeinsamen Eigenschaften aus den spezifisch denjenigen, wie in der mathematischen Operation:

ab + ac => a(b + c) 

Jetzt haben Sie die gleiche Sache mit zwei Operationen tun statt drei. Dieses Factoring machte unseren Ausdruck einfacher.

Ein typisches Beispiel für eine Abstraktion ist das Dateisystem. Beispielsweise möchten Sie, dass Ihr Programm auf viele Arten von Speichergeräten schreiben kann: USB-Sticks, SD-Karten, Festplatten usw.

Wenn wir kein Dateisystem hätten, müssten wir das tun Implementieren der Direktschreibeschreiblogik, der Stiftschreiblogik und der SD-Kartenschreiblogik. Aber all diese Logiken haben etwas gemeinsam: Sie erstellen Dateien und Verzeichnisse, so dass diese allgemeinen Dinge abstrahiert werden können, indem eine Abstraktionsschicht erstellt wird und eine Schnittstelle zum Hardwarehersteller bereitgestellt wird, um die spezifischen Dinge zu tun.

Je mehr die Dinge eine gemeinsame Eigenschaft teilen.Je mehr vorteilhaft kann eine Abstraktion sein:

ab + ac + ad + ae + af 

zu:

a(b + c + d + e + f) 

Dies würde reduziert die 9 Operationen 5.

Grundsätzlich jede gute Abstraktion halbiert in etwa die Komplexität eines Systems.

Sie benötigen immer mindestens zwei Dinge, die eine gemeinsame Eigenschaft teilen, um eine Abstraktion nützlich zu machen. Natürlich können Sie eine einzige Sache auseinander reißen, so dass es wie eine Abstraktion aussieht, aber es bedeutet nicht, ist es nützlich:

10 => 5 * 2 

Sie können nicht das Wort „gemeinsam“ definieren, wenn Sie nur eine Einheit haben.

So, um Ihre Frage zu beantworten. Sie haben genug Abstraktionen, wenn sie Ihr System so einfach wie möglich machen.

(In meinen Beispielen verbindet zusätzlich die Teile des Systems, während die Multiplikation eine abstrakte Beton Beziehung definiert.)

+2

Dies .. nur das –

+0

Diese Antwort beschreibt die Verwendung von Abstraktionen, um Code DRY zu halten, aber es berührt andere wichtige/sinnvolle Verwendungen nicht der Abstraktion - z SOLID- oder GRASP-Muster und Metaprogrammierungsverträge, die die Trennung von Bedenken oder Nutzungskonsistenz erzwingen. – jchook