Forum: Projeler KelimeMatik RSS
Kullanıcı sınıfı tasarımı
zafer #1
Üye Tem 2009 tarihinden beri · 687 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Kullanıcı sınıfı tasarımı
Kullanıcı giriş arayüzümüz ortaya çıktığına göre şimdi bu arayüze hayat verecek işlemleri gerçekleştiren Kullanıcı sınıfını tasarlayabiliriz diye düşünüyorum. Tasarım, sınıflar konusunda çok iyi değilim o sebeple hatalar için her türlü yardıma açığım.

Benim düşündüğüm kullanıcı sınıfını kısaca şöyle özetleyebilirim.

GER : Gereksinim

GER01 : Sisteme yeni bir kullanıcı eklenebilmeli
GER02 : Sistemde mevcut kullanıcı bilgileri düzenlenebilmeli
GER03 : Sistemde mevcut kullanıcı silinebilmeli
GER04 : Kullanıcı listesi alınabilmeli

Bu bilgilerden yola çıkarak şöyle bir sınıf hazırladım,
module kullanici;
 
class Kullanici
{
    public this()
    {
        //    
    }
 
    public void KullaniciEkle(string kullaniciAdi)
    {
        //
    }
 
    public void KullaniciDuzenle(string kullaniciAdi)
    {
        //
    }
 
    public KullaniciSil(string kullaniciAdi)
    {
        //
    }
 
    public string[] VerKullaniciListesi()
    {
        //
    }
}

Benim aklımdaki kullanıcı yapısında şimdilik sadece bir kullanıcı adının yeterli olduğunu düşünüyorum isim dışında başka bir bilgi şimdilik yok. Bu sebeple işlemlerin hepsi kullanıcı ismi üzerinden yürüyor. Bundan dolayı isimlerin sistemde benzersiz olmasını sağlamamız gerekecek.

Diğer bir konu ise Kullanıcı sınıfına baktığım zaman aslında kurucu (this) ile kullaniciAdi bilgisini alıp diğer işlemlerde bunu kullanabiliriz diye düşündüm o zaman yapı şöyle olacak,

module kullanici;
 
class Kullanici
{
    private string _kullaniciAdi;
 
    public this(string kullaniciAdi)
    {
        _kullaniciAdi = kullaniciAdi
    }
 
    public void KullaniciEkle()
    {
        //
    }
 
    public void KullaniciDuzenle()
    {
        //
    }
 
    public KullaniciSil()
    {
        //
    }
 
    public string[] VerKullaniciListesi()
    {
        //
    }
}

Hangisi daha iyi olur şimdilik bir karar veremedim. tabi eksikler ve fazlalar içinde yardımınızı beklerim. Ne dersiniz? hangi tasarım ve neden? Ayrıca eklenecek veya çıkarılacak neler olabilir?
https://github.com/zafer06 - depo
Bu mesaj zafer tarafından değiştirildi; zaman: 2011-11-18, 21:50.
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Çok güzel görünüyor ama sanki iki farklı türün görevleri aynı sınıfta karışmışlar gibi. Çünkü burada aslında iki türe ihtiyaç var:

1) Tek kullanıcının bilgisi. Bu türün şimdilik yalnızca ismi var. Üstelik, ismi olmadan var olması da pek yararlı olmayacağından, bu türün kurucusu parametre olarak isim bilgisini şart koşabilir.

2) Kullanıcı topluluğu. Ekle, sil, vs. gibi işlemler bu türün işlemleridir. Bu tür yaşamına boş olarak da başlayabilir, kullanıcılarını dışarıdan da alabilir. Veya oku("kullanici_dosyasi") gibi bir işlevle de okuyabilir.

Kullanıcı topluluğu da kendi içinde çok basitçe bir eşleme tablosundan yararlanabilir. Kullanıcılara en basitinden isim anahtarıyla erişilebilir:Yani Kullanıcı[string] türünde bir eşleme tablosu olabilir.

