L'elenco dei parametri di un metodo dovrebbe contenere oggetti o identificatori di oggetti?


10

I nostri team stanno discutendo quanto segue:

Diciamo che abbiamo i seguenti due metodi:

public Response Withdraw(int clubId, int terminalId,int cardId, string invoice, decimal amount);

public Response Withdraw(Club club, Terminal terminal,Card card, string invoice, decimal amount);

ciò che viene inviato via cavo sono solo gli ID.

una parte dice che il primo metodo è corretto, perché abbiamo solo gli ID di terminale e club, e dovrebbe essere chiaro che non abbiamo nient'altro, questo è il mio approccio.

l'altra parte afferma che il secondo metodo è corretto perché è più flessibile.

Conosciamo bene l'idea del parametro oggetto, l'altro lato pensa anche che il parametro oggetto debba avere gli oggetti come proprietà.

Qual è l'approccio corretto?

Forse esiste un terzo approccio ancora migliore?


Cosa? ...........
James

1
Contesto? Servizio web? WCF?
Codici InChaos

1
@James - mi dispiace di aver scritto questa domanda in qualche modo veloce, puoi dirmi cosa non è stato compreso, così posso modificarlo?
Mithir

@CodesInChaos i metodi sono in realtà metodi BL
Mithir

Risposte:


10

La risposta dipende dal contesto.

Se ci si aspetta che il client abbia già tutti quegli oggetti disponibili , utilizzerei i parametri dell'oggetto. Altrimenti, il loro codice sembrerà più contorto di quanto debba essere. (Ad esempio avranno chiamate come club.getId(), ad esempio.)

Se il client avrà solo gli ID disponibili facilmente, allora forse il secondo approccio è migliore, poiché potresti non voler che il client debba assemblare / caricare tutti quegli oggetti se hai davvero bisogno solo degli ID.

Un'opzione è fornire entrambi i metodi , in modo che il client possa scegliere quale utilizzare (dato che ciò non ingombra l'API)

In generale, i parametri dell'oggetto sono più estensibili, poiché se in futuro hai bisogno di un altro dato per eseguire il lavoro, non è necessario introdurre un altro metodo che richieda tali informazioni extra.

Infine, le firme del metodo non dovrebbero essere dettate dalle specifiche di ciò che fa il metodo (nel tuo caso, cosa va esattamente oltre il filo). L'API dovrebbe avere senso in modo astratto, quindi se l'implementazione cambia, non sei fregato.


3
+1 Aggiungerei solo un altro punto: per i metodi chiamati in remoto ("over the wire"?), Il passaggio di oggetti può comportare la serializzazione profonda di un vasto albero di oggetti. Gli ID sono ottimi sostituti degli oggetti quando sei preoccupato per le dimensioni di un payload di chiamate remote.
Ross Patterson

1
In questo caso sembra che tu sia accoppiato a una serie di astrazioni, quindi passare gli ID non ti acquisterà più flessibilità e probabilmente aumenterà la probabilità di invertire i parametri. La domanda è: quanto è stretto il codice nel metodo accoppiato con le astrazioni che sto passando? Ad esempio, un metodo come "validateCreditCard (string card, string cvi)" probabilmente dovrebbe rimanere con le primitive per evitare di essere strettamente accoppiato con un qualche tipo di oggetto CreditCard.
ipaul

Mi sarei incontrato nel mezzo e avrei usato un'interfaccia nell'elenco dei parametri. Quindi il tuo club può essere un club, ma anche una sauna in futuro.
Pieter B,

13

Il primo approccio è indicativo dell'ossessione primitiva . Dato che stai passando ints e stringhe, è molto facile per il programmatore fare un errore (es. Passare un clubId al parametro terminalId). Ciò si tradurrà in bug difficili da trovare.

Nel secondo esempio, è impossibile passare un club quando ci si aspetta un terminal - questo ti darebbe un errore di tempo di compilazione.

Anche così, vorrei ancora guardare string invoice. Una fattura è davvero una stringa? Cosa amountsignifica? Questo è più probabilmente un valore monetario.

Hai menzionato nella tua domanda "ciò che viene inviato via cavo sono solo gli ID". Questo è corretto, ma non lasciare che questo requisito offuschi il tuo dominio.

La migliore spiegazione che ho visto a favore di questo approccio è stata nella regola 3 di Object Calisthenics :

Un int da solo è solo uno scalare, quindi non ha alcun significato. Quando un metodo accetta un int come parametro, il nome del metodo deve fare tutto il lavoro per esprimere l'intento. Se lo stesso metodo accetta un'ora come parametro, è molto più facile vedere cosa sta succedendo. Piccoli oggetti come questo possono rendere i programmi più gestibili, poiché non è possibile passare un anno a un metodo che accetta un parametro Hour. Con una variabile primitiva il compilatore non può aiutarti a scrivere programmi semanticamente corretti. Con un oggetto, anche se piccolo, stai fornendo al compilatore e al programmatore ulteriori informazioni su quale sia il valore e perché venga utilizzato.


Quindi il secondo approccio è preferito? anche se c'è un oggetto club con solo la proprietà id riempita?
Mithir

Questo sembra essere un blog casuale. Non ci sono prove per dire ciò che è preferito. A chi importa davvero cosa è preferito? Fai ciò che funziona per te
James

@James Non esiste una risposta definitiva a questa domanda, soprattutto perché l'OP non ci ha dato molto contesto. Chiunque afferma categoricamente che un approccio è preferibile all'altro sta facendo un disservizio all'OP. Non è così bianco e nero.
MattDavey,

1
@James Ho semplicemente sottolineato che il primo approccio rende molto facile introdurre bug difficili da trovare. Non sto dicendo che i tipi primitivi sono cattivi, ma lo scopo dei tipi primitivi è quello di costruire tipi di dominio significativi. Usarli al di fuori di questo contesto è la definizione stessa dell'odore primitivo del codice di ossessione.
MattDavey,

5
@James: Quello che ha detto MattDavey è un fatto ben noto. Non sta dicendo che i tipi nativi sono cattivi, quello che sta dicendo che: someMethod (int, int, int, string, decimal) è molto più difficile da capire e usare da un client rispetto a someMethod (Club, Terminal, Card, String , decimale)
c_maker

2

Non c'è una risposta giusta a questa. Entrambe le opzioni potrebbero essere adatte al lavoro. Beh, quasi in ogni caso, l'argomento della fattura ha sollevato un solco sulla mia fronte, non ho idea di cosa significhi leggere il codice.

Se si invia un ID, entrambi i sistemi devono essere strettamente associati a ciò che rappresenta. ClubID è la chiave nella tabella dei club. Più precisamente, sia il chiamante che il chiamante devono concordare come viene chiamata la tabella dei club e in quale database si trova. Se non si desidera o non si può imporre quel vincolo, si passa l'oggetto utilizzando una descrizione comune, nativo, serializzato, xml, name = value qualunque, un file ini :)

Quello che hai identificato ti costerà "oltre il filo". Evitarlo inviando l'identificatore costa altrove. Quindi quello che ti ferisce di meno, ora (o potrebbe essere più tardi ...) è l'indicatore del bene contro del male.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.