Je comprends l'idée de la portée du package et j'ai même parfois pensé que je le voulais. Cependant, chaque fois que je m'installais avec une intention sérieuse d'essayer de l'utiliser, je découvrais qu'il ne répondait pas aux besoins que je pensais qu'il servirait.
Mon principal problème semble toujours être que les choses dont je souhaite limiter la portée ne sont jamais dans le même paquet. Conceptuellement, ils peuvent tous être liés, mais la division logique des données au sein de l'application les a comme packages enfants séparés d'un package plus grand.
Par exemple, je peux avoir un modèle de mission et je veux que seuls d'autres outils de mission, comme mes missionServices, utilisent certaines méthodes. Cependant, je me retrouve avec Missions.models et Missions.services comme mes packages, donc MissionModel et MissionService ne sont pas la même étendue de package. Il ne semble jamais qu'il y ait une situation où les packages contiennent de manière appropriée les choses que je voudrais avoir des autorisations élevées sans également inclure de nombreuses choses que je ne souhaite pas avoir ces autorisations; et je ressens rarement l’avantage de l’étendue d’un package qui justifie de modifier l’architecture de mon projet pour tout placer dans le même package. Souvent, soit des aspects ou une sorte d'inversion de contrôle s'avèrent être la meilleure approche pour tout problème pour lequel j'ai brièvement envisagé la portée du package.
Je suis curieux plutôt que cela soit généralement considéré comme vrai pour tous les développeurs Java, ou n'est qu'un coup d'œil du travail que je fais. La portée du package est-elle beaucoup utilisée dans le monde réel? Y a-t-il de nombreux cas où il est considéré comme une bonne forme à utiliser, ou est-il considéré principalement comme un comportement hérité qui est rarement exploité dans le développement moderne?
Je ne demande rien sur la raison pour laquelle la portée privée du package est par défaut, je demande quand elle doit être utilisée indépendamment des valeurs par défaut. La plupart des discussions sur la raison pour laquelle il s'agit de la valeur par défaut n'interviennent pas vraiment lorsque la portée du package est réellement utile, plaidant simplement pour la raison pour laquelle les deux autres étendues couramment utilisées ne devraient pas être par défaut afin que le package gagne par processus d'élimination. De plus, ma question porte sur l' état actuel du développement. Plus précisément, avons-nous développé au point où d'autres outils et paradigmes rendent la portée du package moins utile qu'elle ne l'était lorsque la décision de la rendre par défaut était logique.
java.util.String
etjava.util.Integer
.Réponses:
Tout au long du
java.util.*
package, il existe des cas où le code est écrit avec une protection au niveau du package. Par exemple, ce morceau dejava.util.String
- un constructeur dans Java 6 :ou cette méthode getChars :
La raison en est que les concepteurs du code (et
java.util.*
peuvent être considérés comme une bibliothèque assez grande) souhaitaient avoir la possibilité d'avoir des performances plus rapides au prix d'une perte de sécurité variée (contrôles de plage sur les tableaux, accès direct à d'autres champs qui impliquent l'implémentation plutôt que l'interface, un accès «non sécurisé» à des parties de la classe qui sont autrement considérées comme immuables via des méthodes publiques).En limitant l'accès à ces méthodes et champs aux seules autres classes du
java.util
package, cela permet un couplage plus étroit entre elles mais évite également d'exposer ces détails d'implémentation au monde.Si vous travaillez sur une application et n'avez pas à vous soucier des autres utilisateurs, la protection au niveau du package n'est pas quelque chose dont vous devez vous soucier. Outre divers aspects de la pureté du design, vous pouvez tout faire
public
et être d'accord avec cela.Cependant, si vous travaillez sur une bibliothèque qui doit être utilisée par d'autres (ou si vous voulez éviter d'enchevêtrer trop vos classes pour une refactorisation ultérieure), vous devez utiliser le niveau de protection le plus strict qui vous soit accordé pour vos besoins. Cela signifie souvent
private
. Parfois, cependant, vous devez exposer un peu des détails de l'implémentation à d'autres classes du même package pour éviter de vous répéter ou pour faciliter l'implémentation réelle au détriment du couplage des deux classes et de leurs implémentations. Ainsi, la protection au niveau du package.la source
Integer.toString()
etString.valueOf(int)
pouvez partager le code sans l'exposer au monde. Lesjava.util
classes doivent travailler de concert pour fournir un ensemble plus large de fonctionnalités plutôt que d'être des classes individuelles qui sont entièrement des îles en elles-mêmes - elles sont ensemble dans un package et partagent la fonctionnalité d'implémentation via la portée au niveau du package.Parfois, j'augmente la visibilité des méthodes privées ou protégées à empaqueter pour permettre à un junit-test d'accéder à certains détails d'implémentation qui ne devraient pas être accessibles de l'extérieur.
comme le test junit a le même package que l'élément sous test, il peut accéder à ces détails d'implémentation
exemple
C'est discutable si c'est un "bon" usage ou non mais c'est pragmatique
la source
protected
à la portée du package? fournitprotected
déjà un accès au package. C'est un peu bizarre, mais je pense qu'ils ne voulaient pas exiger des déclarations de portée composées telles queprotected packagescope void doSomething()
(qui nécessite également un nouveau mot clé).Ce n'est pas du tout utile, surtout par défaut, dans un monde où les gens ont tendance à utiliser les noms en pointillés des packages comme s'ils étaient des sous-packages. Étant donné que Java n'a pas de sous-package, xyinternals n'a donc pas plus accès à xy qu'à ab Les noms de package sont identiques ou différents, une correspondance partielle n'est pas différente de n'avoir rien en commun.
Je suppose que les développeurs originaux ne s'attendaient pas à ce que cette convention soit utilisée, et voulaient garder les choses simples sans ajouter la complexité des packages hiérarchiques de style Ada.
Java 9 répond en quelque sorte à cela, dans la mesure où vous pouvez placer plusieurs packages dans un module et n'en exporter que certains. Mais cela rendra la portée du package encore plus redondante.
Dans un monde idéal, ils changeraient la portée par défaut en «portée du module, s'il existe un module contenant, sinon portée du paquet». Ensuite, vous pouvez l'utiliser pour partager l'implémentation au sein d'un module, permettant le refactoring sans casser les interfaces exportées. Mais peut-être y a-t-il une subtilité pour laquelle cela romprait la compatibilité descendante, ou serait autrement mauvais.
la source
Le type de cohésion que vous décrivez n'est pas vraiment le meilleur exemple de l'endroit où vous utiliseriez l'accès au package. Le package est pratique pour créer des composants, des modules interchangeables sur une interface.
Voici un exemple approximatif d'un scénario. Supposons que votre code ait été réorganisé pour être davantage axé sur la cohésion fonctionnelle et la composante. Peut-être 3 pots comme:
En utilisant le niveau de package dans Mission5000.java, vous pouvez vous assurer qu'aucun autre package ou composant tel que MissionManager ne peut coupler étroitement l'implémentation de la mission. Ce n'est que le composant "tiers" fourni par "M co" qui crée réellement sa propre mise en œuvre de marque spéciale d'une mission. Le gestionnaire de mission doit appeler le MissionBuiler.createMission (...) et utiliser l'interface définie.
De cette façon, si le composant d'implémentation de Mission est remplacé, nous savons que les implémenteurs de MissionManager.jar n'ont pas contourné l'API et utilisent directement l'implémentation de MCo.
Par conséquent, nous pouvons échanger MCo-missionizer5000.jar avec un produit concurrent. (Ou peut-être une maquette pour tester l'unité du gestionnaire de mission)
À l'inverse, MCo peut faire un peu de dissimulation de ses secrets commerciaux de missionnaires propriétaires.
(Ceci est également lié à l'application des idées d' instabilité et d'abstrait dans les composants.)
la source
Étant donné que la portée du package en java n'est pas conçue de manière hiérarchique, elle n'est guère utile. Nous n'utilisons pas du tout la portée du package et définissons toutes les classes comme publiques.
Au lieu de cela, nous utilisons nos propres règles d'accès basées sur la hiérarchie des packages et les noms de packages prédéfinis.
Si vous êtes intéressé par les détails google pour "CODERU-Rules".
la source