Was ist falsch daran, Hashtabellen von öffentlichen Methoden zurückzugeben, und wann ist dies sinnvoll?

9

Was sind die Entwurfsprobleme beim Zurückgeben einer Hashtabelle von einer öffentlichen Methode, wenn Sie mehrere Elemente zurückgeben möchten, anstatt eine Klasse zu erstellen und ein Objekt davon zurückzugeben?

Wenn es Probleme gibt, unter welchen Umständen ist es sinnvoll, dies zu tun?

Wie ändert sich die Antwort auf diese Frage, je nachdem, ob die Sprache dynamisch ist oder nicht?

Bearbeiten: Hiermit wird klargestellt, dass die Schlüssel konstant sind und Teil des Codes und nicht der Daten sind. Etwas, für das wir normalerweise eine Klasse erstellen. Die Frage ist, warum es falsch wäre, stattdessen Hashtable zu verwenden, wenn das Erstellen einer Klasse tatsächlich die richtige Wahl zu sein scheint.

Muhammad Hasan Khan
quelle

Antworten:

11

Verwenden Sie eine besser definierte Klasse als Rückgabetyp als eine Hashtabelle, die eine beliebige Anzahl von Werten als Name / Wert-Paare enthält.

  1. Der erste und wichtigste Punkt ist - Wartbarkeit. Wenn ein neuer Programmierer den Code betrachtet, kann er niemals sagen, welche Werte die Methode zurückgibt. Wenn eine neue Person dies anhand des Codes nicht versteht, ist der Code nicht nützlich und fehleranfällig, wenn jemand diesen Daten weitere Schlüssel / Werte hinzufügt oder die Anwendung erweitert.

  2. Methoden sind Verträge zwischen dem Anrufer und dem Dienst. Das Wichtigste an einer Methode ist ihre Ein- und Ausgabe. Diese Ein- und Ausgabe sollte leicht lesbar und verständlich sein und sich selbst dokumentieren. Wenn Sie eine Personenklasse als Rückgabewert verwenden, der Vorname, Nachname und Alter enthält, ist sie selbstdokumentierend. Wenn Sie hierfür ein Javadoc generieren, kann der Benutzer zwischen den Klassen navigieren, um dies besser zu verstehen. Wenn Sie eine Hashtabelle verwenden, müssen Sie diese entweder in den Kommentaren erläutern, die niemand lesen wird, oder sie aktualisieren, wenn sich etwas ändert.

  3. Sie können keine Generika verwenden, wie HashMap<String,String>für den Fall, dass Sie der return-Anweisung eine Zahl (z. B. das Alter) hinzufügen möchten. Wenn Sie keine Generika verwenden, müssen Sie zwischen dem Objekt und dem tatsächlichen Typ hin und her wechseln. Sie können dies speichern, wenn Sie dynamische Eingabe verwenden.

  4. Außerdem besteht eine größere Wahrscheinlichkeit, dass die Laufzeit fehlschlägt, als dass Probleme bei der Kompilierung auftreten. Wenn beispielsweise jemand einen Eintrag aus der Hashmap löscht und einer der alten Anrufer den Eintrag erwartet, schlägt der Client zur Laufzeit fehl. Es ist immer besser, dieses Problem in der Kompilierungszeit zu beheben.

  5. Es ist schwierig, einen unveränderlichen Typ zurückzugeben, wenn Sie Hashmap als Rückgabetyp usw. verwenden möchten. Wenn Sie jedoch einen benutzerdefinierten Typ verwenden, können Sie dies steuern.

Es wird verlockend sein, eine Hashmap als Rückgabetyp zu verwenden, da Sie vermeiden können, zu Beginn einige Klassen zu erstellen, aber es wird ein Albtraum sein, den Code in Zukunft beizubehalten. Gehen Sie objektorientiert!

java_mouse
quelle
1
Sie scheinen die Frage richtig verstanden zu haben. Vielen Dank.
Muhammad Hasan Khan
8

Eines der Probleme wäre, dass in vielen Fällen der Schlüssel für die Hash-Tabelle eine Zeichenfolge ist. Die Verbraucher der Methode müssten also vorher wissen, welche Schlüssel zum Extrahieren der Daten verwendet werden sollen. Dies würde zu Fehlern aufgrund von Rechtschreibfehlern beim Zugriff auf die Daten führen.

Ein weiterer Nachteil ist die Refaktorierbarkeit. Wenn Sie sich später entscheiden, den Namen eines Mitglieds zu ändern, haben Sie eine Reihe magischer Zeichenfolgen, die ebenfalls geändert werden müssen. Es ist viel einfacher, ein Klassenmitglied mit Refactoring-Tools umzubenennen, die von den meisten guten IDEs bereitgestellt werden. Mit einer Hash-Tabelle müssten Sie wahrscheinlich einen Such- / Ersetzungsvorgang für alle Quelldateien durchführen, was problematisch sein könnte.

Schließlich verlieren Sie die Kompilierungszeit für die Überprüfung des Mitgliederzugriffs - sowohl hinsichtlich des Namens als auch des Typs. Letzteres ist kein solches Problem, wenn Ihre Hash-Tabelle nur einen Objekttyp enthält, aber wenn sie viele enthält (auch in derselben Hierarchiekette), möchten Sie das Typensystem Ihrer Sprache wirklich nutzen und dort die Kompilierungszeit überprüfen lassen. In den meisten IDEs gibt es eine Art Intellisense- / Autocomplete-Funktionen - diese funktionieren anhand des Typsystems, können Ihnen jedoch bei der Verwendung von Hash-Tabellenschlüsseln nicht helfen.

