Nesneye Dayalı Programlama

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
sadettinpolat
Moderator
Mesajlar: 2131
Kayıt: 07 Ara 2003 02:51
Konum: Ankara
İletişim:

Nesneye Dayalı Programlama

Mesaj gönderen sadettinpolat »

Jetix ' te yayınlanan Casus Köpeklerin Gizli Dünyaları adlı bir çizgi film var. Bu çizgi filmde insanların dostu olarak bilinen köpeklerin kuyruk sallamak, gazete terlik gibi şeyleri getirmekten başka insanları korumak adına yaşadıkları maceraları konu alıyor. Filmn başlangıcında dışses amca köpeklerin kurmuş olduğu bir gizli örgütün yaptıklarını anlatıp sonunda "gerçekte neyi biliyoruz ki?" gibi bir cümle sarfediyor.

Nesneye dayalı program yapıyoruz ama gerçekte programlarımız ne kadar nesneye dayanıyor ki?

Nyp'nin temel bir çok özelliğini bilmemize rağmen bunu programlarımızda yeteri kadar kullanmıyoruz. Kendi nesnelerimiz yerine Delphi'nin bize sunmuş olduğu hazır bileşenlerle işimizi görmeye çalışıyoruz. Onlarda bi yere kadar ...

Şimdi nesnelerle ilgili ufak bir örnek yapıp ardından bunun avantajlarına ve dezavantajlarına değinecez.

Hikayemiz de bir bankada yapılan havale işleminin gerçekleştirilmesi olsun.

Bu işlemde bir hesaptan başka bir hesaba belirtilen miktarda parayı transfer etmemiz gerekiyor. Bize lazım olan bilgiler :

1- Havale yapan hesap no
2- Havale yapılacak hesap no
3- Havale yapılacak miktar


Şimdi THavale sınıfımızın tanımını yazalım.

Kod: Tümünü seç

type
  THavale = class
  private
    fHavaleYapanCariID   :Integer;
    fHavaleYapilanCariID :Integer;
    fHavaleYapilanMiktar :Double;
    function  GetHavaleYapanCariID: Integer;
    procedure SetHavaleYapanCariID(const Value: Integer);
    function  GetHavaleYapilanCariID: Integer;
    procedure SetHavaleYapilanCariID(const Value: Integer);
    function  GetHavaleYapilanMiktar: Double;
    procedure SetHavaleYapilanMiktar(const Value: Double);
  public
  Procedure HavaleYap;
  property  HavaleYapanCariID   : Integer read GetHavaleYapanCariID   write SetHavaleYapanCariID;
  property  HavaleYapilanCariID : Integer read GetHavaleYapilanCariID write SetHavaleYapilanCariID;
  property  HavaleYapilanMiktar : Double  read GetHavaleYapilanMiktar write SetHavaleYapilanMiktar;
  end;

Şimdi de metod ve fonksiyonların gövdelerini yazalım.

Kod: Tümünü seç

{ THavale }

function THavale.GetHavaleYapanCariID: Integer;
begin
    Result := fHavaleYapanCariID;
end;

function THavale.GetHavaleYapilanCariID: Integer;
begin
  Result :=fHavaleYapilanCariID;
end;

function THavale.GetHavaleYapilanMiktar: Double;
begin
  Result := fHavaleYapilanMiktar;
end;

procedure THavale.SetHavaleYapanCariID(const Value: Integer);
begin
  fHavaleYapanCariID := Value;
end;

procedure THavale.SetHavaleYapilanCariID(const Value: Integer);
begin
  fHavaleYapilanCariID := Value;
end;

procedure THavale.SetHavaleYapilanMiktar(const Value: Double);
begin
     fHavaleYapilanMiktar := Value;
end;
Bunlar nesnemizde yer alan değişkenlere değer atamak ve değerlerini okumak için gerekli olan kodlar.

