71 votes

Est-ce que faire beaucoup dans les constructeurs est mauvais?

Faire tous les champs final est en général une bonne idée, mais parfois, je me trouve de tout faire dans le constructeur. Récemment je me suis retrouvé avec une classe va tout dans le constructeur, y compris la lecture d'un fichier de propriété et de l'accès à une base de données.

D'une part, c'est ce que la classe est destinée, il encapsule les données lues et j'aime créer des objets complètement initialisé. Le constructeur n'est pas compliqué du tout comme il délègue la plupart des travaux, de sorte qu'il semble très bien.

D'autre part, il se sent un peu étrange. En outre, dans ce parler , aux environs de 17:58 il y a de bonnes raisons de ne pas faire beaucoup de travail dans le constructeur. Je pense que je peux éliminer le problème en passant approprié nuls que des arguments du constructeur.

La question demeure: Est de faire beaucoup de travail (ou même tout le travail) dans les constructeurs mauvais?

44voto

Emily L. Points 696

Je pense que "Faire le travail dans le constructeur" est correct...

... tant que vous n'avez pas violer le Principe de Responsabilité Unique (SRP) et le bâton à l'aide de l'Injection de Dépendance (DI).

Je me pose aussi cette question ces derniers temps. Et la motivation à l'encontre de faire des travaux dans le constructeur que j'ai trouvé sont soit:

  • C'est difficile à tester
    • Tous les exemples que j'ai vu ont été où DI n'a pas été utilisé. Il n'est pas vraiment la faute du constructeur de travail réel.
  • Vous ne pourriez pas besoin de tous les résultats que votre constructeur calcule, de perdre du temps de traitement et il est difficile de test dans l'isolement.
    • C'est essentiellement d'une violation de la SRP, pas une faute du constructeur de travail par dire.
  • Vieux compilateurs ont/ont eu des ennuis avec les exceptions levées dans les constructeurs, par conséquent, vous ne devriez pas faire autre chose que de l'attribuer des champs dans les constructeurs.
    • Je ne pense pas que c'est une bonne idée d'écrire un nouveau code en prenant historique compilateur carences en compte. Nous pourrions bien faire loin avec le C++11 et tout ce qui est bon, tous ensemble, si nous le faisons.

Mon optionion est-ce que...

... si votre constructeur doit faire un travail pour qu'il adhère à l'Acquisition de Ressources Est d'Initialisation (RAII) et la classe de ne pas violer la SRP et de la DI est correctement utilisé; Ensuite de faire le travail dans le constructeur est d'Accord! Vous pouvez même lancer une exception si vous souhaitez empêcher l'utilisation d'un objet de classe dont l'initialisation a échoué complètement au lieu de compter sur l'utilisateur afin de vérifier certains de la valeur de retour.

20voto

David Titarenco Points 17148

C'est un très ouverts à la question, donc, ma réponse va essayer d'être aussi général que possible...

Faire du travail dans les constructeurs n'est pas comme "mauvais" comme il l'habitude d'être il y a des années lors de la manipulation d'exception n'était pas aussi répandue et a évolué comme il l'est aujourd'hui. Vous remarquerez que Google Tech talk principalement regarde les constructeurs à partir d'un point de vue Test. Les constructeurs ont été historiquement très très difficile à déboguer de sorte que le haut-parleur est correct que de faire aussi peu que possible dans un constructeur, c'est mieux.

Cela étant dit, vous remarquerez qu'il est aussi de toucher sur l'injection de dépendances/le fournisseur de modèle qui est tristement célèbre pour compliquer les constructeurs. Dans un tel cas, le laissant SEUL fournisseur/DI code dans le constructeur est préféré. Encore une fois, la réponse dépend de ce que les modèles que vous utilisez et de votre code "s'adapte" ensemble.

Le point essentiel de l'aide d'un constructeur est de créer un joli objet qui peut être utilisé immédiatement; c'est à dire new Student("David Titarenco", "Senior", 3.5). Il n'y a pas besoin de faire d' david.initialize() comme il serait tout à fait ridicule.

Voici une partie de mon code de production, par exemple:

    Config Conf = new Config();
    Log.info("Loading server.conf");
    Conf.doConfig();

Dans le cas ci-dessus, j'ai décidé de ne pas faire n'importe quoi avec le constructeur (elle est vide), mais ont un doConfig() méthode qui fait tout le disque i/o; j'ai souvent pensé que l' doConfig() méthode est juste inutile et je dois tout faire dans le constructeur. (J'ai seulement vérifier le fichier de configuration une fois, après tout.)

Je pense qu'il est entièrement dépendant de votre code et vous ne devriez pas penser que le fait de mettre des "trucs" dans votre constructeur est une mauvaise chose. C'est ce que les constructeurs sont pour! Parfois, nous avons emporté avec de la POO (getThis, setThat, doBark), alors qu'en réalité toute une classe a besoin de faire est de charger un fichier de configuration. Dans de tels cas, il suffit de mettre le tout dans le constructeur et l'appeler un jour!

16voto

pcjuzer Points 1004

J'ai confronté les problèmes suivants lorsque j'ai mis trop de code dans le constructeur:

  • Il était difficile d'écrire des tests unitaires pour les autres méthodes de la classe, parce qu'il a voulu faire un tas de choses dans le constructeur, donc, je a mis en place beaucoup de choses valables ou au moins se moque (DB, fichier, quel que soit) pour le plus simple des tests unitaires.
  • Il était difficile d'écrire des tests unitaires pour le constructeur lui-même. De toute façon, mettre un bon nombre de code, avec des responsabilités dans une le bloc est même une mauvaise idée. (Simple Principe De Responsabilité.)
  • Pour l'ancien raisons, il était difficile pour l'utilisation de cette classe. Par exemple, il a complètement empêché de me mettre en œuvre certaines différés init méthodes, parce qu'il a besoin de tout dans le moment de l'invocation de la constructeur. Ok, je pourrais écrire le paresseux méthode init dans le constructeur, nice.
  • Tôt ou tard, j'ai réalisé que cela avait du sens pour la réutilisation de certaines parties du code qui sont placés dans le constructeur. Eh bien, quand j'ai d'abord écrit la constructeur j'ai aussi pensé que ces parties de code seront utilisés là, pour toujours.
  • Quand j'ai voulu étendre la classe et insérez la logique avant ou dans le super constructeur de la logique, il n'a tout simplement pas de travail parce que le première chose à faire dans la catégorie " constructeur est d'invoquer la super une.

Donc oui, faire beaucoup de constructeur est une mauvaise idée à mon avis.

En général, je viens de mettre un peu de champ d'initialisation dans le constructeur et faire une méthode init de l'invoquer quand tout le monde est à bord.

15voto

Maurício Linhares Points 19468

Il est généralement, si votre objet est compliqué dans la création de l'algorithme que vous pourriez probablement simplifier à l'aide d'un Générateur ou d'une Usine. Spécialement si il y a des pré-conditions pour être validé pour construire l'objet.

Une fois votre démarrer à l'aide des Constructeurs et des Usines pour construire vos objets de valider les pré-et post-conditions et assurez-vous que les clients de votre code ne sera en mesure d'accéder à un entièrement initialisé objet et non pas un demi-faites un, vous pouvez même utiliser le aujourd'hui en vogue couramment interfaces pour créer votre objet et le faire paraître cool ;D

new EmailMessage()
    .from("demo@guilhermechapiewski.com")
    .to("destination@address.com")
    .withSubject("Fluent Mail API")
    .withBody("Demo message")
    .send();

Évidemment, ce n'est pas vraiment votre cas, ce n'est pas à l'aide d'un Générateur, mais il ressemble beaucoup à quelque chose que vous pourriez construire pour faire de votre constructeur de faire moins de travail et de rendre votre code plus simple.

2voto

over_optimistic Points 444

Ayant des constructeurs et destructeurs, à mon avis, est bonne, mais ne pas faire trop de travail en eux. Surtout pas de fichier/base de données d'accès, à moins que son très très spécifique à la classe. Vous voulez garder vos constructeurs/destructeurs de la lumière pour garder votre programme de sentiment de liquide. Parfois, comme tu est déjà venu à un cas où le constructeur ne fait quasiment tout le travail. Il y a un moyen de rendre les choses plus légères. Le concept de paradigme est appelée évaluation différée. L'idée est d'accepter des entrées et de ne rien faire (par exemple dans le constructeur), mais utiliser des entrées lorsque vous avez besoin d'un calcul demandé.

Exemple: disons que vous avez une classe qui lit un fichier, analyse et vous indique info comme la somme de tous les nombres dans le fichier. Vous pouvez faire tout cela dans le constructeur. À l'aide de l'évaluation différée, vous ouvrez simplement le fichier, et ont un getTotalSum() fonction. Lorsqu'il est appelé, il va faire l'analyse et de vous donner le résultat. De cette façon, vous pouvez également avoir getBestFit() pour obtenir le meilleur ajustement de la ligne. Parfois, vous ne voulez pas d'obtenir le meilleur ajustement et pour quelques entrées que vous faites. De cette façon, l'utilisateur ne sera pas en attente pour le constructeur pour effectuer les calculs avant que l'utilisateur décide quoi faire.

un autre exemple: disons que vous avez un point de vue que les charges de 20 images. Mais seulement 5 sont affichés, et le constructeur qui prend un tableau d'images à montrer. Vous pouvez les charger dans le constructeur, mais à partir d'un point de vue utilisateur ce sera lent au début. Ou vous pouvez charger 1 "chargement" de l'image et de la charge 1 image à la fois. Et à mesure que l'utilisateur fait défiler la charge plus d'images sur un comme illustré/besoin.

De cours 1 problème, c'est que vous trouvez des erreurs comme invalide photos plus tard, sur la route au lieu du constructeur. Vous pouvez toujours effectuer des vérifications simples pour vous-même de pré-valider l'entrée à un certain degré (par exemple, vérifier que le mot de passe).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X