Home > Delphi, Did You Know > Form Load Profiler: Multi Form: Class Helper

Form Load Profiler: Multi Form: Class Helper


Pada kesempatan yang lalu, saya sajikan artikel mengenai bagaimana mengukur waktu tayang (load-time) suatu form dari form tersebut di buat hingga benar – benar tampil dan siap digunakan. Sudah saya sajikan metode untuk form tunggal maupun multi form. Pada teknik multi form, saya menggunakan teknik interposser class. Selain teknik tersebut, ada alternatif lain yaitu dengan menggunakan class helper yang akan dibahas pada kesempatan ini.

Bagi pembaca yang mengikuti blog saya dari awal, tentunya ingat bahwa saya sudah beberapa kali menyajikan artikel Did You Know yang membahas mengenai penggunaan Class Helper. Dan pada kesempatan ini saya tidak akan membahas apa dan bagaimana class helper itu sendiri. Anda dapat mencarinya pada dokumentasi yang disediakan oleh CodeGear atau googling.

Nah, sekarang bagaimana menerapkan class helper dalam kasus ini.

Pertama, buat helper untuk kelas TForm.

  TGlobalFormHelper = class helper for TForm
  end;

Kemudian untuk mendeklarasikan variabel FStart dan FEnd, tidak bisa dilakukan secara sembarangan mengingat class helper memberikan batasan tidak dapat menambah instance data, namun dapat menambah class fields. Nah untuk itu kita memanfaatkan class var, sehingga deklarasi variabelnya menjadi:

  TGlobalFormHelper = class helper for TForm
    class var
      FStart, FEnd : Cardinal;
  end;

langkah selanjutnya adalah mendeklarasikan constructor Create, namun kali ini deklarasinya sedikit berbeda. Jika pada interposer class, kita harus meng-override constructor Create, maka pada class helper tidak perlu. Secara umum, isi dari constructor sebagai berikut:

  TGlobalFormHelper = class helper for TForm
    class var
      FStart, FEnd : Cardinal;
  public
    constructor Create(AOwner: TComponent);
  end;
//
// ....
//
constructor TGlobalFormHelper.Create(AOwner: TComponent);
begin
  FStart := GetTickCount;
  inherited;
end;

Sampai di sini kita sudah mulai menghitung pengukuran, langkah berikutnya tentu saja adalah meletakkan rutin akhir pengukuran pada method Activate. Namun sayang sekali, dalam class helper ini, kita tidak dapat mendeklarasikan dan atau meng-override method Activate karena sudah dideklarasikan. Sebagai alternatif solusinya, kita akan membelokkan event onActivate untuk menjalankan rutin pengukuran. Untuk itu kita harus menyimpan event onActivate yang sebenarnya. Nah di dalam rutin pengukuran tersebut kita jalankan event onActivate yang sebenarnya sebelum mengakhiri perhitungan. Selengkapnya menjadi:

  TGlobalFormHelper = class helper for TForm
    class var
      FStart, FEnd : Cardinal;
      FOnActivateTemporary : TNotifyEvent;
  public
    constructor Create(AOwner: TComponent);
    procedure CalculateLoadTime(Sender: TObject);
  end;
//
// ....
//
procedure TGlobalFormHelper.CalculateLoadTime(Sender: TObject);
begin
  if Assigned(FOnActivateTemporary) then FOnActivateTemporary(Sender);
  FEnd := GetTickCount;
end;

constructor TGlobalFormHelper.Create(AOwner: TComponent);
begin
  FStart := GetTickCount;
  inherited;

  Sleep(50);
  FOnActivateTemporary := Self.OnActivate;
  Self.OnActivate := CalculateLoadTime;
end;

Ok, sampai disini class helper sudah beres, sekarang bagaimana dengan kelas utama nya? Cukup dengan menambahkan constructor Create dan tambahkan directive override. Di dalam constructor tersebut, tambahkan kode inherited untuk memanggil constructor Create yang sebenarnya, yaitu yang dideklarasikan pada class helper.

  TMainForm = class(TForm)
//
// ...
//
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  end;
//
// ...
//
constructor TMainForm.Create(AOwner: TComponent);
begin
  inherited;
end;

Langkah selanjutnya adalah bagaimana memanfaatkan class helper tersebut pada form. Untuk form utama, tidak ada masalah, tidak ada tambahan apapun karena class helper dideklarasikan dalam unit yang sama.

{-----------------------------------------------------------------------------
 The contents of this file are subject to the Mozilla Public License
 Version 1.1 (the "License"); you may not use this file except in compliance
 with the License. You may obtain a copy of the License at
 http://www.mozilla.org/MPL/MPL-1.1.html

 Software distributed under the License is distributed on an "AS IS" basis,
 WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
 the specific language governing rights and limitations under the License.

 The Original Code is: MultipleMainFormUnit.pas, released on 2008-09-25

 The Initial Developer of the Original Code is Bayu Prasetio
 Portions created by Bayu Prasetio are Copyright (C) 2008 Bayu Prasetio.
 All Rights Reserved.
 -----------------------------------------------------------------------------}
