Domanda

Il codebase dove lavoro è un oggetto chiamato Coppia dove A e B sono i tipi di primi e secondo i valori di Coppia.Trovo questo oggetto per essere offensivo, perché viene usato invece di un oggetto chiaramente nominati membri.Quindi trovo questo:

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();
}

Invece di

class ProductsOrdered {
  int productId;
  int quantityOrdered;
  // accessor methods, etc
}

List<ProductsOrderded> productsOrdered = blah();

Molti altri usi della Coppia nel codebase sono allo stesso modo cattivo odore.

Ho cercato su google tuple e sembrano essere spesso frainteso o usato in dubbia modi.C'è un argomento convincente a favore o contro il loro uso?Posso apprezzare il non voler creare enormi gerarchie di classe, ma ci sono realistici e le basi di codice in cui la gerarchia di classe sarebbe esploso se tuple non sono stati utilizzati?

È stato utile?

Soluzione

Prima di tutto, una tupla è semplice e veloce:. Invece di scrivere una classe per ogni volta che si desidera mettere 2 cose insieme, c'è un modello che fa per voi

In secondo luogo, sono generici. Ad esempio, in C ++ std :: mappa utilizza uno std :: coppia di chiave e valore. Pertanto, qualsiasi coppia può essere utilizzato, invece di dover fare qualche tipo di classe wrapper con metodi di accesso per ogni permutazione di due tipi.

Infine, sono utili per la restituzione di più valori. Non c'è davvero alcun motivo per fare una classe appositamente per più valori di ritorno di una funzione, e non devono essere trattati come un unico oggetto se sono estranei.

Per essere onesti, il codice incollato è un cattivo uso di una coppia.

Altri suggerimenti

Le tuple vengono utilizzati per tutto il tempo in Python in cui sono integrati nel linguaggio e molto utile (che consentono a più valori di ritorno per cominciare).

A volte, è davvero solo necessario associare le cose e la creazione di un vero e proprio, onesto a Dio, di classe è eccessivo. Un altro canto, usando tuple quando si dovrebbe davvero utilizzare una classe è proprio così male un'idea quanto il contrario.

L'esempio di codice che ha un paio di odori diversi:

  • Reinventare la ruota

C'è già una tupla disponibili nel quadro;il KeyValuePair struttura.Questo è utilizzato per il Dictionary classe per memorizzare coppie, ma si può usare ovunque, si adatta.(Non dire che essa si inserisce in questo caso...)

  • Facendo una ruota quadrata

Se si dispone di un elenco di coppie è meglio usare il KeyValuePair la struttura di una classe con lo stesso scopo, in quanto si traduce in meno allocazioni di memoria.

  • Nascondere l'intenzione

Una classe con proprietà mostra chiaramente il significato dei valori, mentre un Pair<int,int> la classe non vi dice nulla su ciò che i valori rappresentano (solo che probabilmente sono legate in qualche modo).Per rendere il codice ragionevolmente auto esplicativo, con una lista del genere si dovrebbe dare la lista di un desciptive nome, come productIdAndQuantityPairs...

Per quanto il suo valore, il codice del PO è un casino, non perché usa tuple, ma perché i valori della tupla sono troppo debolmente tipizzato. Confrontare il seguente:

List<Pair<Integer, Integer>> products_weak = blah1();
List<Pair<Product, Integer>> products_strong = blah2();

Mi piacerebbe arrabbio troppo se il mio team di sviluppo passavano gli ID piuttosto che le istanze di classe in tutto, perché un intero può rappresentare niente .


Con questo detto, tuple sono estremamente utile quando si utilizzano a destra:

  • Le tuple esistono per valori di gruppo ad hoc insieme. Essi sono certamente meglio rispetto alla creazione di un numero eccessivo di classi wrapper.
  • alternativa Utile per out / parametri ref quando è necessario restituire più di un valore da una funzione.

