10
votes

Y a-t-il déjà une justification pour le "pseudo-typledef antidiattern"?

J'ai un type générique relativement compliqué (Dites Carte > Code>) que j'utilise en interne dans une classe. (Il n'y a pas de visibilité externe; c'est juste un détail de mise en œuvre.) J'aimerais cacher cela dans un typdef, mais Java n'a pas de telles installations.

hier, j'ai redécouvert l'idiome suivant et j'ai été déçu d'apprendre que c'est considéré comme un anti-motif . P>

class MyClass
{
  /* "Pseudo typedef" */
  private static class FooBarMap extends HashMap<Long,Map<Integer,String>> { };

  FooBarMap[] maps;

  public FooBarMap getMapForType(int type)
  {
    // Actual code might be more complicated than this
    return maps[type];
  }

  public String getDescription(int type, long fooId, int barId)
  {
    FooBarMap map = getMapForType(type);
    return map.get(fooId).get(barId);
  }

  /* rest of code */

}


4 commentaires

Vous appelez ce type générique compliqué? Ha! Quand j'étais un garçon, nous devions nous lever à 3 heures du matin avec des génériques de six niveaux recouverts de ...


Aye ... sans chaussures ... montée ... dans la neige ..


@Marcus Downing: Et le septième niveau que vous mangez au petit-déjeuner au restaurant à la fin de la récursivité. ;-)


Nouvelle archive Lien vers l'article IBM ci-dessus: THÉORIE ET ​​PRATIQUE JAVA: Pseudo-Typedef AntiPattern


6 Réponses :


5
votes

Le problème réel est que cet idiome crée un couplage élevé entre votre pseudo typledef et votre code client. Cependant, depuis que vous utilisez foobarmap en privé, il n'y a pas de véritables problèmes d'accouplement (ce sont des détails de la mise en œuvre).

nb

Un IDE Java moderne devrait définitivement contribuer à traiter avec des types génériques compliqués.


3 commentaires

Si vous n'utilisez pas cet idiome, vous créez un couplage élevé entre la description de type long et complexe ( HASHMAP > ) et code client. Pourriez-vous expliquer pourquoi le couplage de l'anticipation est pire que cela?


@bacar Le problème est de savoir si quelqu'un peut utiliser un hashmap > ou votre foomap . Pour utiliser une API qui prend un foomap , vous ne pouvez pas passer un hashmap. C'est-à-dire qu'ils ne sont que polymorphes dans une direction si déclare sur une méthode d'interface.


L'ancien argument lit comme il devrait être préféré d'utiliser octet [] au lieu de chaîne dans de nombreuses API, mais chaîne est choisi pour une raison, par exemple Pas besoin de penser à l'encodage du personnage et de trucs partout toujours. On ne serait jamais autorisé à des cartes spécialisées dans des interfaces, même si ces spécialisations comptent beaucoup aussi, pensez simplement à des ensembles triés par rapport à ceux sans ordre. Création de certains foomap est parfaitement amende pour mieux décrire la structure et l'utilisation de types, assurez-vous que les gens utilisent réellement le même type si attendu, avoir un endroit pour documenter ce type, etc.



3
votes

Pour les interfaces publiques, je n'aime pas voir des types génériques, car ils n'ont aucune signification. Pour moi voir une méthode avec un argument de hashmap > est un peu comme ces méthodes C comme FOO (int, int, int, vide *, int) et ainsi de suite. Avoir un vrai type rend simplement le code beaucoup plus facile à lire. Pour une interface publique, il serait préférable de créer FOOBARMAP qui enveloppe HASHMAP > plutôt que 'TYPEDEF, mais pour une utilisation interne de classe, je ne vois pas de côté du tout.


1 commentaires

Le problème avec cette approche est que le code client perd l'utilité de la structure de données de carte.



0
votes

Sans ce pseudo-typledef, je préférerais écrire

interface FooBarMap extends Map<Long,Map<Integer,String>> { };
class FooBarHashMap extends HashMap<Long,Map<Integer,String>> implements FooBarMap{ };


2 commentaires

Pas vrai parce que le type dans l'exemple est privé, la route «Typedef» enregistre un peu de frappe car il vous suffit de remplacer la carte -> HASHMAP au même endroit du code.


Si je déclare un champ avec la carte de type, le compilateur ne me permettra pas d'appeler des méthodes qui ne sont pas déclarées dans l'interface. Et si je substitue la classe d'implémentation avec une autre carte d'implémentation de classe, tout le code continuera à fonctionner. Si je le déclare comme un hashmap, je peux appeler des méthodes hashmap. Et le type de substitution dans "Typedef" va casser le code. Si je veux un jour de charger ma carte de DB en utilisant Hibernate, je peux le faire. Si j'ai HASHMAP, je dois créer de nouvelles et copier le contenu de la carte donnée par Hibernate. En général, utiliser des interfaces partout où il est possible est fortement encourage. Cet idiome décourage-le.



0
votes

Il a un bon point à ce sujet quand il s'agit de la mettre dans une interface publique. Cet idiome imite une forme de sucre syntaxique, elle ne devrait pas affecter ce que vous montrez à vos clients.

Mais je ne vois pas de bonne raison de ne pas l'utiliser localement, à condition que cela vous rend la vie plus facile et que vous êtes plus lisible - et vous avez connu ce que vous faites. Brian peut généraliser et conseiller fortement contre elle dans n'importe quelle situation, mais c'est sa sensation de Goetz: p


0 commentaires

0
votes

Si vous n'utilisez que dans une petite unité de code localisée, les problèmes sont petits, vrais.

chose est, de même que les gains: votre programme ne sera probablement même pas textuellement que vous ne référez pas à la pseudo-typledef 5+ fois, ce qui signifie que la zone est visible pour être non triviale.

Je ne voudrais probablement pas réécrire le code qui l'a fait, mais cela semble une mauvaise habitude d'entrer dans.


0 commentaires

13
votes

imo, le problème avec les anti-motifs Java est qu'ils encouragent la pensée en noir et blanc.

En réalité, la plupart des anti-motifs sont nuancés. Par exemple, l'article lié explique comment Pseudo-TypeDefs conduit à des API dont les signatures de type sont trop restrictives, trop liées à des décisions de mise en œuvre particulières, virales, etc. Mais tout cela est dans le contexte des API publiques. Si vous conservez des pseudo-typlefs à partir d'API publiques (c'est-à-dire les restreindre à une classe, ou peut-être un module), ils ne font probablement aucun préjudice réel et ils peuvent rendre votre code plus lisible.

Mon point est que vous devez comprendre les anti-motifs et faire votre propre jugement raisonné à propos de quand et où pour les éviter. Il suffit de prendre la position que "je vais jamais faire x parce qu'il est un anti-motif" signifie que parfois vous excluez pragmatiquement acceptable, voire de bonnes solutions.


0 commentaires