Forum: Projeler d-Ofis RSS
Veri.d
Sayfa:  önceki  1  2  3  sonraki 
acehreli (Moderatör) #16
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4412 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 3075
Çok güzel. :)

Daha iyi olması için bir kaç not aldım. Bunların bazılarını sen de biliyorsundur aslında... :) Bunları yazıyorum diye kötü olduğunu düşündüğümü sanma. Yalnızca "şöyle olsa daha iyi olur" havasında yazıyorum.

1) İlk olarak dikkatimi çeken, bilgilerin deneme.txt dosyasına sürekli olarak eklenmeleri oldu.

(Not: Sanırım bu konu, (4) numaralı madde halledilmeden önce halledilemez.)

Programlarda işlemleri olabildiği kadar "ya oldu ya olmadı" (transactional) şeklinde gerçekleştirmek de isteriz. Örneğin dosyaya yazarken bir hata olsa, dosyaya yarım yazılmış halde kalabiliriz.

Güvenli bir yöntem, verileri önce geçici bir dosyaya (örneğin "deneme.ara.txt" isminde bir dosyaya) yazmak, ve ancak herşey yolunda gittiyse ismini "deneme.txt" olarak değiştirmektir.

D'nin başka dillerde bulunmayan çok güzel bir olanağı var: scope. Andrei de doğal olarak onu özellikle belirtmekten hoşlanıyor. :) Şu sayfa biraz fazlaca uzun ama "scope(exit), scope(success), ve scope(failure)" başlığı scope'u anlatıyor:

  http://ddili.org/ders/d/hatalar.html

2) "deneme.txt", programda birden fazla noktada geçiyor. Bunun bazı sakıncaları var: Öncelikle bu, açıkça kod tekrarıdır; ikincisi, tablo başka bir ortama yazdırılamaz. Örneğin en azından başka bir dosyaya yazdırılabilmeli.

Burada en kolayı, veri ile yazdırma işlemini birbirlerinden ayırmaktır. veri'ye bir yazdırıcı veririz ve "şu yazdırıcıyı kullanarak yazdır" diyebiliriz. Onun da bir OutputRange olması çok yararlı olur.

3) Bir öncekine bağlı olarak, aslında kolon_sayı ve kolon_sayı_yedek üyelerinin veri ile ilgileri bulunmuyor. Onlar, yazdırma işleminin durumu ile ilgili geçici değişkenler. Yazdırma işi veri'den ayrıldığında sanırım onlar da veri'den çıkacaklar

4) Veriler dosyada yaşıyorlar. Bunun bir sakıncası yavaşlıktır. Bence en iyisi, bütün veriyi bellekte, örneğin bir eşleme tablosunda veya bir dizide oluşturmak ve en sonunda birisi "kaydet" dediğinde dosyaya yazmaktır. İşte (1) numaralı maddeki scope'tan da şimdi yararlanabiliriz. "kaydet" dendiğinde her veri ara dosyaya yazılır, vs.

Burada üstü kapalı olan bir gerçek var: bütün veri parçaları aslında dizgi. Sonuçta herşey dosyaya dizgi olarak yazılıyorlar. Bu yeterli olabilir; hatta veri'nin temel amacı zaten budur da... Ama belki de veri'yi herhangi bir türle kullanmayı da düşünebiliriz:

class Kişi
{
    // ...
}

Sonra veriEkle() de o türü alabilir... Ama bu noktada belki de gereksizce geliştirmeye çalışıyorum... :/ Belki de sınıfın amacı bu kadar esnek olmak olmayabilir.

5) main'in içindeki adımlardan anlaşıldığı gibi, programcı olayların gelişimi ile çok ilgilenmek zorunda kalıyor.

En azından, main içinde bazı adımların tekrarlandıkları görülebilir ve bunlar bir işleve taşınabilir (uyarı: derlemeden yazıyorum):

void kişiEkle(veri tablo, string ad, string soyad)
{
    tablo.veriEkle(ad);
    tablo.veriEkle(soyad);
    tablo.satırBitti();
}

Böylece main içindeki kodlar kolaylaşmış olur. Kodların tekrarlandıklarını farkedip onları böyle işlevlere taşımak programcılığın hep yapılan işlemlerindendir. :)

