coding style - paises - ¿Cómo hacer que el código más limpio al informar el progreso a un usuario?
codigos de area mexico (13)
He luchado durante los últimos meses para encontrar un código limpio para informar el progreso a un usuario. Todo parece que se reduce a:
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.
El buen codificador en mí grita "¡Tiene que haber una manera más limpia!" Pero estoy perplejo. ¿Alguna idea?
EDIT :: Estoy buscando más información sobre información arquitectónica que sobre implementación específica. El código dado está muy simplificado.
¿Podría quizás usar la Programación Orientada a Aspectos e idear un Aspecto de Progreso?
Hay una serie de implementaciones de AOP. En el mundo de Java, los 2 más comunes son AspectJ y Spring (que utiliza AspectJ o Aspectos basados en Proxy).
+1 en la sugerencia de AOP. Esta es una clásica preocupación transversal que AOP resolvería elegantemente.
Depende de cuánta configuración se necesite sobre la marcha, espero que el código sea muy general y que las tareas se configuren en primavera o en cualquier contenedor de ioc.
Todo esto estaría en una configuración de primavera: la configuración xml proporcionaría al objeto tarea su nombre y parámetros. luego agregue estas tareas a una colección, y dele esa colección al taskrunner.
El corredor de tareas es entonces un código que señala la parada y el inicio de cada tarea, pero cada tarea es libre de dar un estado específico de cómo va. Además, el correcaminos detectará cualquier excepción y continuará si algo falla. Podría configurarse para decir que ciertas tareas dependen de la finalización de otras, y algunas tareas deberían detener todo si fallan.
No estoy de acuerdo en que el AOP deba usarse aquí. excesivo
En nuestro kit de herramientas, tenemos un controlador de tareas que administra las tareas. Una tarea se ejecuta como un hilo. Además del soporte de subprocesos típico, una tarea admite métodos de progreso. Una posible vista sobre el progreso es una barra de progreso visual con un título que se refiere al nombre de la tarea y al paso dentro de la tarea. Para admitir estadísticas visibles y el estado, el código debe hacer llamadas ocasionales al método de progreso de la tarea. Por lo general, esto se realiza dentro de los bucles for ya que el progreso porcentual se puede estimar mediante el índice actual dividido por el límite.
El controlador de tareas es un lugar útil para agregar control global de hilos, sondeos de estado, otras estadísticas y ganchos de medición de rendimiento. Algunos errores de subprocesos múltiples y problemas de temporización se pueden analizar examinando el estado del controlador y el estado de todas las tareas.
Lamentablemente, creo que la mejor manera de hacerlo depende de los detalles, al menos, del idioma que está utilizando. Por ejemplo, en Python puede usar un administrador de contexto para permitir escribir código como este:
with progress_report("Task 1"):
do_task_1()
Esto podría, por ejemplo, asegurar que la "Tarea 1 está lista" se informa incluso si do_task_1 () genera una excepción. Si quisiera, podría manejar las excepciones por separado e imprimir algo diferente como "Falló la Tarea 1" o "Tarea 1 abortó".
No codificaría manualmente las partes numéricas de los mensajes mostrados de esa manera (cada vez que necesites agregar o quitar acciones o cambiar la secuencia que tienes que hacer para cortar y pegar). Querrá que cualquier objeto que maneje el método ReportProgress se autoincremente a medida que avanza.
Podría llamar a ReportProgress desde dentro de los métodos doTask, que podría hacer que se vea un poco más limpio, en su lugar solo tendría:
doTask1();
doTask2();
Los informes se manejarían dentro de esos métodos.
Podrías usar AOP, pero mi cerebro grita KISS !! (Keep It Simple Stupid) en este caso. Si esto es solo una representación simple de algo más complicado con el que está tratando, el AOP podría ser una opción.
Puede crear una clase Task con una propiedad de nombre y delegar. Coloque cada tarea en una colección, luego repítala, imprima el mensaje e invoca al delegado para cada tarea.
Sería natural tener los informes dentro de las llamadas doTask ().
Típicamente el reportero sería un singleton al que todos los objetos enviaron mensajes y una clase de reportero fue responsable de decidir si y dónde mostrarlo - barra de estado, archivo de registro, stderr, etc.
Si está usando .NET, sugeriría usar el Bloque de aplicación de inyección de políticas de Enterprise Library (Versión mínima: 3.1). Usé un elemento similar para hacer un "Revertir a la identidad del grupo de aplicaciones" para un sitio web que era pesado en la suplantación.
Podrías hacer lo mismo con tu tarea. Simplemente podría definir una clase de tarea con una fábrica que construya el objeto con la fábrica de objetos de la Biblioteca Empresarial y agregue automáticamente un mensaje "Antes" y "Después" a la tarea. Eso le daría EXACTAMENTE lo que quiere con la elección que se requiere.
¡Que te diviertas!
Suponiendo que el patrón en lo que estás haciendo es:
- inicie la tarea de registro
- hacer la tarea
- log tarea final
puede tener una clase "Tarea" (principal para todas sus tareas), cuyo método do () tiene una subclase y registra automáticamente el inicio y el final de la tarea.
Solo una idea.
Una forma bastante simple y limpia sería crear una clase abstracta que tenga un método do()
y los métodos abstractos doTask () y getName ():
do() {
ReportProgress("Starting " + this.getName());
doTask();
ReportProgress("Finished " + this.getName());
}
Luego en tus tareas:
class Task1 extends Task {
getName(){return "Task 1";}
doTask() {
//do stuff here
}
}
Luego podría tener una Tarea que tenga un método doTask () que ejecute do()
en muchas otras tareas. Esto podría ser fácilmente recursivo, ya que cualquier tarea podría ejecutar una cantidad de subtareas.
configure sus tareas como una secuencia de eventos y haga que avance el informe del "motor" de procesamiento de eventos. Cada instancia de evento puede tener su propio nombre, propaganda / plantilla de informes de progreso, etc., si quiere ir tan lejos
si este es un patrón que ocurre a menudo, vale la pena el esfuerzo para la infraestructura. Cuando haya terminado, el código utilizable podría ser algo así como:
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);