Combien d'arguments du constructeur est de trop?
Disons que vous avez une classe appelée Client, qui contient les champs suivants:
- Nom d'utilisateur
- Prénom
- Nom De Famille
Disons aussi que, selon une logique d'entreprise, tous les objets de Client doit avoir ces quatre propriétés définies.
Maintenant, on peut le faire assez facilement en obligeant le constructeur à préciser chacun de ces propriétés. Mais il est assez facile de voir comment cela peut devenir une spirale hors de contrôle lorsque vous êtes forcé d'ajouter plus de champs nécessaires à l'objet Client.
J'ai vu des classes qui prennent en 20+ arguments en leur constructeur et c'est juste une douleur à utiliser. Mais, sinon, si vous n'avez pas besoin de ces champs, vous courez le risque d'avoir pas défini d'informations, ou pour le pire, le référencement d'un objet erreurs si vous comptez sur le code appelant à spécifier ces propriétés.
Existe-il des alternatives à cette ou pensez-vous que vous avez juste à décider si X montant des arguments du constructeur, c'est trop pour vous de vivre?
Vous devez vous connecter pour publier un commentaire.
Deux approches de conception à considérer
La essence modèle
La interface fluide modèle
Ce sont à la fois semblables dans leur intention, en qui nous avons lentement construire un objet intermédiaire, et ensuite créer notre objet cible en une seule étape.
Un exemple de l'interface fluide dans l'action serait:
CustomerBuilder
etCustomer
. En outre, cet exemple est très bien si toutes les variables d'instance sont facultatives, mais si tous sont obligatoires et vous avez des dizaines d'entre eux, alors je ne suis pas sûr que vous serez en mesure d'éviter constructeur avec tous ces arguments. Si vous n'avez pas un constructeur avec tous ces attributs obligatoires puis-je, en tant que client codeur, ne serait pas en mesure de voir que par l'interface d'une classe je suis sur le point de créer et c'est quelque chose que je ne voudrais pas.Je vois que certaines personnes recommandent de sept comme une limite supérieure. Apparemment, il n'est pas vrai que les gens peuvent tenir sept choses dans leur tête à la fois; ils ne peuvent se rappeler de quatre (Susan Weinschenk, 100 Choses à Chaque Concepteur a Besoin de Savoir sur Personnes, 48). De même, je considère que quatre à être quelque chose d'une grande orbite autour de la terre. Mais c'est parce que ma pensée a été modifié par Bob Martin.
Dans Propre Code, Oncle Bob plaide pour trois comme supérieur général de limite pour le nombre de paramètres. Il fait de la radicalité de la demande (40):
Il dit cela à cause de la lisibilité, mais aussi du fait de la testabilité:
Je vous encourage à trouver un exemplaire de son livre et à la lecture de sa pleine discussion des arguments de la fonction (40-43).
Je suis d'accord avec ceux qui ont mentionné le Principe de Responsabilité Unique. Il est difficile pour moi de croire qu'une classe qui a besoin de plus que deux ou trois valeurs/des objets sans valeurs par défaut raisonnables a vraiment qu'une seule responsabilité, et ne serait pas mieux avec une autre classe extrait.
Maintenant, si vous êtes l'injection de vos dépendances par le constructeur, Bob Martin arguments au sujet de combien il est facile d'invoquer le constructeur ne pas tellement s'appliquent (parce que d'habitude, alors il existe un seul point dans votre application où vous fil, ou vous avez même un cadre qui le fait pour vous). Toutefois, le Principe de Responsabilité Unique est toujours d'actualité: une fois qu'une classe a quatre dépendances, je considère que l'odeur qu'elle est en train de faire une grande quantité de travail.
Cependant, comme avec toutes les choses dans l'informatique, il y a sans doute valides pour avoir un grand nombre de paramètres du constructeur. Ne pas déformer votre code afin d'éviter à l'aide d'un grand nombre de paramètres, mais si vous utilisez un grand nombre de paramètres, d'arrêter et de lui donner une certaine pensée, car il peut signifier que votre code est déjà tordu.
Dans votre cas, s'en tenir avec le constructeur. L'information appartient à la Clientèle et les 4 champs sont beaux.
Dans le cas où vous avez de nombreux champs obligatoires et facultatifs le constructeur n'est pas la meilleure solution. Comme @boojiboy dit, c'est difficile à lire et il est aussi difficile d'écrire du code client.
@contagieuse a suggéré d'utiliser le modèle par défaut et les setters pour facultatif des attributs. Que les mandats que les champs sont mutables, mais c'est un problème mineur.
Joshua Bloc sur l'efficacité de Java 2-dire que, dans ce cas, vous devriez envisager un constructeur. Un exemple tiré du livre:
Et ensuite l'utiliser comme ceci:
L'exemple ci-dessus a été prise à partir de Efficace Java 2
Et qui ne fait pas que s'applique à un constructeur. Citant Kent Beck dans La Mise En Œuvre Des Schémas:
Le rectangle explicite comme un objet, explique le code mieux:
Je pense que le "pur OOP", la réponse est que si les opérations de la classe ne sont pas valides lorsque certains membres ne sont pas initialisé, alors ces membres doit être défini par le constructeur. Il y a toujours les cas où les valeurs par défaut peuvent être utilisés, mais je vais supposer que nous n'êtes pas tenu de cette affaire. C'est une bonne approche lorsque l'API est fixe, car la seule admissible constructeur après l'API va public va être un cauchemar pour vous et tous les utilisateurs de votre code.
En C#, ce que je comprends sur les lignes directrices de conception, c'est que ce n'est pas nécessairement la seule façon de gérer la situation. En particulier avec des objets WPF, vous trouverez que .NET les classes ont tendance à favoriser sans paramètre constructeurs et lève des exceptions si les données n'ont pas été initialisé à un état souhaité avant d'appeler la méthode. C'est probablement surtout spécifiques à la composante de base de la conception de bien; je ne peux pas venir avec un exemple concret d'une .NET de classe qui se comporte de cette manière. Dans votre cas, ce serait certainement causer une augmentation de la charge sur des tests pour s'assurer que la classe n'est jamais enregistré à la banque de données, à moins que les propriétés ont été validées. Honnêtement, de ce fait, je préfère le "constructeur définit les propriétés nécessaires à l'approche du" si votre API est définie dans la pierre ou pas public.
La seule chose que je suis certain, c'est qu'il y a probablement d'innombrables méthodes pour résoudre ce problème, et chacun d'eux présente son propre ensemble de problèmes. La meilleure chose à faire est d'apprendre autant de modèles que possible et de choisir le meilleur pour le job. (N'est-ce pas un tel cop-out d'une réponse?)
Je pense que votre question est plus sur la conception de vos classes que sur le nombre d'arguments dans le constructeur. Si j'ai besoin de 20 morceaux de données (arguments) pour réussir à initialiser un objet, je serais probablement envisager de diviser la classe.
Steve Mcconnell écrit dans le Code Complet que les gens ont du mal à tenir plus de 7 choses dans leur tête à un moment, alors que j'avais le numéro, j'ai essayer de rester sous.
Si vous avez unpalatably de nombreux arguments, puis il suffit de les emballer ensemble dans les structures /POD classes, de préférence déclaré que les classes intérieures de la classe en cours de construction. De cette façon, vous pouvez toujours exiger les champs, tout en rendant le code qui appelle le constructeur raisonnablement lisible.
Je pense que tout dépend de la situation. Pour quelque chose comme votre exemple, une classe de clients, je ne voudrais pas courir le risque d'avoir que des données étant pas défini en cas de besoin. Sur le revers de la médaille, le passage d'une structure permettrait d'effacer la liste des arguments, mais vous auriez encore beaucoup de choses à définir dans la structure.
Je pense que le plus simple serait de trouver un acceptable par défaut pour chaque valeur. Dans ce cas, chaque champ dirait qu'il serait requis pour la construction, peut-être que la surcharge de l'appel de la fonction, de sorte que si quelque chose n'est pas défini dans l'appel, pour le mettre en défaut.
Ensuite, de lecture et de définition des fonctions pour chaque propriété de sorte que les valeurs par défaut peut être modifié.
Java mise en œuvre:
C'est aussi une bonne pratique de garder vos variables globales sécurisé.
Style compte pour beaucoup, et il me semble que si il ya un constructeur avec 20+ arguments, la conception doit être modifiée. Fournir des valeurs par défaut raisonnables.
Je suis d'accord sur l'article 7 de la limite Boojiboy mentionne. Au-delà, il peut être intéressant de regarder anonyme (ou spécialisé) types, IDictionary, ou d'indirection via clé primaire d'une autre source de données.
J'avais encapsuler dans des domaines similaires dans un objet de sa propre sa propre construction/validation de la logique.
Dire par exemple, si vous avez des
Je voudrais faire une classe qui stocke le téléphone et l'adresse avec une étiquette précisant que sa "maison" ou une "entreprise" téléphone/adresse. Et puis de réduire les 4 champs de simplement un tableau.
Qui devrait en faire regarder moins comme des spaghettis.
Sûrement, si vous avez beaucoup de domaines, il doit y avoir un modèle, vous pouvez extraire cela ferait une belle unité de la fonction qui lui est propre. Et rendre plus lisible le code aussi.
Et la suivante est aussi des solutions possibles:
CustomerFactory
classe qui m'aiderait à construireCustomer
sSuffit d'utiliser des arguments par défaut. Dans une langue qui prend en charge la méthode par défaut arguments (PHP, par exemple), on pourrait faire ça dans la signature de la méthode:
public function doSomethingWith($this = val1, $this = val2, $this = val3)
Il y a d'autres façons de créer des valeurs par défaut, comme dans les langages qui prennent en charge la surcharge de méthode.
Bien sûr, vous pouvez également définir des valeurs par défaut lorsque vous déclarez les champs, si vous le jugez approprié de le faire.
- Il vraiment tout se résume à savoir si ou non il est approprié pour vous de définir ces valeurs par défaut, ou si des objets specced à la construction de tous les temps. C'est vraiment une décision que vous seul pouvez faire.
À moins qu'il y a plus de 1 argument, j'ai toujours utiliser des tableaux ou des objets comme paramètres du constructeur et de compter sur l'erreur de vérification pour vous assurer que les paramètres requis sont là.