89 votes

Est-il préférable de retourner un ImmutableMap ou une carte ?

Disons que je suis en train d'écrire une méthode qui devrait retourner une Carte. Par exemple:

public Map<String, Integer> foo() {
  return new HashMap<String, Integer>();
}

Après y avoir réfléchi pendant un moment, j'ai décidé qu'il n'y a pas de raison de modifier cette Carte une fois qu'il est créé. Donc, je voudrais revenir un ImmutableMap.

public Map<String, Integer> foo() {
  return ImmutableMap.of();
}

Dois-je laisser le type de retour en tant que générique de la Carte, ou devrais-je préciser que je suis de retour d'un ImmutableMap ?

D'un côté, c'est exactement pourquoi les interfaces ont été créés pour; pour cacher les détails d'implémentation.
D'autre part, si je vais le laisser comme cela, d'autres développeurs risquent de manquer le fait que cet objet est immuable. Donc, je ne vais pas atteindre un objectif majeur des objets immuables; pour rendre le code plus clair en réduisant le nombre d'objets qui peuvent changer. Pire encore, après un certain temps, quelqu'un pourrait essayer de modifier cet objet, et il en résultera une erreur à l'exécution (Le compilateur ne pas avertir à ce sujet).

69voto

Dici Points 6603
  • Si vous êtes à la rédaction d'un public en face de l'API et que l'immuabilité est un aspect important de votre conception, je serais certainement le rendre explicite, soit par le fait d'avoir le nom de la méthode indique clairement que le retour de la carte sera immuable ou en retournant le type concret de la carte. Le mentionner dans la javadoc n'est pas suffisant à mon avis.

    Puisque vous êtes apparemment en utilisant la Goyave mise en œuvre, j'ai regardé la doc et c'est une classe abstraite, donc il vous donne un peu de souplesse sur le réel, type de béton.

  • Si vous écrivez un outil interne/bibliothèque, il devient beaucoup plus acceptable de simplement renvoyer une plaine Map. Les gens vont savoir sur le fonctionnement interne de code qu'ils sont de l'appelant ou au moins avoir un accès facile.

Ma conclusion serait que l'explicite est bon, ne pas laisser les choses au hasard.

36voto

Synesso Points 8865

Vous devriez avoir ImmutableMap que votre type de retour. Map contient des méthodes qui ne sont pas pris en charge par la mise en œuvre de l' ImmutableMap (par exemple, put) et sont marqués @deprecated en ImmutableMap.

À l'aide de méthodes obsolètes entraînera un avertissement du compilateur et la plupart des IDEs avertira lorsque les gens tentent d'utiliser les méthodes obsolètes.

Cette alerte avancée est préférable d'avoir des exceptions d'exécution en tant que votre première indication que quelque chose est faux.

16voto

tkausl Points 7822

D'autre part, si je vais le laisser comme cela, d'autres développeurs risquent de manquer le fait que cet objet est immuable.

Vous devez mentionner que dans la javadoc. Les développeurs ne les lisez, vous savez.

Donc, je ne vais pas atteindre un objectif majeur des objets immuables; pour faire le code plus clair en réduisant le nombre d'objets qui peuvent changer. Pire encore, après un certain temps, quelqu'un pourrait essayer de modifier cet objet, et il en résultera une erreur à l'exécution (Le compilateur ne pas avertir à ce sujet).

Pas de développeur publie son code non testé. Et quand il ne le tester, il obtient une Exception levée lorsqu'il ne voit pas seulement la raison, mais également le fichier et la ligne où il a essayé d'écrire à est immuable la carte.

Notez cependant, que l' Map sera lui-même immuable, et non pas les objets qu'il contient.

10voto

René Link Points 9136

si je vais le laisser comme cela, d'autres développeurs risquent de manquer le fait que cet objet est immuable

C'est vrai, mais d'autres les développeurs doivent tester leur code et de s'assurer qu'il est couvert.

Néanmoins, vous avez 2 options pour résoudre ce problème:

  • L'Utilisation De Javadoc

    @return a immutable map
    
  • Choisi une méthode descriptive nom

    public Map<String, Integer> getImmutableMap()
    public Map<String, Integer> getUnmodifiableEntries()
    

    Pour un cas concret d'utilisation vous pouvez même nom les méthodes mieux. E. g.

    public Map<String, Integer> getUnmodifiableCountByWords()
    

Quoi d'autre pouvez-vous faire?!

Vous pouvez revenir à une

  • copie

    private Map<String, Integer> myMap;
    
    public Map<String, Integer> foo() {
      return new HashMap<String, Integer>(myMap);
    }
    

    Cette approche doit être utilisée si vous vous attendez à ce qu'un grand nombre de clients de modifier la carte et aussi longtemps que la carte ne contient que quelques entrées.

  • CopyOnWriteMap

    la copie sur écriture collections sont généralement utilisés lorsque vous avez à traiter avec
    la simultanéité. Mais le concept sera également vous aider dans votre situation, depuis un CopyOnWriteMap crée une copie de la structure de données interne sur un mutative opération (par exemple, ajouter, supprimer).

    Dans ce cas, vous avez besoin d'un mince wrapper autour de votre carte que les délégués de tous les appels de méthode à la carte sous-jacente, à l'exception de la mutative opérations. Si un mutative opération est invoquée, il crée une copie de la carte sous-jacente et toutes les autres invocations seront déléguées à cette copie.

    Cette approche doit être utilisée si vous vous attendez à ce que certains clients peuvent modifier la carte.

    Malheureusement, java ne pas avoir un tel CopyOnWriteMap. Mais vous pourriez le trouver à un tiers ou à mettre en œuvre par vous-même.

Enfin, vous devez garder à l'esprit que les éléments de votre carte peut encore être mutables.

8voto

Benito Ciaro Points 382

Certainement revenir un ImmutableMap, de la justification:

  • La signature de la méthode (y compris le type de retour) doit être auto-documentation. Les commentaires sont comme service à la clientèle: si vos clients ont besoin de s'appuyer sur eux, alors votre principal produit est défectueux.
  • Si quelque chose est une interface ou une classe qui n'est pertinente que lors de l'extension ou de la mettre en œuvre. Étant donné une instance (objet), 99% du temps, le code client de ne pas savoir ou de soins, ou si quelque chose est une interface ou une classe. J'ai supposé au début que ImmutableMap une interface. Seulement après que j'ai cliqué sur le lien que j'ai compris c'est une classe.

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