6) Yukarıdaki gözlemler altında, sınıfın ismi olarak veri artık uygun olmamaya da başlamış. Bana sanki veri çok alt düzey bir isim gibi geliyor. Tablo adını taşıyan bir üyesi olduğuna göre bu haliyle aslında belki de bir VeriTablosu denmeli...

Ama dediğim gibi, bence aslında çok güzel. Hatta amacı karşılıyorsa hiçbir değişiklik de yapılmamalıdır. :)

Eğer herhangi bir yerini değiştirmeye karar verirsen ve takıldığın bir yer olursa burada (ama belki de başka bir başlık altında) konuşalım.

Ali
Kadir Can #17
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Gerçekten çok teşekkür ederim.Bu benim geliştirdiğim ilk projelerden biri ve acemiliklerim oluyor.Sizler gibi uzmanların tavsiyelerine göre yazılıma şekil vereceğim.Benim işim kod yazmak gibi yani.
Kadir Can #18
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Dosya olayıyla ilgili olarak vtOluştur işlevini yazdım.Fakat hatalı.Bakabilir misiniz?
acehreli (Moderatör) #19
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4412 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
vtOluştur içindeki dosya isminin geçerliliği o işlevle sınırlıdır. Üstelik, orada oluşturulan File nesnesinin de yaşamı o işlevden çıkıldığında sona erer.

Derleme hatasının nedeni, tabloOluştur ve diğer işlevlerde kullanılan dosya'nın ne olduğunun bilinmiyor olmasıdır.

class veri
{
    const char[] tab_adı;
    int kolon_sayı;
    int kolon_sayı_yedek;
    int id;
    string dosyaAdı;
 
/* ... */
 
    void vtOluştur()
    {
    File dosya=File(dosyaAdı,"a");
    }
/* ... */
    void tabloOluştur()
    {
        dosya.writeln(tab_adı);   // <--- Bilinmiyor!
    }
 
/* ... */
 
void main(){
 
veri vt=new veri("Kişiler");
 
vt.vtOluştur();

Bu hatayı gidermek için dosya'yı verinin bir üyesi yapabilirsin:

class veri
{
/* ... */
    File dosya;
 
    this(const char[] tab_adı)
    {
        /* ... */
        this.dosya = File(dosyaAdı,"a");
    }
    
    void vtOluştur()
    {}

Tabii vtOluştur'a da gerek kalmamış olur. Hmmm... Yoksa ona gerek var mı?

Yani tek bir veri sınıfının birden fazla tablosunun bulunmasını mı istiyoruz, yoksa veri zaten tek bir tabloyu mu modelliyor?

Ali
acehreli (Moderatör) #20
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4412 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Amacı hatırlamaya çalışıyorum: veri tabanı gibi çalışan bir sınıf oluşturmak istiyoruz. Bu sınıfın nesnelerinin içine attığımız veriler bir dosyada belirecekler.

Bir soru: Daha önceden dosyada bulunan veriler de geçerli olacaklar mı? Yani "ali" verisine yazdığımızda var olan veri mi değişecek, yoksa dosyanın sonuna yeni bir "ali" mi eklenecek?

Dosya içindeki belirli bir kayıda gitmek çok zordur. Özellikle metin halindeki dosyalarda kayıtların uzunlukları da eşit olmayacaklarından, "'ali' kaydını bul" gibi bir işlem için bütün dosyanın baştan taranması gerekir. (Hızlandırıcı yöntemler de kullanılabilir ama bir sürü karmaşıklık getirir.)

Konuya bir kere de elimizdeki araçlarla başlayarak bakalım. Zaten eşleme tabloları var. O neden yetmiyor? Çünkü kaydetme olanağı yok. Kabul.

O eksikliği veri isminde bir sınıfla gidermek istiyoruz. O da kabul. Yani bu sınıfın yararı, yapılan her değişiklikte dosyanın da değişmesi oluyor, öyle mi?

Tabii veri'de bir eksiklik var: verilere nasıl erişileceğini hiç konuşmadık. Acaba perde arkasında bir eşleme tablosu kullanmak yararlı olur mu? Şöyle bir şey?

class veri
{
    Kişi[string] veri;
    /* ... başka üyeler */
 
    void ekle(string anahtar, Kişi değer)
    {
        veri[anahtar] = değer;
        kaydet();
    }
 
    Kişi eriş(string anahtar)
    {
        return veri[anahtar];
    }
 
    /* ... */
}

Yani verinin depolanmasının bir eşleme tablosu halleder, biz de değişikliklerde dosyayı baştan yazarız. (Sonuna eklemek olmuyor tabii ki; programı her çalıştırdığımızda dosya aynı kayıtlar tekrarlanarak büyüyor.)

Tabii şimdi de konu kaydet()'in nasıl yazılması gerektiğine geliyor. Kişi nasıl bir türdür? Bu sınıf her türle çalışmalı mıdır? (Bence her türle çalışmasını istemiyorsun. Bu her sütunun string olduğu bir tablo. Yani bunun üstünde bir soyutlama ile ilgilenmiyorsun.)

Bence en azından şöyle olmalı (bu fikirde kararlıyım :) : Bütün tablo, bellekte durmalı. Tablo, kullanıcıların veriEkle, satırBitti, vs. gibi işlevleri doğru çağırmasına dayanmamalı. Kullanıcılar bize tutarlı bir nesne vermeliler, biz onları depolamalıyız ve ancak ya kullanıcı söylediğinde, veya otomatik olarak dosyaya kaydetmeliyiz.

Örnek:

module veri;
import std.stdio;
import std.string;
import std.file;
 
class veri
{
    string[][] kayıtlar;
    string dosyaAdı;
 
    this(string dosyaAdı)
    {
        this.dosyaAdı = dosyaAdı;
    }
 
    void ekle(string[] kayıt)
    {
        kayıtlar ~= kayıt;
 
        /* Otomatik kayıt yerine kaydet()'i kullanıcının açıkça çağırmasını da
         * isteyebiliriz */
        kaydet();
    }
 
    void kaydet()
    {
        auto geciciDosyaAdı = dosyaAdı ~ "gecici";
        auto dosya = File(geciciDosyaAdı, "w");
        scope(failure) remove(geciciDosyaAdı);
 
        /* ... burada kayıtlar yazılır; ben öylesine bir şey yazıyorum  */
        foreach (kayıt; kayıtlar) {
            foreach (sütun; kayıt) {
                dosya.writeln(sütun);
            }
            dosya.writeln();
        }
 
        rename(geciciDosyaAdı, dosyaAdı);
    }
}
 
void main()
{
    auto v = new veri("deneme.txt");
    v.ekle(["ali", "ankara" ]);
    v.ekle(["veli", "van"]);
 
    /* Veya dinamik bir kayıt oluşturarak */
    string[] kayıt;
    kayıt ~= "zeynep";
    kayıt ~= "zonguldak";
    v.ekle(kayıt);
}

Orada scope'un da bir örneğini gösterdim. Geçici bir dosyaya yazıyoruz ve en sonunda geçici dosyanın ismini asıl dosyanın ismi olarak değiştiriyoruz.

Ama eğer bir hata olursa (yani "failure" durumunda), geçici dosya remove ile otomatik olarak silinecek. scope(failure)'ın yararı o.

Ali
Kadir Can #21
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Gerçekten çok güzel yazmışsınız.Şimdi sıra gerçekleştirmede.İki boyutlu dizi olayı güzel.Onu yapmaya çalışacağım.
Şu anda dosyaları seçmemin nedeni,dosyaları düşünüyor olmam değil.Programı değiştirdiğimde oluşan değişiklikleri görmek istiyordum..Fakat kaydet() gibi bir fonksiyonu da yazarsam dosyalardan kurtuluruz. :D
Kadir Can #22
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yavaş yavaş gerçekleştiriyorum.Şu arama işlevlerini yazınca(O arada bir de eşleme tablolarına çalışacağım.) eşleme tablolarına komple geçiş yapacağım.

Bazı işlevleri ve kolon sayısı kısıtlamalarını kaldırdım.

çokluEklemeyi desteklemeye karar verdim ve çokluKolonOluştur işlevini yazdım.

Bir inceleme yazınızı daha görmek isterim.

Fazla mı yükleniyorum size?Öyleyse özür dilerim.
acehreli (Moderatör) #23
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4412 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Kadir Can:
eşleme tablolarına komple geçiş yapacağım.

Kesinlikle! Kullanımları da çok kolay... :)

Notlar:

- vtOluştur() içindeki dosya, yerel bir nesne:

    void vtOluştur()
    {
    File dosya=File(dosyaAdı,"a");
    }

dosya, o işleve girildiğinde oluşturuluyor ve o işlevden çıkıldığında sonlanıyor. Şimdiki haliyle o vtOluştur'un hiçbir etkisi kalmamış

- Hazır elin değmişken daha önce de şöylediğim şu kısaltmayı da kullanabilirsin:

    void çizgiÇek(const char[] ÇizgiŞekli)
    {
        for(int i=0;i<=90;i++){
        dosya.write(ÇizgiŞekli);
        }
        dosya.writeln();
    }

yerine

import std.string;
// ...
    void çizgiÇek(const char[] ÇizgiŞekli)
    {
        dosya.writeln(repeat(ÇizgiŞekli.idup, 90));
    }

Doğrusunu istersen .idup çağrısına gerek olmamalı; Phobos ufak düzeltmelerden geçtikçe o da ileride hallolur.

Fazla mı yükleniyorum size?

Tabii ki değil. :)

Ali
Kadir Can #24
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkür ederim.repeat() işlevini de halledeyim.

Bir şey sormak istiyorum.

Eşleme tabloları kullanacağız ,eşleme tablolarında 2den(key ve value) haricinde veri tutmak mümkün mü?
Bu mesaj Kadir Can tarafından değiştirildi; zaman: 2011-01-05, 09:59.
canalpay (Moderatör) #25
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Bende şu okulu temiz bir biçimde halledeyim sana yardımcı olmaya çalışacağım. Şuanlık hiç bakmadan sadece soruna yanıt veriyorum:

Eşleme tabloları kullanacağız ,eşleme tablolarında 2den(key ve value) haricinde veri tutmak mümkün mü?
Evet. Örneğin şurada bende kullanmışım: http://code.google.com/p/dkv/source/browse/trunk/d…?r=49#24
(24 ve 25.satırda tanımlamışım.)



Tanımlanması dchar gibi. Nasıl dchar[] deyince dchar dizisi oluyor aynen öyle.dchar[][] deyincede dchar[] dizisi oluyor dchar[] ise dchar dizisi...

Örneğin orada
bool değiştirildi_mi[string][string][string];

şeklinde tanımlamışım.

eşleme tablosuna özel işlevler işleçler nasıl kullanacağını konuyla az ilgisi olan bir konuda görebilirsin: http://ddili.org/forum/thread/228

Orada örneğin şöyle bir eşleme tablosu tanımlamışım:
bool değiştirildi_mi[string][string][string];

Ve şöyle bir biçimde işleçleri kullanmışım:
 
if(("ilk" in değiştirildi_mi)/*amaç değiştirildiğimi tablosunda ilk diye bir veri var
 mı diye bakmak.*/&&("ikinci" in değiştirildi_mi["ilk"]*/eğer varsa ilk eşleme tab
losuna erişip ikinci diye veri var mı diye bakmak.)
&&("üçüncü" in değiştirildi_mi["ilk"]["ikinci"])/*Eğer ikincide de varsa 3.ye bakm
ak.*/)
Kadir Can #26
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkürler canalpay.Yakında eşleme tablolarına geçerken yardım eder misin?
acehreli (Moderatör) #27
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4412 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #25
İyi fikir Can: Önce okul! :)

