Yazdığım kodu inceler misiniz? (Python ve OOP)

Öncelikle, kod bir miktar uzun olduğu için codeshare üzerinden paylaştım:

https://codeshare.io/5QVNje

Dostlar, henüz Python’da acemi olduğumu belirtmek isterim. Bu sıralar da Nesne Tabanlı Programlama’nın temel mantığını anlamaya çalışıyorum kendimce. Bu gece bu kodu yazdım. Sizlerden ricam, kodda gördüğünüz mantıksızlık var ise eğer veyahut da daha kısa yazılabilirdi dediğiniz kısımlar varsa, yorumlamanız olacaktır. :slight_smile:

Ayrıca kendimce bazı konuları kavramak açısından bir iki soru sormak da istiyorum:

1- Class, programda yazılacak kodları öncelikle daha düzenli ve tertipli yazmamızı sağlayan bir araçtır. Classlar, özelden genele doğru düşünüldüğünde yazılacak kısmın en genel parçasını ifade eder. Yalnızca gerçek hayattaki nesneler gibi düşünmek doğru olmaz, programın içinde kendi içinde dallanan ve özelliklere sahip olan her bölümü classların içinde kodlamak doğru olacaktır. Sizce bu doğru mudur? Ben kendimce bu şekilde anlamlandırdım.

Mesela ben yukarıdaki kodda da aynı şekilde, tkinter ile tasarladığım basit bir formu programın ana gövdesi gibi düşünerek, genel bir class içine aldım. Ve bu ekranı atadığım her nesnede, ki bu koda göre tek bir nesne olacak bu, init sayesinde yapılması gereken işlemleri de yazdım.

Sanırım denilebilir ki tek bir program için OOP kullanmana gerek yoktu. Ancak şunu da sormak istiyorum:

Mesela ben bu programa giriş yapıldıktan sonra bir ekran, o ekranda da farklı işlemler yapmaya yarayacak özellikler eklemek istiyorum. Mantıken bu alanı da ayrı bir sınıf gibi mi düşünmeliyim?

Ayrıca, PEP8 hatası olarak özellikle şu hatayı alıyorum:

instance attribute defined … outside init

Normal şartlar altında instance fonksiyonu tanımlamak için initin dışına yazmam gerekmez mi?

Çok uzattıysam kusuruma bakmayın. Zaman ayırıp cevap vereceklere şimdiden çok teşekkürler :slight_smile:

Bu konuya detaylı bir cevap yazamam fakat bu projemi incelemenizi önerebilirim. Bu basit oyun projesi de nesne tabanlı programlama mantığıyla kodlandığı için neden bu mantıkla kodlanmasının istenebileceği fikrini kapabilirsiniz ve belki de bu sayede ne zaman OOP kullanmak isteyebileceğinizi daha iyi seçebilirsiniz.
Şahsen ben OOP kullanmayı hem hoşuma gittiği için hem de OOP ile kodlamanın bana daha kolay geldiğini düşündüğüm için tercih ettim.

Ben de belirttiğim projemde yalnızca bir class kullandım ve dolayısıyla bütün içerik o classın içerisinde yer alıyor. Kaç tane class oluşturulacağı fikrinin tercih meselesi olduğunu ve bir gereklilik ya da gereksizlik olarak nitelendirilemeyeceğini düşünüyorum.

Kodlarınızı inceledim hocam. Takdir edersiniz ki başlangıç aşamasındaki birisi olarak, anlayamadığım pek yer oldu ama tabi bu sebeple kodlar daha da bir ilgimi çekti :)) Gerçekten çok güzel düşünülmüş, ellerinize sağlık.

OOP kullanımınız hakkında da söyleyebilirim ki sanıyorum benim kendimce düşünerek yazmaya çalıştığım kod biçimi ile aynı mantıkta kodlamışsınız. Evet, NTP sayesinde daha güzel, daha anlaşılır ve derli toplu kodlar yazabildiğimizi düşündükçe, ben de neredeyse her kod yazarken bu yöntemi kullanabilirim :slight_smile:

İlginiz ve cevabınız için çok teşekkür ediyorum.

1 Beğeni

Bu hatanın sebebi __init__ metodu dışında örneklere yeni nitelikler eklemeniz. register_name niteliği __init__ değil, user_register metodunda tanımlanıyor mesela.

1 Beğeni

Hocam anladım ancak ben register_name kısmını ayrı bir pencere olarak tasarladım. Yani o fonksiyon bir butona basınca çalışacak. Hal böyleyken onu init içine yazamadım.

Pekala örneğin user_register kısmını bir başka class olarak mı tanımlamak doğru olur sizce? Orada da butona basıldığı vakit, otomatikman yeni attribute’lar biçiminde “Kayıt Sayfası” oluşsun örneğin. Olur mu sizce de?

        self.form.mainloop()

Objenin kullanima hazir/kararli bir duruma gelmesine yardimci olacak seyler disinda, init’te is yapilmamali. Hele GUI ana loop’unu baslatmak kadar buyuk (ve sanirim asla donmeyecek) bir is objenin sahibine birakilmali. Sirf bunu yapan yardimci bir fonksiyon yazilabilir.

GUI’lerde her seyi init esnasinda (belki yardimci fonksiyonlarla beraber) yaratip programin akisina gore gerektiginde gosterip/saklamak fena bir pattern degil.

        if not len(self.register_name_entry.get()) == 0 and not len(self.register_mail_entry.get()) == 0 and not len(self.register_pas_entry.get()) == 0:
            if "@" in self.register_mail_entry.get() and "." in self.register_mail_entry.get():
                self.vt = sql.connect("veritabanı.sqlite")

Asil kodu dogrulama if’lerinin altina yazmaktansa erken return kullanilabilir:

if hede_yanlis():
    print("hede yanlis")
    return

if not hodo_dogru(): 
    print("hodo yanlis")
    return

ana kod
                self.vt = sql.connect("veritabanı.sqlite")

Veritabani dosyasinin ismini ve yerini belirlemeyi register_database fonksiyonuna vermek yanlis. Parametre olarak almali. Parametre olarak almasinin mantikli olmadigi (bunun gibi) durumlarda sinif uzerindeki bir degiskende durabilir. Sinif bu degeri parametre olarak aliyorsa da almiyorsa da init’te tanimlanabilir.

sqlite cursor’larinda RAII olmasi lazim. (with cursor() as cur) Varsa kullanilmali.

Bu, kodu moduler hale getirmemize yarayan her arac icin gecerli: Module, namespace, compilation unit, dosya, library, fonksiyon.

Class daha cok disaridan manipule edilmesi istenmeyen bir state ile bu state’i manipule eden fonksiyonlarin bir araya gelmesi icin var olan bir yapi. Diger kullanimlari ikincil.

Emin olamiyorsan once yazip sonra sinifa ayirmayi dusunmeyi deneyebilirsin.

Buyuk Tk programlari class’lari (ve diger tertip mekanizmalarini) nasil kullanmis incelemek faydali olabilir.

Fonksiyon degil, attribute’lardan (degiskenlerden) bahsediyor.

3 Beğeni

Üstadım zahmet edip cevap verdiğin için çok teşekkür ediyorum. Yani, ne kadar başarabilirim bilemiyorum ama yazdıkların üzerinde detaylıca durup temel mantığı kavramaya çalışacağım inşallah :slight_smile: