Delphi Can

Orjinalini görmek için tıklayınız: OOP Üzerine
Şu anda (Arşiv) modunu görüntülemektesiniz. Orjinal Sürümü Görüntüle internal link
Sayfalar: 1 2 3 4 5
Lvz1pz.png

Herkese selam

Gördüğünüz üzere bir gözlük reçetesini fiyatlandırıyorum, zemin rengi açık olan kısımlara bakarak, siyahlarda sonuç döndürüyorum. 10 yıllar önce değişkenlerle yaptığım bu işi zevkine sıfırdan yazıyorum, Record larla çok daha mantıklı hale getirdim yalnız, 40 yaşından sonra tavşan deliğine girmeye karar verdim. Bu yapıyı tamamen OOP haline getirmek istiyorum ve ilk tecrübem olacak. ŞİMDİ

1- TRecete isimli 1 Class mı (Tüm property ve functionlar aynı Class ta)

2- THastaBilgileri, TGozluk (Uzak Gözlük Bedeli - Yakın Gözlük Bedeli) 2 Class mı

3- THastaBilgileri, TCam (UzakR-UzakL-YakinR-YakinL),  TCerceve (UzakCer-YakinCer) gibi 3 Class mı

4- Başka bir şey

Aklıma gelen dizaynlar bunlar  ve muhtemelen 4.şık doğru Smile  OOP mantığında neyi öncelemeliyim, okunabilirlik, daha az kod, modülerlik vs vs.  Mümkün olduğunca küçük parçalara ayırmak avantaj mı angarya mı, siz olsaydınız tasarımı nasıl yapardınız? Tecrübelerinizi ve değerli yorumlarınızı bu basit örnek üzerinden (mümkünse nedenleri ile) paylaşırsanız sevinirim.
OOP'de kazanılmaya çalışılan asli fayda, bugün yazdığınız kodu 5-10 sene sonra da alıp rahatça kullanabilmenizi sağlamaktır. Modülerlik, 

Sadece bu parametreler ile çalışacaksanız kurguladığınız nesne yapısında göze batan bir şey gözükmüyor. Fakat ben olsam Ad, Soyad, TC No gibi bilgileri başka yerlerde de kullanacağım için ilk baştan bunu bu nesneden ayırır, nesnenin bir property'sine dönüştürürdüm...

Dolayısıyla bu örnekte ben sadece tek bir sınıf tanımı değil, birden çok sınıfın birleşimi bir nesne yapısı görüyorum. İnsanlar için (müşteriler veya doktorlar, fark etmez) bir nesne, hastalıklar için bir nesne, "GÖZLER" (veya organlar) için bir nesne, gözlükler için bir nesne, dereceler için bir nesne ve çerçeveler için başka bir nesne görüyorum.

Bu noktada "Over Design" denen "aşırı tasarım" durumu da olabiliyor. Detayları ne kadar abarttığınız ile ilgili bir durum. Bunlardan da kaçınmak gerekir.

Angarya konusuna gelecek olursak. Bu işinizi ne kadar ciddiye aldığınızla alakalı bir durum. Gereksiz görüyorsanız cevap basit, angarya... Ama bir de şöyle bakın. Siz yukarıda tarif ettiğim gibi kişileri de ayrı bir sınıf yaptığınız diyelim. İleride kişiler ile ilgili bir geliştirme istendiğinde bu nesne o değişiklikten etkilenmeden çalışmasına devam edebilecek. İşte bugün angarya olarak nitelendirilen şey, yarın size çok büyük bir rahatlık kazandıracak, bunları görmek lazım...
(13-11-2019, Saat: 12:25)uparlayan Adlı Kullanıcıdan Alıntı: [ -> ]OOP'de kazanılmaya çalışılan asli fayda, bugün yazdığınız kodu 5-10 sene sonra da alıp rahatça kullanabilmenizi sağlamaktır. Modülerlik, 

Sadece bu parametreler ile çalışacaksanız kurguladığınız nesne yapısında göze batan bir şey gözükmüyor. Fakat ben olsam Ad, Soyad, TC No gibi bilgileri başka yerlerde de kullanacağım için ilk baştan bunu bu nesneden ayırır, nesnenin bir property'sine dönüştürürdüm...

