向用户报告进度时如何编写最简洁的代码?

发布于 2024-07-09 05:00:56 字数 430 浏览 6 评论 0原文

在过去的几个月里,我一直在努力想出一些干净的代码来向用户报告进度。 一切似乎总是归结为:

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.

我内心的优秀程序员尖叫着“必须有一种更干净的方法!” 但我很困惑。 有什么想法吗?

编辑:我正在寻找更多有关架构信息的信息,而不是特定于实现的信息。 给出的代码非常过于简单化。

I've struggled for the last couple of months to come up with some clean code to report progress to a user. Everything always seems to boil down to:

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.

The good coder in me screams "There's got to be a cleaner way!" But I'm stumped. Any thoughts?

EDIT :: I'm looking more for information on architectural information as opposed to implementation specific. The code given is very oversimplified.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

染年凉城似染瑾 2024-07-16 05:00:56

将您的任务设置为事件流,并让事件处理“引擎”报告进度。 每个事件实例都可以有自己的名称、进度报告简介/模板等。如果您想走那么远,

如果这是经常发生的模式,那么基础设施上的努力是值得的。 完成后,可用的代码可能类似于:

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);

set up your tasks as an event stream, and have the event-processing 'engine' report progress. Each event instance can have its own name, progress-reporting blurb/template, etc. if you want to go that far

if this is a pattern that occurs often, it is worth the effort for the infrastructure. When you're done, the usable code might look something like:

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);
戏蝶舞 2024-07-16 05:00:56

您是否可以使用面向方面编程,并设计一个进度方面?

有许多 AOP 实现。 在 Java 世界中,最常见的两个是 AspectJ 和 Spring(它使用 AspectJ 或基于 Proxy 的方面)。

Could you perhaps use Aspect Oriented Programming, and devise a Progress Aspect?

There are a number of AOP implementations. In the Java world, the 2 most common are AspectJ and Spring (which uses either AspectJ, or Proxy based aspects).

故事未完 2024-07-16 05:00:56

您可以创建一个具有名称属性和委托的任务类。 将每个任务放入一个集合中,然后迭代它,打印消息并为每个任务调用委托。

You could create a Task class with a name property and delegate. Put each task in a collection, then iterate through it, printing the message and invoking the delegate for each task.

长伴 2024-07-16 05:00:56

这取决于动态需要多少配置,我希望代码非常通用,并且通过 spring 或任何 ioc 容器设置任务。

这一切都在 spring 配置中:
xml 配置将为任务对象提供其名称和参数。
然后将这些任务添加到一个集合中,并将该集合交给任务运行程序。

任务运行程序是发出每个任务停止和开始信号的代码,但每个任务都可以自由地给出其运行情况的具体状态。 此外,任务运行程序将捕获任何异常,并在出现错误时继续运行。 可以将其配置为某些任务取决于其他任务的完成,并且某些任务如果失败则应停止一切。

我不同意这里应该使用AOP。 矫枉过正。

It depends how much config is needed on the fly, I would expect the code to be very general, and have the tasks be setup via spring or any ioc container.

This would all be in a spring config:
The xml config would supply the task object with its name and parameters.
then add these tasks to a collection, and hand that collection to the taskrunner.

The task runner is then code that signals the stop and start of each task, but each task then is free to give specific status of how it is going. Also the taskrunner will catch any exceptions and keep going if something errs out. It could be made configurable to say that certain tasks depend on the completion of others, and some tasks should halt everything if they fail.

I disagree that AOP should be used here. overkill.

一个人的旅程 2024-07-16 05:00:56

在 doTask() 调用中包含报告是很自然的。
通常,报告器是一个单例,所有对象都向其发送消息,并且报告器类负责决定是否以及在何处显示它 - 状态栏、日志文件、stderr 等。

It would be natural to have the reporting inside the doTask() calls.
Typically the reporter would be a singleton that all the objects sent messages to and a reporter class was reponsible for deciding if and where to show it - statusbar, log file, stderr etc.

安静被遗忘 2024-07-16 05:00:56

假设您正在做的事情的模式是:

  • 日志任务开始
  • 执行任务
  • 日志任务结束

您可以有一个“任务”类(所有任务的父级),其 do() 方法是子类化的,并自动记录任务的开始和结束。

只是一个想法。

Assuming the pattern in what you're doing is:

  • log task start
  • do task
  • log task end

you can have a "Task" class (parent for all your tasks), whose do() method is subclassed and automatically logs start and end of task.

Just an idea.

豆芽 2024-07-16 05:00:56

我不会像这样对显示消息的数字部分进行手动编码(任何时候您需要添加或删除操作或更改顺序,您都需要进行大量的剪切和粘贴操作)。 您希望任何处理 ReportProgress 方法的对象都能在运行过程中自动递增。

