2010-07-28 3 views
2

J'ai une méthode héritée relativement importante que je voudrais refactoriser. Il correspond au type de "méthode à puces" tel que spécifié dans "Working Effectively With Legacy Code" de Michael Feathers et pourrait donc être divisé en plusieurs méthodes séquentielles de manière plutôt directe. Mais chacune de ses étapes séquentielles génère un message de journal et la formation de ce message nécessite beaucoup plus de données que pour l'étape elle-même. Donc quand j'essaie d'extraire la méthode, je me retrouve avec une méthode ayant, disons, 6 paramètres. Si j'avais supprimé ces instructions de log, j'aurais une méthode avec seulement 1 paramètre. Donc je ne peux vraiment pas refactoriser quoi que ce soit. Et je ne suis pas autorisé à laisser tomber les déclarations de journaux.Les instructions de journal empêchent le refactoring: comment y remédier?

Une partie de la méthode ressemble à ce que:

// much of code before 
Device device = getDevice(deviceID); 
boolean isFirstRegistration = false; 

if (device == null) { 
    /*logger.trace(
      "DeviceId", deviceID, 
      "ADM", adminCode, 
      "Phone", clientData.getPhone() 
    ); 
    logger.info("First registration of the device. Device ID - " + deviceID);*/ 
    isFirstRegistration = true; 
} else { 
    /*logger.trace(
      "DeviceId", deviceID, 
      "ADM", adminCode, 
      "Phone", clientData.getPhone() 
    ); 
    logger.info("Device ID - " + deviceID 
      + " has been previously registered by adminCode: " 
      + device.getAdminCode());*/ 
} 
// much of code after 

Comme vous le voyez, a commenté des déclarations de l'exploitation forestière. Dans ce cas, je peux extraire la méthode boolean isFirstRegistration(String deviceId). Mais quand ils ne sont pas commentés, la signature gonfle jusqu'à boolean isFirstRegistration(String deviceId, String adminCode, ClientData clientData). Et ce n'est pas le cas le plus extrême, juste un du premier coup d'oeil. Avez-vous des idées comment devrais-je refactoriser une telle méthode?

+1

Pouvons-nous le voir? Vous pouvez faire en sorte que la méthode log helper prenne les données supplémentaires et renvoie une seule chaîne/objet que vous transmettez ensuite à votre méthode pour la consignation. Ou mettez tous les éléments nécessaires à la connexion dans un seul tableau ou un hachage et transmettez-le. – CaffGeek

+0

Qu'essayez-vous d'accomplir grâce à votre refactoring? –

+0

Je vais essayer d'écrire un extrait similaire à la partie de cette méthode. – Rorick

Répondre

6

Classe de germination. Activez la connexion à une classe d'assistance et alimentez-y toutes les données dont elle a besoin, selon ses besoins.

Mise à jour: En utilisant les variables d'exemple présentées, j'appellerais, par exemple, myLogger.setDevice(device) dès que le périphérique a été rempli; de même pour adminCode, clientData, etc. Donnez les méthodes de journalisation de journal comme traceDeviceAdminCodeAndPhone() et logFirstRegistration(), où il utilise ses propres variables d'instance. Partout où les variables changent, renvoyez-les à l'enregistreur. Maintenant, passez l'enregistreur aux méthodes que vous extrayez, plus tous les paramètres qui sont directement requis par la nouvelle méthode (mais pas plus), et votre enregistreur peut toujours signaler ce dont il a besoin à partir de la méthode extraite. De plus, au cas où cela commence à donner l'impression que votre enregistreur est trop intime avec votre méthode, une alternative serait d'extraire la méthode dans une nouvelle classe et de convertir certaines variables locales en variables d'instance; alors l'enregistreur pourrait simplement demander à la nouvelle classe pour les valeurs au lieu de les retenir elle-même. Mais la classe logger comme aide est probablement un refactoring plus petit et moins percutant. Que ce soit bon ou mauvais dépend de l'endroit où vous voulez aller avec.

+0

C'est la bonne réponse, mais elle pourrait utiliser plus de détails. –

+1

@Peter, mis à jour en conséquence. Est-ce mieux? –

+0

Oui en effet. Merci de bien vouloir. –

3

La réponse de Carl est certainement valide, mais je pense qu'il existe au moins une autre bonne option.

Certains cadres de journalisation prennent en charge ce que l'on appelle un Mapped Diagnostic Context. Vous pouvez y stocker des paires clé-valeur, puis le framework peut les ajouter aux lignes de journal dans le format que vous spécifiez dans ses fichiers de configuration. Comme vous semblez enregistrer habituellement les mêmes données (au moins en trace), je pense que cela correspondrait plutôt bien à vos besoins. Log4J, SLF4J, mais je pense que quelque chose de similaire devrait exister dans le monde "non-Java".

Je pense que vous pouvez l'utiliser au moins pour/au lieu des messages trace et gagneriez beaucoup:

  • moins, un code plus propre
  • pas besoin de passer params qui sont seulement nécessaires pour l'exploitation forestière
  • messages uniformément enregistrés (formatés par le cadre selon le modèle que vous lui donnez)
  • plus de flexibilité - quoi/quand/comment est enregistré est contrôlé dans la configuration de la connexion (où il appartient).

Une chose à noter: les paires clé/valeur sont généralement stockés dans variables locales thread qui conduit à certains écueils possibles:

  • trop bien/ne fonctionne pas ne sera pas facile à utilisez si vous changez fréquemment de threads
  • généralement le nettoyage (suppression des valeurs indésirables) est votre tâche, ce qui n'est pas fait automatiquement par le framework.
Questions connexes