Warum die Verwendung von Tupeln anstelle von Objekten?
Codebase wo ich arbeite hat ein Objekt namens Paar, wo A und B die Typen der ersten und zweiten Werte in das Paar. Ich finden Sie dieses Objekt um beleidigend zu werden, weil Sie benutzt wird, anstatt ein Objekt mit klar benannten Mitglieder. Also ich find das:
List<Pair<Integer, Integer>> productIds = blah();
//snip many lines and method calls
void doSomething(Pair<Integer, Integer> id) {
Integer productId = id.first();
Integer quantity = id.second();
}
Statt
class ProductsOrdered {
int productId;
int quantityOrdered;
//accessor methods, etc
}
List<ProductsOrderded> productsOrdered = blah();
Viele andere Verwendungen für das Paar in der codebase sind auch schlecht riechen.
Habe ich Gegoogelt Tupel und Sie scheinen oft missverstanden oder in zweifelhafter Weise. Gibt es ein überzeugendes argument für oder gegen deren Einsatz? Ich kann verstehen, dass Sie nicht wollen, um große Klasse Hierarchien aber sind es realistische codebase, wo die Klasse Hierarchie würde explodieren, wenn Sie Tupel nicht verwendet?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zunächst ein Tupel ist schnell und einfach: statt eine Klasse zu schreiben, die für jedes mal, wenn Sie wollen, um 2 Dinge zusammen, gibt es eine Vorlage, die es für Sie tut.
Sekunde alle, Sie sind generisch. Zum Beispiel in C++ std::map verwendet ein std::pair von Schlüssel und Wert. So JEDES paar kann verwendet werden, anstatt eine Art von wrapper-Klasse mit Zugriffsmethoden für jede permutation von zwei Arten.
Schließlich, Sie sind nützlich für die Rückgabe mehrere Werte. Es gibt wirklich keinen Grund, um eine Klasse, die speziell für eine Funktion mehrere Werte zurückgeben, und Sie sollten diese nicht als ein Objekt behandelt, wenn Sie nicht verwandt sind.
Um fair zu sein, den code, der eingefügt wird, eine schlechte Nutzung ein paar.
TryParse
Methode für die eingebauten Datentypen in C#. Hier, Sie brauchen, um wieder einebool
(ob das Parsen erfolgreich war) und, sagen wir, einint
(der Wert, wenn das Parsen erfolgreich war). Zu ermöglichen, eine zweite return-Wert, derout
- Schlüsselwort verwendet wird. Ich denke, ein Tupel wäre schön hier statt, aber ich bin mir nicht sicher, ob es besser ist als das deklarieren eines Typs mit einerbool
namensParseSuccessful
und einen generischenT
namensValue
.equal_range
gibt ein paar von Iteratoren. Maps in c++ gleichwertig ist, setzt derpair<key, value>
. Es gibt andere Fälle, aber ich kann nicht von Ihnen denken jetzt.Tupel verwendet werden, die ganze Zeit in Python, wo Sie integriert sind in die Sprache und sehr nützlich (Sie können mehrere return-Werte für den Anfang).
Manchmal Sie wirklich brauchen nur paar Dinge und erstellen eine echte, ehrlich zu Gott, Klasse ist übertrieben. Auf der anderen Seite mit Tupeln, wenn Sie sollten wirklich mit einer Klasse ist nur so schlimm, eine Idee, wie die Rückseite.
Code-Beispiel hat ein paar verschiedene Gerüche:
Es ist schon ein Tupel verfügbar in den Rahmen; die
KeyValuePair
Struktur. Dies wird durch dieDictionary
- Klasse zum speichern von Paaren, aber Sie können es verwenden, überall passt es. (Nicht sagen, dass es passt in diesem Fall...)Wenn Sie haben eine Liste von Paaren, es ist besser, verwenden Sie die
KeyValuePair
Struktur als eine Klasse mit dem gleichen Zweck, wie es die Ergebnisse in weniger Speicherzuordnungen.Einer Klasse mit Eigenschaften, die deutlich zeigt, was die Werte bedeuten, während ein
Pair<int,int>
Klasse nicht sagen, nichts darüber, was die Werte darstellen (nur, dass Sie wahrscheinlich irgendwie verwandt). Um den code einigermaßen selbsterklärend mit so einer Liste, dass müssten Sie geben Sie die Liste ein sehr desciptive Namen, wieproductIdAndQuantityPairs
...Für das, was seinen Wert, wird der code im OP ist ein Chaos, nicht, weil es Tupel verwendet, aber da die Werte im Tupel sind zu schwach typisiert. Vergleichen Sie die folgenden:
Ich würd mich aufregen, wenn mein dev-team waren vorbei-IDs statt Klassen-Instanzen Rum, weil ein integer darstellen kann nichts.
Mit, dass gesagt wird, die tuples sind äußerst nützlich, wenn Sie Sie richtig benutzen:
Jedoch Tupel in C# machen meine Augen Wasser. Viele Sprachen wie OCaml, Python, Haskell, F# und so weiter, haben eine Besondere, prägnante syntax für die Definition von Tupeln. Zum Beispiel, in F#, die Map Modul definiert einen Konstruktor wie folgt:
Kann ich erstellen Sie eine Instanz von einer Karte mit:
Den equilvalent code in C# ist ridicuous:
Ich glaube nicht, dass es etwas falsch mit Tupeln im Prinzip, aber in C# - syntax zu umständlich, um den größten nutzen aus Ihnen heraus.
Es ist die Wiederverwendung von code. Vielmehr als das schreiben Noch eine Andere Klasse Mit Genau Der Gleichen Struktur Wie Die Letzten 5 Tupel-Wie Klassen, die Wir Gemacht Sie zu machen... eine Tuple-Klasse, und verwenden Sie, Wann immer Sie brauchen ein Tupel.
Wenn die einzige Bedeutung, die der Klasse "zu speichern, ein paar von Werten", dann würde ich sagen, mit Tupel ist eine naheliegende Idee. Ich würde sagen, es war ein code, der Geruch (so viel wie ich hasse den Begriff), wenn Sie begann mit der Umsetzung mehrere identische Klassen, nur damit könnten Sie benennen Sie die zwei Mitglieder.
Dies ist nur Prototyp-Qualität code, wahrscheinlich war zertrümmert zusammen und hat noch nie umgestaltet. Nicht in Ordnung ist es nur Faulheit.
Die Reale Nutzung für Tupel ist für generische Funktionen, die wirklich egal, was die Teile sind, aber nur betreibt auf Tupel-Ebene.
Scala hat tuple-valued Typen, die den ganzen Weg von 2-Tupeln (Paaren) bis zu Tupeln mit 20+ Elemente. Sehen Erste Schritte in Scala (Schritt 9):
Tupel sind nützlich, wenn Sie brauchen, um bundle-Werte für einige relativ ad-hoc - Zweck. Zum Beispiel, wenn Sie eine Funktion, die zurückkehren muss zwei relativ unabhängigen Objekten, anstatt eine neue Klasse erstellen, halten Sie die beiden Objekte, Sie kehren ein Paar von der Funktion.
Ich Stimme mit anderen Plakate, dass Tupel missbraucht werden kann. Wenn ein Tupel für jede Art von Semantik, die wichtig für Ihre Bewerbung, sollten Sie eine geeignete Klasse statt.
Das offensichtlichste Beispiel ist ein Koordinatenpaar (oder dreifach). Die Etiketten sind irrelevant; die Verwendung von X-und Y - (und Z -) ist nur eine Konvention. Machen Sie uniform macht es klar, dass Sie behandelt werden können in der gleichen Weise.
Tuple
erwartet werden, um unterschiedliche Bedeutungen haben. Dies ist der Grund, warum müssen Sie angeben, deren Typen individuell:Item1
kann ein string sein, aberItem2
eine Ganzzahl, etc.x
undy
tatsächlich Symmetrie (in der Regel in ein Koordinatensystem wir behandeln jede dimension identisch), und so es würde sogar noch mehr Sinn, einen Schritt weiter gehen und setzen Sie Sie in ein array!Viele Dinge wurden bereits erwähnt, aber ich denke, man sollte auch erwähnen, dass es einige Programmier-Stile, die unterscheiden sich von OOP und für diejenigen Tupel sind sehr nützlich.
Funktionale Programmiersprachen wie Haskell zum Beispiel nicht haben, die Klassen überhaupt.
Wenn Sie tun eine Schwartzian verwandeln zu Sortieren, indem Sie einen bestimmten Schlüssel (die ist teuer zu berechnen wiederholt), oder etwas wie, dass eine Klasse, scheint ein bisschen übertrieben:
Dass ein
class DataAndKey
oder was auch immer scheint ein wenig überflüssig hier.Deinem Beispiel war kein gutes Beispiel für ein Tupel, obwohl, ich bin einverstanden.