9
votes

Est-ce dans un anti-motif d'utiliser toujours des méthodes d'obtention et de définition pour accéder aux champs membres de la classe?

Dans les classes Java est considérée comme une bonne ou une mauvaise pratique pour accéder aux champs des membres avec leurs getters et leurs setters?

EG, ce qui est meilleur: p>

public Order {
    private Agreement agreement;

    public Agreement getAgreement() {
    return agreement;
    } 

    public void process() {
       //should I use:
       getAgreement().doSomething();
       //Or:
       agreement.doSomething();
    }
}


3 commentaires

De même, quelqu'un pourrait remplacer GetAgreement () et vous accéder au champ le brise directement.


Pourquoi GetAgreement est-il public? Il est difficile de répondre à la question sans savoir que. Si vous définissez toujours des getters publics pour tous les champs, vous aurez des problèmes beaucoup plus gros que de décider comment écrire cet appel de méthode.


Dupliqué possible de Utilisation de getters dans les méthodes de classe , Stackoverflow.com/questions/586087/...


11 Réponses :


7
votes

Je pense que l'interface publique d'une classe représente l'encapsulation autour de l'état et, même si, même les autres fonctionnements de la classe bénéficient de cette encapsulation.

Si vous avez enveloppé un champ dans une méthode de public, il y a une raison pour laquelle vous l'avez fait. Il y a peut-être une logique dans cette méthode pour charger le champ paresseux, ou fournir une piste d'audit. Quelle que soit la raison de la méthode, votre classe aura probablement besoin de cette logique.


4 commentaires

J'ai vu des problèmes spécifiques avec cela lors de l'utilisation de Hibernate pour ormes. Le code utilisant les variables utilisait directement utilisait toujours des valeurs nulelles, le code utilisé les getters a toujours fonctionné. Hibernate fournissait une classe de proxy pour supporter le chargement paresseux.


John, ce problème ne se poserait-il pas que si vous avez les annotations hibernées sur le getter / Setter? J'ai mis les annotations sur le terrain de la classe et les documents Hibernate disent que cela lui permet de manipuler directement le terrain. Cela vous permet également de fournir aux getters sans setters car Hibernate ne les utilise pas.


@LumpyNose: Je crois que les hibernes L'utilisation d'un accès sur le terrain ou sur la propriété est orthogonale pour déterminer s'il génère des cours de proxy pour le chargement paresseux. Hibernate peut toujours utiliser l'accès au niveau du champ et nécessiter des proxies pour mettre en œuvre la fonctionnalité de charge paresseuse, déclenchant les NPES que vous obtenez si le chargement paresseux n'est pas correctement exécuté sur l'accès au champ.


@Lumpynose J'oublie comment c'était la configuration, les annotations peuvent avoir été sur les getters. Il utilisait également JPA plutôt que hibernate directement, afin que cela ait peut-être changé de choses. Mes points sont cependant, sauf si vous déclarez votre classe en finale, vous devez penser à ce qui se passera si quelqu'un remplace l'une de vos méthodes publiques.



-1
votes

Pour que ce soit un anti-motif, il devra être décidément nocif. Je ne vois pas comment il peut être quelque mal à définir des getters et des setters. Au plus, c'est une perte de temps (et de taper), ce qui le rend inutile, mais pas un anticipateur.


0 commentaires

2
votes

Garder une couche d'abstraction est une bonne chose en Java.

Le problème est que tout le code qui accède directement à vos variables de membre sans la classement ne le remarque pas sous le contrôle de votre classe.

Donc, le moment où vous décidez de modifier votre classe d'une manière qu'un membre utilisé dans une division, comme exemple, ne doit jamais être 0, vous devez être en mesure de vous assurer que cette valeur n'est modifiée que de manière à ce que cette valeur ne soit modifiée. . Vous allez donc ajouter un setter pour cette méthode et modifieriez le membre en privé. Mais maintenant, vous devez modifier tout le code qui accède au membre sans le réglage.
Si vous savez que vous modifiez la valeur de l'extérieur de la classe et que vous fournissez uniquement un setter si vous ne connaissez pas la variable privée et si vous avez besoin d'un accès ultérieurement, fournissez peut-être un getter ou un setter.

Il obtient un anti-motif s'il existe certaines méthodes d'autres objets qui utilisent toujours obtenir un membre pour un membre, puis effectue des calculs, puis utilise le get. Cela montre que soit le membre devrait être dans l'autre classe ou que la méthode doit être dans cette classe.

Avoir un getter et un setter sans y penser pour chaque membre qui brise l'encapsulation et n'est pas un bon choix de conception. Pour Mor Insides, lisez ce Article


0 commentaires

9
votes

Honnêtement, à mon avis, cela dépend de ce que vous utilisez. Personnellement, en cas de doute, je laisse toujours ce niveau supplémentaire d'abstraction là-bas au cas où je devrais le remplacer plus tard dans une sous-classe. À plusieurs reprises, j'ai été sauvé de la douleur de la réécriture d'une classe juste parce que j'ai laissé un getter ou un setter ouvert pour remplacer.

Une autre chose est que d'autres clients / programmeurs devraient avoir besoin d'utiliser votre classe d'une manière que vous n'avez pas encore pensé, par exemple, en tirant par exemple la classe d'accord d'une base de données. Dans ce cas, lorsqu'ils remplacent votre classe, vous l'avez rendu indolore (ou potentiellement un avenir vous) pour modifier la manière dont ces données sont récupérées.

Donc, à moins que vous soyez absolument certain qu'il n'y a qu'un seul moyen d'accéder à ce domaine et qu'il est 100% direct, il est probablement préférable de découpler la récupération et la modification des valeurs afin que, à un moment quelconque, vous pouvez vous épargner de réécrire les difficultés.


0 commentaires

0
votes

Cela dépend de ce que vous utilisez vos getters et vos setters. En règle générale, je les utilise lorsque j'ai besoin de vérifier la santé de la santé des données entrant dans une classe ou formater des données sortez. À cet égard, j'utilise vraiment des getters et des setters comme une couche d'interface entre cette classe et d'autres classes qui pourraient avoir besoin d'un accès à ses données.

J'ai tendance à écrire mon code interne de telle sorte qu'il sait gérer les données privées à cette classe, ce qui l'accède à ses propres getters et setters est généralement inutile et indésirable.

Tout dépend de la manière dont vous utilisez vos getters and Setters, cependant.


0 commentaires

0
votes

Ma règle de base est que si elles font quelque chose de plus complexe que de simplement définir ou renvoyer la valeur, utilisez les Setteurs / Getters. Sinon, ce n'est pas nécessaire car vous pouvez résoudre tout problème causé par les modifications apportées aux variables des membres.


1 commentaires

Mais la raison de manière constante à l'aide de la getter and Setter est que, tandis que lorsque le getter / setter peut ne rien faire d'autre que d'obtenir et de définir la valeur aujourd'hui , cela peut ne pas être vrai demain.



1
votes

Je travaille maintenant sur quelque chose qui me rend en faveur des getters: Nous déplaçons maintenant une partie de nos propriétés dans un "sac de propriété", ce qui signifie que vous ne pouvez pas simplement faire référence à la variable. Ainsi, en plus de changer le getter, nous devons changer tous les endroits qui font référence à cette variable. C'est quelque chose à garder à l'esprit.


2 commentaires

Maintenant, j'appellerais un sac de propriété un anti-motif. Il apporte à l'esprit une carte des paires de valeur de nom lorsque les valeurs sont non typées. C'est une alternative paresseuse à réellement avoir une conception de classe et peut vous mordre dans le cul.


En général, oui, il est préférable de stocker les données dans des variables. La raison pour laquelle nous sommes convoqués est que nous transférons notre application pour utiliser le magasin BlackBerry Persistant. Lorsque vous utilisez le magasin persistant, chaque modification de la structure d'objet (l'ajout d'une autre variable Int) corrompre les données persistées. Il existe d'autres solutions, mais nous avons trouvé un sac de propriété pour être le meilleur ajustement pour nous. En tout état de cause, il s'agit simplement d'un exemple de situation lorsque des changements d'accès variable.



8
votes

Le problème de base ici est que l'accès direct sur le terrain n'est pas éligible à l'interception par des méthodes de sous-classement remplacées, AOP, des proxies dynamiques et similaires. Cela peut être une bonne ou mauvaise chose en fonction du cas. Je dirais que l'utilisation de getters et de setters interne n'est pas un anti-motif ni un motif. C'est une bonne ou mauvaise chose en fonction de la situation et de la conception de votre classe.


0 commentaires

0
votes

Vous avez raison en ce que c'est gênant de faire tout ce travail supplémentaire pour chaque variable d'attribut. Pourquoi la langue autorise-t-elle quelque chose de si basique que personne ne le fait? Il existe toutefois des raisons très impérieuses de ne pas autoriser l'accès à l'attribut direct.

Je préfère le principe d'accès unifié d'Eiffel. Vous ne pouvez jamais attribuer à un attribut, et les attributs et les fonctions sont accessibles de la même manière: xxx


0 commentaires

4
votes

Cela me semble que certaines personnes interprètent cette question comme étant sur les getters et les setters utilisés à l'extérieur; Mon interprétation de la question de Pablojim était qu'il s'agit de les utiliser au sein de la classe, par opposition à la classe accédant directement à ses champs. (Qui sont privés.)

Dans cette lumière, je suis avec Jhérico et Patros; Utilisez un accès direct de l'intérieur de la classe à moins qu'il n'y ait de raisons de ne pas.


2 commentaires

Le problème est que la "raison de ne pas" appartenir à un autre développeur à l'aide de votre bibliothèque, à un moment donné et de loin. Ils remplacent l'accessor et la classe ne fonctionne pas correctement. Contourner un accessor non final est un bug.


Vrai. Je suppose que je ne m'inquiète pas tellement parce que j'ajoute automatiquement une finale à ma déclaration de classe. Je suis de la religion que si une classe n'a pas le modificateur final sur lequel elle devrait être une classe abstraite; Il a été conçu dès le début à sous-classement. Bien sûr, il y a ce problème de proxy, et de vouloir une classe non finale et je suis peut-être le constructeur de no-arg ajouta en désordre.



0
votes

Je pense que c'est quelque chose qui doit être pris en compte au cas par cas. L'utilisation d'un getter tout au long de votre code de classe la complique et le rend probablement légèrement plus lent. Cependant, il le rend aussi plus extensible et réutilisable.

Ce que j'ai habituellement fait est d'utiliser le getter si je peux renseigner une raison quelconque quelqu'un voudra peut-être remplacer mon getter avec un autre. Si c'est quelque chose de tellement basique et simple qu'il n'aurait jamais de sens, je n'utilise généralement pas getters.

Si vous écrivez votre code pour accéder aux variables sans getter, envisagez de faire la fonction getter "finale". De cette façon, personne ne tentera de remplacer votre code et de déchirer ses cheveux se demandant pourquoi cela ne fonctionne pas. (Notez que les proxy de printemps et d'hibernation pourraient en faire une mauvaise idée.)


0 commentaires