Je vois souvent deux stratégies conflictuelles pour les interfaces de méthode, résumées de manière vague comme suit:
// Form 1: Pass in an object. double calculateTaxesOwed(TaxForm f) { ... } // Form 2: Pass in the fields you'll use. double calculateTaxesOwed(double taxRate, double income) { ... } // use of form 1: TaxForm f = ... double payment = calculateTaxesOwed(f); // use of form 2: TaxForm f = ... double payment = calculateTaxesOwed(f.getTaxRate(), f.getIncome());
12 Réponses :
Cela dépend de l'intention de votre méthode. P>
Si la méthode est conçue pour fonctionner Mais, si la méthode est
Je ne pense pas que ça compte vraiment. Vous vous ouvrez aux effets secondaires si vous passez dans l'objet car il pourrait être muté. Cela pourrait cependant être ce que vous voulez. Pour atténuer cela (et pour faciliter les tests), vous êtes probablement mieux en train de passer l'interface plutôt que du type concret. La prestation est que vous n'avez pas besoin de modifier la signature de la méthode si vous souhaitez accéder à un autre champ de l'objet. P>
Passer tous les paramètres permet plus de préciser ce que les besoins de type et pourraient faciliter la test (bien que si vous utilisez l'interface, cela est moins avantages). Mais vous aurez plus de refactoring. P>
juge chaque situation sur ses mérites et choisissez le moins douloureux. P>
Un avantage du premier formulaire est P>
Je recommande vivement la deuxième solution - La méthode exécutant le calcul doit (habituellement) n'appartient même pas au même modul que l'interface utilisateur. Dans ce cas, vous obtenez une dépendance circulaire car l'interface utilisateur nécessite la logique commerciale et la logique d'entreprise nécessite le formulaire d'interface utilisateur - une très forte indication que quelque chose ne va pas (mais pourrait encore être résolu à l'aide de la programmation basée sur l'interface). P>
Si le formulaire de taxe n'est pas un formulaire d'interface utilisateur, les choses changent un peu. Dans ce cas, je suggère d'exposer la valeur à l'aide d'une méthode d'instance CalculateTaTaxesEfed () code> calcule certaines données, il faut donc une entrée numérique. La méthode n'a absolument rien à voir avec l'interface utilisateur et ne doit à son tour pas consommer un formulaire comme entrée, car vous souhaitez que votre logique commerciale soit séparée de votre interface utilisateur. P>
greatowedtaxes () code> ou d'une propriété d'instance
owedtaxes code> du
de la forme de taxe code> mais je n'utiliserais pas une méthode statique. Si le calcul peut être réutilisé ailleurs, on pourrait toujours créer une méthode d'assistance statique consommant les valeurs, non le formulaire et appeler cette méthode d'assistance à partir de la méthode d'instance ou de la propriété. P>
Je lis "formulaire de taxe" ici comme "formulaire 1040", pas "un écran d'interface utilisateur utilisé pour la saisie de données".
(Oh, et pour les lecteurs non américains, le 1040 est la principale forme utilisée pour soumettre des déclarations de revenus personnelles aux États-Unis. Donc, je suppose que le "Taxform" est une classe qui encapsule les informations et les procédures liées à un document de taxe spécifique. )
Désolé pour la confusion. Oui, par "formulaire" Je voulais dire "un ensemble de données et de comportements représentant une soumission de l'impôt sur le revenu auto-calculant".
En toute honnêteté, cela dépend de la méthode en question. P>
Si la méthode est logique sans l'objet, le deuxième formulaire est plus facile à réutiliser et supprime un couplage entre les deux classes. P>
Si la méthode s'appuie sur l'objet, alors assez juste, passez l'objet. P>
Il y a probablement un bon argument pour une troisième forme où vous passez une interface conçue pour fonctionner avec cette méthode. Vous donne la clarté de la première forme avec la flexibilité de la seconde. P>
Passage Just Les arguments peuvent être plus faciles à tester l'unité forts>, car vous n'avez pas besoin de se moquer de des objets entiers pleins de données uniquement pour tester des fonctionnalités essentiellement statiques. S'il n'y a que deux champs utilisés, de nombreux champs de l'objet, je me pencherais vers le passage de ces champs, tout le reste étant égal. P>
qui dit, L'autre option consiste à en faire une méthode de classe, de sorte que vous n'avez rien à passer. Il est moins pratique de tester, mais la peine d'être envisagée lorsque votre méthode n'est jamais utilisée que sur les données d'un objet de taxes. P>
C'est la même chose que "introduire l'objet de paramètre" du livre de Martin Fowler sur le refactoring. Fowler suggère de remplir ce refactoring s'il existe un groupe de paramètres qui ont tendance à être adoptés. P>
Si vous croyez en la loi de Demeter, vous favoriseriez en passant exactement ce qui est nécessaire: p>
Dans votre cas, il vous manque une classe intermédiaire, disons, taxInfo, représentant l'entité à taxer. La raison en est que l'interface utilisateur (la forme) et la logique commerciale (comment calculer le taux d'imposition) figurent sur deux "pistes de changement" différentes, une modification avec la technologie de présentation ("the web", "the web 2.0", "wpf" ,. ..), l'autre change avec leghantse. Définissez une interface claire entre eux. p>
Discussion générale, en utilisant un exemple: strong> p>
Considérez une fonction pour créer un bitmap pour une carte de visite. Est le but de la fonction p>
(1) // formats un titre de carte de visite à partir du prénom et du nom de famille em> p>
ou p>
(2) // formats un titre de carte businnes à partir d'un La première option est plus générique, avec un couplage plus faible, qui est généralement préférable. Cependant, dans de nombreux cas moins robustes contre les demandes de changement - par ex. Considérons "Cas 2017: Ajoutez des personnes initiales à la carte de visite". p>
Modification de la mise en œuvre (Ajout de la personne.Initial) est généralement plus facile et plus rapide que la modification de l'interface. P>
Le choix est en définitive quel type de changements vous attendez: est-il plus probable que davantage d'informations à partir d'une personne code> est requise ou est-il plus probable que vous souhaitiez créer des titres de carte de visite pour d'autres structures de données que Si cela est "indécis", ANFD que vous ne pouvez pas utiliser l'OPF à des fins (1) ou (2), je préfère aller avec (2), pour la propreté syntaxique. p>
personne code> record em> p>
personne code>? p>
Je réalise que cela est largement un artefact de l'exemple utilisé et il peut donc ne pas s'appliquer dans de nombreux cas mondiaux réels, mais si la fonction est si fortement attachée à une classe spécifique, alors ne devrait-il pas être: < PRE> XXX PRE>
Cela me semble plus approprié pour moi qu'un document fiscal assumerait la responsabilité elle-même du calcul des taxes pertinentes plutôt que de faire tomber cette responsabilité sur une fonction d'utilité, en particulier étant donné que différents formulaires d'impôt ont tendance à utiliser différentes tables d'impôt ou méthodes de calcul. p> p>
Si j'ai été fait pour choisir l'un des deux, j'irais toujours avec le second - que si vous constatez que vous (pour une raison quelconque) besoin de caculer les taxes dus, mais vous n'avez pas d'instance de < Code> Taxform code>?
Il s'agit d'un exemple assez trivial, mais j'ai vu des cas où une méthode faisant une tâche relativement simple avait des intrants complexes difficiles à créer, ce qui rend la méthode beaucoup plus difficile à utiliser que Cela aurait dû être. (L'auteur n'a tout simplement pas considéré que d'autres personnes voudront peut-être utiliser cette méthode!) P>
personnellement, pour rendre le code plus lisible, je voudrais probablement avoir les deux: p> Ma règle echétique est que dans la mesure du possible, avoir une méthode qui prend exactement l'entrée dont il a besoin - ses méthodes d'emballage très faciles à écrire. P> P>
Personnellement, je vais aller avec # 2 car il est beaucoup plus clair de ce que la méthode a besoin. En passant la taxe (si c'est ce que c'est ce que je pense que c'est, comme un formulaire Windows) est une sorte de smelly et me fait de me faire grincer un peu (> _ <). P>
J'utiliserais la première variation que si vous passez une DTO spécifique au calcul, comme l'objet IncometaxCalculSInfo qui contiendra le taxrate et le revenu et quoi que ce soit nécessaire pour calculer le résultat final dans la méthode, mais jamais quelque chose comme un Formulaire Windows / Web. P>