web-dev-qa-db-fra.com

Comment décidez-vous si un paramètre devrait aller sur le constructeur de la méthode qu'elle concerne?

J'utilise Python mais je suppose que ma question s'applique à OOP en général. Chaque fois que je crée une classe, je ne suis jamais sûr que je devrais mettre un paramètre/attribut dans le constructeur ou dans la méthode, le paramètre se rapporte.

Par exemple, prenons une classe de personne qui a un days_away méthode. Le rôle de Days_away est de calculer le nombre quelconque jours la personne a été éloignée de timestamps. Le constructeur de personne (c'est-à-dire __init__) obtiendra name comme paramètre. Va-t-il aussi obtenir timestamps comme paramètre ou si timestamps va sous forme de paramètre de la days_away Méthode censée calculer combien de jours la personne absorbée compte-t-elle certaines périodes de date de l'heure? Pourquoi?

Edit: Ajouter un contexte. C'est pour diviser une facture d'électricité entre les personnes partageant un appartement. Le projet de loi sera divisé en fonction du nombre de jours d'une personne éloignée de manière à ne pas avoir à payer pour ces dates. Les jours d'absence seront calculés par la méthode Days_away, compte tenu des horodatages, une personne est restée et retournée à l'appartement.

9
Andy Gondzer

Je regarde l'utilisation du code.

Quelle est la différence entre ça

duration = Person(then).days_away(now)

et ça?

duration = Person().days_away(then, now)

rien. Mais

duration = person.days_away(now)

est différent. Ce code n'a pas à savoir then. Il suffit de savoir now. C'est très puissant. Ce code fonctionne dans des endroits qui ne connaissent que now.

Donc, la seule question est que si vous avez besoin de découpler then de now. Si vous ne le faites pas, meh.

9
candied_orange

Un moyen de comprendre s'il faut utiliser un membre d'instance, par exemple passé comme paramètre dans le constructeur, ou un paramètre de méthode, ou autre consiste à considérer la durée de vie des informations.

Si un Person a timestamps qui vit efficacement aussi longtemps que l'objet de la personne, c'est probablement là que cela appartient.

Pour le regarder, un objet est une liaison d'informations ensemble dans une abstraction. Nous nous attendons plutôt à ce que cette liaison soit appropriée pendant la durée de l'objet. Cette liaison est réalisée via des paramètres de constructeur (idéalement, mais il y a des raisons pour lesquelles cela ne peut parfois pas être fait).

Mais nous ne voulons pas utiliser les champs d'instance pour passer des paramètres à une méthode - qui aurait bon nombre des mêmes problèmes que d'utiliser des variables globales telles que des paramètres (par exemple encombrant et une erreur d'erreur, et non de la sécurité de la sécurité).

Est-il possible d'invoquer le days_away méthodes sur le même person dans différentes situations avec différents timestamps? Si tel est le cas, alors timestamps est un état vécu plus court (au moins il a sans doute une durée de vie différente) que le person lui-même et appartiennent ainsi comme un paramètre de méthode plutôt que par paramètre de constructeur.

En résumé, êtes-vous liant quelque chose en une seule abstraction, ou si vous souhaitez que l'on veut un élément à condition dynamiquement, par ex. Définissez et réinitialisez et utilisée dans certaines situations qui dépassent ce que vous recevriez avec contraignation.

6
Erik Eidt

Il s'agit de dépendances, d'une portée et du processus de pensée. Commençons par ce dernier.

Vous allez probablement sur ce genre de problème vous demandant comment le faire fonctionner. Vous avez déjà une application à l'esprit pour l'objet que vous êtes sur le point de créer et concentrez-vous sur sa tâche. Ce n'est pas le OO Way to Go. Vous sautez dans une solution basée sur le scénario.

Une fois que vous avez reconnu que vous avez besoin d'une classe de personne, vous vous concentrez sur cela et de vous demander ce que c'est qui identifie une personne. Avez-vous besoin de savoir quoi que ce soit avant de pouvoir l'appeler une personne? Quand une personne va-t-elle commencer à avoir un sens dans votre application?

Si c'est un nom, c'est ce que le constructeur obtient. Si c'est pour une demande gouvernementale dans laquelle les personnes sont des chiffres, vous aurez besoin de ce nombre pour faire une personne entière. S'il s'agit d'un service de livraison, vous pouvez trouver que vous êtes plus intéressé par l'adresse après tout et que la personne elle-même est juste un attribut nice-savoir de l'adresse et vous modifiez votre objectif.

Ce qui précède devrait vous empêcher d'injecter des choses dans un constructeur d'objet simplement parce que vous en aurez peut-être besoin plus tard pour une tâche. La tâche du constructeur est de construire votre objet, de ne pas vous préparer à un comportement.

Maintenant votre exemple. DaysAway n'est pas un acte, il ne devrait pas être une méthode. Apparemment, vous devez faire face à l'absence. Si tel est tout, vous pouvez inclure une liste des créneaux horaires à la personne en tant que propriété et ajoutez des machines à sous si elles sont connues que la personne sera éloignée pendant une autre période, mais vous serez peut-être mieux servis avec une propriété d'objet Agenda. Donc, je pense que ce n'est pas un bon exemple.

Si les données ne sont pas liées à l'objet, mais plutôt à la loi, vous devez le transmettre à la méthode comme paramètres. Un objet n'est pas un porte-manteau pour les variables dont vous pourriez avoir besoin à un moment donné pour une tâche dans un contexte dans un contexte, les données d'objet devraient avoir un sens à l'objet lui-même pour la durée de vie de l'objet. Cela couvre à la fois les problèmes de portée et de dépendance.

4
Martin Maat

Les données appartenant à la classe doivent entrer dans le constructeur. Ces données doivent idéalement être encapsulées en la plaçant dans des champs privés. Les méthodes peuvent fonctionner sur ces données, mais parfois, une méthode nécessite des données supplémentaires qui n'appartiennent pas à la classe.

Disons qu'une personne a une date de naissance comme un domaine privé et que vous souhaitez connaître l'âge de la personne à une date donnée. Cette deuxième date devrait être un argument de la méthode qui calcule l'âge.

3
Rik D

Une seule façon de penser à un constructeur est une fonction qui instancie d'une instance d'objet avec tout ce qu'elle nécessite d'être "complète".

Si vous voulez un objet de sac, un sac peut être vide, son constructeur, ou un constructeur pour celui-ci, pourrait être créé qui ne nécessite aucune variables qui lui sont transmises

Bag b = new Bag();

Mais, si l'objet est, peut-être, une connexion de base de données, son constructeur pourrait alors nécessiter des attributs, disons le nom de base de donnéesAppasses et la base de donnéesAname, comme ceux-ci sont "obligatoires" pour que l'objet se connecte à la base de données, pour cette illustration intimée.

DatabaseConnection dc = new DatabaseConnection(user, pwd);
2
mrflash818

J'ai trouvé ce qui suit Heuristic Pour être assez utile dans la plupart des cas.

Prémisse

  • Les endroits où vous instanciate L'objet, et où vous appelez ses méthodes sont séparés, à la fois en Time , et in Scope .

Théorème

  • La meilleure conception émerge lorsque vous définissez le injection de paramètres le plus tôt possible , tôt ​​Signification en ce qui concerne le flux de votre code.

Corollaire

  • Si, dans votre flux de conception, vous apprenez à connaître la valeur de paramètre à la durée de construction de votre objet, vous le définissez comme une entrée au constructeur, sinon , vous devez la définir comme une entrée à la méthode. .

Récit

Si vous prenez le Premise comme un axiome de bonne conception orientée objet, alors le theorem peut aider à guider votre conception, étant donné que Vous avez en fait un à portée de main (et ne pas nommer aveuglément des objets juste pour le bien des noms de classe).

Dans sa version TL; DR, cette réponse se lit comme suit: Si la valeur du paramètre est connue au plus dernier moment de votre conception, mettez-la simplement dans la méthode. Si vous le saviez plus tôt à l'avance, sortez-le, soit dans le constructeur, soit dans une autre méthode.

Exemples

  • Exemple 1

Créez une classe Point, avec une méthode distanceFrom, pour calculer la distance d'un autre point. Cela a-t-il un sens d'avoir la méthode distanceFrom(x, y, xOther, yOther)? Nope, parce que vous saviez X et Y du point sur sa construction, vous auriez donc dû passer cela au constructeur. Donc la méthode appropriée est distanceFrom(x,y) (ou plus probable, distanceFrom(point))

  • Exemple 2 ( votre cas )

Lorsque vous calculez des jours à partir d'une personne, vous devez soustraire deux horodatages. L'un d'entre eux est maintenant . L'autre d'entre eux est parfois dans le passé . L'horodatage passé était connu antérieur afin que la conception optimale consiste à éviter de la mettre dans la méthode. Trouvez un moyen de familiariser votre objet Person avec l'horodatage passé le plus tôt possible, de préférence au moment où il est connu, c'est-à-dire éventuellement, dans le constructeur ou, si vous souhaitez le changer le long de la durée de vie de votre Person objet, Créer une autre méthode le long des lignes de Person.cameBack(timestamp), de sorte que la personne puisse marquer l'horodatage pour l'utiliser plus tard pour le daysAway méthode.

0
Vector Zita