Site menu
Section categories
Dersler [9]
Delphi proqramlari [3]
Xeberler [4]
Yeni informasiyalar [6]
Tag Board
Our poll
Rate my site
Total of answers: 22
Statistics

Total online: 1
Guests: 1
Users: 0
Login form
Wednesday, 15.05.2024, 20:58
Welcome Guest
Main » 2009 » December » 22 » Delphi
13:51
Delphi
Delphide Api Fonksiyonlarını Kullanmak [/b] Delphi'de Api Fonksiyonlarını KullanmakBilindiği gibi Delphi'de API fonksiyonlarını kullanmak son derece kolaydır. çünkü Delphi ile gelen Windows ve ShellApi gibi bir kaç Unit sayesinde Api fonksiyonlarını Delphi fonksiyonuymuş gibi kullanmak mümkün olmaktadır. Bu makelede Delphi'nin API fonksiyonlarının kullanımını kolaylaştıran Unit'lerinden yararlanmadan nasıl kullanılabileceğini GlobalMemoryStatus() fonksiyonu üzerinde anlatmayı deneyeceğim. Delphi projelerinde Windows'un GlobalMemoryStatus() fonksiyonundan yararlanıp kullanılan bilgisayarın belleği hakkında bilgi edinebilirsiniz. Tahmin edebileceğiniz gibi Windows'un API fonksiyonları C dili ile yazılmıştır. Bu nedenle bu fonksiyonları Turbo Delphi projesi dahilinde kullanabilmek için Delphi'ye uyarlamak gerekmektedir. Borland programcıların API fonksiyonlarını kolay kullanabilmesini sağlamak birkaç Unit hazırlamıştır. Windows adlı Unit bunlardan birisidir. Windows.pas adlı kod dosyasında yüzlerce API fonksiyonu hakkında bilgi bulabilirsiniz. Aşağıda verdiğim satırı Windows.pas dosyasından aldım.procedure GlobalMemoryStatus(var lpBuffer: TMemoryStatus); stdcall;Verilen satırdan tespit edebileceğiniz gibi Windows'un GlobalMemoryStatus fonksiyonu TMemoryStatus tipinde bir parametreye sahiptir. TMemoryStatus adı verilen bu yapının orijinal halini aşağıda görebilirsiniz.typedef struct _MEMORYSTATUS { DWORD dwLength; DWORD dwMemoryLoad; DWORD dwTotalPhys; DWORD dwAvailPhys; DWORD dwTotalPageFile; DWORD dwAvailPageFile; DWORD dwTotalVirtual; DWORD dwAvailVirtual;} MEMORYSTATUS, *LPMEMORYSTATUS; Delphi projelerinde Windows'un GlobalMemoryStatus fonksiyonunu kullanabilmek için bu yapının Delphi'ye dönüştürülmesi gerekir. Başka bir deyişle C'de Struct olarak yapılan tanımlananın Delphi'de Record olarak yapılması gerekmektedir. Bu hazırlık Delphi ile gelen Windows.pas adlı Unit'te yapılmış olduğu için sizler GlobalMemoryStatus fonksiyonun gerek duyduğu tipi hazırlamak zorunda değilsiniz.typePMemoryStatus = ^TMemoryStatus;_MEMORYSTATUS = record dwLength: DWORD; dwMemoryLoad: DWORD; dwTotalPhys: DWORD; dwAvailPhys: DWORD; dwTotalPageFile: DWORD; dwAvailPageFile: DWORD; dwTotalVirtual: DWORD; dwAvailVirtual: DWORD;end;Her ne kadar Windows'a ait bir fonksiyon olsa bile Delphi'nin Windows.pas adlı Unit'inde gerekli tanımlamalar yapıldığı için sanki Delphi'nin bir fonksiyonuymuş gibi kullanabileceği­niz GlobalMemoryStatus() fonksiyonu hakkında bilgi vermek için forma 3 Edit yerleştirdim. Devamında aşağıda verdiğim kodu yazdım. Windows adlı Unit veya Windows.pas dosyası formları temsil eden Unit'lere otomatik olarak dahil edildiği için Uses bloğu ile ilgilenmenize gerek yoktur. procedure TForm1.Bellek_durumuClick(Sender: TObject);VarBellek : TMEMORYSTATUS;beginGlobalMemoryStatus(Bellek);Edit 1.Text := IntToStr(Bellek.dwTotalPhys div 1024 div 1024) +' MB';Edit2.Text := '%' + IntToStr(Bellek.dwMemoryLoad);Edit3.Text := IntToStr(Bellek.dwAvailPhys Div 1024 Div 1024) +' MB';end;Bu kodu incelediğinizde önce TMEMORYSTATUS tipinde bir değişkenin tanımlanıp bu değişkenin GlobalMemoryStatus() fonksiyonuna parametre olarak verildiğini, devamında ise bu tipin elamanlarından 3 tanesinin içeriğinin Edit'lere aktarıldığını görürsünüz. GlobalMemoryStatus fonksiyonu hakkında şimdiye kadar anlatılanlara göre konu Windows'un API fonksiyonları olduğunda bu fonksiyonları kullanmak son derece kolaydır. çünkü Windows'un çok sayıda fonksiyonu için Windows.pas ve ShellApi.pas gibi Delphi'ye ait Unit'lerde gereken hazırlıklar önceden yapılmıştır. Şimdi Windows.pas adlı Unit'i Delphi projesine dahil etmeden GlobalMemoryStatus fonksi­yonundan yararlanıp bilgisayarın belleği hakkında bilgi edineceğim. Bu amaçla üzerinde çalıştığım projenin ilk formunun tanımlandığı Unit'in Uses bloğundan Windows adlı Unit'i sildim ve TBELLEK_DURUMU adında bir tip tanımladım.unit Unit1;interfaceusesMessages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ComCtrls, ExtCtrls, Menus;TypeTBELLEK_DURUMU = record dwLength: LONGINT; dwMemoryLoad: LONGINT; dwTotalPhys: LONGINT; dwAvailPhys: LONGINT; dwTotalPageFile: LONGINT; dwAvailPageFile: LONGINT; dwTotalVirtual: LONGINT; dwAvailVirtual: LONGINT;end;typeTForm1 = class(TForm) procedure FormClick(Sender: TObject);privatepublicend;varForm1: TForm1;Bu tipi tanımlarken yukarıda verdiğim Windows'a ait orijinal Struct veya yapıdan yararlan­dım. üzerinde çalıştığım projenin ilk formunu temsil eden bu Unit'in Uses bloğunu inceler­seniz Windows adlı hazır Unit'in olmadığını görürsünüz. Windows'un GlobalMemoryStatus adlı API fonksiyonun gerek duyduğu tipi bu şekilde tanımladıktan sonra formu temsil eden Unit'in implementation bölümde bu API fonksiyonunu aşağıdaki gibi deklare ettim.implementationFunction GlobalMemoryStatus(Var Bellek : TBELLEK_DURUMU): Integer; StdCall; External 'Kernel32.dll';{$R *.dfm}Bu fonksiyon Microsoft tarafından hazırlanırken StdCall yönetimi ile çağrılması konusunda ayarlama yapıldığı için fonksiyonun yapısına StdCall anahtar kelimesini ekledim. Deva­mında External anahtar kelimesi ile fonksiyonun tanımlı olduğu DLL dosyasını işaret ettim. Fonksiyonu deklare ederken fonksiyonun gerek duyduğu parametrenin yukarıda kendi tanımladığım tipte(TBELLEK_DURUMU) olmasını sağladım. Her ne kadar bu fonksiyonun dönüş değeri Integer tipinde olsa bile geriye gönderilen bilgiyi yakalamak zorunda değilsiniz. Bu hazırlıktan sonra bu fonksiyonu aşağıdaki gibi kullandım.procedure TForm1.Bellek_durumuClick(Sender: TObject);VarBellek : TBELLEK_DURUMU;beginGlobalMemoryStatus(Bellek);Edi t1.Text := IntToStr(Bellek.dwTotalPhys div 1024 div 1024) + ' MB';Edit2.Text := '%' + IntToStr(Bellek.dwMemoryLoad);Edit3.Text := IntToStr(Bellek.dwAvailPhys Div 1024 Div 1024) + ' MB';end;Şimdi ise Windows'un orijinali GlobalMemoryStatus olan adını kullanmak yerine fonksi­yona takma bir isim vereceğim. Fonksiyonlara takma isim verme işlemi Unit'lerin implementation bölgesinde fonksiyon deklare edilirken verilir. implementationFunction Bellek_bilgisi(var Bellek :TBELLEK_DURUMU): Integer; StdCall; external 'kernel32.dll' Name 'GlobalMemoryStatus';{$R *.dfm}procedure TForm1.Bellek_durumuClick(Sender: TObject);Var Bellek : TBELLEK_DURUMU;begin Bellek_bilgisi(Bellek); Edit1.Text := IntToStr(Bellek.dwTotalPhys div 1024 div 1024) + ' MB'; Edit2.Text := '%' + IntToStr(Bellek.dwMemoryLoad); Edit3.Text:= IntToStr(Bellek.dwAvailPhys Div 1024 Div 1024) + ' MB';end;Burada Name anahtar kelimesinden sonra yazılan ad, işaret edilen DLL dosyasındaki fonksi­yonun gerçek adıdır. Bu tanımlamadan sonra Windows'un GlobalMemoryStatus adlı API fonksiyonu Delphi projesi dahilinde Bellek_bilgisi() adıyla çağrılabilir. GlobalMemoryStatus fonksiyonunda yapıldığı gibi diğer API fonksiyonların hem Delphi'den yardım alarak hem almayarak nasıl kullanıldığı uzun uzun anlatılabilir ancak buna gerek yoktur. ___________________________________________________________________________ Anet haber grubunda okudum. güzel bir yazı buraya da göndereyim dedim. konuyla ilgili daha fazla bilgisi olan arkadaşlar varsa onların bilgilerinden de yararlanmak isteriz. Ahhh test meselesi. Versiyon kontrolle ilgili postunu da okumuştum. O mesele burada çok kereler konu edilmişti. Aşağı yukarı bu iki postundan ne durumda olduğunu anlayabiliyorum. Bu test işi burada pek geçmediği için şöyle genel anlamda birşeyler karalayım dedim. Hem genel bir bilgi olsun hem de belki işe yarar birşeyler bulursun. Artık Delphi ile pek program yazamıyorum ama hala delphi gurubumuza bir katkıda bulunabiliriz. Program yazarken zaman zaman varsayımlar yaparız. Mesela bir değişkenin değerinin her zaman 0 dan büyük olacağını farzederiz. Bu varsayımlar bizi if myvar < 0 then raise exception ...... gibi bir test yapmaktan kurtarır. Ancak böyle bir varsayımda bulunduğumuzu unutmamak için assert(myvar > 0, 'Dikaaaaaat değişken sıfırdan küçük'); gibi bir kod ilave ederiz. Bu bilhassa birden fazla kişinin çalıştığı ortamlarda faydalıdır. Bu sayede birisi ilgili kuralı ihlal ederse bundan haberi olabilir. Nasıl ki kullanıcılarımız için yapmamaları gereken bir durumda uyarı veriyorsak asserti de programcılar (veya kendimiz) için bir uyarı olarak düşünebiliriz. Hem programı da gereksiz testlerden kurtarmış oluruz. Peki assertin kendisi zaten bir test değil mi neden normal bir if testi yerine assert kullanacağız? Assertler kapatılabilirler. Yani isterseniz kullanıcı için derlediğiniz versiyonlarda assert satırlarını derleyicinin ignore etmesini sağlayabilirsiniz. Aslında sağlamalısınız. Eğer programı assertli derlenmiş halde kullanıcılarımıza gönderirsek zaten programın düzgün çalışması durumunda her zaman true döndürmesi gereken testleri de yapıyoruz anlamına gelir. Bu performans kaybına neden olacaktır. Test için yazılan kodlar test versiyonunda kullanılmalıdır. Eğer kullanıcılardan assert hataları geliyorsa bu test sisteminde zaaflar var demektir. Gelelim asıl konuya. Assert basit işler için çok kullanışlı olsa da aslında yetersizdir. Çünkü asıl ihtiyacımız yeni eklediğimiz özelliklerin mantıkta genel bir soruna yol açıp açmadığını anlamaktır. Genelde belirli bir seviyeden sonra programın kontrolü zorlaşır. Zaten bir test prosedürüne ihtiyaç duyuyorsak program belli bir aşamaya gelmiş demektir. İki nedenle kodda değişiklik yapıyoruz. Biri müşteri ihtiyaçlarından kaynaklanıyor biri de altyapıda değiştirmek istediğimiz meselelerden. Müşteri istekleri genellikle iyi tasarlanmış programlarda kolay çözülür. Genel olarak OOP kurallarını ihlal etmeden yazılmış her programda istek kabilinden meseleleri eklemek kolaydır. Ama ya altyapı konuları? İşte kazık olan kısım burası. İsteklerle ilgili müdaheleler estetik amelliyata benzese de altyapıyla ilgili meseleler açık kalp amelliyatına benzer. Hatta bazen hastalık o kadar çok yayılır ki deyim yerindeyse kalbi, mideyi, kokoreçleri felan çıkarıp masanın üzerine yaymak gerekebilir. Assert bu işi ne yazık ki kurtarmaz. Bize yaptığımız müdaheleden sonra hasta tüm eski işlevlerini yerine getirebiliyor mu bunu denetleyecek bir sistem lazım. "Acaba bir yeri bozdum mu?" cidden kötü bir soru. İşte birim testleri (unit tests) bu noktada iyi bir yardımcı olacaktır. Buradaki anafikir programımızdaki sınıflarımızı (veya genel olarak bazı işlevleri) küçük bir simülasyon tarzında sınamaktır. Yine OOP kurallarına uyulmuş olması bu tür testlerin hazırlanmasında iyi bir ortam olacaktır. Yani event-driven (evente tıkla kodu yaz) şeklindeki programcılık bize ayak bağı olabilir. Bunun için Delphide kullanılmak üzere tasarlanmış DUnit isimli program kullanılır. Programa yeni bir işlev eklediğinizde DUnit'e de bu işlevi denetleyecek bir test yazar ve eklersiniz. DUnitte her test bir renkli kutu ile ifade edilir. Kırmızı kutular patlayan testleri, yeşil kutular ise geçerli testleri ifade eder. Program yazılırken bir taraftan testleri de yazarsınız. Yani programda yazdığınız kodları kullanan bir başka program da bu esnada yazılır. Sonra zamanı geldiğinde bu testler tümüyle işletilir ve patlayan kısımlar düzeltilerek hatalar ayıklanır. Örneğin ortalama vade hesaplayan bir fonksiyonumuz olsun. calcOrtalamaVade(Tarih arrayi; Tutar arrayi) :Gün sayısı; gibi. Biz bu fonksiyona örnek bir bir değer kümesi gönderen ve önceden hesapladığımız vadeyi bulup bulamadığımızı test eden ayrı bir fonksiyon daha yazarak testlerimiz arasına ekliyoruz. Sonra bu testleri her çalıştırdığımızda bu ortalamaVade testi de çalışıyor. Böylelikle biz böyle bir işlevi unutsak dahi aylar sonra buradaki kodu kıracak bir kod yazarsak ortalama vadenin doğru hesaplanıp hesaplanmadığı testler esnasında ortaya çıkacaktır. Gavurlar bu tarz program yazmacaya "Test Driven Development" derler. Bir de şunu düşünelim Yukarıdaki vade hesabı gibi bir fonksiyonu yazdık ve bir müşterimiz 29 şubat vadeli bir çeki girdiğinde ortalama vadenin bir gün eksik hesaplandığından bahsetti. Ne yazıkki artık paldır küldür koda dalıp "lan bu 29 şubatın ta bilmemnesini" nidalarıyla bug temizlemek yok. Hemen gidip paşa paşa önce 29 şubat tarihinde hatalı hesaplanan durumu ortaya çıkaran bir test yazıyoruz. Testi çalıştırdığımızda kırmızı kutu bize hatalı durumu gösteriyor. Sonra tüm kırmızı kutucuklar yeşile dönene kadar bu tarih sorununu çözecek kodu düzeltiyoruz. Programa girip çek felan işleyerek yaptığımız düzeltmeyi test etmek hem uzun sürer ve sıkıcıdır hem de bu düzeltmeyi yaparken başka bir tarafı bozduysak bu gözden kaçar. XP (Extreme Programming) son günlerin en moda yazılım metodojilerinden biridir. Birim testleri XP'nin en can alıcı noktalarından biridir. Hatta XP guruları der ki programa birşey eklemeden önce testini yazın. Mesela mail atacak bir sınıf yazacaksınız. TMailSender = class procedure Sendmail(AMessage,AAddress:String); Function CheckMail(AAddress):AMessage; end; Şimdi ctrl +c ile boş metodları oluşturuyoruz ve birşey implement etmeden önce testi yazacağız. Bu sınıf uMail.pas unitinde ise uMail_Test.pas unitine de aşağıdaki kodu ekleyebiliriz. // MailSender testi const teststr = 'DENEME 1 2 3'; var s:String; MS := TMailSender.Create; MS.SendMail(teststr, 'adresim@domainim.com'); s :=MS.CheckMail('adresim@domainim.com'); MS.free; assert(s=teststr); // ve bu testi bir satır kod daha yazarak DUnit'e register ediyoruz. Test programını çalıştırdığımızda DUnit çalışacak ve ilgili testi kırmızı ile gösterecektir. Artık yeşil görene kadar sınıfı implement edeceğiz. İşimiz bittiğinde hem denemelerimizi yapacağımız güzel bir ortamımız olacak hem de birgün bozulursa direk haberdar olacağımız şekilde kodu garantiye almış olacağız. Gerçekten de bu şekilde çalışıldığında belkide sadece kullanıcı arabirimini test etmek için programı çalıştıracaksınız :))) Eğer programımızın işlevlerini DUnit ile test edebiliyorsak altyapıyı veya tasarımı yenilerken (buna da gavurlar Refactoring diyor) programın doğru çalıştığından tam olarak emin olacağımız ortamı da oluşturmış oluruz. Tabii ben bu mail meselesini örnek olarak verdim. Test bir sınıfla alakalı olabileceği gibi bir işlev bütününün testi de olabilir. Eğer yeni bir projede birim testlerini de yazmaya karar verirsek iş nispeten kolay. Ancak mevcut bir projeye birim testleri yazmaya kalkarsak muhtemelen çakılırız. Çünkü kodumuz büyük ihtimalle *test edilebilir* durumda olmayacaktır. Dolayısıyla neyin nasıl test edileceği konusu havada kalır. Muhtemelen mail gönderecek bir sınıf yazmamış ve değişik mail işlevlerini bir formun buton eventlerine yaptırıyoruzdur. İşte en başta dediğim gibi OOP kurallarına uymama sorunu budur. Projeyi test edilebilir hale getirmek de apayrı bir konudur. Bunun da gavurcası Retrofitting' dir. Ama zorluğuna rağmen bence Test Driven Development işinin en güzel yanı da budur. Bu çalışma programcıyı test edilebilir kod yazmaya mecbur eder. Test edebildiğimiz kod iyi koddur. Genelde ilk başlarda biraz karmaşık gibi görünse de alışkanlıklarımızı bir an bir kenara bırakıp farklı bir tarz yakalayabilirsek bu çalışma şekli çok faydalıdır. Belki normalden biraz fazla kod yazılması gerekecektir ancak uzun dönemdeki kazanç büyüktür. Hadi abartalım ideal bir sistemde programın bir bölümünü silip gönül rahatlığıyla yeniden kodlayabilirsiniz. Özellikle uzun süre yaşaması gereken bir proje üzerinde çalışıyorsak ve test konusunda milyarlarca lira dökecek bir dayı firmamız da yoksa bu basit iş hayati önem taşır. Uzun yazdım inşallah bir okuyan bulunur:)) Her gün yeni şeyler öğrenmek ve uygulamak durumundayız. Bu programcının kaderi. Googılda Test Driven Development yazarsak karşımıza birçok kaynak çıkacaktır. Ayrıca DUnit opensource bir projedir ve tam adresini hatırlayamayacağım ama sourceforge de aratılabilir.
 
                              Hazırladı DjZORRO
Category: Dersler | Views: 1872 | Added by: DjZORRO | Rating: 0.0/0
Total comments: 2
2 SergAdusy  
0
<a href=http://zmkshop.ru/uslugi/zdaniya-i-doma-iz-metallokarkasa/>преимущество зданий из стального каркаса при землетрясениях</a>

1 BrandonWilky  
0
drug treatment statistics <a href=""> https://forums.dieviete.lv/profils/127605/forum/ </a> warts remedies

Name *:
Email *:
Code *:
Search
Calendar
«  December 2009  »
SuMoTuWeThFrSa
  12345
6789101112
13141516171819
20212223242526
2728293031
Entries archive
Site friends
  • Create your own site