I wouldn't hand-code the numeric parts of the displayed messages like that (any time you need to add or remove actions or change the sequence you've got a mess of cut-and-paste to do). You'd want whatever object is handling the ReportProgress method to auto-increment itself as it goes along.

眉目亦如画i 2024-07-16 05:00:56

一个相当简单和干净的方法是创建一个具有 do() 方法和抽象 doTask() 和 getName() 方法的抽象类:

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

然后在您的任务中:

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

然后您可以有一个任务有一个 doTask() 方法,可以在一大堆其他任务上运行 do() 。 这很容易是递归的,因为任何任务都可能运行许多子任务。

A fairly simple and clean way would be to create an abstract class that has a do() method and abstract doTask() and getName() methods:

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

Then in your tasks:

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

You could then have a Task that has a doTask() method that runs do() on a whole bunch of other tasks. This could easily be recursive, in that any Task might then run a number of sub-Tasks.

以可爱出名 2024-07-16 05:00:56

对 AOP 建议+1。 这是一个经典的横切问题,AOP 可以优雅地解决。

+1 on the AOP suggestion. This is a classic crosscutting concern that AOP would solve elegantly.

苦笑流年记忆 2024-07-16 05:00:56

您可以从 doTask 方法内部调用 ReportProgress,这可能会使它看起来更干净一些,相反,您只需:

doTask1();
doTask2();

报告将在这些方法内部处理。

你可以使用 AOP,但在这种情况下我的大脑尖叫 KISS!!(Keep It Simple Stupid)。 如果这只是您正在处理的更复杂事物的简单表示,AOP 可能是一个选择。

You could call ReportProgress from inside the doTask methods, that might make it look a little cleaner, instead you would just have:

doTask1();
doTask2();

The reporting would be handled inside those methods.

You could use AOP, but my brain screams KISS!!(Keep It Simple Stupid) in this case. If this is just a simple representation of something more complicated that you are dealing with, AOP could be an option.

无言温柔 2024-07-16 05:00:56

不幸的是,我认为做到这一点的最佳方法确实取决于细节——至少取决于您使用的语言。 例如,在 python 中,您可以使用 上下文管理器 来编写代码例如,

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

这可以确保即使 do_task_1() 引发异常,也会报告“任务 1 已完成”。 如果您愿意,您可以单独处理异常并打印不同的内容,例如“任务 1 失败”或“任务 1 中止”。

Unfortunately I think the best way to do this does depend on the details -- at the very least what language you are using. For example in python you could use a context manager to allow for writing code like this:

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

This could, e.g., ensure that the "Task 1 is done" is reported even if do_task_1() raises an exception. If you wanted to, you could handle exceptions separately and print something different like "Task 1 failed" or "Task 1 aborted."

怎会甘心 2024-07-16 05:00:56

在我们的工具包中,我们有一个管理任务的任务控制器。 任务作为线程运行。 除了典型的线程支持之外,任务还支持进度方法。 一种可能的进度视图是视觉进度条,其标题引用任务名称和任务中的步骤。 为了支持可见的统计数据和状态,代码必须偶尔调用任务的进度方法。 通常,这是在 for 循环内完成的,因为进度百分比可以通过当前索引除以限制来估计。

任务控制器是添加全局线程控制、状态探测器、其他统计信息和性能测量挂钩的有用位置。 一些多线程错误和计时问题可以通过检查控制器的状态和所有任务的状态来分析。

In our tool kit, we have a task controller that manages tasks. A task is run as a thread. In addition to typical thread support, a task supports progress methods. One possible view onto the progress is a visual progress bar with a title that refers to task name and step within task. To support visible statistics and status, the code must make occasional calls to the task's progress method. Typically, this is done within for loops since the percentage progress can be estimated by the current index divided by the limit.

The task controller is a useful place to add global thread control, status probes, other statistics and performance measurement hooks. Some multithreaded bugs and timing issues can be analyzed by examining the controller's state, and the state of all the tasks.

三五鸿雁 2024-07-16 05:00:56

如果您使用 .NET,我建议使用 企业库 中的策略注入应用程序块(最低版本:3.1)。 我使用类似的东西为一个严重模仿的网站执行“恢复到应用程序池身份”。

你也可以对你的任务做同样的事情。 您可以简单地定义一个带有工厂的任务类,该工厂使用企业库对象工厂构建对象,并自动向任务添加“之前”和“之后”消息。 这将完全满足您想要的以及所需的优雅。

玩得开心!

If you are using .NET, I would suggest using the Policy Injection Application Block from Enterprise Library (Minimum Version: 3.1). I used a similar stuff to do a "Revert to the application pool identity" for a website that was heavy on impersonation.

You could do the same with your task. You could simply define a task class with a factory that build the object with the Enterprise Library object factory and automatically add a "Before" and "After" message to the task. That would give EXACTLY what you want with the elegence that is required.

Have fun!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文