Dolayısıyla bu örnekte ben sadece tek bir sınıf tanımı değil, birden çok sınıfın birleşimi bir nesne yapısı görüyorum. İnsanlar için (müşteriler veya doktorlar, fark etmez) bir nesne, hastalıklar için bir nesne, "GÖZLER" (veya organlar) için bir nesne, gözlükler için bir nesne, dereceler için bir nesne ve çerçeveler için başka bir nesne görüyorum.

Bu noktada "Over Design" denen "aşırı tasarım" durumu da olabiliyor. Detayları ne kadar abarttığınız ile ilgili bir durum. Bunlardan da kaçınmak gerekir.

Angarya konusuna gelecek olursak. Bu işinizi ne kadar ciddiye aldığınızla alakalı bir durum. Gereksiz görüyorsanız cevap basit, angarya... Ama bir de şöyle bakın. Siz yukarıda tarif ettiğim gibi kişileri de ayrı bir sınıf yaptığınız diyelim. İleride kişiler ile ilgili bir geliştirme istendiğinde bu nesne o değişiklikten etkilenmeden çalışmasına devam edebilecek. İşte bugün angarya olarak nitelendirilen şey, yarın size çok büyük bir rahatlık kazandıracak, bunları görmek lazım...

Uğur Bey, "göze batan bir şey görünmüyor" demişsiniz hangi şıkkı kastettiğinizi anlamadım ama açıklamalarınızdan 3 Class lı 3.şıkkı tavsiye ettiğinizi anlıyorum, hatta mümkünse aşırıya kaçmadan daha da parçalara ayırmak en doğrusu...
Esasen bir sistemi sınıflandırıp farklı sınıflar oluşturma çabası, farklı tablolar oluşturma çabasıyla benzer şeyler. Özellikle bu örnekte Entity'leri yani veri kayıt sistemini oluşturuyorken bu daha da belirgin. Bu şekilde bakınca, bunları hangi tablolarda, nasıl tutacağım diye sorduğumuzda ayrımlar daha belirginleşiyor.
1-Bir defa HASTA bilgileri için bir sınıf-tablo oluşturmamız gerekli.
2-Her hasta birden fazla reçete sahibi olabileceği için bir REÇETE sınıfı-tablosu gerekli ve bunun HASTA sınıfıyla ilişkilendirilmesi gerekiyor.
3-Reçetenin içeriği sabit mi diye soruyoruz (yani kalem sayısı ya da satır sayısı sabit mi), sabitse ayrı bir sınıf-tablo açmaya gerek yok. Bunları reçete sınıfında tutabiliriz. Değilse bir de REÇETE DETAY sınıfı-tablosu oluşturup bunu REÇETE ile ilişkilendirmek gerekli.
4-Doktor bilgisi bizim için ayrıca gerekli mi, gerekliyse bir DOKTOR sınıfı-tablosu oluşturmak gerekir değilse doktor adını yine REÇETE sınıfında tutmak yeterlidir.
5-Çerçeve bilgisinin (özellikle markası fiyatı gibi) ayrı bir sınıf-tabloda tutulması gerekebilir.
6-Gözlük camı bilgilerinin (yine marka, fiyat, numara vb. gibi) de bir sınıf-tablo olarak tutulması gereklidir.
(13-11-2019, Saat: 13:04)Hayati Adlı Kullanıcıdan Alıntı: [ -> ]
(13-11-2019, Saat: 12:25)uparlayan Adlı Kullanıcıdan Alıntı: [ -> ]OOP'de kazanılmaya çalışılan asli fayda, bugün yazdığınız kodu 5-10 sene sonra da alıp rahatça kullanabilmenizi sağlamaktır. Modülerlik, 

Sadece bu parametreler ile çalışacaksanız kurguladığınız nesne yapısında göze batan bir şey gözükmüyor. Fakat ben olsam Ad, Soyad, TC No gibi bilgileri başka yerlerde de kullanacağım için ilk baştan bunu bu nesneden ayırır, nesnenin bir property'sine dönüştürürdüm...

Dolayısıyla bu örnekte ben sadece tek bir sınıf tanımı değil, birden çok sınıfın birleşimi bir nesne yapısı görüyorum. İnsanlar için (müşteriler veya doktorlar, fark etmez) bir nesne, hastalıklar için bir nesne, "GÖZLER" (veya organlar) için bir nesne, gözlükler için bir nesne, dereceler için bir nesne ve çerçeveler için başka bir nesne görüyorum.