In Zeiten, in denen es angebracht wäre , eine Hash-Tabelle (oder eine andere solche Sammlung von Schlüsselwertpaaren) zurückzugeben, würden Sie dies verwenden, wenn sowohl die Werte als auch die Schlüssel zur Kompilierungszeit nicht bekannt sind. Wenn Sie beispielsweise eine Methode haben, die eine Abfragezeichenfolge analysiert und die Schlüssel und entsprechenden Werte zurückgibt, ist eine Hash-Tabelle eine gute Wahl. In diesem Fall möchten Sie auch darüber nachdenken, eine unveränderliche oder schreibgeschützte Hash-Tabelle zurückzugeben.

Bearbeiten - Die meisten Punkte in dieser Antwort gelten nicht mehr, wenn Sie über dynamische Sprachen sprechen :)

MattDavey
quelle
Was ist, wenn die Sprache dynamisch ist?
Muhammad Hasan Khan
Ich bin kein Experte für dynamische Sprachen, daher kann wahrscheinlich jemand anderes eine bessere Antwort darauf geben. Aber ich weiß, dass dynamische Sprachen sowieso keine Überprüfung der Kompilierungszeit durchführen. Aber in diesem Fall sind das Zurückgeben eines Objekts und das Zurückgeben einer Hash-Tabelle nicht so unähnlich.
MattDavey
3
@ Hasan Khan: In diesem Fall gibt es möglicherweise keinen Unterschied zwischen einer Hashtabelle und einer Klasseninstanz. In Javascript sind beispielsweise alle Objekte Hashtabellen, und object.property ist genau dasselbe wie object ['property']
Michael Borgwardt,
"Mit einer Hash-Tabelle müssten Sie wahrscheinlich einen Such- / Ersetzungsvorgang für alle Quelldateien durchführen, was problematisch sein könnte." Nur wenn Sie schlechte Schlüssel ausgewählt haben und nie versucht haben, die Standardschlüssel so herauszufiltern, dass sie an einem Ort definiert sind…
Donal Fellows
7

Das wichtigste Argument dagegen wäre, dass Sie dem Verbraucher zu viele Informationen zur Verfügung stellen. Der konsumierende Code muss nur wissen, dass es sich um eine Schlüsselwertsammlung (Wörterbuch) handelt. Ob es als Hashmap, Assoziationsliste, Trie oder was auch immer implementiert ist, ist relativ uninteressant. Der richtige Weg wäre also, über eine geeignete Schnittstelle ( IDictionaryoder was auch immer Ihre Sprache Ihrer Wahl verwendet) anstelle des tatsächlichen Typs zurückzukehren.

All dies unter der Annahme, dass Sie tatsächlich ein Wörterbuch benötigen, um Ihre Daten darzustellen, dh Ihre Daten bestehen aus Schlüssel / Wert-Paaren, wobei die Schlüssel innerhalb des Datasets eindeutig sind und zur Kompilierungszeit nicht festgelegt werden können. Wenn Sie bereits bekannte Schlüssel haben, sollten Sie einen geeigneten Typ (oder mehrere, je nach Bedarf) für Ihre Daten erstellen. Es kommt darauf an, ob Sie die Schlüssel selbst als Teil der Daten oder als Teil des Codes betrachten.

EDIT :

Zur Verdeutlichung verwende ich den Begriff Wörterbuch , um hier den allgemeinsten Typ der Schlüsselwertdatenstruktur zu bezeichnen. Ich meine keine sprachspezifische Implementierung wie Pythons dictoder .NETs Dictionary.

tdammers
quelle
1
+1 für "Es kommt darauf an, ob Sie die Schlüssel selbst als Teil der Daten oder als Teil des Codes betrachten." - Das ist ein guter Weg, um es auszudrücken. Ich bin mir nicht sicher, wie universell der Begriff "Wörterbuch" im Gegensatz zu "Karte" ist.
MattDavey
Die Rückgabe des Wörterbuchs war nicht beabsichtigt. Schlüssel waren Teil des Codes, nicht der Daten.
Muhammad Hasan Khan
Die eigentliche Frage ist die Begründung für "Sie sollten einen geeigneten Typ erstellen". Frage ist warum?
Muhammad Hasan Khan
2

Eine Frage, die ich mir stellen würde, lautet: "Ändern sich die Schlüssel in diesem Wörterbuch?" Wenn sie konstant sind, sollten Sie ein Objekt oder eine andere geeignete Datenstruktur zurückgeben. Wenn sie dynamisch sind, möchten Sie möglicherweise eine Art Wörterbuchstilstruktur zurückgeben. Wenn es einige Schlüssel gibt, die konstant sein sollen, und einen unbekannten Satz dynamischer Schlüssel, möchten Sie möglicherweise eine hybride Datenstruktur mit einigen festen Werten und einer Art Wörterbuch für den Überlauf zurückgeben.

Wyatt Barnett
quelle
In der Tat ist Ihr Rat richtig, aber die Frage ist, was falsch ist, wenn Sie sich für die Verwendung von Hashtabellen entscheiden, wenn der Unterricht die bessere Wahl ist.
Muhammad Hasan Khan
Es ist nicht entweder / oder; Eine Klasse kann bei Bedarf problemlos ein Wörterbuch enthalten.
Wyatt Barnett