Döviz Sınıfı Oluşturmak....

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
cappy2005
Üye
Mesajlar: 35
Kayıt: 30 Kas 2005 02:42

Döviz Sınıfı Oluşturmak....

Mesaj gönderen cappy2005 »

Kod: Tümünü seç

  TMyExchange = Class
  private
    FDolar: Currency;
    FEuro: Currency;
  public
    Constructor ExChange(Dolar, Euro: Currency);
    function ToDolar(MoneyPrice: Currency): Currency;
    function ToEuro(MoneyPrice: Currency): Currency;
    function ToExchnage(MoneyPrice: Currency;
      Parite: Double): Currency; Override;
  end;
Merhaba,

Yukarıdaki şekilde bir döviz dönüşüm işlemleri yapan bir sınıf tasarlamak istiyorum, lütfen sizlerde bu konuda düşüncelerinizi veya söyle veya böyle devam etmeli şeklinde fikirlerinizi ekler misiniz? Bu konuda yeni sayılırım özellikle OOP konusunda deneyimli arkadaşların yaklaşımını merak ediyorum. Hala tam olarak OOP düşünemiyorum hep tıkla butona yaz kodu şeklinde alıştığımız için özellikle OOP konusunda deneyimli arkadaşlar yaklaşımlarını neden ve sonuç ilişkisi içince açıklarlarsa sanırım bu konu herkese büyük fayda sağlayan bir döküman olucaktır.
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Başlangıç olarak güzel yaklaşım ama işin içine bir başka döviz karıştığı zaman sınıfını değiştirmen ve geliştirmen gerekebilir. Sırf bu iki döviz için düşünüyorsan da basit bir örnek vermek isterim.

Kod: Tümünü seç

TMyExchange=class
  private    
    FDolar: Currency;
    FEuro, FYTL, FDolarYTL, FEuroYTL: Currency;
    procedure SetDolarYTL(Value:Curency);
    procedure SetEuroYTL(Value:Curency);
    procedure SetDolar(Value:Curency);
    procedure SetEuro(Value:Curency);
    procedure SetYTL(Value:Curency);
  public
    constructor ExChange(_Dolar, _Euro: Currency);//YTL karşılıkları
    property DolarYTL:currency read FDolarYTL write SetDolarYTL;
    property EuroYTL:currency read FEuroYTL write SetEuroYTL;
    property Dolar:Currency read FDolar write SetDolar;
    property Euro:Currency read FEuro write SetEuro;
    property YTL:Currency read FYTL write SetYTL;
  end;

constructor TMyExchange.ExChange(_Dolar, _Euro: Currency);
begin
  FDolarYTL:=_Dolar; //1$= _Dolar YTL
  FEuroYTL:=_Euro;  //1€=_Euro YTL
  YTL:=0;
end;

procedure TMyExchange.SetDolarYTL(Value:Curency);
begin
  FDolarYTL:=Value;
  YTL:=FYTL;//değerlerin yeniden hesaplanması için
end;

procedure TMyExchange.SetEuroYTL(Value:Curency);
begin
  FEuroYTL:=Value;
  YTL:=FYTL;//değerlerin yeniden hesaplanması için
end;

procedure TMyExchange.SetDolar(Value:Curency);
begin
  FDolar:=Value;
  FYTL:=Value*FDolarYTL;
  FEuro:=FYTL/FEuroYTL;
end;

procedure TMyExchange.SetEuro(Value:Curency);
begin
  Feuro:=Value;
  FYTL:=Value*FEuroYTL;
  FDolar:=FYTL/FDolarYTL;
end;

procedure TMyExchange.SetYTL(Value:Curency);
begin
  FYTL:=Value;
  FDolar:=FYTL/FDolarYTL;
  FEuro:=FYTL/FEuroYTL;
end;
Kullanıma basit bir örnek:

Kod: Tümünü seç

var MyExchange:TMyExchange;
begin  
  try
    MyExchange:=TMyExchange.Create(1.44,1.88);
    MyExchange.Dolar:=100;//100$ atandı
    ShowMessage(Format('%n $=> %n YTL %n €', [MyExchange.Dolar,MyExchange.YTL,MyExchange.Euro]));
    MyExchange.Euro:=100;//100€ atandı
    ShowMessage(Format('%n €=> %n YTL %n $', [MyExchange.Euro,MyExchange.YTL,MyExchange.Dolar]));
    MyExchange.YTL:=100;//100 YTL atandı
    ShowMessage(Format('%n YTL=> %n € %n $', [MyExchange.YTL,MyExchange.Euro,MyExchange.Dolar]));
    MyExchange.DolarYTL:=1.49;//dolar kuru arttı :)
    ShowMessage(Format('%n YTL=> %n € %n $', [MyExchange.YTL,MyExchange.Euro,MyExchange.Dolar]));
    MyExchange.EuroYTL:=1.77;//Euro düştü borsa göçtü :)
    ShowMessage(Format('%n YTL=> %n € %n $', [MyExchange.YTL,MyExchange.Euro,MyExchange.Dolar]));
  finally
    MyExchange.Free;
  end;
end;
Bu örneği uygularsan OOP'nin çok karmaşık bir teknik olmadığını anlayacaksın. Aslında bu örneklerin dışında zengin özellikleri bulunsa da karmaşık değil. Sihirli anahtar doğru tasarım. Verdiğim örneğin sihrinden bahsetmek imkansızdır o sadece bir örnek. Programcı neye ihtiyaç duyuyorsa o alanda hizmet verecek doğru tasarımı uygulaması gerekmektedir. Bu da zeka ve tecrübe ile sihrini tamamlar. İyi çalışmalar.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

İlla OOP mantığı ile kod yazıcam diye her şeyi sınıf olarak tanımlamana gerek yokki.

Döviz kurları arasında dönüşüm yapan bir sınıfın ihtiyaç duyduğu parametreler, doviz1, doviz2 ve parite'dir. Peki senin tasarlamaya çalıştığın sınıf bunları kendisi mi buluyor? Hayır, senin bu bilgileri ona geçmen lazım. E bu durumda basit bir çarpma işlemi için bir sınıf yapmanın mantığı nedir? Üstelik her dönüşüm işlemi yapmak istediğinde bu sınıftan bir nesne yaratman lazım ki bu senin kodunun hem okunmasını hem de bakımını zorlaştırır.

Bu işi fonksiyona göm demiyorum ama illa bir sınıf tanımlayıp bu işi nasıl hallederim diyorsan şunlara dikkat et:
  • Tasarladığın sınıfın kod içinde kullanıırlığı rahat olmalı. Bu sınıfı kullanacak kişi tek işlem için 5-6 satır kod yazmamalı. Çünkü işlem özünde o kadar karışık değil.
  • Sınıf, belli bir kaç döviz kuruyla sınırlandırılmamalı.

Kod: Tümünü seç

TCurrencyConverter = class
  class function Convert(amount: Currency; parity: Double):Currency;
end;
class function TCurrencyConverter.Convert(amount: Currency;
  parity: Double): Currency;
begin
  Result := amount * parity;
end;

...

TCurrenyConverter.Convert(100, 1.49); // 100 dolar = 149 YTL
TCurrenyConverter.Convert(100, 0.67); // 100 YTL = 67 dolar
TCurrenyConverter.Convert(100, 1.26); // 100 euro = 126 dolar
Asıl önemli olan pariteleri de bir şekilde ifade edebilmek ve dönüşüm yapabilmek.

O yüzden sınıfın amacını biraz genişletelim:

1) Parite bilgilerini tutabilsin.
1.1) Sınırsız sayıda parite bilgisi eklenebilsin
2) Kurlar arası çevirim yapabilsin.

O zaman sınıf arayüzünü tekrar tanımlayalım.

Kod: Tümünü seç

  TCurrencyConverter2 = class
  private
    FParityTable : array of array of double;
    FCurrencies: TStringList;
  protected
    procedure BuildParityTable; virtual;
    function CalculateParity(symbol1,symbol2:String):Double; overload;
    function CalculateParity(parity1,parity2:Double):Double;overload;
  public
    constructor Create;
    destructor Destroy; override;
    procedure AddParity(const currencySymbol:string; const parity:double);
    // RemoveParity vs..'de eklenebilir...
    function Convert(amount:currency; parity: double):currency; overload;
    function Convert(amount:currency; symbol1,symbol2: string):currency; overload;
  end;
procedure TCurrencyConverter2.AddParity(const currencySymbol: string;
  const parity: double);
var
  i : integer;
begin
  //Dövizlere ekle
  FCurrencies.Add(currencySymbol);

  // boyutu gerektiği kadar arttır.
  SetLength(FParityTable,FCurrencies.Count);
  // tabloya döviz sayısı kadar sütun ekle
  for i := Low(FParityTable) to High(FParityTable) do
    SetLength(FParityTable[i],FCurrencies.Count);

  FParityTable[0][FCurrencies.Count-1] := parity;
  // Dönüşüm tablosunu oluştur.
  BuildParityTable;
end;

procedure TCurrencyConverter2.BuildParityTable;
var
  i,j : integer;
  total : integer;
begin
  total := High(FParityTable) - Low(FParityTable);
  // dönüşüm tablo pariteleri hesapla ve tabloyu oluştur
  for i := low(FParityTable) to High(FParityTable) do
    for j := low(FParityTable[i]) to High(FParityTable[i]) do
      FParityTable[i][j] := CalculateParity(FCurrencies[i],FCurrencies[j]);
end;

function TCurrencyConverter2.CalculateParity(symbol1,
  symbol2: String): Double;
var
  parity1,parity2 : double;
begin
  parity1 := FParityTable[0][FCurrencies.IndexOf(symbol1)];
  parity2 := FParityTable[0][FCurrencies.IndexOf(symbol2)];
  Result := parity2 / parity1;
end;

function TCurrencyConverter2.CalculateParity(parity1,
  parity2: Double): Double;
begin
  Result := parity2 / parity1;
end;

function TCurrencyConverter2.Convert(amount: currency;
  parity: double): currency;
begin
  Result := amount * parity;
end;

function TCurrencyConverter2.Convert(amount: currency; symbol1,
  symbol2: string): currency;
var
  i,j : integer;
begin
  i := FCurrencies.IndexOf(symbol1);
  j := FCurrencies.IndexOf(symbol2);
  Result := amount * FParityTable[i][j];
end;

constructor TCurrencyConverter2.Create;
begin
  FCurrencies := TStringList.Create;
end;

destructor TCurrencyConverter2.Destroy;
begin
  FCurrencies.Free;
  inherited;
end;

Bu sınıftan bir nesne oluşturup parite bilgilerini ekliyoruz.

Kod: Tümünü seç

  CurrConvert := TCurrencyConverter2.Create;
  try
    CurrConvert.AddParity('YTL',1.00);
    CurrConvert.AddParity('USD',1.49);
    CurrConvert.AddParity('EUR',1.88);
    CurrConvert.AddParity('YEN',2.65);
    // pariteler sallamadır.
....
ve şu şekilde kullanıyoruz:

Kod: Tümünü seç

    CurrConvert.Convert(100,'EUR','USD');  // 79.25
    CurrConvert.Convert(100,'YTL','USD');  // 149.00
    CurrConvert.Convert(100,'EUR','YTL');  // 53.19
    CurrConvert.Convert(100,'USD','YEN');  // 177.85
...
Kullanıcı avatarı
sadettinpolat
Moderator
Mesajlar: 2131
Kayıt: 07 Ara 2003 02:51
Konum: Ankara
İletişim:

Mesaj gönderen sadettinpolat »

herkesin oncelikleri, beklentileri, hedefleri farklidir.
bu oop icinde gecerlidir.

oop'un program yazmayi kismen kolaylastiran cesitli ozellikleri vardir. kalitim, bilgi gizleme ve cok bicimlilik. oop denince akla bunlar gelir hemen. oysa oop denince benim aklima ilk gelen sey bunlardan biri olmaz. benim aklima ilk gelen sey tekrar kullanilabilirliktir. tekrar kullanilabilirlik benim amacimdir kalitim, bilgi gizleme ve cok bicimlilik ise sadece bu amaca giderken kullanilan bazi araclardir.

