Tüm Platformlar için Hızlı Uygulama Geliştirme --->    Kitabımız...      Delphi

Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
IF Nedir, Nasıl Kullanılır
#1
Merhaba,

Bu yazımızda IF kullanımı ile ilgili bazı tekniklerden bahsedeceğim. Bununla birlikte bu yazının içeriği PERFORMANS ODAKLI OLMAYACAK. Performans ile ilgili eleştiriler haklı da olabilir, haksız da olabilir o konuda yorum yapmıyorum. Yazının amacı, IF kullanım tekniklerinin çeşitliliğini göstererek dil ile kurduğumuz etkileşimin, kodlamada ve okunabilirlikte elde edeceğimiz faydalarından ve kod ile kurduğumuz bağdan yararlanmaya çalışmak olacak. Yazının devamında gösterilecek olan tekniklerin dikkatli kullanılmaması durumunda spagetti koda dönüşebileceği tehlikesinden de bahsetmeden edemeyiz. Tüm bunlardan önce mebzuya dalmadan, bir karar verme yapısının nasıl bir iskeleti olduğuna değinmemiz gerekecek. Sonrasında da gerek PHP'de, gerekse Transact SQL'de sıkça karşılaşmaya başladığımız inline IF tekniğini Delphi'de nasıl kullanabiliriz ve bu tekniği bir adım öteye nasıl taşıyabiliriz onun örneklerine bakacağız.

Bismillah;

Karar Verme Yapıları dendiğinde, kabaca programcının, program tarafından sırası geldiğinde değerlendirilecek veya test edilecek olan herhangi bir durumun sorguladığı, ortaya konulan koşulun / şartın doğru olup olmadığının tespit edilmesi (veya edilmemesi) durumunda devreye girmesi için tasarlanan mekanizmaların kastediğildiğini anlamamız gerekir. Bu mekanizmaları kullanarak yazdığımız programlara (tabiri caizse bir çeşit) akıl katmış oluruz. İnsanları hayvanlardan ayıran en temel özelliklerden birisinin de karar almak olduğunu varsayarsak ilginçtir ki insanlarla makinalar arasındaki en temel ayrımın da bu olduğuna dikkat çekmekte fayda var.

Pascal Programlama Dili, Karar Verme Yapısı olarak "IF" ve "CASE" anahtar kelimelerini kullanır. Fakat kendi yazacağınız fonksiyonlarla da bu yapıları genişletebilir, çeşitlendirebilirsiniz. Standart karar verme yapılarının kendi içinde çeşitli kombinasyonları vardır. Kısaca bu yapılara bir göz atalım;

IF için en bilinen yapı "IF - THEN" yapısıdır. Örnek olarak aşağıdaki kodu inceleyebiliriz;

var
  a: Integer;
  S: String;
begin
  if (a > 100) then ShowMessage('100''den büyük');
  // veya
  if (S.Trim <> '') then ShowMessage('S, boş değil');
end;

Alternatif olarak "IF - THEN - ELSE" yapısıda kullanılabilir. Aşağıdaki örneğe bir göz atalım;

MajQza.png

var
  a: Integer;
begin
  if (a > 100) THEN ShowMessage('100''den büyük') ELSE ShowMessage('100 veya daha altı');
end;

Ayrı bir alternatif olarak ardışık IF ELSE IF yapıları da kullanılabilir. Devamındaki örneği inceleyelim;

var
  a: Integer;
begin
  if (a <= 0) then ShowMessage('Negatif')
  ELSE 
  if (a > 50) then ShowMessage('100 veya daha altı') ;
end;

Veya aynı örneği begin / end blokları içine de alabiliriz. Yukarıdaki örneğin daha okunaklı alternatif bir sürümünü aşağıdaki kodu inceleyerek görebiliriz; Bu örneği, yukarıdakinden ayıran temel nitelik ise ilgili koşula birden çok direktifte bulunabilmemize olanak sağlamasıdır.

var
  a: Integer;
begin
  if (a <= 0) then begin
      ShowMessage('Negatif');
      //... ilgili diğer kodlar
  end else 
  if (a > 50) then begin
      ShowMessage('100 veya daha altı') ;
      //... ilgili diğer kodlar
  end;
end;

Bir kaç koşulun tek bir koşul gibi değerlendirilmesi gereken durumlar da olabilir;

var
  a: Integer;
  s: String;
begin
  a:= 32;
  if (  (a > 1) AND (a < 33)  ) then ShowMessage('a istenen aralıkta');
  s := 'JEST';
  if ( (a < 155) or (s = 'test') ) then ShowMessage('a 155''ten küçük veya s''in içeriği "test"');
end;

Bir değerin bir kümede olup olmadığına da bakılabilir;

var
  a: Integer;
  c: Char;
begin
  c := 'a';
  if c in [#0..#255] then ShowMessage('VAR') else ShowMessage('YOK');

  a := 4;
  if a in [1,4,5,3] then ShowMessage('a = ' + A.ToString) else ShowMessage('a, beklenen değerlerden herhangi birisine sahip değil');
end;

Bazı durumlarda ELSE'nin dikkatsiz kullanılması beklenmeyen sonuçlara neden olabilir. "IF THEN ELSE IF" yapısı ardışık kullanıldığında, yani bir CASE gibi kullanılmaya çalışıldığında derleyici, "karşılaşılan" ilk şartın doğru olması durumunda devamında gelen diğer şartların doğru olup olmadığına bakmaz ve doğrudan IF bloğunun sonuna dallanır. Bu davranışı anlamak için derleyicinin bir IF ifadesiyle karşılaştığında "tam olarak" neye baktığına bir göz atmak gerekir. Derleyici, IF ifadesinde geçen koşulun sonucunun "boolean" açısından "TRUE" olup olmadığına bakar. Yani siz koşul olarak her ne yazarsanız yazın, aslında derleyici o koşulun ikili sayı sistemindeki karşılığının 1 olup olmadığına bakar. Sonuç 1 ise koşulun doğru (TRUE) olduğuna karar verir ve hemen devamındaki kodları çalıştırır. Eğer sonuç 0 ise bu koşulun YANLIŞ (FALSE) olduğuna karar verir ve varsa "ELSE" ile ifade edilen kısma dallanır. Bundan sonrasında, IF ifadesi bir silsile izliyorsa, yani "IF THEN ELSE IF..." gibi birbirine bağlı bir kullanım söz konusu ise silsilenin devamına bakmaz ve doğrudan silsilenin en sonundaki END'e dallanır. 

Örneklendirmek gerekirse şöyle bir senaryo kurabiliriz;

begin
  if FALSE then begin
      ShowMessage('1');
  end else
  if TRUE then begin
      ShowMessage('2');
  end else
  if TRUE then begin
      ShowMessage('3');
  end else
  begin
      ShowMessage('4');
  end;
  // Bu örnekte sadece ShowMessage('2'); olan kısım çalışır. Devamında gelen koşullar doğru bile olsa IF komutu ifadenin en sonuna dallanır.
end;

Konuyu anlamak adına örnekleri biraz daha derinleştirmek gerekirse, derleyicinin bir IF komutuyla karşılaştığında özünde neye baktığını daha iyi anlamış oluruz.

var
  a: Integer;
begin
  if TRUE then ShowMessage('1) DOĞRU');

  // veya

  if False
     then ShowMessage('2) TRUE')
     else ShowMessage('2) FALSE');

  // veya

  if TRUE  then ShowMessage('3) TRUE')  else ShowMessage('3) NOT TRUE');
  if FALSE then ShowMessage('3) FALSE') else ShowMessage('3) NOT FALSE');

  // veya

  if 0 = 0 then begin
    ShowMessage('4) Sıfır eşittir sıfır');
  end else
  if 1 = 1 then begin
    // 1=1 koşulu doğru olduğu halde, yukarıdaki (0 = 0) koşulu derleyici açısından doğru olarak ilk karşılaşılan koşul olduğu için, derleyici bu kısmı görmezden gelir.
    ShowMessage('4) Bir eşittir bir (ama bu kısım hiç çalışmayacak...)');
  end;
end;

Yukarıda değindiğimiz özel durum, iç içe geçmiş (nested if) ifadeleri açısından soyutlanmıştır ve kendi skopları içinde değerlendirilir. Bunu biraz açmak gerekirse şöyle bir örnek konuyu anlamamız açısından yeterli olacaktır;

var
  a, b: Integer;
begin
  a := 50;
  b := a * 2;
  if (a = 50) then begin
      if ( b = (a * 2) ) then begin
           ShowMessage('B = 100 (Sadece bu kısım çalışır. diğerleri atıl kalacaktır.)');
      end else
      if ( a = (b div 2) ) then begin
           ShowMessage('Atıl kısım');
      end;
  END ELSE {< buraya dikkat edelim...}
  if (50 = a) then begin
      // dikkat ederseniz "a = 50" ile "50 = a" aslında aynı şey...
      // dolayısıyla bir önceki if koşulu doğru olduğu zaman asla bu kısma dallanmayacak.
      // o nedenle "END ELSE" ifadesini dikkatli kullanmak gerekir.
      ShowMessage('Atıl kısım');
  end;
end;

Bunun dışında NOT operatörü, öne sürdüğünüz koşulun tersini kullanmanıza olanak sağlar, mesela;

var
  a, b: Integer;
begin
  if (a <> 50) then ShowMessage('a, 50''ye eşit değildir...');
  // ile
  if NOT (a = 50) then ShowMessage('a, 50''ye eşit değildir...');
  // aynı şeyi ifade eder...

  // veya başka bir örnek daha verelim;
  if not false then ShowMessage('NOT FALSE = TRUE'); // gibi...
end;

Buraya kadar IF'in nasıl kullanıldığına bir göz attık. IF ifadesinin temel mekaniğini inceledik ve nelere dikkat etmemiz gerektiğini öğrendik. Değinecek, dokunacak başkaca ayrıntılar mutlaka vardır. Hatırladıkça bu makalenin devamına eklemeye devam edeceğim.

Yazının bundan sonraki kısmında ise tıpkı PHP ve T-SQL'deki gibi inline bir IIF fonksiyonunu Delphi'de nasıl tanımlanabileceğine ve bunu nasıl kullanabileceğimize bakacağız.

Özel bir if fonksiyonu, Satıriçi IF kullanımı.

İki stringi bir koşula göre birleştirmek istediğimizde genelde aşağıdakine benzer bir yapı kullanırız;

function TeslimatMesaji(Ad: String; aCinsiyet: Boolean): String;
begin
  Result := 'Sayın ' + Ad + ' ';
  if aCinsiyet = TRUE then begin
      Result := Result + 'Bey,';
  end else begin
      Result := 'Hanım,';
  end;
  Result := Result + #13#10 + 'Talep ettiğiniz sipariş adresinize teslim edilmiştir.';
end

Peki bu fonksiyonu şöyle yazsaydık daha anlaşılır ve sade olmaz mıydı?

function TeslimatMesaji(Ad: String; aCinsiyet: Boolean): String;
begin
  Result := 'Sayın ' + Ad + ' ' + IFF( aCinsiyet, 'Bey,', 'Hanım,') + #13#10 + 'Talep ettiğiniz sipariş adresinize teslim edilmiştir.' ;
end

Her iki fonksiyon da temelde ve yöntemde aslında aynı şeyi yapıyor. Her ikisi de bir parametrenin değerini karşılaştırıyor, değerin doğru olup olmamasına göre belli bir içeriği sonuç kümesine işliyor. Burada, yazının performans odaklı olmadığından bahsetmiştik, yine bu konuya girmeyeceğiz. Bizim buradaki odak noktamız okunabilirik ve kod ile kurduğumuz anlam ilişkisinin basitliği ve anlaşılabilirliği olduğu için ben her zaman ikinci yöntemi tercih edenlerdenimdir. 

Örnek kodumuzda önizlemesini yaptığımız IFF fonksiyonunun yapısını incelemeye başlayalım isterseniz. Bu bir fonksiyon olması sebebiyle doğal olarak veri tiplerine bağımlı bir yapıya sahip olacaktır, o nedenle aynı mekanizmayı kurabilmek için bazı temel veri tipleriyle harmanlayıp overload etmemiz gerekecek. Ben, burada en sık kullandığım veri tipleri ve nesnelerden oluşam bir kolaj hazırladım ve aşağıda kullanımınıza sunuyorum; Bu arada, INDY bileşen paketinde yer alan ve IDGLOBAL.PAS dosyasında iif adı altında benzer fakat sayıca az olan fonksiyonlar da bulunmaktadır.

interface

uses
  System;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: String)   : String;    overload;
function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Integer)  : Integer;   overload;
function IFF(aKosul: Boolean; aDogruysa, aYanlissa: TDateTime): TDateTime; overload;
function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Boolean)  : Boolean;   overload;
function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Currency) : Currency;  overload;
function IFF(aKosul: Boolean; aDogruysa, aYanlissa: TObject)  : TObject;   overload;
function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Variant)  : Variant;   overload;

implementation

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: String): String;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Integer): Integer;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: TDateTime): TDateTime; overload;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Boolean): Boolean; overload;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Currency): Currency; overload;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: TObject): TObject; overload;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

function IFF(aKosul: Boolean; aDogruysa, aYanlissa: Variant): Variant; overload;
begin
  if aKosul then Result := aDogruysa else Result := aYanlissa;
end;

Yukarıdaki tüm IIF fonksiyonlarının kullanımı tamamen aynıdır. Hepsi için örnek kullanımı Özel bir if fonksiyonu, Satıriçi IF kullanımı. bölümünün 2. örneğinde görebilirsiniz. Bununla birlikte IFF fonksiyonunu iç içe veya ard arda da kullanabilirsiniz. Bu noktada size engel oluşturacak herhangi bir kullanım söz konusu değil. Tıpkı PHP'deki ve T-SQL''deki IIF gibi...
Cevapla
#2
Çok efsane bir kaynak olmuş hocam, emeğiniz için teşekkürler.
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Cevapla
#3
Elinize, emeğinize sağlık. Bu arada ilave olarak hatırlatmak isterim, benzer işlevselliğin sağlayan IfThen isimli bir fonksiyon vardır Delphi'de de.