unit MultipleMainFormUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TMainForm = class(TForm)
    btnShowResult: TButton;
    mmoLegend: TMemo;
    stbMain: TStatusBar;
    btnLoadSecondary: TButton;
    lblLoadTime: TLabel;
    btnLoadAnotherForm: TButton;
    procedure btnShowResultClick(Sender: TObject);
    procedure btnLoadSecondaryClick(Sender: TObject);
    procedure btnLoadAnotherFormClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  end;

  TGlobalFormHelper = class helper for TForm
    class var
      FStart, FEnd : Cardinal;
      FOnActivateTemporary : TNotifyEvent;
  public
    constructor Create(AOwner: TComponent);
    procedure CalculateLoadTime(Sender: TObject);
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

uses
  MultipleSecondaryFormUnit, MultipleAnotherFormUnit;

procedure TMainForm.btnLoadAnotherFormClick(Sender: TObject);
begin
  AnotherForm := TAnotherForm.Create(nil);
  AnotherForm.ShowModal;
  AnotherForm.Free;
end;

procedure TMainForm.btnLoadSecondaryClick(Sender: TObject);
begin
  SecondaryForm := TSecondaryForm.Create(nil);
  SecondaryForm.ShowModal;
  SecondaryForm.Free;
end;

procedure TMainForm.btnShowResultClick(Sender: TObject);
begin
  lblLoadTime.Caption := ' Form Load Time: ' + IntToStr(FEnd - FStart) + ' ms';
  btnShowResult.Enabled := False;
end;

constructor TMainForm.Create(AOwner: TComponent);
begin
  inherited;
end;

procedure TGlobalFormHelper.CalculateLoadTime(Sender: TObject);
begin
  if Assigned(FOnActivateTemporary) then FOnActivateTemporary(Sender);
  FEnd := GetTickCount;
end;

constructor TGlobalFormHelper.Create(AOwner: TComponent);
begin
  FStart := GetTickCount;
  inherited;

  Sleep(50);
  FOnActivateTemporary := Self.OnActivate;
  Self.OnActivate := CalculateLoadTime;
end;

end.

Nah untuk form yang lainya, deklarasi mirip dengan menggunakan interposer class, yaitu cukup dengan menambahkan pada klausul uses dengan nama unit dimana class helper dideklarasikan, seperti contoh kode berikut:

{-----------------------------------------------------------------------------
 The contents of this file are subject to the Mozilla Public License
 Version 1.1 (the "License"); you may not use this file except in compliance
 with the License. You may obtain a copy of the License at
 http://www.mozilla.org/MPL/MPL-1.1.html

 Software distributed under the License is distributed on an "AS IS" basis,
 WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
 the specific language governing rights and limitations under the License.

 The Original Code is: MultipleAnotherFormUnit.pas, released on 2008-09-25

 The Initial Developer of the Original Code is Bayu Prasetio
 Portions created by Bayu Prasetio are Copyright (C) 2008 Bayu Prasetio.
 All Rights Reserved.
 -----------------------------------------------------------------------------}
unit MultipleAnotherFormUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TAnotherForm = class(TForm)
    btnShowResult: TButton;
    procedure btnShowResultClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  AnotherForm: TAnotherForm;

implementation

{$R *.dfm}

uses
  MultipleMainFormUnit;

procedure TAnotherForm.btnShowResultClick(Sender: TObject);
begin
  ShowMessage('Load Time : ' + IntToStr(FEnd - FStart));
end;

procedure TAnotherForm.FormCreate(Sender: TObject);
begin
  Sleep(200);
end;

end.

Nah selesai…

Selengkapnya mengenai demo class helper dapat di-unduh di sini: Source Code.

Jika Anda sudah lupa dengan form load profiler untuk form tunggal, silahkan disimak di sini: Form Load Profiler: Single Form

Jika Anda sudah lupa dengan form load profiler dengan menggunakan teknik interposer class, silahkan disimak di sini: Form Load Profiler: Multiple Form: Interposer Class

Lalu mana yang terbaik antara interposer class dan class helper ?

Dilihat dari faktor kompatibilitas compiler Delphi, jelas interposer class karena class helper baru diperkenalkan mulai Delphi 2005 (CMIIW).

Di sisi lain, CodeGear dalam dokumentasinya menyebut secara khusus class helper:

Class helpers provide a way to extend a class, but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding.

Namun menurut saya tergantung kebutuhan dan pemahaman Anda mengenai kedua teknik tersebut.

Semoga bermanfaat.

Advertisements
  1. herux
    January 15, 2009 at 6:14 pm

    Bagus boss artikelnya

  2. January 16, 2009 at 12:59 am

    thanks, seperti biasa, apa yang saya sajikan masih kulitnya saja, jika berminat, silahkan mendalami lebih jauh. 😀

    btw saya menyertakan statement sleep(50) di dalam constructor Create form class helper dan sleep lainnya pada constructor yang lain, hanya sebagai penanda saja, agar efek dari metode ini terlihat. Pada kode yang sesungguhnya, sebaiknya sleep tersebut dihilangkan.

    Semoga bermanfaat.

  1. October 6, 2008 at 6:00 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: