Comment créer le code le plus propre lors du signalement des progrès à un utilisateur?

StackOverflow https://stackoverflow.com/questions/297119

  •  08-07-2019
  •  | 
  •  

Question

Au cours des deux derniers mois, je me suis efforcé de créer un code propre permettant de rendre compte des progrès réalisés à un utilisateur. Tout semble toujours se résumer à:

ReportProgress("Starting Task 1");
doTask1();
ReportProgress("Task 1 is done");

ReportProgress("Starting Task 2");
doTask2();
ReportProgress("Task 2 is done");

//etc... where report progress does some form of output to the user.

Le bon codeur en moi crie "Il doit y avoir une méthode plus propre!" Mais je suis perplexe. Des pensées?

EDIT :: Je cherche plus d'informations sur les informations architecturales que sur les implémentations spécifiques. Le code donné est très trop simplifié.

Était-ce utile?

La solution

configurez vos tâches en tant que flux d'événements et faites en sorte que le rapport "moteur" de traitement des événements progresse. Chaque instance d’événement peut avoir son propre nom, son rapport de progression / son modèle, etc. si vous voulez aller aussi loin

Si cela se produit souvent, cela vaut la peine pour l’infrastructure. Une fois que vous avez terminé, le code utilisable peut ressembler à quelque chose comme:

EventQueue tasks = new EventQueue();
tasks.Add(new TaskEvent(this.doTask1,"Foo-ing the bar"));
tasks.Add(new TaskEvent(this.doTask2,"Bar-ing the foo"));
tasks.Add(new TaskEvent(this.doTask3,"Glitching and whinging"));
...
tasks.Execute(this.ProgressEventHandler);

Autres conseils

Pourriez-vous peut-être utiliser la Programmation orientée aspect et concevoir un aspect progressif?

Il existe un certain nombre d'implémentations AOP. Dans le monde Java, les deux plus courants sont AspectJ et Spring (qui utilisent des aspects AspectJ ou basés sur le proxy).

Vous pouvez créer une classe de tâches avec une propriété de nom et un délégué. Placez chaque tâche dans une collection, puis parcourez-la, imprimez le message et appelez le délégué pour chaque tâche.

Cela dépend de la quantité de configuration requise à la volée. Je m'attendrais à ce que le code soit très général et que les tâches soient configurées via spring ou n'importe quel conteneur ioc.

Tout cela serait dans une config de printemps: La configuration xml fournirait à l'objet de tâche son nom et ses paramètres. Ajoutez ensuite ces tâches à une collection et remettez-la au Taskrunner.

Le gestionnaire de tâches est alors un code qui signale l’arrêt et le début de chaque tâche, mais chaque tâche est libre de donner un statut spécifique de son déroulement. De plus, le taskrunner interceptera toutes les exceptions et continuera si quelque chose se glissait. Il pourrait être configurable de dire que certaines tâches dépendent de l'achèvement d'autres tâches, et que certaines tâches doivent tout arrêter en cas d'échec.

Je ne suis pas d'accord pour dire que l'AOP devrait être utilisé ici. surpuissance.

Il serait naturel que les rapports soient inclus dans les appels à doTask ().
En général, le journaliste était un singleton auquel tous les objets envoyaient des messages et une classe de journalistes était responsable de décider si et où l'afficher - barre de statut, fichier journal, stderr, etc.

En supposant que le modèle dans ce que vous faites est:

  • démarrage de la tâche de journal
  • faire la tâche
  • fin de la tâche de journal

vous pouvez avoir une "tâche" class (parent pour toutes vos tâches), dont la méthode do () est sous-classée et enregistre automatiquement le début et la fin de la tâche.

Juste une idée.

Je ne coderais pas à la main les parties numériques des messages affichés de cette manière (à chaque fois que vous devez ajouter ou supprimer des actions ou modifier la séquence, vous avez un fouillis de copier-coller à faire). Vous voudriez que n'importe quel objet manipulant la méthode ReportProgress s'incrémente lui-même au fur et à mesure.

Une façon assez simple et propre serait de créer une classe abstraite ayant une méthode do () et des méthodes abstraites doTask () et getName ():

do() {
    ReportProgress("Starting " + this.getName());
    doTask();
    ReportProgress("Finished " + this.getName());
}

Ensuite, dans vos tâches:

class Task1 extends Task {
    getName(){return "Task 1";}
    doTask() {
        //do stuff here
    }
}

Vous pourriez alors avoir une tâche ayant une méthode doTask () qui exécute do () sur de nombreuses autres tâches. Cela peut facilement être récursif, dans la mesure où n'importe quelle tâche peut ensuite exécuter plusieurs sous-tâches.

+1 sur la suggestion d'AOP. C’est un problème classique qui se pose de manière transversale et que l’AOP réglerait avec élégance.

Vous pouvez appeler ReportProgress depuis l’intérieur des méthodes doTask, ce qui pourrait le rendre un peu plus propre, mais vous auriez simplement:

doTask1();
doTask2();

Les rapports seraient traités dans ces méthodes.

Vous pouvez utiliser AOP, mais mon cerveau hurle KISS !! (Keep It Simple Stupid) dans ce cas. S'il ne s'agit que d'une simple représentation de quelque chose de plus compliqué que vous avez affaire, AOP pourrait être une option.

Malheureusement, je pense que la meilleure façon de procéder dépend des détails, du moins de la langue que vous utilisez. Par exemple, en python, vous pouvez utiliser un gestionnaire de contexte pour permettre la rédaction de code. comme ceci:

with progress_report("Task 1"):
    do_task_1()

Cela pourrait, par exemple, garantir que la "Tâche 1 est terminée". est signalé même si do_task_1 () lève une exception. Si vous le souhaitez, vous pouvez gérer les exceptions séparément et imprimer quelque chose de différent, tel que "Échec de la tâche 1". ou "Tâche 1 abandonnée."

Dans notre boîte à outils, nous avons un contrôleur de tâches qui gère les tâches. Une tâche est exécutée en tant que thread. En plus du support de threads typique, une tâche prend en charge les méthodes de progression. Une vue possible sur la progression est une barre de progression visuelle avec un titre qui fait référence au nom de la tâche et à l'étape dans la tâche. Pour prendre en charge les statistiques et le statut visibles, le code doit faire des appels occasionnels à la méthode de progression de la tâche. En règle générale, cette opération est effectuée dans les boucles for, car le pourcentage de progression peut être estimé en divisant l'indice actuel par la limite.

Le contrôleur de tâches est un endroit utile pour ajouter un contrôle de thread global, des sondes d'état, d'autres statistiques et des points d'ancrage de mesure de performance. Certains bogues multithreads et problèmes de minutage peuvent être analysés en examinant l'état du contrôleur et l'état de toutes les tâches.

Si vous utilisez .NET, je vous conseillerais d'utiliser le bloc d'application Policy Injection de de la bibliothèque d'entreprise . (Version minimale: 3.1). J'ai utilisé un outil similaire pour effectuer une opération "Revenir à l'identité du pool d'applications". pour un site Web qui était lourd sur l'usurpation d'identité.

Vous pouvez faire la même chose avec votre tâche. Vous pouvez simplement définir une classe de tâches avec une fabrique qui construit l'objet avec la fabrique d'objets Bibliothèque d'entreprise et ajoute automatiquement un symbole "Avant". et " Après " message à la tâche. Cela donnerait EXACTEMENT ce que vous voulez avec l’élégance requise.

Amusez-vous!

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