Math unitinde bir IfThen tanımı ve StrUtils unitinde bir başka IfThen tanımı mevcuttur.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#4
Güzel yazı emeğinize sağlık, 

Tuğrul beyin bahsettiği fonksiyonlar,

StrUtils deki IfThen fonksiyonu,
function IfThen(AValue: Boolean; const ATrue: string;
  AFalse: string = ''): string;
begin
 if AValue then
   Result := ATrue
 else
   Result := AFalse;
end;

Math'dekiler,
function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer = 0): Integer; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Int64; const AFalse: Int64 = 0): Int64; overload; inline;
function IfThen(AValue: Boolean; const ATrue: UInt64; const AFalse: UInt64 = 0): UInt64; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Single; const AFalse: Single = 0.0): Single; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Double; const AFalse: Double = 0.0): Double; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Extended; const AFalse: Extended = 0.0): Extended; overload; inline;
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Kuvvete dayanamayan adalet aciz, 
Adalete dayanamayan kuvvet zalimdir.
WWW
Cevapla
#5
(12-12-2017, Saat: 17:48)yhackup Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlGüzel yazı emeğinize sağlık, 

Tuğrul beyin bahsettiği fonksiyonlar,

StrUtils deki IfThen fonksiyonu,
function IfThen(AValue: Boolean; const ATrue: string;
  AFalse: string = ''): string;
begin
 if AValue then
   Result := ATrue
 else
   Result := AFalse;
end;

Math'dekiler,
function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer = 0): Integer; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Int64; const AFalse: Int64 = 0): Int64; overload; inline;
function IfThen(AValue: Boolean; const ATrue: UInt64; const AFalse: UInt64 = 0): UInt64; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Single; const AFalse: Single = 0.0): Single; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Double; const AFalse: Double = 0.0): Double; overload; inline;
function IfThen(AValue: Boolean; const ATrue: Extended; const AFalse: Extended = 0.0): Extended; overload; inline;

Yazıyı beğenmenize sevindim. Puan ile taçlandırırsanız daha makbule geçer. 

Bahsettiğiniz fonksiyonların varlığından bihaber değilim, indy paketinde benzer fonksiyonların olduğundan da bahsetmiştim yazıda...  Esasen yazı bu fonksiyonlardan daha fazlasına dokunuyor. Bu arada verdiğim örneklerin veri tiplerinin bir kısmının farklı olduğuna dikkat edelim.
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol,Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol,Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol,Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol / Neyi bilmediğimiz hakkında hiçbir fikrimiz yok (EM)
Cevapla
#6
Ben de generic halini yazarak ekleme de bulunayım :

  &IF = record
  public
   class function &Then<T>(const AValue : Boolean; const ATrue, AFalse : T) : T; static;
 end;

class function &IF.&Then<T>(const AValue: Boolean; const ATrue, AFalse: T): T;
begin
  Result := AFalse;

  if AValue then
    Exit(ATrue);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  A : Integer;
  B : Byte;
  C : Char;
  D : Double;
begin
  A := &IF.Then<Integer>(true, 10, 20);
  ShowMessage(A.ToString);

  B := &IF.Then<Byte>(false, 10, 20);
  ShowMessage(B.ToString);

  C := &IF.Then<Char>(true, 'A', 'B');
  ShowMessage©;

  D := &IF.Then<Double>(true, 10.5, 20.1);
  ShowMessage(D.ToString);
end;
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#7
Yazının ruhuna uygun bir katkı sağlamışsınız, teşekkür ederim. Takım çalışması gibi oldu neredeyse Smile
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol,Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol,Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol,Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol / Neyi bilmediğimiz hakkında hiçbir fikrimiz yok (EM)
Cevapla
#8
(13-12-2017, Saat: 15:14)uparlayan Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlYazının ruhuna uygun bir katkı sağlamışsınız, teşekkür ederim. Takım çalışması gibi oldu neredeyse Smile

Konu şampiyonlar ligi gibi oldu  Big Grin Big Grin
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Cevapla
#9
Delphide mevcut degil ama konu if olunca en azindan genel kultur babinda burada bulunmasinda fayda var Smile

Ternary Operator (Üçlü Operatör)

C türevi dillerde yer alan bu operator ifthen ifadesini tek seferde yazmaya olanak saglar.

Syntax su sekildedir.

result = testCondition ? value1 : value2


Ornek bir kullanim durumu

returnString = "Thank you " + (person.isMale() ? "Mr. " : "Ms. ") + person.getLastName() + ".";


Kimi insan kullanisli buluyor kimisi kodun okunabilirligini azalttigini soyluyor.
Sanirim okunabilirligi azalttigi dusuncesi nedeniyle pascala eklenmemis bu operator.
WWW
Cevapla
#10
(13-12-2017, Saat: 15:14)uparlayan Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlYazının ruhuna uygun bir katkı sağlamışsınız, teşekkür ederim. Takım çalışması gibi oldu neredeyse Smile

Rica ederim. Bizler zaten kocaman bir takımız Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla

Konuyu Paylaş : facebook gplus twitter



Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Array Nedir, Nasıl Kullanılır (Güncellendi) uparlayan 10 471 18-12-2017, Saat: 21:55
Son Yorum: hyperxman
  Delphi ve Github Entegrasyonu Nasıl Yapılır uparlayan 14 673 18-11-2017, Saat: 14:56
Son Yorum: uparlayan
  UPnP Nedir? Delphi İle Nasıl Kullanılır? hyperxman 2 275 28-10-2017, Saat: 22:32
Son Yorum: SimaWB



Konuyu Okuyanlar: 1 Ziyaretçi