canalpay:
Orada örneğin şöyle bir eşleme tablosu tanımlamışım:
bool değiştirildi_mi[string][string][string];

Öyle olur ama onun bir sakıncası da görülebilir. Orada, değiştirilme bilgisi veriden ayrı olarak duruyor. Veriyle ilgili başka bilgiler de olsa, örneğin sıkıştırılmış mı, şifrelenmeli mi, vs., o zaman aynı biçimde devam edersek iki eşleme tablosu daha gerekebilir:

bool sıkıştırılmış_mı[string][string][string];
bool şifrelenmiş_mi[string][string][string];

Bunu ben de eskiden C'de yapıyordum; ama yapıların yararını anladıktan sonra bir daha o duruma düşmedim veya düşmemeye çalıştım. :) Bu işin daha iyisi, ilgilendiğimiz bütün bilgiyi bir arada (bir yapıda veya bir sınıfta), tutmak olabilir.

Kadir Can'ın sorusunun yanıtı, hayır, eşleme tablolarında yalnızca indeks (anahtar) ve değer tutulabilir. Ama Can'ın da gösterdiği gibi, değer olarak başka eşleme tabloları da kullanılabilir; veya benim burada önereceğim gibi bir sınıf kullanılabilir.

Belirli indeksle ilgili olan bilgiler o sınıfın içinde tutulur.

import std.stdio;
import std.string : format;
 
class KayıtBilgisi
{
    /* Asıl veri bu; örnek olsun diye int seçiyorum; herhangi başka bir tür de
     * olabilirdi */
    int veri;
 
    // Bunlar o veriyle ilgili ek bilgiler
    bool değiştirildi_mi;
    bool sıkıştırılmış_mı;
    bool şifrelenmiş_mi;
    /* ... ve daha başka kayıt bilgileri ... */
 
    /* Bir kayıt oluşturulabilmesi için veri değerinin bize söylenmesi şart; o
     * yüzden bunu kurucu işlev parametresi olarak almak istiyoruz */
    this(int veri)
    {
        this.veri = veri;
        /* Diğerlerinin ilk değerleri 'false'tur; öyle bırakıyorum ama
         * özellikle kendimiz de atayabilirdik */
    }
 
    /* Bu nesneyi güzelce string'e dönüştürmek için */
    override string toString() const
    {
        /* Örneğin şöyle bir düzende: */
        return format("%s (%s,%s,%s)",
                      veri, değiştirildi_mi, sıkıştırılmış_mı, şifrelenmiş_mi);
    }
}
 
/* Bu, anahtar olarak string kullanan ve içinde KayıtBilgisi tutan bir eşleme
 * tablosudur. Programda 'KayıtTablosu' gibi güzel bir ismi olsun diye burada
 * 'alias' ile ona güzel bir isim veriyoruz. (Yani bu adım şart değil ama
 * yararlı.) */
alias KayıtBilgisi[string] KayıtTablosu;
 
void main()
{
    /* İstenirse hazır değerlerle ilklenebilir: */
    KayıtTablosu tablo = [ "kadir can" : new KayıtBilgisi(42),
                           "can"       : new KayıtBilgisi(7),
                           "ali"       : new KayıtBilgisi(3) ];
 
    /* Veya çalışma zamanında veri eklenebilir: */
    tablo["veli"] = new KayıtBilgisi(18);
 
    /* Daha sonradan: */
    foreach (indeks, değer; tablo) {
        writeln(indeks, ": ", değer);
    }
 
    /* Bir verinin tabloda bulunup bulunmadığını görmek için */
    auto bulunan = "şükran" in tablo;
 
    if (bulunan) {
        /* 'bulunan'ın türü bir göstergedir; onun için değerine '*' ile
         * erişiyoruz */
        writeln("bulunan kayıt: ", *bulunan);
 
    } else {
        writeln("Öyle bir kayıt yok");
    }
}

Aslında o programda da bir kopukluk var: kayıtların indeksleri ile kayıtlar birbirlerinden ayrı duruyorlar. Evet, indeks ve kayıtlar eşleme tablosu tarafından bir arada tutuluyorlar ama bazen indeks de asıl verinin parçasıdır. O zaman 'int' gibi basit veri türü yerine indeksle asıl veriyi bir arada tutan bir yapı veya sınıf kullanılabilir.

Programı şu şekilde değiştirmeye başlayabiliriz:

struct Veri
{
    string isim;      // <-- indeks de aslında Veri'nin parçası
    int kapıNumarası;
}
 
class KayıtBilgisi
{
    Veri veri;
/* ... */
    this(Veri veri)
    {

Kadir Can, şu dersi görmüş olduğunu ve anlamadığını varsayıyorum: ;)

  http://ddili.org/ders/d/esleme_tablolari.html

Bana o dersi daha kolay anlaşılır yapmamda yardım eder misin. Seni neresinde kaybettim? :)

Ali
Kadir Can #28
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Aslında ders oldukça açıklayıcı.Son bir haftaya kadar D ile ilişiğimi kesmiş olduğum için ben unutum.Yoksa derste sıkıntı yok.

Yapı fikri iyi gibi duruyor.Yapıları hatırlıyorum.

Sizce eşleme tablosu mu,yapı mı,yoksa karışık kullanımı mı?
acehreli (Moderatör) #29
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4412 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Daha fazlası gerekene kadar bu konunun #20 numaralı yazısındaki programdaki gibi olabilir bence:

string[][] kayıtlar;

Başka çözümleri yetersizlikler görüldükçe düşünürüz.

Ali
Kadir Can #30
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkürler.
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  önceki  1  2  3  sonraki 
Forum: Projeler d-Ofis RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-06-24, 11:59:04 (UTC -07:00)