İşlev isimleri de her zaman sorunlu olabiliyor. :) Eylem yapan işlevlerin "oku", "yaz" gibi emirler içermeleri uygun oluyor. Ama VerKullaniciListesi gibi yalnızca veri döndüren işlevlerde ben başka bir kuralı daha yararlı buluyorum. (Aslında bunu dizilerin 'length' niteliğinde de görüyoruz.) O gibi işlevler verdikleri verinin ismini taşıyabilirler ve @property olarak işaretlenirlerse parantez de kullanmak gerekmez. Örneğin burada kullanıcılar.liste, kullanıcılar.hepsi, vs. gibi olabilir. (Bu da aslında bir kişisel seçim; ama bana mantıklı geliyor. :))

Ali
zafer #3
Üye Tem 2009 tarihinden beri · 687 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli on 2011-11-19, 06:11:
2) Kullanıcı topluluğu. Ekle, sil, vs. gibi işlemler bu türün işlemleridir. Bu tür yaşamına boş olarak da başlayabilir, kullanıcılarını dışarıdan da alabilir. Veya oku("kullanici_dosyasi") gibi bir işlevle de okuyabilir.

Bu maddeyi anlamadım! Benim tasarlamaya çalıştığım kullanıcı sınıfının her zaman tek bir kullanıcı için çalışacağını varsayıyorum. Program yapısıdan dolayı zaten büyük bir kullanıcı listem olmayacak belki üç veya beş kişi, ayrıca toplu olarak silme veya ekleme özelliğinede ihtiyaç olmayacak diye düşünüyorum. Bu sebeplerle bir kullanıcı topluluğunu yönetecek bir yapı yerine tek bir kullanıcı yönetecek yapı kurmak niyetindeyim. Bu doğru mu yanlış mı bilmiyorum sadece anlamadığım için soruyorum? Aslında senin yaklaşımında doğru görünüyor ama yukarıda belirttiğim gibi ben kullanıcı sınıfının tek bir kullanıcı için çalışmasını istiyorum, bu doğrumu onuda biilmiyorum tabi ama tasarımı öyle düşünmüştüm.

VerKullaniciListesi gibi yalnızca veri döndüren işlevlerde ben başka bir kuralı daha yararlı buluyorum. (Aslında bunu dizilerin 'length' niteliğinde de görüyoruz.) O gibi işlevler verdikleri verinin ismini taşıyabilirler ve @property olarak işaretlenirlerse parantez de kullanmak gerekmez. Örneğin burada kullanıcılar.liste, kullanıcılar.hepsi, vs. gibi olabilir. (Bu da aslında bir kişisel seçim; ama bana mantıklı geliyor. :))

Bu konuda sana katılıyorum listeyi sınıfın bir niteliği (@property) olarak tasarlamak hem daha temiz hemde güzel bir tasarım olacak gibi kullanici.liste gibi bir kullanım benimde hoşuma gitti. VerKullaniciListesi() metodunu bir nitelik olarak tasarlamak bence de daha güzel oalcak.
https://github.com/zafer06 - depo
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
zafer:
Benim tasarlamaya çalıştığım kullanıcı sınıfının her zaman tek bir kullanıcı için çalışacağını varsayıyorum.

KullanıcıEkle gibi isimler beni yanıltmışlar demek ki. "Kullanıcı ekle" deyince "al bir kullanıcı daha, bunu ekle" gibi anlaşılıyor. O da bir kullanıcı topluluğunda anlamlı oluyor.

Eğer Kullanıcı diye bir sınıf varsa ve tek kullanıcıyı belirliyorsa, programa kullanıcı eklemekle görevli işlemler de bu sınıfın üyeleri olmamalılar. Kullanıcı sınıfının kullanıcının kendisiyle ilgili işlemleri barındırması doğru olur.

Derlenmemiş bir fikir:

class Kullanıcı
{
    string isim;   // Not: zaten Kullanıcı içinde olduğumuz için üyenin başına
                   // "kullanıcı" demek de gerekmiyor. Basitçe 'ad' veya 'isim'
                   // yeterli...
 
    string[] sorulanlar;
    string[] bildikleri;
    // ... ve kullanıcı ile ilgili başka şeyler ...
}

Programa kullanıcı ekleyen işlev en basitinden serbest bir işlev olabilir:

Kullanıcı[] kullanıcılarıOku(string dosya_ismi)
{
    Kullanıcı[] kullanıcılar;
 
    // ... kullanıcılar okundukça ...
        kullanıcılar ~= kullanıcı;
 
    // ...
 
    return kullanıcılar;
}

Bu sefer Kullanıcılar diye ayrı bir sınıf yerine Kullanıcı[] kullanmış oluyoruz.

bir kullanıcı topluluğunu yönetecek bir yapı yerine tek bir kullanıcı yönetecek yapı kurmak niyetindeyim

Yani şimdilik Kullanıcı[] yeterli.

kullanıcı sınıfının tek bir kullanıcı için çalışmasını istiyorum

Kesinlikle öyle olmalı. KullanıcıEkle ve KullanıcıSil gibi isimler beni yanılttı.

Ali
zafer #5
Üye Tem 2009 tarihinden beri · 687 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Sanırım çözüme farklı açılardan bakıyoruz buda olayı biraz karıştırıyor ama aşamayacağımız bir sorun değil  ;-)

Anladığım kadarıyla sen kullanıcıyı sıra düzenin tepesine yerleştiriyorsun ve onun altında projeyi kuruyorsun yani öncelikle bir kullanıcı diyorsun sonra kullanıcının soruları, kullanıcının cevapları ve belki kullanıcının kelimeleri, kullanıcının egzersizleri v.s.

Bense sıra düzenin tepesini egzersiz olarak düşünmüş ve projeyi onun altına kurmayı planlamıştım. Belkide yanlış bir tasarım dı? Yani ben kullanıcıyı egzersiz işleminin küçük bir parçası gibi görüyordum. Senin yazdıklarından anladığım ise esas öğenin kullanıcı olduğu bir durum. Bilmiyorum belki benim düşüncem yanlış, şöyle bir düşününce senin yapın daha doğru geliyor. Tabi eğer böyle düşünüyorsan, bunlar benim varsayımlarım, yazılarından anladıklarım yani :)

Öncelike bu noktada bir anlaşma sağlarsak sonrası netleşecektir diye düşünüyorum.
https://github.com/zafer06 - depo
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Evet, bir anlaşmazlık olduğu doğru. Ben de tam tersine, benim düşündüğümü en altta, seninkini de daha yukarıda görmüştüm! :)

sorulanlar ve bildikleri gibi üyeleri son anda ve içinde isimden başka da bir şey olsun diye yazdım. Çünkü en başta da aslında yalnızca isim olacak diye düşünüyoruz. Yani onlar da dışarı çıkabilir.

Benim kafamı karıştıran şu işlevlerdi: KullaniciEkle(), KullaniciDuzenle(), KullaniciSil(), VerKullaniciListesi(). Çünkü tek bir Kullanıcı nesnesine örneğin KullanıcıEkle() demek doğru gelmiyor. Küçücük Kullanıcı, kendisi gibi başka bir Kullanıcı eklememeli:

    auto ali = Kullanıcı("ali");
    auto zafer = Kullanıcı("zafer");
 
    ali.KullanıcıEkle("ahmet");     // ali'ye mi ekleniyor?
    zafer.KullanıcıEkle("zeki");    // zafer'e mi ekleniyor? 

Yani bu işlemler basit Kullanıcı'nın bilemeyeceği işlemler. Örneğin Ekle() denen kullanıcıyı nereye eklerler? Eğer kendileriyle ilgili bir üyeye eklemeyeceklerse bu işlemler Kullanıcı ile ilgili olmamalı.

