Ich habe gehört, wie der Satz herumgeworfen wurde, und für mich klingen die Argumente völlig verrückt (sorry, wenn ich hier Strohmann bin, es ist nicht meine Absicht), im Allgemeinen geht es etwas in der Art von:
Sie möchten keine Abstraktion erstellen, bevor Sie den allgemeinen Fall kennen. Andernfalls (1) können Sie Dinge in Ihre Abstraktionen einfügen, die nicht dazu gehören, oder (2) wichtige Dinge weglassen.
(1) Für mich klingt dies so, als ob der Programmierer nicht pragmatisch genug ist. Sie haben Annahmen getroffen, dass Dinge im endgültigen Programm existieren würden, die dies nicht tun. Sie arbeiten also mit einem zu geringen Abstraktionsgrad, das Problem ist es nicht vorzeitige Abstraktion, es ist vorzeitige Konkretion.
(2) Das Weglassen wichtiger Dinge ist eine Sache. Es ist durchaus möglich, dass etwas in der Spezifikation weggelassen wird, das sich später als wichtig herausstellt. Die Lösung hierfür besteht nicht darin, Ihre eigene Konkretion zu finden und Ressourcen zu verschwenden, wenn Sie es herausfinden falsch geraten, um mehr Informationen vom Kunden zu erhalten.
Wir sollten immer von Abstraktionen bis hin zu Konkretionen arbeiten, da dies die pragmatischste Art ist, Dinge zu tun, und nicht umgekehrt.
Wenn wir dies nicht tun, riskieren wir, Kunden falsch zu verstehen und Dinge zu schaffen, die geändert werden müssen. Wenn wir jedoch nur die Abstraktionen erstellen, die die Kunden in ihrer eigenen Sprache definiert haben, sind wir diesem Risiko nie ausgesetzt (zumindest bei weitem nicht so wahrscheinlich wie das Eingehen ein Schuss in die Dunkelheit mit einer gewissen Konkretion), ja, es ist möglich, dass Kunden ihre Meinung über die Details ändern, aber die Abstraktionen, mit denen sie ursprünglich kommunizierten, was sie wollen, sind in der Regel immer noch gültig.
Angenommen, ein Kunde möchte, dass Sie einen Artikelverpackungsroboter erstellen:
public abstract class BaggingRobot() {
private Collection<Item> items;
public abstract void bag(Item item);
}
Wir bauen etwas aus den Abstraktionen auf, die der Kunde verwendet hat, ohne näher auf Dinge einzugehen, die wir nicht kennen. Dies ist äußerst flexibel. Ich habe gesehen, dass dies als "vorzeitige Abstraktion" bezeichnet wird, obwohl es in Wirklichkeit verfrüht wäre anzunehmen, wie das Absacken implementiert wurde. Nehmen wir beispielsweise an, dass nach der Besprechung mit dem Kunden mehr als ein Gegenstand gleichzeitig verpackt werden soll . Um meine Klasse zu aktualisieren, muss ich nur die Signatur ändern, aber für jemanden, der von unten nach oben gestartet ist, kann dies eine umfassende Systemüberholung bedeuten.
Es gibt keine vorzeitige Abstraktion, nur vorzeitige Konkretion. Was ist falsch an dieser Aussage? Wo sind die Fehler in meiner Argumentation? Vielen Dank.
Antworten:
Zumindest meiner Meinung nach ist vorzeitige Abstraktion ziemlich häufig und war besonders früh in der Geschichte von OOP.
Zumindest nach dem, was ich gesehen habe, bestand das Hauptproblem darin, dass die Leute die typischen Beispiele objektorientierter Hierarchien durchgelesen haben. Sie bekamen viel gesagt über bereit machen alles mit zukünftigen Änderungen zu befassen , die möglicherweise entstehen (auch wenn es keinen besonders guten Grund zu glauben , sie würden). Ein anderes Thema, das vielen Artikeln für eine Weile gemeinsam war, waren Dinge wie das Schnabeltier, das sich einfachen Regeln über "Säugetiere sind alle so" oder "Vögel sind alle so" widersetzt.
Infolgedessen haben wir Code erhalten, der sich wirklich nur mit Aufzeichnungen von Mitarbeitern befassen musste, aber sorgfältig geschrieben wurde, um bereit zu sein, falls Sie jemals ein Spinnentier oder vielleicht ein Krebstier eingestellt haben.
quelle
Es ist wichtig, sich daran zu erinnern, dass Abstraktion ein Mittel zum Zweck ist. Sie verwenden die Abstraktion, um das Verhalten in Ihrem Programm zu vereinheitlichen und das Hinzufügen neuer Klassen zu vereinfachen, wenn Sie erwarten, dass neue Klassen hinzugefügt werden, jedoch nur dann, wenn die Abstraktion in diesem Moment benötigt wird.
Sie würden keine Abstraktion hinzufügen, nur weil Sie sie möglicherweise benötigen (ohne echte Grundlage für die Annahme, dass Sie in Zukunft neue Klassen hinzufügen müssen). Eine richtige Metapher hier könnte Sanitär sein. Hoffentlich stimmen Sie zu, dass ein 6-Richtungsrohr, mit dem Wasser nach oben / unten, Ost / West, Nord / Süd fließen kann, der flexibelste Rohrtyp ist, den Sie haben könnten. Sie könnten theoretisch ein 6-Richtungsrohr überall dort verwenden, wo ein Rohr benötigt wird, und die nicht benötigten Richtungen blockieren, oder?
Wenn Sie versucht haben, ein Problem mit einem Leck unter Ihrem Waschbecken zu beheben, und festgestellt haben, dass alle Rohrabschnitte 6-Richtungs-Rohrstücke sind, möchten Sie dem Mann, der es so entworfen hat, frustriert die Haare ausreißen. Sie wissen nicht nur nicht, wo das Problem liegt, sondern es wäre mit ziemlicher Sicherheit einfacher, einfach von vorne zu beginnen und es richtig zu machen.
Natürlich ist Codierung kein Sanitär, aber die Metapher steht immer noch. Die Abstraktion ähnelt der Verwendung dieser 6-Richtungs-Rohrstücke. Verwenden Sie sie, wenn Sie ehrlich glauben, dass Sie eines Tages in naher Zukunft Rohre aus allen 6 Richtungen anschließen müssen. Ansonsten ist Abstraktion einfach eine Komplikation, nicht viel anders als die Verwendung eines Musters, bei dem keines erforderlich ist, oder die Verwendung einer Gottklasse, die versucht, alles zu tun. Wenn es nicht verwendet wird und wahrscheinlich nie verwendet wird, fügen Sie letztendlich eine zusätzliche Klasse für nichts hinzu.
Zugegeben, die Kunst, Programme zu schreiben, ist konzeptionell sehr, sehr abstrakt. Es ist nur erwähnenswert, dass Abstraktionen nicht existieren, um eine Abstraktion zu sein, sondern weil sie auf echte Weise praktisch sind . Wenn Sie das Bedürfnis haben, Abstraktion zu verwenden, sollten Sie es tun, aber bitten Sie mich nicht, Ihre Installation anschließend zu überprüfen. ;)
quelle
class
zentriert zu sein ... Selbst wenn es viele Klassen gibt, ist die Abstraktion nicht darauf beschränkt, in ihnen verwendet zu werden.Als ich vor vielen Jahren etwas über objektorientierte Analyse und Design erfuhr, begannen wir mit einer einfachen englischen Beschreibung des Systems, das der Kunde benötigte.
Wenn man das durchschaut, wird jedes Substantiv (oder jede Nominalphrase) als mögliche Klasse betrachtet. Alle Verben (oder Verbalphrasen) wären mögliche Methoden für Klassen. "Bagging Robot" könnte also eine Klasse sein
BaggingRobot
. "Öffnen Sie eine Tasche" könnte Methode werdenOpenBag
.Nach einigen Iterationen würde dies zu einem Klassendiagramm.
Zu diesem Zeitpunkt gibt es keine abstrakten Klassen. Der Kunde möchte kein abstraktes Konzept eines Absackroboters. Sie wollen einen Roboter, der Dinge in Taschen packt. Alle Klassen sind konkret und haben eine Reihe von Methoden.
Abstrakte Klassen werden nur eingeführt, wenn klar wird, dass:
Für mich bedeutet "vorzeitige Abstraktion", dass jeder von einigen erben
BaggingRobot
mussBaseRobot
und, schlimmer noch, versucht, eine Reihe von Methoden zu entwickeln,BaseRobot
bevor Sie überhaupt wissen, was allen Robotern gemeinsam ist.quelle
Es hört sich ein bisschen so an, als ob Sie ein Problem lösen möchten, das noch nicht existiert, und dass Sie keinen guten Grund haben anzunehmen, dass es auftreten wird, es sei denn, Sie glauben nur, dass der Client in dem, was er anfordert, falsch liegt. In diesem Fall würde ich mehr Kommunikation empfehlen, als eine abstrakte oder sonstige Vermutungslösung zu implementieren. Es mag zwar harmlos erscheinen, nur "abstrakt" auf die Klassendefinition zu setzen und sich sicher zu fühlen, dass Sie sie später erweitern können, aber Sie werden feststellen, dass Sie dies niemals tun müssen, oder Sie werden feststellen, dass Sie sie auf eine Weise erweitern, die das Design zu kompliziert macht die Linie, indem man die falschen Dinge abstrahiert.
Stellen Sie sich anhand Ihres Beispiels vor, dass es der Roboter selbst , die verpackten Gegenstände oder die Art des Absackens ist , die sich später ändern werden?
Vorzeitige Abstraktion bedeutet wirklich nur, dass Sie keinen guten Grund haben, die Abstraktion durchzuführen, und da Abstraktionen in vielen Sprachen weit davon entfernt sind, kostenlos zu sein, können Sie ohne Begründung Overhead verursachen.
Bearbeiten Um einige Punkte aus OP in den Kommentaren zu beantworten, aktualisiere ich dies, um dies zu verdeutlichen und so zu beantworten, dass keine lange Kommentarkette erforderlich ist, während die Punkte (1) und (2) genauer angesprochen werden.
(Hervorhebung von mir). Angenommen, im endgültigen Programm gibt es Dinge, die nicht genau das sind, was ich in Ihrem Beispiel sehe. Der Kunde bat um einen Roboter zum Absacken von Gegenständen. Dies ist eine sehr spezifische Anfrage, wenn auch in ihrer Sprache etwas vage. Der Kunde wünscht sich einen Roboter, der Gegenstände einpackt, sodass Sie ein Paar Objekte herstellen können
Ihr Modell ist einfach und präzise. Es folgt den vom Kunden gestellten Anforderungen, ohne die Lösung komplexer zu gestalten und ohne davon auszugehen, dass der Kunde mehr wollte, als er wollte. Wenn dies die Notwendigkeit eines austauschbaren Absackmechanismus des Roboters verdeutlicht, verfügen Sie nur dann über genügend Informationen, um die Erstellung einer Schnittstelle oder einer anderen Abstraktionsmethode zu rechtfertigen, da Sie jetzt auf einen bestimmten Mehrwert verweisen können , der hinzugefügt wird das System durch die Abstraktion.
Im Gegenteil, wenn Sie mit der Abstraktion vom reinen Pragmatismus beginnen, verbringen Sie entweder Zeit damit, eine separate Schnittstelle zu erstellen und diese in einer Konkretion zu implementieren, oder erstellen eine abstrakte Klasse oder eine beliebige Art der Abstraktion, die Sie mögen. Sollte sich dann herausstellen, dass der Kunde damit zufrieden ist und keine weitere Erweiterung erforderlich ist, haben Sie Zeit und Ressourcen vergeblich aufgewendet und / oder Overhead und Komplexität ohne Gewinn in das System eingeführt.
In Bezug auf (2) stimme ich zu, dass das Weglassen wichtiger Dinge kein Zeichen vorzeitiger Abstraktion ist. Abstraktion oder nicht, Sie können etwas Wichtiges weglassen, und wenn es nicht weit unten in einer Abstraktionskette gefunden wird, wird es nicht schwieriger oder einfacher sein, dies so oder so zu klären.
Stattdessen würde ich das so interpretieren, dass jede Abstraktion das Risiko birgt, Ihr Domain-Modell zu verschleiern. Eine falsche Abstraktion kann es sehr schwierig machen, über ein System nachzudenken, da Sie Beziehungen erstellen, die das weitere Wachstum des Domänenmodells und des Domänenverständnisses drastisch beeinflussen können. Sie laufen Gefahr, nicht wichtige Informationen über das zu abstrahierende Objekt , sondern über das gesamte System wegzulassen , indem Sie Ihr Modell in das falsche Kaninchenloch bringen.
quelle