Bu noktada "Over Design" denen "aşırı tasarım" durumu da olabiliyor. Detayları ne kadar abarttığınız ile ilgili bir durum. Bunlardan da kaçınmak gerekir.

Angarya konusuna gelecek olursak. Bu işinizi ne kadar ciddiye aldığınızla alakalı bir durum. Gereksiz görüyorsanız cevap basit, angarya... Ama bir de şöyle bakın. Siz yukarıda tarif ettiğim gibi kişileri de ayrı bir sınıf yaptığınız diyelim. İleride kişiler ile ilgili bir geliştirme istendiğinde bu nesne o değişiklikten etkilenmeden çalışmasına devam edebilecek. İşte bugün angarya olarak nitelendirilen şey, yarın size çok büyük bir rahatlık kazandıracak, bunları görmek lazım...

Uğur Bey, "göze batan bir şey görünmüyor" demişsiniz hangi şıkkı kastettiğinizi anlamadım ama açıklamalarınızdan 3 Class lı 3.şıkkı tavsiye ettiğinizi anlıyorum, hatta mümkünse aşırıya kaçmadan daha da parçalara ayırmak en doğrusu...


@Hayati Bey Smile 

Siz bir otoban arayışındasınız, fakat ben farklı bir şey söylüyorum. İlla taksiye binmenize gerek yok, helikopter de bir seçenek...

Mesela @mustafaozpinar Bey de aslında benim dediklerime uygun önerilerde bulunmuş, dolayısıyla sözünü ettiğiniz 3. maddeyle kendinizi kısıtlamayın. Biz esasen "4" diyoruz...
Sizin için bir "taslak" hazırladım. İlla böyle olacak değil fakat sizin için güzel bir başlangıç olabilir;

CAM Nesnesi için;
unit Cam_;

interface

type
  TCamTipi      = (Organik, Duz);
  TCamRengi     = (Colormatik, Beyaz);
  TCamDurum     = (OK, AYNI);
  TCam = class
    private
      FCamTipi  : TCamTipi;
      FCamRengi : TCamRengi;
      FSPH      : Double;
      FCYL      : Double;
      FAX       : Double;
      FGrup     : String;
      FDurum    : TCamDurum;
    function GetFiyat: Currency;
    protected
    public
      property CamTipi  : TCamTipi  read FCamTipi   write FCamTipi;
      property CamRengi : TCamRengi read FCamRengi  write FCamRengi;
      property SPH      : Double    read FSPH       write FSPH;
      property CYL      : Double    read FCYL       write FCYL;
      property AX       : Double    read FAX        write FAX;
      property Grup     : String    read FGrup      write FGrup;
      property Durum    : TCamDurum read FDurum     write FDurum;
      property Fiyat    : Currency  read GetFiyat;
  end;

implementation

{ TCam }

function TCam.GetFiyat: Currency;
begin
  Result := 0;
  if  (FDurum = AYNI) then Result := 0
  else begin
       //  Bu noktaya kendi hesaplama formülünüzü uygulayın...
       Result := 7;
  end;
end;

end.

ÇERÇEVE Nesnesi için;

unit Cerceve_;

interface

type
  TCerceveTipi  = (Yerli, Ithal);
  TCerceve = class
    private
      FCerceve  : TCerceveTipi;
      FHakTarihi: TDateTime;
      function GetFiyat: Currency;
      function GetHakSahibi: Boolean;
    protected
    public
      property Cerceve  : TCerceveTipi  read FCerceve   write FCerceve;
      property HakSahibi: Boolean       read GetHakSahibi;
      property HakTarihi: TDateTime     read FHakTarihi write FHakTarihi;
      property Fiyat    : Currency      read GetFiyat;
  end;

implementation

uses
    System.SysUtils
  ;

{ TCerrceve }

function TCerceve.GetHakSahibi: Boolean;
begin
  Result := (FHakTarihi <= Now);
end;

function TCerceve.GetFiyat: Currency;
begin
  if  (HakSahibi = True)
  then Result := 0
  else begin
       //  Bu noktaya kendi hesaplama formülünüzü uygulayın...
       Result := 35; // veya 40...
  end;
