Ist die List-Schnittstelle eine undichte Abstraktion?

9

Wenn ich eine Variable habe, die a Listenthält, kann sie Objekte vieler verschiedener Typen enthalten, z . B. ArrayListoder LinkedList. Der Unterschied zwischen a LinkedListund an ArrayListist ziemlich groß. Das große O-Verhalten der Methoden ist sehr unterschiedlich. Zum Beispiel ist das Sortieren Listund anschließende Verwenden für binäre Suchen für a vollkommen in Ordnung ArrayList, würde aber mit a keinen Sinn ergeben LinkedList.

Blass
quelle
Was bedeutet "das große O"?
Tulains Córdova

Antworten:

25

Das würde ich nicht sagen.

Eine undichte Abstraktion zwingt Sie dazu, sich mit Implementierungsdetails zu befassen, die abstrahiert werden sollen. Die Leistung ist jedoch zwischen den Implementierungen immer unterschiedlich. Wenn Sie dies als undicht betrachten, gibt es keine nicht undichten Abstraktionen.

Wenn etwas als Listohne weitere Dokumentation deklariert wird , sollte klar sein, dass es einfach keine Garantien für die Leistung gibt, und wenn Sie etwas leistungsabhängiges damit machen wollen, sollten Sie eine Kopie erstellen und damit arbeiten.

Vergessen Sie auch nicht, dass es eine noch allgemeinere Benutzeroberfläche gibt, deren Funktionalität häufig ausreicht und die Sie nicht dazu verleitet, so viele Annahmen über die Leistung zu treffen : Collection.

Michael Borgwardt
quelle
9
Es gibt eine noch allgemeinere Schnittstelle, deren Funktionalität häufig ausreicht : Iterable.
Emory
Leistungsunterschiede zwischen den verschiedenen Implementierungen werden erwartet. ZB gibt es Unterschiede zwischen Vector und ArrayList, aber eine Abrufoperation für eine LinkedList scheint nur seltsam.
Blass
17

Alle nicht trivialen Abstraktionen sind bis zu einem gewissen Grad undicht. Trotzdem bin ich mir nicht sicher, ob es hier zutrifft. :-)

Abstraktionen befassen sich mit Verhalten. Sofern das Verhalten Listkeine bestimmte Leistung angibt (was Java nicht tut), handelt es sich um ein Implementierungsdetail - dh irrelevant.

In Java können Sie keine Mindestleistung für Schnittstellen außerhalb der Dokumentation angeben, und mir sind keine Sprachen bekannt, die dies tun. Die Überprüfung durch den Compiler wäre unglaublich schwierig (unmöglich?). Ich kann einige Optionen sehen, wenn die Leistung ein Problem darstellt:

  1. Dokumentieren Sie es in der Klasse / Schnittstelle, zu der die Listeninstanz gehört.
  2. Erstellen Sie eine neue Schnittstelle - z. B. BinarySearchPerformantList(yuck!) -, die die Leistungsanforderungen der verschiedenen Methoden angibt.

Option 2 ist wahrscheinlich die bessere Abstraktion, bringt jedoch zusätzlichen Aufwand mit sich.

Vaughandroid
quelle
1
+1. Technisch gesehen ist eine Liste eine undichte Abstraktion , aber auch ein Objekt zum Ausblenden der Komplexität im Zusammenhang mit der Verwendung equalszum Vergleichen von Objekten.
Neil
2
@Neil Ich denke, es ist umstritten ... Da die Abstraktion die Leistung nicht erwähnt, denke ich nicht, dass es in diesem Fall fehlschlägt (wie ich argumentiert habe). Ich würde sagen, wenn Sie über Leistung nachdenken, brauchen Sie eine andere / engere Abstraktion. Wird bearbeiten, um das zu erwähnen.
Vaughandroid
Es hängt davon ab, was Sie verstecken, nehme ich an. Ist die Nutzung komplex oder liegt sie in der Speichernutzung und -implementierung? Denn wenn es sich um eine abstrakte Klasse handelt, werden eine oder mehrere dieser Komplexitäten auf die eine oder andere Weise verborgen.
Neil
Ich spielte viele Jahre eine Variation von Option 2 unter Verwendung von Marker - Schnittstellen wie die Umsetzung rück LinearSpaceund LogarithmicTimeund wie dann erklären Klassen public class BinarySearch : ISearchStrategy<T>, LogarithmicTime. Andere Klassen könnten Parameter verwenden public T find<T, S>(IList<T> list, S strategy) where S : ISearchStrategy<T>, LogarithmicTime { }, um Leistungsbeschränkungen durchzusetzen.
Lucas
2
Wenn wir uns an den Artikel von Joel Spolsky halten, denke ich, dass er "bis zu einem gewissen Grad undicht" ist. Lesen Sie das folgende Zitat aus dem Artikel: "Wenn Sie mit den Systemadministratoren in Ihrem Unternehmen knapp waren und diese Sie bestraften, indem sie Sie an einen überlasteten Hub anschließen, werden nur einige Ihrer IP-Pakete durchkommen und TCP wird funktionieren, aber alles wird funktionieren." sei wirklich langsam "Ich denke, das trifft zu
Amish Programmer
4

In Java gibt es eine RandomAccess- Schnittstelle, die als Liste mit im Allgemeinen konstanter Direktzugriffszeit (O (1) get, put usw.) definiert ist. Wenn Sie der Meinung sind, dass für Ihr Modul eine Liste mit diesen Leistungsmerkmalen erforderlich ist, sollten Sie RandomAccessstatt verwenden List. Wenn Sie nicht das Bedürfnis haben, diese Änderung vorzunehmen (und nur wenige tun dies), ist List möglicherweise nicht so undicht.

MikeFHay
quelle
1

Sie haben Recht, eine Liste ist eine undichte Abstraktion. Die STL verwendet die Idee von Konzepten , um dieses spezifische Problem zu modellieren. Um Ihr Beispiel zu verwenden, ArrayListmodelliert eine einen Iterator mit wahlfreiem Zugriff, während eine LinkedList einen Vorwärtsiterator modelliert . Unterschiedliche Konzepte haben unterschiedliche Leistungsanforderungen, wodurch sie für unterschiedliche Algorithmen geeignet sind .

Matthew Finlay
quelle