HavaleYap metodunu yazarken eksik olan bir şey farkttim. HavaleYap metodu sonuçta kendisine gelen verileri kullanarak bi Sql ifadesi oluşturup bunu veritabanına gönderecekti ama nesnenin veritabanı ile iletişim kurması için her hangi bir özelliği yoktu. Bu nedenle nesnemizin özelliklerine Veritabanı adında bir alan eklemeye karar verdim. Veritabanı olarakta Firebird / IBX kullandığımdan bu alanın tipini TIBDatabase olarak ayarladım.

Kod: Tümünü seç

type
  THavale = class
  private
    fHavaleYapanCariID   :Integer;
    fHavaleYapilanCariID :Integer;
    fHavaleYapilanMiktar :Double;
    fIBDatabase :TIBDatabase; //
    ...
    ...
    ...   
    function  GetVeritabani: TIBDatabase;
    procedure SetVeritabani(const Value: TIBDatabase);
  public
  ...
  ...
  ...
  property  Veritabani          : TIBDatabase  read GetVeritabani write SetVeritabani;
  end;

  ...
  ...

function THavale.GetVeritabani: TIBDatabase;
begin
  Result :=fIBDatabase;
end;

procedure THavale.SetVeritabani(const Value: TIBDatabase);
begin
     fIBDatabase := Value;
end;
Nesnemizde eksik olan bir şey daha var. Sql ifadelerini çalıştıracak bir nesne. Bunun için nesnemize birde TIBSql nesnesi ekliyorum.

Kod: Tümünü seç

type
  THavale = class
  private
    fHavaleYapanCariID   :Integer;
    fHavaleYapilanCariID :Integer;
    fHavaleYapilanMiktar :Double;
    fIBDatabase :TIBDatabase;
    fIbSql : TIBSQL; //
   ...
   ...
Şimdi HavaleYap metodunu yazabilirim.

Kod: Tümünü seç

procedure THavale.HavaleYap;
begin

 IBSqlOlustur;

 if fibsql.Transaction.InTransaction = False Then
    fibsql.Transaction.StartTransaction;
try
 try

   fibsql.Close;
   fibsql.SQL.Clear;
   fibsql.SQL.Add('Update CARI set BAKIYE = BAKIYE + :P_BAKIYE' );
   fibsql.SQL.Add('Where ID = :P_CARIID');
   fibsql.Params[0].AsFloat   := HavaleYapilanMiktar;
   fibsql.Params[1].AsInteger := HavaleYapilanCariID;
   fibsql.ExecQuery;

   fibsql.Close;
   fibsql.SQL.Clear;
   fibsql.SQL.Add('Update CARI set BAKIYE = BAKIYE - :P_BAKIYE');
   fibsql.SQL.Add('Where ID = :P_CARIID');
   fibsql.Params[0].AsFloat   := HavaleYapilanMiktar;
   fibsql.Params[1].AsInteger := HavaleYapanCariID;
   fibsql.ExecQuery;

   fibsql.Transaction.CommitRetaining;

 except
   fibsql.Transaction.RollbackRetaining;
   Raise Exception.Create('Dikkat!!! Havale işlemi başarılı olamadı...');
 end;

finally
 IBSqlYokEt;
end;

end;


procedure THavale.IBSqlOlustur;
begin

 if not Assigned(fIBDatabase) Then
   Raise Exception.Create('Bağlanılacak Veritabanı bulunamadı. İşlem iptal ediliyor !!!');

  if Assigned(fibsql) Then Exit;

  fIbSql := TIBSQL.Create(nil);
  fIbSql.Database := Veritabani;
  fIbSql.Transaction := Veritabani.DefaultTransaction;
end;

procedure THavale.IBSqlYokEt;
begin
   FreeAndNil(fibsql);
end;

Nesnemiz tamam gibi. Şimdi bu uniti UnitHavale.pas olarak kaydedelim ve yeni bir proje açıp projemize ekleyelim. İlk önce programın kullanıcı arabirimini yapalım ve veritabanına bağlanmak için gerekli bileşenleri forma bırakalım.

Form1.dfm

Kod: Tümünü seç