Kullanıcılar diye başka bir türe en azından şimdilik gerek olmadığını düşünsek de şu olabilir:

    auto oyuncular = Kullanıcılar();
    oyuncular.ekle(Kullanıcı("ali"));
    oyuncular.ekle(Kullanıcı("zafer"));

Belki de KullanıcıEkle() gibi işlevleri 'static' olarak düşünüyorsun. Kullanıcı'larla ilgili bir işlem olduğu için o arayüzde bulunması doğru geliyor.

Ben senin tasarımınla gitmekten yanayım. Zaten tam olarak da anlamış değilim. Nasıl olsa değiştirmek kolay. :)

Ali
zafer #7
Üye Tem 2009 tarihinden beri · 687 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Benim kafamı karıştıran şu işlevlerdi: KullaniciEkle(), KullaniciDuzenle(), KullaniciSil(), VerKullaniciListesi(). Çünkü tek bir Kullanıcı nesnesine örneğin KullanıcıEkle() demek doğru gelmiyor. Küçücük Kullanıcı, kendisi gibi başka bir Kullanıcı eklememeli:

    auto ali = Kullanıcı("ali");
    auto zafer = Kullanıcı("zafer");
 
    ali.KullanıcıEkle("ahmet");     // ali'ye mi ekleniyor?
    zafer.KullanıcıEkle("zeki");    // zafer'e mi ekleniyor? 

Belkide kafamızdaki bir bütünü burada parça parça anlatmaya çalıştığımız için eksikler ortaya çıkıyor. Ben bu kullanıcı yönetimi ile ilgili senaryoyu baştan sona anlatayım sonra senin senaryonu dinlemek istiyorum. Çünkü farklı bir bakışın var ve bunu merak ediyorum.

Benim düşündüğüm kullanıcı yönetimi şöyle; öncelikle sisteme eklenen kullanıcıları (yani sadece isimleri) saklayacak bir dosya hazırlamayı düşündüm. Bu dosyanın isminide "kullanıcılar.xml" olarak belirledim. Sonrasında program tarafına geçince doğal olarak bu dosyayı yönetecek (ekle, sil v.s) bir yapı kurmak gerekti. Bu noktada Kullanıcı isimli bir sınıf tanımladım aslında doğrusu KullanıcıIslem olmalı burada kullanıcı biraz yanıltıcı olmuş kabul ediyorum. Bu sınıf doğal olarak dosyayı işleyecek ekleme, silme gibi metodları içermesi gerektiği için KullanıcıEkle(), KullanıcıSil() gibi metodları bu sınıfın üye metodları olarak tanımladım (burada senin daha önce belirttiğin gibi sadece Ekle(), Sil() gibi isimler kullanmak daha doğru olurmuş, ben biraz abartmışım  :-D ). Bu noktada senin yazdığın örnek kodu tekrar yazmak istiyorum, tabi biraz değiştirerek :)

    auto islem = KullanıcıIslem();
 
    islem.KullanıcıEkle("ali");     // ali artık kullanıcılar.xml dosyasına ekleniyor.
    islem.KullanıcıEkle("zafer");    // zafer artık kullanıcılar.xml dosyasına ekleniyor. 

Sanırım kodlar yapmak istediğimi kelimelerden daha iyi anlatıyor :) Yani Kullanıcı (KullanıcıIslem) sınıfının ekleme, silme v.s özellikleri dosya ile ilgili, program içerisinde mevcut bir kullanıcı topluluğu veya kullanıcı nesnesi tasarlamadım. Peki program içinde kullanıcı dediğimiz ne olacak dersen, ben sadece basit bir string türünde değişken olarak düşünmüştüm, benim kendimce tasarımım işte böyle, aklına takılan yerleri yaz tekrar anlatabilirim.

Senin bakış açın daha farklı bunu sezebiliyorum ama tabi senin durumunda olduğu gibi bende senin kafandaki tasarımı tam olarak bilmediğim için malesef anlayamıyorum ama çok merak ettiğimi söylemeliyim. Vaktin varsa sende kendi tasarımını baştan sona özetlersen çok mutlu olurum.

Ben senin tasarımınla gitmekten yanayım. Zaten tam olarak da anlamış değilim. Nasıl olsa değiştirmek kolay. :)

Senin veya benim tasarımımı kullanmak önemli değil hatta ben değişik bir fikir denemek amacıyla özellikle senin tasarımını anlamak ve kullanmak istiyorum. Tabi sende yardımcı olursan  ;-)

Değiştirmek tabi ki mümkün, neticede süre sınırlı bir iş projesi yapmıyoruz. Geliştirmek, değiştirmek, denemek, öğrenmek adına uğraşıyoruz.
https://github.com/zafer06 - depo
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ben yalnızca isimlerden yola çıkmış olduğum için tasarımım da yok. :) Farklı bir bakış açısı olsun diye şöyle düşünebiliriz:

Kullanıcı, isim (ve belki de 'şimdiki seviyesi', 'çalışmakta olduğu dil' gibi konular da) içeren basit bir tür. Bu türün bir nesnesini Oyun türündeki bir nesneye verebiliriz (bunları şu anda düşünüyorum; fazla önemsemeyelim lütfen):

    auto oynatıcı = new Oynatıcı();
    auto kullanıcı = new Kullanıcı(isim/*, ve başka (?) */);
    oynatıcı.oynat(kullanıcı);

Burada Oynatıcı'yı yalnızca soru/cevap konusunu halleden bir tür olarak görmüşüm. Kullanıcılarla ilgili konu da belki Oyun gibi daha büyük bir türe aittir:

    auto oyun = new Oyun(/* */);
    // ...
    oyun.KullanıcıEkle(yeniKullanıcıİsmi);
    // ...
    oyun.oynat(kullanıcıİsmi);

Yukarıdaki son satır Oyun'un 'oynatıcı' üyesine havale edilebilir. Hatta hangi dil kullanılacağını da oynat()'a verme fikri ile:

class Oyun
{
    Oynatıcı oynatıcı;
    Kelimeler[string] kelimeler; // Kelimeler, örneğin İngilizce'nin kelimeleri olabilir
    Kullanıcı[string] kullanıcılar;
 
    void oynat(string kullanıcıİsmi, string dil)
    {
        // kullanıcıİsmi'nin ve dil'in yasal olduklarını denetledikten sonra
        oynatıcı.oynat(kullanıcılar[kullanıcıİsmi],
                       kelimeler[dil]);
        // ...
    }
}

Ama ben gerçekten toplam 5 dakika düşündüm; seninkini anlıyorum ve kabul ediyorum. Farklı bir bakış açısı olarak kabul et.

Ali
zafer #9
Üye Tem 2009 tarihinden beri · 687 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Ama ben gerçekten toplam 5 dakika düşündüm; seninkini anlıyorum ve kabul ediyorum. Farklı bir bakış açısı olarak kabul et.

Güzel düşünmüşsün! Tabi konu parça parça olunca anlamak çok kolay olmuyor. Yinede senin kodların bana güzel fikirler verdi. Örneğin bir kullanıcı türü oluşturmak konusunda seninle aynı fikirdeyim, çünkü gördüğüm kadarıyla işlemlerde çok temiz ve kullanışlı olacak. Ancak amacım hızlı bir şekilde çalışan bir sürüm elde etmek olduğu için o konuları gereceğe bırakmaya karar verdim. Şimdilk daha basit yapılarla yola devam :)
https://github.com/zafer06 - depo
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:
Forum: Projeler KelimeMatik 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-04-30, 11:33:08 (UTC -07:00)