Tuttavia, tuple in C # fanno lacrimare gli occhi. Molti linguaggi come OCaml, Python, Haskell, F #, e così via hanno una speciale, la sintassi concisa per la definizione di tuple. Per esempio, in F #, il modulo Mappa definisce un costruttore come segue:

val of_list : ('key * 'a) list -> Map<'key,'a>

posso creare un'istanza di una mappa utilizzando:

(* val values : (int * string) list *)
let values = 
    [1, "US";
     2, "Canada";
     3, "UK";
     4, "Australia";
     5, "Slovenia"]

(* val dict : Map<int, string> *)
let dict = Map.of_list values

Il codice equilvalent in C # è ridicuous:

var values = new Tuple<int, string>[] {
     new Tuple<int, string>(1, "US"),
     new Tuple<int, string>(2, "Canada"),
     new Tuple<int, string>(3, "UK"),
     new Tuple<int, string>(4, "Australia"),
     new Tuple<int, string>(5, "Slovenia")
     }

 var dict = new Dictionary<int, string>(values);

Non credo ci sia qualcosa di sbagliato con le tuple in linea di principio , ma la sintassi C # s 'è troppo ingombrante per ottenere il massimo utilizzo fuori di essi.

E 'il riutilizzo del codice. Piuttosto che scrivere un'altra classe con esattamente la stessa struttura come gli ultimi 5 classi tuple come abbiamo fatto, fate ... una classe Tuple, e l'uso che ogni volta che hai bisogno di una tupla.

Se l'unico significato della classe è "per memorizzare una coppia di valori", allora direi usando tuple è un'idea ovvia. Direi che è stato un odore di codice (per quanto io odio il termine) se hai iniziato attuazione più classi identiche solo in modo che si potrebbe rinominare i due membri.

Si tratta di codice appena prototipo di qualità, che probabilmente è stato distrutto insieme e non è mai stata riscritta. Non fissa è solo pigrizia.

Il vero uso per le tuple è per funzionalità generiche che in realtà non importa quali sono le parti che lo compongono sono, ma solo opera a livello tupla.

Scala ha tipi tuple con valori, tutta la strada da 2-tuple (coppie) fino a tuple con 20+ elementi. Vedere Primi punti a Scala (punto 9):

val pair = (99, "Luftballons")
println(pair._1)
println(pair._2)

Le tuple sono utili se avete bisogno di raggruppare insieme i valori per alcuni hoc scopo relativamente annuncio. Ad esempio, se si dispone di una funzione che deve restituire due oggetti abbastanza indipendenti, piuttosto che creare una nuova classe per contenere i due oggetti, è restituire un pari da funzione.

Sono completamente d'accordo con altri manifesti che tuple possono essere oggetto di abuso. Se una tupla ha alcun tipo di semantica importanti per la vostra applicazione, è necessario utilizzare invece una classe propria.

L'esempio ovvio è una coppia di coordinate (o tripla). Le etichette sono irrilevanti; con X e Y (e Z) è solo una convenzione. Rendendoli uniforme rende chiaro che possono essere trattati nello stesso modo.

Molte cose sono già stati menzionati, ma penso che si dovrebbe anche ricordare, che ci sono alcuni stili di programmazione, che si differenziano da OOP e per quelle tuple sono molto utili.

linguaggi di programmazione funzionali come Haskell per esempio non hanno classi a tutti.

Se stai facendo un Trasformata di Schwartz per ordinare in un determinato tasto (che è costoso per calcolare più volte), o qualcosa di simile, una classe sembra essere un po 'eccessivo:

val transformed = data map {x => (x.expensiveOperation, x)}
val sortedTransformed = transformed sort {(x, y) => x._1 < y._1}
val sorted = sortedTransformed map {case (_, x) => x}

Avere un class DataAndKey o qualsiasi altra cosa sembra un po 'superfluo qui.

Il tuo esempio non è stato un buon esempio di una tupla, però, sono d'accordo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top