18 Mart 2018 Pazar

Mobil uygulamalardan bir veritabanına niçin bağlanmamalısınız!

Craig Chapman'ın aynı başlıklı yazısını okuyunca bunu kendi sözcüklerimle de harmanlayarak, aktarmak ve yaymak gerektiğini düşündüm. Özellikle tüm masaüstü Delphi yazılımcıları, böylesi işlerine kolay geldiği için, program mimarisinde değişiklikler olmaması için bu yola gidiyorlar. Ancak bilin ki bu çıkmaz yol!

Elbette mobil uygulamadan veritabanına bağlantıyı tümüyle reddetmek mümkün değil. Hele ki bu veritabanı mobil cihazda tutulan lokal bir veritabanıysa...


  • Ancak herşeyden önce bu veritabanı sunucularının, mobil cihazlar için, client library desteğinin olup olmadığını sorgulamamız gerekiyor. Örneğin, bildiğime göre şu anda Arm işlemcide çalışan Android OS için bilinen SQL sunucular için client kütüphanesi yok. Diğer bilinen SQL sunucular için de aynı durum geçerli. Buna istisna olarak; Bazı veritabanı üreticileri client library de üretiyorlar ancak ben bunlarla çalışmadım. Bazı veritabanlarına da ODBC ya da JDBC kullanarak bağlanmak mümkün. Ancak şu unutulmamalı ki bu yöntem native bağlantı gibi hızlı olmayacaktır.
  • İkinci olarak veritabanı bağlantısının kalıcı olması mobil cihazlarda mümkün değildir. Yani programı açtığınızda bağlantı açılacak, kapanıncaya kadar bu bağlantı üzerinden işlemler yapılacaktır?.. İşte bu mobil cihazlarda pek mümkün görünmemektedir, çünkü arada bağlantı gittiğinde program bağlantı hatası verecektir. Ancak program yapısını SOAP ya da REST client tarzı bir mimariye çevirirseniz bu sistem kullanılabilir. İyi de bunun için mimariyi değiştirmek gerekiyor. O zaman bunun sahicisini yapıp REST sistemi kullanın!
Tüm bu sıkıntıya girmek yerine REST client-server sistemini kullanmak çok daha mantıklı olacaktır. Üstelik Delphi bu konuda inanılmaz destek vermektedir ve sistemlerini müthiş geliştirmiştir. Eski sistemlerinizi kısa sürede bu sisteme geçirebilirsiniz. Burada yaşayacağınız en büyük sorun FMX grid konusunda olacaktır (bu görüş benden). Buna rağmen bu zorlukları aşabilirsiniz. 


Masaüstü ve MS Windows hegemonyası bitti. Yeni bir devir başlıyor ve Delphi de bu dünyadaki yerini sağlamlaştırmaya, genişletmeye çalışıyor. Size de aynısını tavsiye ederim. (Bunlar da benden MÖ).

17 Mart 2018 Cumartesi

Generic (soysal) listeler ve kullanımı - 1

Delphi de diğer dillerdeki gibi Generic listeleri object pascal içine alarak dildeki önemli geliştirmelerden birini gerçekleştirmiş oldu.

Generic nedir: Bir listeye, liste elemanı olacak şeyin (değişken, nesne ve her neyse) tipini vererek, liste içinde yapılan tüm işlemlerin bu tipe göre yapılmasını sağlayabilen listelerdir.

Örnek verirsek, önce bir Console projesi yaratalım. Sonra aşağıdaki kodları yazalım

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;
var
  tamsayiliste : TList<Integer>;
  i : integer;
begin
  tamsayiliste := TList<Integer>.Create;
  tamsayiliste.Add(181);
  tamsayiliste.Add(22);
  tamsayiliste.Add(11); 
  tamsayiliste.Add(17);
  for i in tamsayiliste do
    WriteLn(i);
  ReadLn;
end.

Bunu çalıştırdığımızda sırayla eklediğimiz rakamları yazacaktır. Bu listeye farklı tipte bir eleman eklemeye çalıştığımızda derleme esnasında hata verecektir. Bu da bize büyük esneklik sağlayan bir gereç veriyor. 
Bize ne sağlar: Her ayrı tip için ayrı bir liste sınıfı yazmamız gerekiyordu.
Önceden TList kullandığımızda elemenın tipi Pointer idi. Haliyle bunu şu şekilde yapıyorduk;

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;
var
  lst : TList;
  i : integer;
begin
  lst := TList.Create;
  lst.Add(Pointer(181));
  lst.Add(Pointer(22));
  lst.Add(Pointer(11));
  lst.Add(Pointer(17));
  for i:=0 to lst.Count-1 do
    WriteLn(IntToStr(Integer(lst[i])));
  ReadLn;
end.
Eğer string'lerden oluşan bir liste istiyorsak TStringList'i kullanmak ya da TList'i değiştirmek gerekiyordu. Şimdi ise bunlara hiç gerek kalmadı. Yapmamız gereken sadece;

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections;
var
  lstr : TList<string>;
  s : string;
begin
  lstr := TList<string>.Create;
  lstr.Add('Ahmet');
  lstr.Add('okula');
  lstr.Add('gelecek,');
  lstr.Add('ama yarın...');
  for s in lstr do
    Write(s+' ');
  ReadLn;
end.

Bu listeye string'den başka bir tip eklemeye kalksak bize hata verecektir. Bu da bize, üst düzey dillerin çok önem verdiği ve önemli hata kaynaklarından biri olan, Type Safe (Tip Güvenliği)'ni sağlayacaktır. Yani bir tamsayı listesine başka bir tipte değişkeni eklememizi engelleyecektir.

Generic listeleri her tür class'lar için de kullanabiliriz.

program Project1;
{$APPTYPE CONSOLE}

{$R *.res}
uses
  System.SysUtils,
  System.Classes,
  System.Generics.Collections;

type
  TContact = class
    ContactId : Integer;
    ContactName : string;
    BirthPlace : string;
    BirthDay : TDate;
    Gender : string;
    function ToString : string; override;
    constructor Create(aContactId : Integer; aContactName : String; aBirthPlace : String; aBirthDay : TDate; aGender : String);
  end;

{ TContact }

constructor TContact.Create(aContactId: Integer; aContactName, aBirthPlace: String;
  aBirthDay: TDate; aGender: String);
begin
  ContactId := aContactId;
  ContactName := aContactName;
  BirthPlace := aBirthPlace;
  BirthDay := aBirthDay;
  Gender := aGender;
end;

function TContact.ToString: string;
begin
  result := IntToStr(ContactId)+'/'+ContactName+'/'+BirthPlace+'/'+DateToStr(BirthDay)+'/'+Gender;
end;

var
  MyContacts : TList<TContact>;
  fcon : TContact;
begin
  MyContacts := TList<TContact>.Create;
  MyContacts.Add(TContact.Create(1, 'Ahmet Acar', 'Rize', EncodeDate(1977, 1, 10), 'Erkek'));
  MyContacts.Add(TContact.Create(2, 'Çoşkun Pireli', 'Artvin', EncodeDate(1992, 5, 3), 'Erkek'));
  MyContacts.Add(TContact.Create(3, 'Mehmet Kesmez', 'Bolu', EncodeDate(1983, 11, 27), 'Erkek'));
  MyContacts.Add(TContact.Create(4, 'Cahide Küskün', 'Eskişehir', EncodeDate(1996, 6, 12), 'Kadın'));

  for fcon in MyContacts do
    WriteLn(fcon.ToString);
  ReadLn;
end.


Peki bu listeye farklı bir class eklemeye kalkarsak ne olur. Önce yukarıya şöyle bir sınıf tanımlayalım;
type
  TInvalidContact = class
    Id : Integer;
    Name : string;
  end;

daha sonra ise bunu listeye eklemeye çalışalım;
...
...
  MyContacts.Add(TInvalidContact.Create);
...
...
...


İşte Generic listin özelliği burada belli olacak. Bu satıra derleme hatası verecek ([dcc32 Error] Project1.dpr(nn): E2010 Incompatible types: 'TContact' and 'TInvalidContact'). Ve bu tür hatalar da bizi büyük hatalardan koruyacak!...
















1 Mart 2018 Perşembe

Firemonkey ListView veri tabanıyla birlikte kullanımı

FMX kütüphanesinin en yararlı elemanlarından birisi ListView'dur.

İlk amacımız şu görüntüdeki bir ana form elde etmek olacaktır.



1-Bunun için öncelikle yeni bir boş MultiDevice Application oluşturup onu diskte bir klasöre kaydedelim.
2-Form üzerine önce bir ClientDataSet ve bir ListView koyalım onu görüntüdeki gibi düzenleyelim.
3-ClientDataset1 üzerinde sağ-klik yapıp <Load from MyBase Table...> seçeneğini tıklayalım ve açılan Open Dialog'da biolife.xml'i seçelim (biolife.xml kurulu Delphi sürümünün Samples\Data klasörü altındadır.).
4-ListView1 üzerinde sağ klik yapıp Toggle Designmode'a tıklayalım.


Bu şekildeki gibi ListView1 görünümü değişecektir. Şimdi bunun üzerine bir Image alanı ve bir de 2. bir Text alanı ekleyelim.
5-ListView1'in ItemAppearance özelliğinin detaylarını açalım.


6-Burada ItemAppearance özelliğini DynamicAppearance olarak değiştirelim. Artık ListViewItem'a istediğimiz kadar metin ve resim ekleyebiliriz.
7-Bu aşamada Item'e yeni alanlar eklemek için üstteki Structure penceresinden Item'i seçelim. Bunun property editor'unde Add new'a tıklayalım ve TTextObjectAppearance 'ı seçelim. Burada bize 2 adet text alanı verecektir (Text1 ve Text2).
8-Yine aynı şekilde Add new'a tıklayıp TImageObjectAppearance'ı seçelim bu kez.
Text1'e Biolife tablosunun CommonName alanını, Text2'ye ise SpeciesName alanını ve Image3'e de aynı tablonun Graphic alanını yazdıracağız. Şimdi bu alanları ekranda düzenleyelim.

9-Yine üstten Item'ın sırayla Image3, Text1 ve Text2'sini seçip yerleştirelim.








Sonuçta şöyle bir görüntü çıkacak.

10-Şimdi ClientDataSet1 ve ListView1'i birbirine bağlayacağız. Bunun için Menu'den View/LiveBindings Designer'i seçelim.
11-Burada ClientDataSet1 ve ListView1 görülecektir. ClientDataSet1'in * alanını ListView1'in Synch alanı ile birleştirelim. (Yani önce * alanının üzerinde tıklayıp parmağımızı kaldırmadan bunu Synch'ya kadar uzatalım. İki alanın bir okla birbirine bağlandığını ve Designer'in otomatik olarak BindSourceDB1 adlı yeni bir nesneyi eklediğini göreceğiz. Şimdi Common_Name'i tutup Item.Text1'le, Species Name'i tutup Item.Text2 ile ve Graphic'i tutup Item.Image3'le birleştirelim.
12-ListView1 üzerinde sağ klik yapıp menüden ToggleDesignMode'ye basalım. Şimdi formumuz şu hale geldi...

13-BindSourceDB1 üzerinde sağ klik yapıp Add Navigator'ı seçelim ve düzgün bir şekilde yerleştirelim...
14-Programı çalıştıralım...