Nos équipes ont la discussion suivante:
Disons que nous avons les deux méthodes suivantes:
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);
ce qui est envoyé par câble n'est que les identifiants.
un côté dit que la première méthode est correcte, car nous n'avons que les identifiants de terminal et de club, et il doit être clair que nous n'avons rien d'autre, c'est mon approche.
l'autre côté dit que la deuxième méthode est correcte car elle est plus flexible.
Nous connaissons l'idée du paramètre d'objet, l'autre côté pense également que le paramètre d'objet devrait avoir les objets comme propriétés.
Quelle est la bonne approche?
Peut-être existe-t-il une troisième approche encore meilleure?
Réponses:
La réponse dépend du contexte.
Si le client devrait avoir tous ces objets déjà disponibles , j'utiliserais les paramètres d'objet. Sinon, leur code sera plus compliqué qu'il ne devrait l'être. (Par exemple, ils auront des appels comme
club.getId()
, par exemple.)Si le client ne dispose que des identifiants facilement, alors la deuxième approche est peut-être meilleure, car vous ne voudrez peut-être pas que le client assemble / charge tous ces objets si vous n'avez vraiment besoin que des identifiants.
Une option consiste à fournir les deux méthodes , afin que le client puisse choisir celle à utiliser (étant donné que cela n'encombre pas votre API)
En général, les paramètres d'objet sont plus extensibles, car si à l'avenir vous avez besoin d'un autre élément de données pour faire le travail, vous n'avez pas besoin d'introduire une autre méthode qui prend ces informations supplémentaires.
Enfin, les signatures de votre méthode ne doivent pas être dictées par les détails de ce que fait la méthode (dans votre cas, ce qui se passe exactement sur le fil). L'API devrait avoir un sens abstrait, donc si l'implémentation change, vous n'êtes pas foutu.
la source
La première approche indique une obsession primitive . Parce que vous passez des entiers et des chaînes, il est très facile pour le programmeur de faire une erreur (par exemple en passant un clubId au paramètre terminalId). Cela entraînera des bogues difficiles à trouver.
Dans le deuxième exemple, il est impossible de dépasser un club lorsqu'un terminal est attendu - cela vous donnerait une erreur de temps de compilation.
Même ainsi, je regarderais toujours
string invoice
. Une facture est-elle vraiment une chaîne? Que veutamount
dire? Il s'agit plus probablement d'une valeur monétaire.Vous avez mentionné dans votre question "ce qui est envoyé par câble n'est que les identifiants". C'est correct, mais ne laissez pas cette exigence brouiller votre domaine.
La meilleure explication que j'ai vue en faveur de cette approche était dans la règle 3 de la callisthénie objet :
la source
Il n'y a pas de bonne réponse à celle-ci. L'une ou l'autre option pourrait convenir à l'emploi. Eh bien presque de toute façon, l'argument de la facture a soulevé un sillon sur mon front, je n'ai aucune idée de ce que c'est en lisant le code.
Si vous envoyez un identifiant, les deux systèmes doivent être étroitement couplés à ce que cela représente. ClubID est la clé du tableau des clubs. Plus précisément, l'appelant et l'appelé doivent s'entendre sur le nom de la table Clubs et sur la base de données dans laquelle elle se trouve. Si vous ne voulez pas ou ne pouvez pas imposer cette contrainte, vous passeriez l'objet en utilisant une description commune, natif, sérialisé, xml, nom = valeur quelconque, un fichier ini :)
Cela, comme vous l'avez identifié, vous coûtera "sur le fil". Éviter cela en envoyant simplement l'identifiant vous coûte ailleurs. Alors, lequel vous fait le moins mal, maintenant (ou peut-être plus tard ...) est l'indicateur du bon contre le mauvais.
la source