object Form1: TForm1
  Left = 256
  Top = 248
  Width = 382
  Height = 212
  Caption = 'Havale'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 32
    Top = 22
    Width = 93
    Height = 13
    Caption = 'Havale Yapan Kişi :'
  end
  object Label2: TLabel
    Left = 28
    Top = 52
    Width = 97
    Height = 13
    Caption = 'Havale Yapılan Kişi :'
  end
  object Label3: TLabel
    Left = 3
    Top = 84
    Width = 122
    Height = 13
    Caption = 'Havale Yapılacak Miktar :'
  end
  object btnHavaleYap: TButton
    Left = 214
    Top = 112
    Width = 147
    Height = 25
    Caption = 'Havale Yap'
    TabOrder = 0
    OnClick = btnHavaleYapClick
  end
  object DBLookupComboBox1: TDBLookupComboBox
    Left = 136
    Top = 18
    Width = 225
    Height = 21
    KeyField = 'ID'
    ListField = 'AD;SOYAD'
    ListSource = DataSource1
    TabOrder = 1
  end
  object DBLookupComboBox2: TDBLookupComboBox
    Left = 136
    Top = 48
    Width = 225
    Height = 21
    KeyField = 'ID'
    ListField = 'AD;SOYAD'
    ListSource = DataSource1
    TabOrder = 2
  end
  object Edit1: TEdit
    Left = 136
    Top = 80
    Width = 225
    Height = 21
    TabOrder = 3
  end
  object IBDatabase1: TIBDatabase
    Connected = True
    DatabaseName = 'F:\Developers\Delphi\Samples\OOP\Ornek1\DATA2.GDB'
    Params.Strings = (
      'user_name=sysdba'
      'password=masterkey'
      'lc_ctype=WIN1254')
    LoginPrompt = False
    DefaultTransaction = IBTransaction1
    Left = 8
    Top = 144
  end
  object IBTransaction1: TIBTransaction
    Active = True
    DefaultDatabase = IBDatabase1
    Params.Strings = (
      'read_committed'
      'rec_version'
      'nowait')
    Left = 40
    Top = 144
  end
  object IBDataSet1: TIBDataSet
    Database = IBDatabase1
    Transaction = IBTransaction1
    SelectSQL.Strings = (
      'select * from CARI')
    Active = True
    Left = 72
    Top = 144
    object IBDataSet1ID: TIntegerField
      FieldName = 'ID'
      Origin = '"CARI"."ID"'
      ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
      Required = True
    end
    object IBDataSet1AD: TIBStringField
      FieldName = 'AD'
      Origin = '"CARI"."AD"'
    end
    object IBDataSet1SOYAD: TIBStringField
      FieldName = 'SOYAD'
      Origin = '"CARI"."SOYAD"'
    end
    object IBDataSet1BAKIYE: TIBBCDField
      FieldName = 'BAKIYE'
      Origin = '"CARI"."BAKIYE"'
      Precision = 18
      Size = 2
    end
  end
  object DataSource1: TDataSource
    DataSet = IBDataSet1
    Left = 104
    Top = 144
  end
end

Bu da kullandığımız tablo...

Kod: Tümünü seç

CREATE TABLE CARI (
    ID      INTEGER NOT NULL,
    AD      VARCHAR(20) COLLATE PXW_TURK,
    SOYAD   VARCHAR(20) COLLATE PXW_TURK,
    BAKIYE  NUMERIC(15,2)
);

Form üstünde 2 adet DBLookupComboBox var. Bunların yardımıyla sırasyıla havale yapan ve yapılan kişileri listeden seçebileceğiz. Hemen alttaki edit bileşenine de yapmak istediğimiz havale miktarını girip düğmemize tıkladığımızda devreye nesnemiz girecek ve havale işlemini gerçekleştirecektir.

Kod: Tümünü seç

procedure TForm1.btnHavaleYapClick(Sender: TObject);
var
Havale :THavale;
begin

Havale :=THavale.Create;
try
 Havale.Veritabani :=IBDatabase1;
 Havale.HavaleYapanCariID :=DBLookupComboBox1.KeyValue;
 Havale.HavaleYapilanCariID :=DBLookupComboBox2.KeyValue;
 Havale.HavaleYapilanMiktar :=StrToFloat(edit1.Text);
 Havale.HavaleYap;
 ShowMessage('Havale Başarılı');
finally
 FreeAndNil(Havale);
end;

end;
işte bu kadar ...

Kendi oluşturduğumuz nesneyi kullanmadan bu işi nasıl yapardık ?

Kod: Tümünü seç

procedure TForm1.btnHavaleYapClick(Sender: TObject);
begin
 if IBSQL1.Transaction.InTransaction = False Then
    IBSQL1.Transaction.StartTransaction;
 try

   IBSQL1.Close;
   IBSQL1.SQL.Clear;
   IBSQL1.SQL.Add('Update CARI set BAKIYE = BAKIYE + :P_BAKIYE' );
   IBSQL1.SQL.Add('Where ID = :P_CARIID');
   IBSQL1.Params[0].AsFloat   := strtofloat(Edit1.Text);
   IBSQL1.Params[1].AsInteger := DBLookupComboBox1.KeyValue;
   IBSQL1.ExecQuery;


   IBSQL1.Close;
   IBSQL1.SQL.Clear;
   IBSQL1.SQL.Add('Update CARI set BAKIYE = BAKIYE - :P_BAKIYE');
   IBSQL1.SQL.Add('Where ID = :P_CARIID');
   IBSQL1.Params[0].AsFloat   := strtofloat(Edit1.Text);
   IBSQL1.Params[1].AsInteger := DBLookupComboBox2.KeyValue;
   IBSQL1.ExecQuery;

   IBSQL1.Transaction.CommitRetaining;

 except
   IBSQL1.Transaction.RollbackRetaining;
   Raise Exception.Create('Dikkat!!! Havale işlemi başarılı olamadı...');
 end;
end;
HavaleYap metodunun nerdeyse aynısı. Peki böyle yapmak varken biz neden işi daha da uzattık ? Nesne tanımladık, nesnenin metodlarını yazdık daha sonra da bu nesneyi programdan kullandık.

İki -procedure TForm1.btnHavaleYapClick(Sender: TObject); - metodu bi karşılaştıralım.

:arrow: Hangisi daha basit ve anlaşılır :?:
:arrow: Hangisi daha okunaklı :?:
:arrow: Hangisi daha az hata yapmanıza neden olabilecek bir kod :?:
:arrow: Hangisi değişikliklere daha çabuk ve hatasız adapte olabilir :?:
:arrow: Hangi kodu DUnit ile test etme imkanınız var :?:
:arrow: Hangi kodu hiç korkmadan başka bir programda veya aynı programın farklı yerlerinde rahatlıkla kullanabilirsiniz :?:
:arrow: Hangi kodda -Bu örnek için komik gelsede- havale gibi bir işlemde acemi bir programcının Update CARI set BAKIYE = BAKIYE * HAVALEMIKTARI gibi bir kod yazmasını engellersiniz:?:

Bu kadar sebep yetmez mi ? :elsalla:

-------------------------------------------
Günün birinde size dedilerki "Bakiyesi yeterli olmayan insanlar havale yapamazlar !". Ne yapacaksınız ?

Çok basit...

Nesnenin olduğu uniti açalım ve nesnenin private alanına

Kod: Tümünü seç

...
fIbQuery : TIBQuery; 
...
Function  HavaleYapacakKisininYeterliBakiyesiVarmi:Boolean;
...
alanlarını ekleyelim.

Kod: Tümünü seç

function THavale.HavaleYapacakKisininYeterliBakiyesiVarmi: Boolean;
begin
fIbQuery :=  TIBQuery.Create(nil);
try
  Result := False;
  fIbQuery.Database    := fIBDatabase;
  fIbQuery.Transaction := fIBDatabase.DefaultTransaction;
  fIbQuery.Close;
  fIbQuery.SQL.Clear;
  fIbQuery.SQL.Add('Select BAKIYE FROM CARI WHERE ID =' + IntToStr(HavaleYapanCariID));
  fIbQuery.Open;
  Result := fIbQuery.Fields[0].AsFloat - HavaleYapilanMiktar >= 0.00;
finally
 FreeAndNil(fIbQuery);
end;

end;
HavaleYap metodunu uygun şekilde değiştirelim.

Kod: Tümünü seç

procedure THavale.HavaleYap;
begin

 IBSqlOlustur;

 if HavaleYapacakKisininYeterliBakiyesiVarmi = False Then
   Raise Exception.Create('İşlem yapacak kişinin bakiyesi yeterli değil. İşlem iptal ediliyor !!!');

 if fibsql.Transaction.InTransaction = False Then
    fibsql.Transaction.StartTransaction;
...
...
Bu kadar. İsterseniz bu nesnenizi, programın 40.000 yerinde kullanın veya 40.000 programınızda bu nesneyi kullanın farketmez ....


------------------------------------
Yine bir gün size "Bundan sonra havale işlemlerinde havale yapan kişiden yaptığı havale miktarının % 1 'i işlem ücreti olarak kesilecek" dediler. Desinler mesele yok :D

Kod: Tümünü seç

  THavale = class
  private
    fHavaleYapanCariID   :Integer;
    fHavaleYapilanCariID :Integer;
    fHavaleUcreti : Double; //--> havale ücreti
    fHavaleYapilanMiktar :Double;
    fIBDatabase :TIBDatabase;
    fIbSql : TIBSQL;
    fIbQuery : TIBQuery;
    ...
    ...


procedure THavale.HavaleYap;
begin

   IBSqlOlustur;
   ...
   ...
   fibsql.ExecQuery;

   fHavaleUcreti := HavaleYapilanMiktar / 100; //--> ***
   fibsql.Close;
   fibsql.SQL.Clear;
   fibsql.SQL.Add('Update CARI set BAKIYE = BAKIYE - :P_BAKIYE');
   fibsql.SQL.Add('Where ID = :P_CARIID');
   fibsql.Params[0].AsFloat   := HavaleYapilanMiktar - fHavaleUcreti; //-->***
   fibsql.Params[1].AsInteger := HavaleYapanCariID;
   fibsql.ExecQuery;

  ...
  ...
Bol nesneli günler... :wink:

Not: Bu nesnenin Dunit kullanarak nasıl test edilebileceğini de en yakın zamanda buraya yazmaya çalışırım.


UnitHavale.pas

Kod: Tümünü seç


unit UnitHavale;

interface

uses
  SysUtils,IBDatabase,ibsql,IBQuery;

type
  THavale = class
  private
    fHavaleYapanCariID   :Integer;
    fHavaleYapilanCariID :Integer;
    fHavaleUcreti : Double;
    fHavaleYapilanMiktar :Double;
    fIBDatabase :TIBDatabase;
    fIbSql : TIBSQL;
    fIbQuery : TIBQuery;
    function  GetHavaleYapanCariID: Integer;
    procedure SetHavaleYapanCariID(const Value: Integer);
    function  GetHavaleYapilanCariID: Integer;
    procedure SetHavaleYapilanCariID(const Value: Integer);
    function  GetHavaleYapilanMiktar: Double;
    procedure SetHavaleYapilanMiktar(const Value: Double);
    Function  HavaleYapacakKisininYeterliBakiyesiVarmi:Boolean;
    function  GetVeritabani: TIBDatabase;
    procedure SetVeritabani(const Value: TIBDatabase);
    Procedure IBSqlOlustur;
    Procedure IBSqlYokEt;

  public
  Procedure HavaleYap;
  property  HavaleYapanCariID   : Integer read GetHavaleYapanCariID   write SetHavaleYapanCariID;
  property  HavaleYapilanCariID : Integer read GetHavaleYapilanCariID write SetHavaleYapilanCariID;
  property  HavaleYapilanMiktar : Double  read GetHavaleYapilanMiktar write SetHavaleYapilanMiktar;
  property  Veritabani          : TIBDatabase  read GetVeritabani write SetVeritabani;
  end;


implementation

{ THavale }

function THavale.GetHavaleYapanCariID: Integer;
begin
    Result := fHavaleYapanCariID;
end;

function THavale.GetHavaleYapilanCariID: Integer;
begin
  Result :=fHavaleYapilanCariID;
end;

function THavale.GetHavaleYapilanMiktar: Double;
begin
  Result := fHavaleYapilanMiktar;
end;


function THavale.GetVeritabani: TIBDatabase;
begin
  Result :=fIBDatabase;
end;

procedure THavale.HavaleYap;
begin

 IBSqlOlustur;

 if HavaleYapacakKisininYeterliBakiyesiVarmi = False Then
   Raise Exception.Create('İşlem yapacak kişinin bakiyesi yeterli değil. İşlem iptal ediliyor !!!');

 if fibsql.Transaction.InTransaction = False Then
    fibsql.Transaction.StartTransaction;
try
 try

   fibsql.Close;
   fibsql.SQL.Clear;
   fibsql.SQL.Add('Update CARI set BAKIYE = BAKIYE + :P_BAKIYE' );
   fibsql.SQL.Add('Where ID = :P_CARIID');
   fibsql.Params[0].AsFloat   := HavaleYapilanMiktar;
   fibsql.Params[1].AsInteger := HavaleYapilanCariID;
   fibsql.ExecQuery;

   fHavaleUcreti := HavaleYapilanMiktar / 100;
   fibsql.Close;
   fibsql.SQL.Clear;
   fibsql.SQL.Add('Update CARI set BAKIYE = BAKIYE - :P_BAKIYE');
   fibsql.SQL.Add('Where ID = :P_CARIID');
   fibsql.Params[0].AsFloat   := HavaleYapilanMiktar - fHavaleUcreti;
   fibsql.Params[1].AsInteger := HavaleYapanCariID;
   fibsql.ExecQuery;

   fibsql.Transaction.CommitRetaining;

 except
   fibsql.Transaction.RollbackRetaining;
   Raise Exception.Create('Dikkat!!! Havale işlemi başarılı olamadı...');
 end;

finally
 IBSqlYokEt;
end;

end;

function THavale.HavaleYapacakKisininYeterliBakiyesiVarmi: Boolean;
begin
fIbQuery :=  TIBQuery.Create(nil);
try
  Result := False;
  fIbQuery.Database    := fIBDatabase;
  fIbQuery.Transaction := fIBDatabase.DefaultTransaction;
  fIbQuery.Close;
  fIbQuery.SQL.Clear;
  fIbQuery.SQL.Add('Select BAKIYE FROM CARI WHERE ID =' + IntToStr(HavaleYapanCariID));
  fIbQuery.Open;
  Result := fIbQuery.Fields[0].AsFloat - HavaleYapilanMiktar >= 0.00;
finally
 FreeAndNil(fIbQuery);
end;

end;

procedure THavale.IBSqlOlustur;
begin

 if not Assigned(fIBDatabase) Then
   Raise Exception.Create('Bağlanılacak Veritabanı bulunamadı. İşlem iptal ediliyor !!!');

  if Assigned(fibsql) Then Exit;

  fIbSql := TIBSQL.Create(nil);
  fIbSql.Database := Veritabani;
  fIbSql.Transaction := Veritabani.DefaultTransaction;
end;

procedure THavale.IBSqlYokEt;
begin
   FreeAndNil(fibsql);
end;

procedure THavale.SetHavaleYapanCariID(const Value: Integer);
begin
  fHavaleYapanCariID := Value;
end;

procedure THavale.SetHavaleYapilanCariID(const Value: Integer);
begin
  fHavaleYapilanCariID := Value;
end;

procedure THavale.SetHavaleYapilanMiktar(const Value: Double);
begin
     fHavaleYapilanMiktar := Value;
end;


procedure THavale.SetVeritabani(const Value: TIBDatabase);
begin
     fIBDatabase := Value;
end;

end.

Unit1.pas

Kod: Tümünü seç

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DBCtrls, DB, IBCustomDataSet, IBDatabase, IBSQL,
  IBQuery;

type
  TForm1 = class(TForm)
    btnHavaleYap: TButton;
    Label1: TLabel;
    Label2: TLabel;
    DBLookupComboBox1: TDBLookupComboBox;
    DBLookupComboBox2: TDBLookupComboBox;
    Label3: TLabel;
    Edit1: TEdit;
    IBDatabase1: TIBDatabase;
    IBTransaction1: TIBTransaction;
    IBDataSet1: TIBDataSet;
    IBDataSet1ID: TIntegerField;
    IBDataSet1AD: TIBStringField;
    IBDataSet1SOYAD: TIBStringField;
    IBDataSet1BAKIYE: TIBBCDField;
    DataSource1: TDataSource;
    procedure FormCreate(Sender: TObject);
    procedure btnHavaleYapClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses UnitHavale;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
IBDataSet1.FetchAll;
end;

procedure TForm1.btnHavaleYapClick(Sender: TObject);
var
Havale :THavale;
begin

Havale :=THavale.Create;
try
 Havale.Veritabani :=IBDatabase1;
 Havale.HavaleYapanCariID :=DBLookupComboBox1.KeyValue;
 Havale.HavaleYapilanCariID :=DBLookupComboBox2.KeyValue;
 Havale.HavaleYapilanMiktar :=StrToFloat(edit1.Text);
 Havale.HavaleYap;
 ShowMessage('Havale Başarılı');
finally
 FreeAndNil(Havale);
end;

end;

end.

"Sevmek, ne zaman vazgececegini bilmektir." dedi, bana.

---
http://sadettinpolat.blogspot.com/
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Öncelikle çok güzel bir yazı olduğunu söylemek istedim. Devamı umarım gelir.

Ben bir öneride bulunmak istedim. Şu bölümde ve altında birer örnek ile sınıfa ekleme yapmışsın.
Günün birinde size dedilerki "Bakiyesi yeterli olmayan insanlar havale yapamazlar !". Ne yapacaksınız ?

Çok basit...
Bu bölümdeki örnekte "HavaleYap" method unu virtual tanımlayıp, THavale sınıfından yeni bir TBakiyesiYeterliOlmayanKontrolluHavale sınıfı türeterek,
şu kodu şu şekilde yazmamız OOP i tam anlamıyla kullanmamızı ve ata sınıfı bozmamamızı sağlardı.

Örnek:

Kod: Tümünü seç

type
  TBakiyesiYeterliOlmayanKontrolluHavale = class(THavale)
  private
    function THavale.HavaleYapacakKisininYeterliBakiyesiVarmi: Boolean; 
  public
    procedure HavaleYap; override;
  end;

procedure TBakiyesiYeterliOlmayanKontrolluHavale.HavaleYap;
begin
    if HavaleYapacakKisininYeterliBakiyesiVarmi = False Then
      raise Exception.Create('İşlem yapacak kişinin bakiyesi yeterli değil. İşlem iptal ediliyor !!!')
    else
      inherited HavaleYap;
end;
İyi çalışmalar.
Kullanıcı avatarı
husonet
Admin
Mesajlar: 2962
Kayıt: 25 Haz 2003 02:14
Konum: İstanbul
İletişim:

Mesaj gönderen husonet »

Elinize sağlık güzel olmuş devamını bekleriz.

Gazete manşetleri
* DİKKAT :Lütfen forum kurallarını okuyalım ve uyalım...!
* Warez,crack vs. paylaşımı kesinlikle yasaktır.
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

Merhaba,

Hocam makale gerçekten güzel, elinize sağlık. Ben nacizane bir fikrimi belirtmek istiyorum:
Hangi kodda -Bu örnek için komik gelsede- havale gibi bir işlemde acemi bir programcının Update CARI set BAKIYE = BAKIYE * HAVALEMIKTARI gibi bir kod yazmasını engellersiniz:?:
Hocam acemi programcı arkadaşımız :) farkında olmadan kodunu şu şekilde yazarsa :

Kod: Tümünü seç

Havale :=THavale.Create;
try
 Havale.Veritabani :=IBDatabase1; // bunu yazmayı unutursa
 Havale.HavaleYapanCariID :=DBLookupComboBox1.KeyValue;
 Havale.HavaleYapilanCariID :=DBLookupComboBox2.KeyValue;
 Havale.HavaleYapilanMiktar :=StrToFloat(edit1.Text);
 Havale.HavaleYap;
 ShowMessage('Havale Başarılı');
