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.
+1 on the AOP suggestion. This is a classic crosscutting concern that AOP would solve elegantly.
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!
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:
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."
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).
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.
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: