Solved

3 level software architecture

Posted on 2010-08-17
13
324 Views
Last Modified: 2012-05-10
what is the best way to move progress information from a 3rd. level routine to the GU level ???

procedure button1.click (......)
begin
         
         MyClass.DoSomeAction (...;  aGuiProgressBar; ......);

end;


procedure TMyClass.DoSomeAction (........aGuiProgressBar : TProgressbar...);
begin
   
          ExecuteComplexCalc( ...aGuiProgressBar .... ...);
end;



procedure  ExecuteComplexCalc (........ .aGuiProgressBar : TProgressbar   .....................  )
begin
         

            aGuiProgressBar.value := i;       //  set the value here

end;
0
Comment
Question by:BdLm
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
  • 2
  • +1
13 Comments
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 33455606
1 way: read my article on this site
probably not the best, but it shows independance of a class towards a form using a callback procedure

a lot of solutions i see, have the name of the form or the progress inside the thread
which is useless if using the same unit in a other unit/form with a different name
0
 
LVL 8

Author Comment

by:BdLm
ID: 33455685
you refer to http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/A_239-Displaying-progress-in-the-main-form-from-a-thread-in-Delphi.html  ??  

from design style level 3 should only talk to level 2 but never to level 1, but this is much more coding instead of the dirty way .....

I need the reuse design as I use the level 3 libraries for many different projects
0
 
LVL 25

Assisted Solution

by:epasquier
epasquier earned 71 total points
ID: 33456371
I'm not sure what your problem is. Your way could work, with just the addition of something to tell the progressbar to update itself once set to a new value. Otherwise, passing the reference to the progressbar from one level to the next is not a problem.

In fact, you can use a SetProgress global function that will do that, and other things very much needed regularly during lengthy calculations, like treating pending windows events
For a Cancel button for example, that would break the current calculation.
procedure SetProgress(aGuiProgressBar : TProgressbar; Val:Integer);
begin
 aGuiProgressBar.value := i;       //  set the value here
 Application.ProcessMessages; // treat all pending system messages NOW
// among them, redraw the progress bar, and a cancel button event
 if Canceled Then Abort; // raise a silent exception that will break all the process
end;

procedure TForm.btnCancelClick(Sender:TObject);
begin
 Canceled:=True; // Canceled is a public variable set to false at start
 // this will abort the process next time its progress is supdated
end;

procedure  ExecuteComplexCalc (........ .aGuiProgressBar : TProgressbar   .....................  );
Var
 i:integer;
begin
 for i:=0 to 1000 do 
  begin
   SetProgress(aGuiProgressBar , i);
   sleep(1000);
  end;
end;


procedure TMyClass.DoSomeAction (........aGuiProgressBar : TProgressbar...);
begin
 Canceled:=False;
 ExecuteComplexCalc( ...aGuiProgressBar .... ...);
end;

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 32

Accepted Solution

by:
Ephraim Wangoya earned 143 total points
ID: 33456942
Always try as much as possible to separate your GUI controls from your backend controls. This way if you need to change your progress bar at some time in the future, you only do so in the interface part of your program

Heres what I would do

  TUpdateProgressEvent = procedure(Sender: TObject; const AProgress: Int64);

  TMyObject = class(TSomething)
  private
    FOnUpdateProgressEvent: TUpdateProgressEvent;
    procedure DoProgressEvent(const AProgress: Int64);
  public
    procedure DoSomeAction;
    property OnUpdateProgressEvent: TUpdateProgressEvent read FOnUpdateProgressEvent write FOnUpdateProgressEvent;
  end;

  TForm1 = class(TForm)
  private
    procedure OnUpdateProgress(Sender: TObject; const AProgress: Int64);
  public
    procedure DoSomething;
  end;

......

{ TMyObject }

procedure TMyObject.DoProgressEvent(const AProgress: Int64);
begin
  if Assigned(FOnUpdateProgressEvent) then
    FOnUpdateProgressEvent(Self, AProgress);
end;

procedure TMyObject.DoSomeAction;
var
  I: Integer;
begin
  for I := 0 to 1000 do
    DoProgressEvent(I);
end;

{ TForm1 }

procedure TForm1.DoSomething;
var
  MyObject: TMyObject;
begin
  MyObject := TMyObject.Create;
  try
    //initialize your progress bar
    MyObject.OnUpdateProgressEvent := OnUpdateProgress;
    MyObject.DoSomeAction;
  finally
    FreeAndNil(MyObject);
  end;
end;

procedure TForm1.OnUpdateProgress(Sender: TObject; const AProgress: Int64);
begin
  ProgressBar1.Value := AProgress;
  //Application.ProcessMessages;
end;
0
 
LVL 37

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 286 total points
ID: 33457459
um, ewangoya,
that's what that article is about ...

and the reason i wrote it, was to reference it
try reading it ...

you're almost there, you still need to let the progressbar update it's on screen display
ProgressBar.Value := aProgress;
ProgressBar.Update;

ow ... the TSomething ... descending from TThread ?
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 33457473
I agree with the separation,
but in this case consider the observer pattern

even for multiple levels

i'll show a sample in a minute with different  levels and the observer pattern
0
 
LVL 37

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 286 total points
ID: 33457566
well i was going to create a sample, but then i bumped into this
http://tdelphihobbyist.blogspot.com/2009/11/observer-design-pattern-in-delphi-pull.html

if you think about levels in coding then you should certainly look at design patterns
you might want to think about mvc (model-view-controller) ...
0
 
LVL 32

Assisted Solution

by:Ephraim Wangoya
Ephraim Wangoya earned 143 total points
ID: 33460548
@Geert_Gruwez

I should have read your article first. Same thing only you pass the procedure pointer on create.
0
 
LVL 37

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 286 total points
ID: 33461939
yes, passing parameters gives total indepedence to the lower level
0
 
LVL 8

Author Comment

by:BdLm
ID: 33461955
what about for level 3 :

function heavyCalcLevel3(.......;  aFeedBackElement : TObject);
begin


        if  ( aFeedBackElement  is TProgresslbar then  
                    begin

                      ......

                   end;


end;

Thanks for your discussion
0
 
LVL 37

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 286 total points
ID: 33462237
you are expecting inside the thread that you are working with a progressbar
this limits the GUI to giving a progressbar to your thread

what if someone invented this really cool amazing TCalcStatus object which had a PercentDone value as a property

if you want to take a general approach to a problem then don't pin it down on using a TProgressbar

in nearly all calculations which have a indication with feedback
it's up to the gui how to display the progress or percentdone, not the thread
the thread is there to do the hard work, not the fancy screen work

a sample: lets consider something like bit torrent > this can download several files with different threads

level 1: download x number of files
level 2: download 1 specific file out of this list
level 3: download a chunk of this specific file

so:
in level 3: you have x number of bytes out of a total of Y >> translate to x/y*100 for percent done of this thread
in level 2: you could have 10 threads running, each downloading a chunk
  > the total of downloaded bytes / total file size * 100 for percent done of this file
in level 1: you could show the percentage of total bytes downloaded / total files size > total percent done

this is allways passing x number out of y number to do
i didn't talk about a progressbars yet in these threads

and there is the problem ... you could have a progressbar for each individual percentage
so you would need to report the individual progress to the higher level using x,y
it's allways up to the higher level what it does with this value ...

and how display it ?
i would do this within a devexpress TcxProgressbar within a devexpress TcxGrid
Off course it would have a progressbar for each level


so i would use this as feedback

type 
  TFeedbackProgressEvent = 
    procedure (Sender: TObject; WorkDone, WorkToDo: integer) of object;

function heavyCalcLevel3(.......;  FeedBack : TFeedbackProgressEvent);
var x, y: integer;
begin
  x := 0;
  y := FileSize('x.zip');
  Feedback(Self, x, y);
  repeat
    file.ReadByte;
    x := x +1;
    Feedback(Self, x, y);
  until x >= y;
  Feedback(Self, y, y);
end;

type
  THeavyCalc2 = class
  private
    fFilesToProcess: TList;
    fTotalFilesSize: Cardinal;
    fTotalWorkDone: Cardinal;
    Calc3Threads: TList;
    procedure FeebackEvent(Sender: TObject; WorkDone, WorkToDo: integer);  
    
  end;

procedure THeavyCalc2.FeebackEvent(Sender: TObject; WorkDone, WorkToDo: integer);
begin
  if WorkDone = WorkToDo then 
  begin
    fTotalWorkDone := fTotalWorkDone + WorkToDo;
    Feeback(Self, fTotalWorkDone,  fTotalFileSize);
  end; 
end;

Open in new window

0
 
LVL 25

Expert Comment

by:epasquier
ID: 33462446
BdLm, Thanks for giving me some points, Geert has done a great job helping you with this topic where I only added stone to the building. I was ready to accept I would get no credit.

BUT :
When you select multiple answers, please do not select everything without consideration of the value of the answers. And you can change the amount of points each answers is worth, not just let the automatic division calculate it for you. With your way, it gives the impression that it is only needed to post a maximum of comments whatever the quality, and if more than one is selected then you will have better reward than a single complete explanation.

for example, you selected ewangoya #33460548 and geert response about it. They bring no value to the discussion.

Next time, select only the real answers to the question and change the value of the ones that helped you most (geert last post in this case is the main one and is worth by itself 300-400 pts). This will also ensure that the 'ACCEPTED SOLUTION' is the one with most points, so the one that really deserves it.
0
 
LVL 8

Author Comment

by:BdLm
ID: 33462498
Thanks for the inputs, my intension was to honor the complete discusssion, even geert again made a great job with very useful inputs for me. Should increase to points to 1000 :-)  

btw:

is there any language forcing people to develop software in 3 levels of architecture ? getting contributions to my software project from different people I get crazy if the violate the 3 level design style ....  
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question