programlama hayatinizda muhakkak iki farkli proje gelistirmissinizdir. eger bu projelerinizde ortak olan tek sey vcl bilesenleriyse zamaninizi yeni seyler ogrenmek, cozulmemis problemleri cozmek, sevdiklerinizle daha fazla vakit ayirmak yerine ayni seyleri surekli, tekrar , yeni bastan yaziyorsunuz demektir.

oop'un tercih edilmesinde baska nedenlerde vardir. bakimi daha kolay olan kodlar yazmak, bilgi gerektiren islemlerde bu bilgiyi nesnenin icerisine yerlestirip bu islemin acemi programcilar tarafindan sorunsuz bir sekilde kullanilabilmesini saglamak, kodun bakimini ve testini otomatik hale getirebilmek vs. vs...

oop'un tek basina gerceklestirebilecegi yuzde cok buyuk olmasada benim icin bu nedenlerden en degerlisi tekrar kullanilabilirliktir. sizde bu amaclardan birini, birkacini veya hepsini gerceklestirmek icin nesneleri kullanin. aksi takdirde zamaniniz heba olur cunku delphi her ne kadar hizli uygulama gelistirme araci olsada oop isine merak sardiginizda sizi kodlarla basbasa birakir.
"Sevmek, ne zaman vazgececegini bilmektir." dedi, bana.

---
http://sadettinpolat.blogspot.com/
cappy2005
Üye
Mesajlar: 35
Kayıt: 30 Kas 2005 02:42

Mesaj gönderen cappy2005 »

sabanakman, t-hex, sadettinpolat ilgi gösterip cevap yazdığınız için teşkkürler.

sadettinpolat, blog yazılarını severek takip ediyorum ama son zamanlarda ne OOP ne de TDD hakkında yeni bişeyler göremiyorum. Umarım yakın zamanda bu konularda yeni makaleler eklersin bunlara ihtiyaç var.

t-hex yaklaşımın gerçekten çok hoştu ayrıca vakit ayırıp kodda hazırlamışsın bu yaklaşımını çok daha açık bir şekilde anlamamı sağladı teş. ederim. Ayrıca çok güzel tespitlerinde oldukça faydalı oldu şu an senin yazdığın sınıf üzerinde çalışıyorum. Hatta satır satır inceliyorum desem yalan olmaz :)

Ama yeni yaklaşımlarıda bekliyoruz. OOP gibi bir yaklaşımı temel alan Delphi dilinin programcılarından başka örneklerde bekliyorum. Lütfen paylaşalım.
Kullanıcı avatarı
lazio
Moderator
Mesajlar: 1527
Kayıt: 11 Tem 2003 04:55
Konum: İstanbul

Mesaj gönderen lazio »

Vakitsizlikten örnek kod yazamıyorum ama ben olsam şöyle yapardım;
Parity ve Amount property si olan bir interface tanımlayım tüm döviz birimlerini bu interface den türetirdim.
türeyen bu döviz birimleride tahmin edeceğiniz gibi sadece 2 property içerecek Parity ve Amount olarak.
Birde örneklerde olduğu gibi CurrencyConverter sınıfı hazırlayarak aldığı parametreleri interface türünden verirdim, yok ben sürekli koda girip yeni birimler türetmek istemem dersen o zaman DovizBirimi isimli bir sınıf tanımlayıp (Parity, Amount ve BirimAdı özellikleriyle) CurrencyConverter a parametre olarak bu sınıfı geçebilirsin..
DeveloperToolKit

..::|YeşilMavi|::..
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

sabanakman yazdı:Sihirli anahtar doğru tasarım. ... Programcı neye ihtiyaç duyuyorsa o alanda hizmet verecek doğru tasarımı uygulaması gerekmektedir.
Bu örenekten sayısız metot çıkartılabilir. Asıl vurgulanması gereken ise programcının kendi ihtiyaçlarına olan yeterliliğidir. Bu yeterlilik zeka ve tecrübe ile en üst seviyeye çıkacaktır.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Cevapla