finally
 Havale.Veritabani.Free; // yanlışlıkla bunu da eklerse
 FreeAndNil(Havale);
end; 
her şeyi mahveder.

Bu gibi olası hataları önlemek için class tanımlanırken Veritabanı property'sini kaldırıp onun yerine fIBDatabase atamasını constructor içine taşımak daha sağlıklı olur diye düşünüyorum.

Kod: Tümünü seç

constructor THavale.Create(const AIBDatabase : TIBDatabase);
begin
  // AIBDatabase'in nil olmadığının kontrolü yapıldıkktan sonra
  fIBDatabase := AIBDatabase;
end;
dolayısıyla nesne yaratılırken IBDatabase atamasının kesinlikle yapılmış olmasını sağlamış ve fibdatabase nesnesinin yanlışlıkla yokedilmesini de engellemiş oluruz.
Kullanıcı avatarı
sadettinpolat
Moderator
Mesajlar: 2131
Kayıt: 07 Ara 2003 02:51
Konum: Ankara
İletişim:

Mesaj gönderen sadettinpolat »

coderlord yazdı:.
Ben bir öneride bulunmak istedim. Şu bölümde ve altında birer örnek ile sınıfa ekleme yapmışsın.
t-hex yazdı:.
Ben nacizane bir fikrimi belirtmek istiyorum:
aslına bakarsanız nesne de daha bir çok tasarım hataları var. :shock:

Ben sadece belirli bir konuya dikkat çekmek istediğimden dolayı aklıma ilk gelen örneği çok fazla düşünmeden burda belirttim. Daha sonradan farkettiğim hata ise

Kod: Tümünü seç

procedure THavale.IBSqlOlustur; 
metodunda.

Formda 2 adet TIBDatabase bileşin olduğunu düşünürsek ve nesne ilk çalıştığında

Kod: Tümünü seç

Havale.Veritabani :=IBDatabase1; 
bu şekilde bir atama yaptığımızı düşünelim.

Ardından nesnemizi yok etmeden bu sefer aynı işlemi bir de diğer veritabanına uygulamak için aşağıdaki kodu yazdığımızı düşünelim.

Kod: Tümünü seç

Havale.Veritabani :=IBDatabase2; 
Bu durumda Havale nesnesi değişikliği hangi veritabanında yapar ?

Kod: Tümünü seç

procedure THavale.IBSqlOlustur;
begin

 if not Assigned(fIBDatabase) Then
   Raise Exception.Create('Bağlanılacak Veritabanı bulunamadı. İşlem iptal ediliyor !!!');

// fIBDatabase (IBDatabase2) geçerli bir nesne olduğu için bu satırda sorun çıkmaz

  if Assigned(fibsql) Then Exit;

// fibsql geçerli bir nesne olduğu için bu satırda ki exit 
//devreye girer ve aşağıdaki kodlar çalıştırılmaz !!!
//ve fibsql'in bağlı olduğu veritabanı hala IBDatabase1 olarak kalır

  fIbSql := TIBSQL.Create(nil);
  fIbSql.Database := Veritabani;
  fIbSql.Transaction := Veritabani.DefaultTransaction;
end; 
Bu felaket bir hata :) Belki şöyle derinlemesine incelersek daha bir çok hata bulabiliriz ama zamanla hata yapmamasını da öğreniriz. Birde bu nesnemiz için uygun birim tesltlerini yazdığımız zaman hata yaparsak bile çok kısa bir sürede bu hataları yakalayabiliriz.

Aslında burda nesneye dayalı programlamanın avantajlarını görüyoruz. İçerisinde barındırdığı tasarım hatalarını ve yanlışlıkları çok kolay bir şekilde fark edebiliyoruz. Önemli olan da bu değil midir ? :)
"Sevmek, ne zaman vazgececegini bilmektir." dedi, bana.

---
http://sadettinpolat.blogspot.com/
oguzozturk74
Kıdemli Üye
Mesajlar: 574
Kayıt: 01 Şub 2004 12:29
Konum: Erdemli - MERSİN

Mesaj gönderen oguzozturk74 »

Hocam teşekkürler , Allah razı olsun.
Cevapla