end;

end.

KİŞİ, HASTA, DOKTOR gibi nesneler için;

unit Kisi_;

interface

uses
    Cam_
  ;

type
  TSigortaTipi    = (Calisan, Emekli, Muaf);
  TSigortaKapsam  = (YesilKart, _4C);
  TKisiKagetori   = (Doktor, Hasta);
  TKisi           = class
    private
      FAd         : String;
      FSoyad      : String;
      FTCNo       : String;
      FKategori   : TKisiKagetori;
    protected
    public
      property Ad         : String        read FAd          write FAd;
      property Soyad      : String        read FSoyad       write FSoyad;
      property TCNo       : String        read FTCNo        write FTCNo;
      property Kategori   : TKisiKagetori read FKategori    write FKategori;
  end;

  THasta          = class(TKisi)
    private
      FSigortaTipi: TSigortaTipi;
      FKapsam     : TSigortaKapsam;
    protected
    public
      property SigortaTipi: TSigortaTipi    read  FSigortaTipi  write FSigortaTipi;
      property Kapsam     : TSigortaKapsam  read  FKapsam       write FKapsam;
  end;

  TDoktor = class(TKisi)
    private
      FDiplomaNo: Integer;
    protected
    public
      property DiplomaNo: Integer read FDiplomaNo write FDiplomaNo;
  end;

implementation

{ TKisi }

end.

REÇETE Nesnesi için;

unit Recete_;

interface

uses
    Kisi_
  , Cam_
  , Cerceve_
  ;

type
  TRecete = class
    type
      TSonuc = class
        private
          Owner: TRecete;
        public
          constructor Create(aOwner: TRecete);
          function CamTutar     : Currency;
          function CerceveTutari: Currency;
          function Toplam       : Currency;
          function KatilimPayi  : Currency;
          function ReceteTutari : Currency;
      end;
    private
      FHasta        : THasta;
      FDoktor       : TDoktor;
      FUzakDerece   : TCam;
      FYakinDerece  : TCam;
      FYakinCerceve : TCerceve;
      FUzakCerceve  : TCerceve;
      FTesisAdi     : String;
      FTesisKodu    : String;
      FReceteTarihi : TDateTime;
      FKatilimOrani : Integer;
      FSonuc        : TSonuc;
    protected
    public
      Constructor Create;
      Destructor Destroy; override;
      property Hasta        : THasta    read FHasta         write FHasta;
      property Doktor       : TDoktor   read FDoktor        write FDoktor;
      property UzakDerece   : TCam      read FUzakDerece    write FUzakDerece;
      property YakinDerece  : TCam      read FYakinDerece   write FYakinDerece;
      property UzakCerceve  : TCerceve  read FUzakCerceve   write FUzakCerceve;
      property YakinCerceve : TCerceve  read FYakinCerceve  write FYakinCerceve;
      property TesisAdi     : String    read FTesisAdi      write FTesisAdi;
      property TesisKodu    : String    read FTesisKodu     write FTesisKodu;
      property ReceteTarihi : TDateTime read FReceteTarihi  write FReceteTarihi;
      property KatilimOrani : Integer   read FKatilimOrani  write FKatilimOrani;
      property Sonuc        : TSonuc    read FSonuc         write FSonuc;
  end;

implementation

uses
    System.SysUtils
  ;

{ TRecete }

destructor TRecete.Destroy;
begin
  FreeAndNil(FHasta        );
  FreeAndNil(FDoktor       );
  FreeAndNil(FUzakDerece   );
  FreeAndNil(FYakinDerece  );
  FreeAndNil(FYakinCerceve );
  FreeAndNil(FUzakCerceve  );
  FreeAndNil(FSonuc        );
  inherited;
end;

constructor TRecete.Create;
begin
  FHasta        := THasta.Create;
  FDoktor       := TDoktor.Create;
  FUzakDerece   := TCam.Create;
  FYakinDerece  := TCam.Create;
  FYakinCerceve := TCerceve.Create;
  FUzakCerceve  := TCerceve.Create;
  FSonuc        := TSonuc.Create(Self);
end;

{ TRecete.TSonuc }

constructor TRecete.TSonuc.Create(aOwner: TRecete);
begin
  inherited Create;
  Owner := aOwner;
end;

function TRecete.TSonuc.CamTutar: Currency;
begin
  Result := Owner.UzakDerece.Fiyat
          + Owner.YakinDerece.Fiyat
          ;
end;

function TRecete.TSonuc.CerceveTutari: Currency;
begin
  Result := Owner.UzakCerceve.Fiyat
          + Owner.YakinCerceve.Fiyat
          ;
end;

function TRecete.TSonuc.Toplam: Currency;
begin
  Result := Self.CamTutar
          + Self.CerceveTutari
          ;
end;

function TRecete.TSonuc.KatilimPayi: Currency;
begin
  Result := Self.Toplam * (Owner.KatilimOrani * 0.01); // " X / 100 "
end;

function TRecete.TSonuc.ReceteTutari: Currency;
begin
  Result := Self.Toplam
          - Self.KatilimPayi
          ;
end;

end.
(13-11-2019, Saat: 13:38)mustafaozpinar Adlı Kullanıcıdan Alıntı: [ -> ]Esasen bir sistemi sınıflandırıp farklı sınıflar oluşturma çabası, farklı tablolar oluşturma çabasıyla benzer şeyler. Özellikle bu örnekte Entity'leri yani veri kayıt sistemini oluşturuyorken bu daha da belirgin. Bu şekilde bakınca, bunları hangi tablolarda, nasıl tutacağım diye sorduğumuzda ayrımlar daha belirginleşiyor.
1-Bir defa HASTA bilgileri için bir sınıf-tablo oluşturmamız gerekli.
2-Her hasta birden fazla reçete sahibi olabileceği için bir REÇETE sınıfı-tablosu gerekli ve bunun HASTA sınıfıyla ilişkilendirilmesi gerekiyor.
3-Reçetenin içeriği sabit mi diye soruyoruz (yani kalem sayısı ya da satır sayısı sabit mi), sabitse ayrı bir sınıf-tablo açmaya gerek yok. Bunları reçete sınıfında tutabiliriz. Değilse bir de REÇETE DETAY sınıfı-tablosu oluşturup bunu REÇETE ile ilişkilendirmek gerekli.
4-Doktor bilgisi bizim için ayrıca gerekli mi, gerekliyse bir DOKTOR sınıfı-tablosu oluşturmak gerekir değilse doktor adını yine REÇETE sınıfında tutmak yeterlidir.
5-Çerçeve bilgisinin (özellikle markası fiyatı gibi) ayrı bir sınıf-tabloda tutulması gerekebilir.
6-Gözlük camı bilgilerinin (yine marka, fiyat, numara vb. gibi) de bir sınıf-tablo olarak tutulması gereklidir.

Mustafa Bey değerli tavsiyeleriniz için teşekkür ederim, tablo örneği güzeldi.

Uğur Bey, Uğur Üstad... Kodlara bilerek bakmadım, akşam sindire sindire evde inceleyeceğim, çok teşekkür ediyorum.
Formülleri ve yapıyı tam olarak bilmeden yorum yapmak biraz zor aslında. Dikkat edilmesi gereken ilerde bir değişiklik ya da yeni bir ekleme olduğunda sistemin bundan en az şekilde etkilenmesini sağlamak olmalı.

Yeni bir cam ya da çerçeve sisteme eklenmesi gerektiğinde bunun en az çaba ile sisteme başarılı bir şekilde ekleyebilmelisiniz. Bu tür senaryolar hangi sıklıkla yaşanabilir şahsen benim çok bilgim olmadığı için çok net bir yorum yapamıyorum.
(13-11-2019, Saat: 15:10)uparlayan Adlı Kullanıcıdan Alıntı: [ -> ]Sizin için bir "taslak" hazırladım. İlla böyle olacak değil fakat sizin için güzel bir başlangıç olabilir;

CAM Nesnesi için;
unit Cam_;

interface

.....

@uparlayan hocam bu sınıfları ayrı unitler içinde değilde tek unit içinde kullansak biraz kod kalabalığı olur ama ayrı kullanmanın extra bir faydası olurmu?
(13-11-2019, Saat: 15:10)uparlayan Adlı Kullanıcıdan Alıntı: [ -> ]Sizin için bir "taslak" hazırladım. İlla böyle olacak değil fakat sizin için güzel bir başlangıç olabilir;

