Ir al contenido


Foto

Mostrar formulario, que haga algo y luego se cierre

formulario mostrar

  • Por favor identifícate para responder
17 respuestas en este tema

#1 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 10 septiembre 2015 - 02:02

Hola. De nuevo por aquí y esta vez con una tontería pero que no sé cómo resolverla.

 

Con Codetyphon quiero crear un programa que muestre un formulario, realice alguna acción (por ejemplo mostrar unas estadísticas) y al cabo de unos segundos, cuando termine la acción, se cierre solo. Todo esto sin la intervención del usuario, es decir, el usuario no tiene que tocar ningún botón para iniciar la acción o cerrar el formulario.

 

Esto es sencillo, pero aquí viene el problema: el formulario se abre correctamente pero no se muestra en pantalla, tan solo se dibujan los bordes pero no el contenido, realiza la acción bien (sigue sin mostrarse) y justo unas décimas antes de cerrarse, se muestra y se cierra, con lo que no te da tiempo a ver nada.

 

Como no sé si me entiende bien, pongo un ejemplo muy sencillo: Tengo una aplicación con dos formularios, form1 y form2. En el principal, form1, pongo un botón que al hacer click me muestra el form2


delphi
  1. procedure tform1.button1click(sender: tobject);
  2. begin
  3. form2.ShowModal;
  4. end;

El form2 quiero que muestre en un label una cuenta creciente de 0 a 10.000. Cuando llegue a 10.000 que se cierre automáticamente


delphi
  1. procedure HagoAlgoySalgo;
  2.  
  3. ....
  4. procedure tform2.hagoalgoysalgo;
  5. var
  6. i: integer;
  7. begin
  8. for i := 0 to 10000 do //cuenta de 0 a 10.000
  9. begin
  10. Application.ProcessMessages; //para que procese mensajes
  11. label2.Caption := IntToStr(i); //veo la cuenta en un label
  12. label2.Refresh; //refresco el label
  13. end;
  14. close; //cierro el formulario
  15. end;
  16.  
  17. procedure tform2.formshow(sender: tobject);
  18. begin
  19. HagoAlgoySalgo;
  20. end;

Bueno, pues al darle al botón del form1, no veo nada (o acaso veo los bordes del form2 pero el contendio es transparente, no veo el label2 contando) y cuando termina la cuenta, ves por una décima de segundo algo que se cierra inmediatamente.

 

He probado a poner la función HagoAlgoYSalgo en el OnPaint, pero me da el mismo resultado.

 

¿Alguna solución? Como véis, bastante tonto el problema...

 

Un saludo.

 


  • 0

#2 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 10 septiembre 2015 - 06:06

Vale, me respondo yo mismo


php
  1. procedure tform2.hagoalgoysalgo;
  2. var
  3. i: integer;
  4. begin
  5. form2.Refresh; //<-- Con esto se muestra el formulario
  6. for i := 0 to 10000 do //cuenta de 0 a 10.000
  7. begin
  8. Application.ProcessMessages; //para que procese mensajes
  9. //if (i mod 15) = 0 then form2.Refresh;
  10. label2.Caption := IntToStr(i); //veo la cuenta en un label
  11. label2.Refresh; //refresco el label
  12. end;
  13. Close; //cierro el formulario

Poniendo form2.refresh antes de empezar el bucle, se muestra el formulario correctamente.


  • 0

#3 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 07:27

Aún así creo que esta mal diseñado. Lo ideal es desde temprano acostumbrarse a programar bien. Lo digo porque lamentablemente yo lo aprendí tarde y ahora me quiero matar

Yo crearía una clase que haga ese trabajo, y le agregaria un evento OnFinished. De esa manera tu clase provee un mecanismo "decime que querés que haga cuando termine".

Ahora desde el teléfono no me dan ganas de escribir código pero te prometo un ejemplo más tarde

Igual para que lo vayas pensando

Enviado desde mi XT1032 mediante Tapatalk
  • 0

#4 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 09:59

Bueno, como te decia, yo creo que lo ideal es crearse una clase que se va a encargar de realizar cierto proceso, y el Form simplemente sirve para interactuar con ella. Vamos a hacer tambien que tu clase pueda proveer un mecanismo de feedback (retroalimentacion) para poder, en este caso, mostrar el progreso
 
 


delphi
  1. unit Unit2;
  2.  
  3. interface
  4.  
  5. uses
  6. Classes;
  7.  
  8. type
  9. TOnProgress = procedure(const ACurrent, ACount: Integer) of object;
  10. TBeforeStart = procedure(const ACount: Integer) of object;
  11.  
  12. THacerAlgo = class
  13. private
  14. FOnProgress: TOnProgress;
  15. FCount: Integer;
  16. FBeforeStart: TBeforeStart;
  17. FOnCompleted: TNotifyEvent;
  18. procedure SetOnProgress(const Value: TOnProgress);
  19. procedure SetBeforeStart(const Value: TBeforeStart);
  20. procedure SetOnCompleted(const Value: TNotifyEvent);
  21. public
  22. constructor Create(const ACount: Integer);
  23. procedure HacerAlgo; overload;
  24. procedure HacerAlgo(const ACount: Integer); overload;
  25. property OnProgress: TOnProgress read FOnProgress write SetOnProgress;
  26. property BeforeStart: TBeforeStart read FBeforeStart write SetBeforeStart;
  27. property OnCompleted: TNotifyEvent read FOnCompleted write SetOnCompleted;
  28. property Count: Integer read FCount;
  29. end;
  30.  
  31. implementation
  32.  
  33. { THacerAlgo }
  34.  
  35. constructor THacerAlgo.Create(const ACount: Integer);
  36. begin
  37. inherited Create;
  38. FCount := ACount;
  39. end;
  40.  
  41. procedure THacerAlgo.HacerAlgo;
  42. var
  43. LCurrent: Integer;
  44. begin
  45. if Assigned(FBeforeStart) then
  46. FBeforeStart(Count);
  47.  
  48. for LCurrent := 0 to Count - 1 do
  49. begin
  50. // hacer algo :)
  51. if Assigned(FOnProgress) then
  52. FOnProgress(LCurrent, Count);
  53. end;
  54.  
  55. if Assigned(FOnCompleted) then
  56. FOnCompleted(Self);
  57. end;
  58.  
  59. procedure THacerAlgo.HacerAlgo(const ACount: Integer);
  60. begin
  61. FCount := ACount;
  62. HacerAlgo;
  63. end;
  64.  
  65. procedure THacerAlgo.SetBeforeStart(const Value: TBeforeStart);
  66. begin
  67. FBeforeStart := Value;
  68. end;
  69.  
  70. procedure THacerAlgo.SetOnCompleted(const Value: TNotifyEvent);
  71. begin
  72. FOnCompleted := Value;
  73. end;
  74.  
  75. procedure THacerAlgo.SetOnProgress(const Value: TOnProgress);
  76. begin
  77. FOnProgress := Value;
  78. end;
  79.  
  80. end.


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Unit2, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7. Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button1: TButton;
  12. ProgressBar1: TProgressBar;
  13. Label1: TLabel;
  14. procedure Button1Click(Sender: TObject);
  15. private
  16. { Private declarations }
  17. public
  18. { Public declarations }
  19. procedure HacerAlgoOnProgress(const ACurrent, ACount: Integer);
  20. procedure HacerAlgoBeforeStart(const ACount: Integer);
  21. procedure HacerAlgoOnCompleted(Sender: TObject);
  22. end;
  23.  
  24. var
  25. Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.dfm}
  30.  
  31. procedure TForm1.Button1Click(Sender: TObject);
  32. var
  33. LHacerAlgo: THacerAlgo;
  34. begin
  35. LHacerAlgo := THacerAlgo.Create(1000);
  36. try
  37. LHacerAlgo.BeforeStart := HacerAlgoBeforeStart;
  38. LHacerAlgo.OnProgress := HacerAlgoOnProgress;
  39. LHacerAlgo.OnCompleted := HacerAlgoOnCompleted;
  40. LHacerAlgo.HacerAlgo;
  41. finally
  42. LHacerAlgo.Free;
  43. end;
  44. end;
  45.  
  46. procedure TForm1.HacerAlgoBeforeStart(const ACount: Integer);
  47. begin
  48. Button1.Enabled := False;
  49. Label1.Caption := 'Inicializando...';
  50. ProgressBar1.Min := 0;
  51. ProgressBar1.Max := ACount;
  52. ProgressBar1.Position := 0;
  53. end;
  54.  
  55. procedure TForm1.HacerAlgoOnCompleted(Sender: TObject);
  56. var
  57. Procesados: Integer;
  58. begin
  59. Procesados := THacerAlgo(Sender).Count;
  60. Button1.Enabled := True;
  61. ShowMessageFmt('Termine y procese %d elementos', [Procesados]);
  62. Label1.Caption := 'Terminado!';
  63. end;
  64.  
  65. procedure TForm1.HacerAlgoOnProgress(const ACurrent, ACount: Integer);
  66. begin
  67. TThread.Synchronize(NIL,
  68. procedure
  69. begin
  70. Label1.Caption := Format('%d / %d', [ACurrent, ACount]);
  71. ProgressBar1.Position := ACount;
  72. end);
  73. end;
  74.  
  75. end.

Fijate que le dimos la capacidad a los usuarios de la clase de suscribirse a "eventos" que sirven como bandera, avisan cuando pasa ciertas cosas y proveen informacion. De esta manera uno puede actuar en consecuencia

 

Hacer que una cosa suceda a otra es algo super facil de hacer en Object Pascal, el lenguaje fue pensado para ello (gracias a Dios!!)


  • 2

#5 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 12:28

Interesante propuesta OrtuAgustin, has definido una especie de "single observer"  :)  Lo que quizá podría rediseñarse es buscar la forma de "independizar" el sistema de notificación del proceso de las tareas.

Supongamos que tenemos varias clases "Hacer Algo", o varias tareas semi independientes y que nos interesa poder mostrar un proceso en cada una de ellas. Bajo el esquema que tu propones implicaría estar duplicando código, en concreto la parte de los eventos. Una alternativa podría ser definir una clase TProcess que define justamenta la interface común a todas: los eventos. Y luego heredar de ésta para añadir y adaptar la lógica por cada "Haz Algo". Por ejemplo, digamos quen tenemos pensado que una clase Ordene, otra que realice sumas y queremos ver una especie de proceso o avance por cada una. Asi de pronto podríamos tener una clase TSortProcess y TSumsProcess. Entonces dentro de sus propios métodos de interés y cuando éstas vean necesario invocar a los métodos OnProcess, BeforeStart y/o OnCompleted.

 

Me haz dado una interesante idea de diseño para mi actual proyecto. Quizá me sirva. (y)

 

Saludos,


  • 0

#6 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 02:13

Sabes que justo me entro a dar vueltas por la cabeza lo mismo; el problema es que es medio raro que me surgan estas ideas y no agarro ni el papel y lapiz; hasta que resulta que me vendria bien y ahi es cuando de a poco empiezan a tomar forma las cosas

 

Creo que una solucion para tener a multiples observadores seria almacenar alguna estructura con los eventos a procesar

 

Lo que decis sobre la herencia es correcto pero no queria complicar tanto el ejemplo. A veces estos cambios de paradigma cuestan un poco masticarlos, pero me parece que dar un paso de "todo en los forms" a "el form solamente muestra que pasa y nada mas" es crecer muchisimo


  • 0

#7 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 03:02

Se que esto no tiene mucho que ver con lo que pusiste en tu mensaje pero creo que puede resultar interesante ir por este lado tambien :)


A ver que tul:
 
Form:

delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls,
  7. Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. ProgressBar1: TProgressBar;
  12. lbPosition: TLabel;
  13. Button1: TButton;
  14. Memo1: TMemo;
  15. Label1: TLabel;
  16. procedure Button1Click(Sender: TObject);
  17. private
  18. { Private declarations }
  19. procedure MemoOnProgress(const ACurrent, ACount: Integer);
  20. procedure LabelOnProgress(const ACurrent, ACount: Integer);
  21. procedure ProgressBarOnProgress(const ACurrent, ACount: Integer);
  22.  
  23. procedure MemoBeforeStart(const ACount: Integer);
  24. procedure LabelBeforeStart(const ACount: Integer);
  25. procedure ProgressBarBeforeStart(const ACount: Integer);
  26.  
  27. procedure MemoOnFinished(Sender: TObject);
  28. procedure LabelOnFinished(Sender: TObject);
  29. procedure ProgressBarOnFinished(Sender: TObject);
  30. public
  31. { Public declarations }
  32. end;
  33.  
  34. var
  35. Form1: TForm1;
  36.  
  37. implementation
  38.  
  39. uses
  40. Unit2;
  41.  
  42. {$R *.dfm}
  43.  
  44. procedure TForm1.Button1Click(Sender: TObject);
  45. var
  46. LHacerAlgo: THacerAlgo;
  47. begin
  48. Button1.Enabled := False;
  49. LHacerAlgo := THacerAlgo.Create(500);
  50. try
  51. LHacerAlgo.BeforeStart(LabelBeforeStart);
  52. LHacerAlgo.BeforeStart(MemoBeforeStart);
  53. LHacerAlgo.BeforeStart(ProgressBarBeforeStart);
  54.  
  55. LHacerAlgo.OnProgress(LabelOnProgress);
  56. LHacerAlgo.OnProgress(MemoOnProgress);
  57. LHacerAlgo.OnProgress(ProgressBarOnProgress);
  58.  
  59. LHacerAlgo.OnFinished(LabelOnFinished);
  60. LHacerAlgo.OnFinished(MemoOnFinished);
  61. LHacerAlgo.OnFinished(ProgressBarOnFinished);
  62.  
  63. LHacerAlgo.HacerAlgo;
  64. finally
  65. LHacerAlgo.Free;
  66. Button1.Enabled := True;
  67. end;
  68. end;
  69.  
  70. procedure TForm1.LabelBeforeStart(const ACount: Integer);
  71. begin
  72. Label1.Caption := Format('Vamos a procesar %d elementos...', [ACount]);
  73. end;
  74.  
  75. procedure TForm1.LabelOnFinished(Sender: TObject);
  76. begin
  77. Label1.Caption := 'Label se entero que termino el proceso!';
  78. end;
  79.  
  80. procedure TForm1.LabelOnProgress(const ACurrent, ACount: Integer);
  81. begin
  82. Label1.Caption := Format('Procesando: %d / %d', [ACurrent, ACount]);
  83. end;
  84.  
  85. procedure TForm1.MemoBeforeStart(const ACount: Integer);
  86. begin
  87. Memo1.Clear;
  88. Memo1.Lines.Add('Comenzo el proceso a las ' + DateTimeToStr(Now));
  89. Memo1.Lines.Add(EmptyStr);
  90. end;
  91.  
  92. procedure TForm1.MemoOnFinished(Sender: TObject);
  93. begin
  94. Memo1.Lines.Add(EmptyStr);
  95. Memo1.Lines.Add('Termino el proceso ' + DateTimeToStr(Now));
  96. end;
  97.  
  98. procedure TForm1.MemoOnProgress(const ACurrent, ACount: Integer);
  99. begin
  100. Memo1.Lines.Add(Format('%s -- Voy por el %d, me faltan %d', [DateTimeToStr(Now), ACurrent, ACount - ACurrent]));
  101. end;
  102.  
  103. procedure TForm1.ProgressBarBeforeStart(const ACount: Integer);
  104. begin
  105. ProgressBar1.Min := 0;
  106. ProgressBar1.Max := ACount;
  107. ProgressBar1.Position := 0;
  108. end;
  109.  
  110. procedure TForm1.ProgressBarOnFinished(Sender: TObject);
  111. begin
  112. lbPosition.Caption := 'Progress bar se entero que termino el proceso!';
  113. end;
  114.  
  115. procedure TForm1.ProgressBarOnProgress(const ACurrent, ACount: Integer);
  116. begin
  117. TThread.Synchronize(NIL, procedure
  118. begin
  119. lbPosition.Caption := IntToStr(ACurrent);
  120. ProgressBar1.Position := ACurrent;
  121. Application.ProcessMessages;
  122. end);
  123. end;
  124.  
  125. end.

THacerAlgo:
 

delphi
  1. unit Unit2;
  2.  
  3. interface
  4.  
  5. uses
  6. System.Classes, System.Generics.Collections;
  7.  
  8. type
  9. TOnProgress = procedure(const ACurrent, ACount: Integer) of object;
  10. TBeforeStart = procedure(const ACount: Integer) of object;
  11.  
  12. TOnProgressEventsList = TList<TOnProgress>;
  13. TBeforeStartEventsList = TList<TBeforeStart>;
  14. TOnNotifyEventsList = TList<TNotifyEvent>;
  15.  
  16. THacerAlgo = class
  17. private
  18. FCount: Integer;
  19. FOnProgressEventsList: TOnProgressEventsList;
  20. FBeforeStartEventsList: TBeforeStartEventsList;
  21. FOnCompletedEventsList: TOnNotifyEventsList;
  22. protected
  23. procedure NotifyOnProgress(const ACurrent: Integer); virtual;
  24. procedure NotifyOnBeforeStart; virtual;
  25. procedure NotifyOnCompleted; virtual;
  26. public
  27. constructor Create(const ACount: Integer);
  28. destructor Destroy; override;
  29. procedure HacerAlgo; overload;
  30. procedure HacerAlgo(const ACount: Integer); overload;
  31. procedure OnProgress(DoOnProgress: TOnProgress);
  32. procedure BeforeStart(DoBeforeStart: TBeforeStart);
  33. procedure OnFinished(DoOnFinished: TNotifyEvent);
  34. property Count: Integer read FCount;
  35. end;
  36.  
  37. implementation
  38.  
  39. { THacerAlgo }
  40.  
  41. constructor THacerAlgo.Create(const ACount: Integer);
  42. begin
  43. inherited Create;
  44. FOnProgressEventsList := TOnProgressEventsList.Create;
  45. FBeforeStartEventsList := TBeforeStartEventsList.Create;
  46. FOnCompletedEventsList := TOnNotifyEventsList.Create;
  47. FCount := ACount;
  48. end;
  49.  
  50. destructor THacerAlgo.Destroy;
  51. begin
  52. FOnProgressEventsList.Free;
  53. FOnCompletedEventsList.Free;
  54. FBeforeStartEventsList.Free;
  55. inherited Destroy;
  56. end;
  57.  
  58. procedure THacerAlgo.HacerAlgo;
  59. var
  60. LCurrent: Integer;
  61. begin
  62. NotifyOnBeforeStart;
  63.  
  64. for LCurrent := 0 to Count - 1 do
  65. begin
  66. { hacer algo }
  67. NotifyOnProgress(LCurrent);
  68. end;
  69.  
  70. NotifyOnCompleted;
  71. end;
  72.  
  73. procedure THacerAlgo.HacerAlgo(const ACount: Integer);
  74. begin
  75. FCount := ACount;
  76. HacerAlgo;
  77. end;
  78.  
  79. procedure THacerAlgo.NotifyOnBeforeStart;
  80. var
  81. LBeforeStartEvent: TBeforeStart;
  82. begin
  83. for LBeforeStartEvent in FBeforeStartEventsList do
  84. LBeforeStartEvent(Count);
  85. end;
  86.  
  87. procedure THacerAlgo.NotifyOnCompleted;
  88. var
  89. LOnCompleted: TNotifyEvent;
  90. begin
  91. for LOnCompleted in FOnCompletedEventsList do
  92. LOnCompleted(Self);
  93. end;
  94.  
  95. procedure THacerAlgo.NotifyOnProgress(const ACurrent: Integer);
  96. var
  97. LOnProgressEvent: TOnProgress;
  98. begin
  99. for LOnProgressEvent in FOnProgressEventsList do
  100. LOnProgressEvent(ACurrent, Count);
  101. end;
  102.  
  103. procedure THacerAlgo.BeforeStart(DoBeforeStart: TBeforeStart);
  104. begin
  105. FBeforeStartEventsList.Add(DoBeforeStart);
  106. end;
  107.  
  108. procedure THacerAlgo.OnFinished(DoOnFinished: TNotifyEvent);
  109. begin
  110. FOnCompletedEventsList.Add(DoOnFinished)
  111. end;
  112.  
  113. procedure THacerAlgo.OnProgress(DoOnProgress: TOnProgress);
  114. begin
  115. FOnProgressEventsList.Add(DoOnProgress)
  116. end;
  117.  
  118. end.

Salida:

aeffac3ae183426d69878e6cda8a5ad5o.jpg
  • 3

#8 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 03:08

Creo que modificando un poco el codigo anterior se podria agregar manejo de prioridades. Yo use estructura lista para almacenar los eventos que se deben procesar, pero se podria usar la que mas comodo le quede a cada uno

 

Siguiendo con la lista, si uno cambia los metodos que se usan paran "suscribirse" se podria agregar en distintas posiciones de la lista utilizando Insert en lugar de Add; de esta manera, un Insert(0, Evento) seria un evento de prioridad alta

 

Saludos


  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 04:58

Hace un tiempo expuse parte del modelo del patrón Observer que he diseñado para mis trabajos. No ha cambiado al día de la fecha, a pesar de haberme hecho tantas preguntas. No es tan diferente el diseño que tiene de lo que se ha planteado aquí.

 

Saludos,


  • 1

#10 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 10 septiembre 2015 - 09:25

Uff largo para leer y masticar y menos ahora que ya tengo la cabeza medio quemada

 

En fin, la moraleja: Aprovechar y abusar de los eventos y tratar de que todo el procesamiento, calculo, o trabajo real pase dentro de los objetos que saben hacer ese proceso; los formularios y controles solamente sirven para pedir/mostrar datos, y disparar metodos de las clases: avisarles que empiecen, que paren y poco, poco mas

 

A la larga (no miuy lejana, en realidad) termina dando muchisimo redito a lo(s) desarrolladores


  • 0

#11 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 11 septiembre 2015 - 01:05

¡Madre de Dios!

Agustín, muchas gracias por tu tiempo. Parece que no era tan tonto lo que pretendía.

De todas maneras me temo que para mi nivel de programación tu código me supera. No soy informático, no he estudiado nunca programación y he aprendido a base de foros y lo que escribo en delphi y lazarus. Soy ingeniero que hace cosillas de bases de datos y poco más.

 

Parece que a Delphius le has dado ideas para trabajar así que tu tiempo en enseñarnos va a ser bien aprovechado.

 

Muchas gracias.


  • 0

#12 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 11 septiembre 2015 - 11:15

no he estudiado nunca programación y he aprendido a base de foros y lo que escribo en delphi y lazarus.

 

En esto somos identicos (bueno, casi, 2 años y medios de estudio universitario)

 

Igual es todo cuestion de practica, de a poco la cabeza se va abriendo; de ultima un poco de ejercicio muscular al cerebro mal no le viene nunca  :tongue:

 

Saludos


  • 1

#13 giulichajari

giulichajari

    Advanced Member

  • Miembros
  • PipPipPip
  • 477 mensajes

Escrito 13 septiembre 2015 - 01:47

Hace un tiempo expuse parte del modelo del patrón Observer que he diseñado para mis trabajos. No ha cambiado al día de la fecha, a pesar de haberme hecho tantas preguntas. No es tan diferente el diseño que tiene de lo que se ha planteado aquí.

 

Saludos,

Hola Delphius..veo todas tus implementacion de patrones aqui en el foro...son muy buenas..

Por cierto.. tienes los diagramas UML de todo eso? Pregunto si es posible programarlo sin diagramar, de hecho se que llegar a semejante codigo sin imagenes es imposible....


  • 0

#14 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 septiembre 2015 - 10:44

Hola Delphius..veo todas tus implementacion de patrones aqui en el foro...son muy buenas..

Por cierto.. tienes los diagramas UML de todo eso? Pregunto si es posible programarlo sin diagramar, de hecho se que llegar a semejante codigo sin imagenes es imposible....

 

La verdad es que no tengo los diagramas de mis implementaciones.

Mis creaciones son fruto del estudio y análisis del tema. Tengo varias fuentes de consulta las que más consulto y son fundamentales:

* UML y Patrones. Craig Larman.

* Wikipedia

* OODesign

* Source Making

 

El Diagrama de mi implementación no variará de otro. Es sólo una aplicación del patrón. Y como tal, visto desde dicho patrón tiene un diseño definido. Justamente eso es lo que hace al patrón: definir una solución especifíca para un problem específico. Ergo: tiene un diseño específico, desde la perspectiva de UML. Por ejemplo, para el caso del patrón Observer lo que se nota es que existe una clase Sujeto que tiene una relación de agregación con otra que actúa base de Observador.  La clase que actúa de Sujeto tiene los métodos necesarios para registrar a los sujetos y para llevar a cabo las notificaciones necesarias. Por su parte las clases Observadores que heredan del Observador base implementarán sus métodos de respuesta al mensaje de notificación que el sujeto les emite.

 

Puedes ver el diagrama UML en wiki.

 

El diagrama puede "ampliarse" para ilustrar un diseño más "personalizado". Por ejemplo, en mi caso podría verse que mis clases Sujeto y Observador heredan de sus respectivas interfaces. Y también podría añadir al diagrama la relación de mi TAbstractSubject con TInterfacedList, y que ésta última es la que finalmente hace la relación de agregación con IAbstractObserver.

 

Lo importante es entender el concepto. Naturalmente que los diagramas ayudan, pero repito: uno puede darles los detalles necesarios según sus necesidades. La estructura básica y fundamental es la que puedes ver en los sitios fuentes que te dí. Cuando uno ya se hace la idea del patrón incluso la imagen UML ya ni es necesaria. Uno ya asimila que la clase Sujeto debe tener una lista, que los observadores implementen las respuestas, etc... y ni se pone a pensar en si tiene que trazar una flechita, o en poner el rombo en la relación de agregación... etc.

Al comienzo era muy meticuloso en los diagramas. En la medida en que iba estudiando los patrones cada vez me ha sido necesario dibujar menos. A la fecha sólo me siento a dibujar para ayudar a ordenar mis ideas y sólo lo necesario. No me pongo a hacer cientos...

 

Y cuando necesito dibujar, lo hago a mano. Me siento con el lápiz y el papel. A los que realmente necesito los llevo al mundo digital para formar la documentación "oficial".

 

Saludos,


  • 0

#15 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 septiembre 2015 - 11:32

Uff largo para leer y masticar y menos ahora que ya tengo la cabeza medio quemada

 

En fin, la moraleja: Aprovechar y abusar de los eventos y tratar de que todo el procesamiento, calculo, o trabajo real pase dentro de los objetos que saben hacer ese proceso; los formularios y controles solamente sirven para pedir/mostrar datos, y disparar metodos de las clases: avisarles que empiecen, que paren y poco, poco mas

 

A la larga (no miuy lejana, en realidad) termina dando muchisimo redito a lo(s) desarrolladores

 

Asi es como debiera ser... en la práctica es otra cosa. ¡Cuántas veces nos vemos obligados a hacer unas mezclas que nos afecta la cohesión! Hay que recordar que la cohesión y el acoplamiento son necesarios, e inevitables. Van de la mano.

 

Estos tipos de relación entre interfaz-lógica/procesal se hace más complicado cuando ya no se trata de un diseño tradicional que sugiere 3 capas: lógico, interfaz, datos. En cuanto ya se vuelve de interés tener las capas de aplicación, presentación, dominio ya se hace más lioso el trabajo.

 

Y si, el perfil del diseñador es fundamental tenerlo. Ayuda mucho.

 

Y como dije, hay cosas inevitables. Por ejemplo hace unas semanas que estuve dando batalla a un diseño que me comía la cabeza... necesitaba ahorrarme código hasta cuadruplicado (salvo algunos detalles entre ellos), pero también un par de evaluaciones. Si me centraba en el ahorro de esos codigos repetibles, generaba evaluaciones innecesarias en otros lados... Y si centraba las evaluaciones, me condicionaba a estar repitiendo parte del código que se dedicada a tareas de procesamiento. Si sumaba todas las evaluaciones llegaba a una V(G) de 6 a 7. Y 7 es considerado el número mágico en el que uno debe prender la lamparita y revisar lo que tiene.

Y si considero que incluso el rediseño era necesario para evitar mover grandes estructuras de datos entre diferentes métodos para no provocar un error de memoria... puff. No hay cabeza que aguante. Te consume.

Esto nos lleva a que uno debe hacer aceptar ciertos compromisos.

Sea el camino que elija en algo se pierde.

 

Hay batallas que no necesariamente nos lleve a una respuesta definitiva o clara. Y esa es una lección que debemos aprender. En informática existe el gris.

 

¡Madre de Dios!

Agustín, muchas gracias por tu tiempo. Parece que no era tan tonto lo que pretendía.

De todas maneras me temo que para mi nivel de programación tu código me supera. No soy informático, no he estudiado nunca programación y he aprendido a base de foros y lo que escribo en delphi y lazarus. Soy ingeniero que hace cosillas de bases de datos y poco más.

 

Parece que a Delphius le has dado ideas para trabajar así que tu tiempo en enseñarnos va a ser bien aprovechado.

 

Muchas gracias.

 

En realidad la idea es una refrescura de un concepto en el que venía trabajando.

Tenía un diseño más elaborado... y complejo. Una serie de observadores encadenados... Es decir que un observador era a su vez un sujeto y notificaba a alguien de más "arriba". Y se estaba yendo de la mano. Rediseñé mi trabajo, y parte del problema se eliminó pero aún no había dedicado a estudiar en como haría la comunicación entre interfaz y la parte "procesal" adaptada al nuevo esquema.

En mi nuevo esquema procesal hay varios objetos interviniendo, operando, y hay info de interés que viene bien estar dando aviso de como va el trabajo. Justamente es lo que me estaba maquinando la cabeza hasta que vi la propuesta de Agustín con sus eventos OnBefore, OnProcess y OnFinish y la lamparita prendió.

 

No te sientas mal por si sientes que esto te supera. No temas. Las propuestas de Agustín como la mía es aprovechar el concepto de eventos. Tienen un potencial enorme. En resumen, e independientemente de la complejidad de nuestros diseños, todo se resume en dotar a las clases de interés de un mecanismo de publicación de avances o cambios que otros estén interesados.

Entonces tenemos una clase que hace algo, y otra que quiere ser avisada de eso. Entonces ambas deciden compartir un "protocolo de comunicación", para eso son los eventos. La clase que se dedica a "procesar" define el cuerpo (las estructuras) de los eventos que considera necesario para compartir los cambios y avisos. La clase que "escucha" los cambios va a implementar los métodos de respuesta para dichos eventos.

 

Eso es lo que propone el patrón Observador, únicamente que lo abstrae más. En lugar de asumir una relación 1-1, propone que sean varios los interesados en ser notificados. La clase Sujeto (la que procesa y notifica) registra en una lista a los observadores. Luego simplemente recorre la lista y les envía el mensaje de que algo ha cambiado/sucedido y les pasa por parámetro el dato que necesitan. Ya cada observador implementará el algoritmo adecuado para dar respuesta al aviso.

 

En el ejemplo de Agustín puedes ver el caso 1-1. Tiene una clase que define 3 eventos (uno para antes de empezar, en proceso y otra para cuando finaliza) y es la que centra el trabajo. Luego está el observador que es el form. En el form implemeta los algoritmos de respuesta para los 3 eventos.

 

Saludos,


  • 0

#16 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 14 septiembre 2015 - 12:12

Sí, la idea general, el porqué de hacerlo así lo entiendo. Lo que se me escapa es el cómo, el código que desarrolla Agustín, que desde luego está varios escalones por encima de mi nivel.

Pero como bien decís, así se aprende, que leche.

 

Muy agradecido por compartir vuestros conocimientos y sobre todo, el tiempo que nos dedicáis.


  • 0

#17 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 14 septiembre 2015 - 07:35

Sí, la idea general, el porqué de hacerlo así lo entiendo. Lo que se me escapa es el cómo, el código que desarrolla Agustín, que desde luego está varios escalones por encima de mi nivel.

Pero como bien decís, así se aprende, que leche.

 

Muy agradecido por compartir vuestros conocimientos y sobre todo, el tiempo que nos dedicáis.

 

No te minimices.

Lo más importante del código está en definir que tipos de datos se necesita notificar y en que momentos dispararlos. Como he dicho: se trata de pensar en un "protocolo" que tanto el proceso como el oyente sepan manejarlo.

Si te abruma el código de Agustín, puedes empezar leyendo en el foro de Manuales los conceptos. He dedicado un "capítulo" al tema de eventos y el sistema de notificaciones.

 

Saludos,


  • 0

#18 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 15 septiembre 2015 - 05:42

Muy interesante.

 

Gracias.


  • 0





Etiquetado también con una o más de estas palabras: formulario, mostrar

IP.Board spam blocked by CleanTalk.