Question

Voici un problème qui me pose problème depuis que j'ai commencé à apprendre la programmation orientée objet: comment implémenter un enregistreur dans " own " Code POO?

J'entends par là un objet qui possède une méthode à laquelle tous les autres objets du code doivent pouvoir accéder; cette méthode sortirait en console / fichier / peu importe, que nous utiliserions pour la journalisation - par conséquent, cet objet serait l'objet logger.

Nous ne voulons pas établir l'objet enregistreur en tant que variable globale, car les variables globales sont mauvaises, n'est-ce pas? Mais nous ne voulons pas non plus que l'objet logger soit passé dans les paramètres de chaque méthode que nous appelons dans chaque objet.

À l'université, quand j'ai parlé de cela au professeur, il n'a pas pu me donner de réponse. Je me rends compte qu’il existe effectivement des packages (par exemple, Java) qui pourraient implémenter cette fonctionnalité. Cependant, ce que je recherche en définitive, c’est la connaissance de la manière de mettre en œuvre cette démarche correctement et de façon appropriée.

Était-ce utile?

La solution

Vous voulez établir le consignateur en tant que variable globale, car les variables globales ne sont pas mauvaises. Au moins, ils ne sont pas intrinsèquement mauvais. Un enregistreur est un bon exemple d'utilisation appropriée d'un objet accessible globalement. Consultez le modèle de conception Singleton si vous souhaitez plus d'informations.

Autres conseils

Il existe des solutions très bien pensées. Certains impliquent le contournement de OO et l’utilisation d’un autre mécanisme (AOP).

La journalisation ne se prête pas vraiment bien à OO (ce qui n’est pas grave, tout ne se passe pas bien) Si vous devez l'implémenter vous-même, je vous suggère simplement d'instancier & log; Log " au sommet de chaque classe:

journal final privé = nouveau journal (this);

et tous vos appels de journalisation sont alors triviaux: log.print ("Hey");

Ce qui le rend beaucoup plus facile à utiliser qu'un singleton.

Demandez à votre enregistreur de déterminer la classe que vous transmettez et utilisez-le pour annoter le journal. Puisque vous avez alors une instance de journal, vous pouvez ensuite faire les choses suivantes:

log.addTag ("Bill");

Et log peut ajouter la facture de balises à chaque entrée afin que vous puissiez implémenter un meilleur filtrage pour votre affichage.

log4j et la tronçonneuse sont une solution prête à l'emploi, mais si vous n'êtes pas académique, utilisez-les.

Un enregistreur accessible dans le monde entier est difficile à tester. Si vous avez besoin d’un compte "centralisé" la fonction de journalisation la crée au démarrage du programme et l'injecte dans les classes / méthodes nécessitant une journalisation. Comment testez-vous les méthodes qui utilisent quelque chose comme ceci:

public class MyLogger 
{
    public static void Log(String Message) {}
}

Comment le remplacez-vous par une maquette?

Mieux:

public interface ILog 
{
    void Log(String message);
}

public class MyLog : ILog 
{
    public void Log(String message) {}
}

J'ai toujours utilisé le modèle Singleton pour implémenter un objet de journalisation.

Vous pouvez regarder le motif Singleton.

Créez le consignateur en tant que classe singleton, puis accédez-y à l'aide d'une méthode statique.

Je pense que vous devriez utiliser AOP (programmation orientée aspect) pour cela, plutôt que OOP.

En pratique, une méthode singleton / global fonctionne bien, à mon avis. De préférence, l’objet global est simplement un cadre auquel vous pouvez connecter différents écouteurs (modèle d’observateur), par exemple. un pour la sortie de la console, un pour la sortie de la base de données, un pour la sortie de Windows EventLog, etc.

Attention toutefois à la sur-conception, je trouve qu'en pratique une classe unique utilisant uniquement des méthodes globales peut très bien fonctionner.

Vous pouvez également utiliser l'infrastructure du cadre dans lequel vous travaillez dans les offres.

Le bloc d'application de journalisation de la bibliothèque d'entreprise issu du modèle de Microsoft & amp; Le groupe Pratiques est un excellent exemple de la mise en œuvre d'un cadre de journalisation dans un environnement POO. Ils ont une excellente documentation sur la manière dont ils ont implémenté leur bloc d’application de journalisation et tout le code source est disponible pour votre propre révision ou modification.

Il existe d'autres implémentations similaires: log4net, log4j, log4cxx

La manière dont ils ont implémenté le bloc d’application de journalisation de la bibliothèque de l’entreprise est d’avoir une classe statique Enregistreur avec un certain nombre de méthodes différentes qui effectuent réellement l’opération de journalisation. Si vous examiniez des modèles, cela constituerait probablement l’une des meilleures utilisations du modèle Singleton.

Je suis tout pour AOP avec log4 *. Cela nous a vraiment aidé. Google m'a fourni par exemple cet article . Vous pouvez essayer de chercher plus sur ce sujet.

(IMHO) comment la "journalisation" se produit ne fait pas partie de la conception de votre solution, mais de l’environnement quel que soit votre environnement d’exploitation - comme System et Calendar en Java.

Votre "bonne" solution est celle qui est couplée aussi vaguement que possible à une implémentation de journalisation particulière, pensez donc aux interfaces. Je jetterai un coup d'œil au sentier ici Vous trouverez un exemple de la façon dont Sun l'a abordé, car ils ont probablement conçu un très bon design et tout exposé pour que vous puissiez apprendre!

utilise une classe statique, elle a le moins de temps système et est accessible à partir de tous les types de projets dans une simple référence d'assemblage

notez qu'un singleton est équivalent, mais implique une allocation inutile

Si vous utilisez plusieurs domaines d'application, sachez qu'un objet proxy peut être nécessaire pour accéder à la classe statique à partir de domaines autres que celui principal.

également si vous avez plusieurs threads, vous devrez peut-être verrouiller les fonctions de journalisation pour éviter l’entrelacement de la sortie

La journalisation à mon humble avis est insuffisante, c’est pourquoi j’ai écrit CALM

.

bonne chance!

Peut-être que l'insertion de la journalisation de manière transparente appartiendrait plutôt à l'idiome de programmation orientée aspect. Mais nous parlons de conception OO ici ...

À mon avis, le modèle Singleton est peut-être le plus utile. Vous pouvez accéder au service de journalisation à partir de n'importe quel contexte via une méthode publique publique, statique, d'une classe LoggingService.

Bien que cela puisse ressembler beaucoup à une variable globale, ce n’est pas le cas: elle est correctement encapsulée dans la classe singleton, et tout le monde n’y a pas accès. Cela vous permet de modifier la manière dont la journalisation est gérée même au moment de l'exécution, mais protège le fonctionnement de la journalisation du code "vilain".

Dans le système sur lequel je travaille, nous créons un certain nombre de «singletons» de journalisation, afin de pouvoir distinguer les messages de différents sous-systèmes. Ceux-ci peuvent être activés / désactivés au moment de l'exécution, des filtres peuvent être définis, l'écriture dans un fichier est possible ... nommez-le.

J'ai déjà résolu ce problème en ajoutant une instance d'une classe de journalisation à la (aux) classe (s) de base (ou à l'interface, si le langage le permet) pour les classes devant accéder à la journalisation. Lorsque vous enregistrez quelque chose, le consignateur examine la pile d'appels en cours et détermine le code appelant à partir de celui-ci, en définissant les métadonnées appropriées à propos de l'instruction de journalisation (méthode source, ligne de code si disponible, classe ayant ouvert une session, etc.). nombre de classes ont des enregistreurs, et les enregistreurs n'ont pas besoin d'être spécifiquement configurés avec les métadonnées qui peuvent être déterminées automatiquement.

Cela ajoute des frais généraux considérables. Ce n'est donc pas forcément un choix judicieux pour la journalisation de la production. Toutefois, certains aspects de l'enregistreur peuvent être désactivés de manière conditionnelle si vous le concevez de cette manière.

En réalité, j'utilise la plupart du temps la journalisation commune (je travaille beaucoup en java), mais certains aspects de la conception que j'ai décrits ci-dessus me semblent bénéfiques. Les avantages d'un système de journalisation robuste que quelqu'un d'autre a déjà passé beaucoup de temps à déboguer l'emportent sur la nécessité de concevoir ce qui pourrait être considéré comme une conception plus propre (c'est évidemment subjectif, compte tenu en particulier du manque de détails dans cet article).

J'ai eu des problèmes avec les enregistreurs statiques qui causaient des problèmes de mémoire permgen (du moins, je pense que c'est le problème), je vais donc probablement revoir bientôt les enregistreurs.

Pour éviter les variables globales, je propose de créer un REGISTRY global et d’enregistrer vos globals à cet emplacement.

Pour la journalisation, je préfère fournir une classe singleton ou une classe fournissant des méthodes statiques pour la journalisation.

En fait, j'utiliserais l'un des cadres de journalisation existants.

Une autre solution possible consiste à avoir une classe Log qui encapsule la procédure de journalisation / stockée. De cette façon, vous pouvez simplement instancier un new Log (); chaque fois que vous en avez besoin sans avoir à utiliser un singleton.

Ceci est ma solution préférée, car la seule dépendance à injecter est la base de données si vous vous connectez via base de données. Si vous utilisez potentiellement des fichiers, vous n'avez pas besoin d'injecter de dépendances. Vous pouvez également éviter complètement une classe / fonction de journalisation globale ou statique.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top