CAM Nesnesi için;
unit Cam_;

interface

type
  TCamTipi      = (Organik, Duz);
  TCamRengi     = (Colormatik, Beyaz);
  TCamDurum     = (OK, AYNI);
  TCam = class
    private
      FCamTipi  : TCamTipi;
      FCamRengi : TCamRengi;
      FSPH      : Double;
      FCYL      : Double;
      FAX       : Double;
      FGrup     : String;
      FDurum    : TCamDurum;
    function GetFiyat: Currency;
    protected
    public
      property CamTipi  : TCamTipi  read FCamTipi   write FCamTipi;
      property CamRengi : TCamRengi read FCamRengi  write FCamRengi;
      property SPH      : Double    read FSPH       write FSPH;
      property CYL      : Double    read FCYL       write FCYL;
      property AX       : Double    read FAX        write FAX;
      property Grup     : String    read FGrup      write FGrup;
      property Durum    : TCamDurum read FDurum     write FDurum;
      property Fiyat    : Currency  read GetFiyat;
  end;

implementation

{ TCam }

function TCam.GetFiyat: Currency;
begin
  Result := 0;
  if  (FDurum = AYNI) then Result := 0
  else begin
       //  Bu noktaya kendi hesaplama formülünüzü uygulayın...
       Result := 7;
  end;
end;

end.

ÇERÇEVE Nesnesi için;

unit Cerceve_;

interface

type
  TCerceveTipi  = (Yerli, Ithal);
  TCerceve = class
    private
      FCerceve  : TCerceveTipi;
      FHakTarihi: TDateTime;
      function GetFiyat: Currency;
      function GetHakSahibi: Boolean;
    protected
    public
      property Cerceve  : TCerceveTipi  read FCerceve   write FCerceve;
      property HakSahibi: Boolean       read GetHakSahibi;
      property HakTarihi: TDateTime     read FHakTarihi write FHakTarihi;
      property Fiyat    : Currency      read GetFiyat;
  end;

implementation

uses
    System.SysUtils
  ;

{ TCerrceve }

function TCerceve.GetHakSahibi: Boolean;
begin
  Result := (FHakTarihi <= Now);
end;

function TCerceve.GetFiyat: Currency;
begin
  if  (HakSahibi = True)
  then Result := 0
  else begin
       //  Bu noktaya kendi hesaplama formülünüzü uygulayın...
       Result := 35; // veya 40...
  end;
end;

end.

KİŞİ, HASTA, DOKTOR gibi nesneler için;

unit Kisi_;

interface

uses
    Cam_
  ;

type
  TSigortaTipi    = (Calisan, Emekli, Muaf);
  TSigortaKapsam  = (YesilKart, _4C);
  TKisiKagetori   = (Doktor, Hasta);
  TKisi           = class
    private
      FAd         : String;
      FSoyad      : String;
      FTCNo       : String;
      FKategori   : TKisiKagetori;
    protected
    public
      property Ad         : String        read FAd          write FAd;
      property Soyad      : String        read FSoyad       write FSoyad;
      property TCNo       : String        read FTCNo        write FTCNo;
      property Kategori   : TKisiKagetori read FKategori    write FKategori;
  end;

  THasta          = class(TKisi)
    private
      FSigortaTipi: TSigortaTipi;
      FKapsam     : TSigortaKapsam;
    protected
    public
      property SigortaTipi: TSigortaTipi    read  FSigortaTipi  write FSigortaTipi;
      property Kapsam     : TSigortaKapsam  read  FKapsam       write FKapsam;
  end;

  TDoktor = class(TKisi)
    private
      FDiplomaNo: Integer;
    protected
    public
      property DiplomaNo: Integer read FDiplomaNo write FDiplomaNo;
  end;

implementation

{ TKisi }

end.

REÇETE Nesnesi için;

unit Recete_;

interface

uses
    Kisi_
  , Cam_
  , Cerceve_
  ;

type
  TRecete = class
    type
      TSonuc = class
        private
          Owner: TRecete;
        public
          constructor Create(aOwner: TRecete);
          function CamTutar     : Currency;
          function CerceveTutari: Currency;
          function Toplam       : Currency;
          function KatilimPayi  : Currency;
          function ReceteTutari : Currency;
      end;
    private
      FHasta        : THasta;
      FDoktor       : TDoktor;
      FUzakDerece   : TCam;
      FYakinDerece  : TCam;
      FYakinCerceve : TCerceve;
      FUzakCerceve  : TCerceve;
      FTesisAdi     : String;
      FTesisKodu    : String;
      FReceteTarihi : TDateTime;
      FKatilimOrani : Integer;
      FSonuc        : TSonuc;
    protected
    public
      Constructor Create;
      Destructor Destroy; override;
      property Hasta        : THasta    read FHasta         write FHasta;
      property Doktor       : TDoktor   read FDoktor        write FDoktor;
      property UzakDerece   : TCam      read FUzakDerece    write FUzakDerece;
      property YakinDerece  : TCam      read FYakinDerece   write FYakinDerece;
      property UzakCerceve  : TCerceve  read FUzakCerceve   write FUzakCerceve;
      property YakinCerceve : TCerceve  read FYakinCerceve  write FYakinCerceve;
      property TesisAdi     : String    read FTesisAdi      write FTesisAdi;
      property TesisKodu    : String    read FTesisKodu     write FTesisKodu;
      property ReceteTarihi : TDateTime read FReceteTarihi  write FReceteTarihi;
      property KatilimOrani : Integer   read FKatilimOrani  write FKatilimOrani;
      property Sonuc        : TSonuc    read FSonuc         write FSonuc;
  end;

implementation

uses
    System.SysUtils
  ;

{ TRecete }

destructor TRecete.Destroy;
begin
  FreeAndNil(FHasta        );
  FreeAndNil(FDoktor       );
  FreeAndNil(FUzakDerece   );
  FreeAndNil(FYakinDerece  );
  FreeAndNil(FYakinCerceve );
  FreeAndNil(FUzakCerceve  );
  FreeAndNil(FSonuc        );
  inherited;
end;

constructor TRecete.Create;
begin
  FHasta        := THasta.Create;
  FDoktor       := TDoktor.Create;
  FUzakDerece   := TCam.Create;
  FYakinDerece  := TCam.Create;
  FYakinCerceve := TCerceve.Create;
  FUzakCerceve  := TCerceve.Create;
  FSonuc        := TSonuc.Create(Self);
end;

{ TRecete.TSonuc }

constructor TRecete.TSonuc.Create(aOwner: TRecete);
begin
  inherited Create;
  Owner := aOwner;
end;

function TRecete.TSonuc.CamTutar: Currency;
begin
  Result := Owner.UzakDerece.Fiyat
          + Owner.YakinDerece.Fiyat
          ;
end;

function TRecete.TSonuc.CerceveTutari: Currency;
begin
  Result := Owner.UzakCerceve.Fiyat
          + Owner.YakinCerceve.Fiyat
          ;
end;

function TRecete.TSonuc.Toplam: Currency;
begin
  Result := Self.CamTutar
          + Self.CerceveTutari
          ;
end;

function TRecete.TSonuc.KatilimPayi: Currency;
begin
  Result := Self.Toplam * (Owner.KatilimOrani * 0.01); // " X / 100 "
end;

function TRecete.TSonuc.ReceteTutari: Currency;
begin
  Result := Self.Toplam
          - Self.KatilimPayi
          ;
end;

end.

Merhaba,
@uparlayan hocam için mini bir antrenman (daha zor işlerin adamı olduğunuz için affınıza sığınarak bu tabiri kullandım) olmuş. Smile
Ellerinize sağlık. Güzel bir örnek ve güzel bir paylaşım olmuş.
Konuyu daha iyi anlamak (belkide benim bir eksikliğimdir) adına; iki sorum olacak.
1- TRecete sınıfı içerisinde neden bir nested class kullanma ihtiyacımız oldu? Bunu hangi durumlarda kullanmalıyız?

[attachment=805]

2- TSonuc nested class'ı kod içerisinde published olarak bildirilmemesine rağmen, model diyagramına baktığımızda neden published olarak görünüyor? Bug mu? Yoksa bir sebebi var mı?

[attachment=806]
Sayfalar: 1 2 3 4 5