Bir sınıftaki öznitelikleri önceden başlatmak veya bunları yol boyunca eklemek daha iyi bir uygulama mıdır?


11

Bu KESİNLİKLE ikinci sınıf bir soru ise özür dilerim, ancak en iyi uygulamaların ne olduğunu merak ediyorum ve Google'da iyi bir cevap bulamıyorum.

Python, genellikle boş bir sınıfı bir süper-catchall veri yapısı kapsayıcı (JSON dosyası gibi bir tür) olarak kullanın ve yol boyunca öznitelikleri ekleyin:

class DataObj:
    "Catch-all data object"
    def __init__(self):
        pass

def processData(inputs):
    data = DataObj()
    data.a = 1
    data.b = "sym"
    data.c = [2,5,2,1]

Bu bana çok büyük bir esneklik sağlıyor, çünkü konteyner nesnesi temelde her şeyi saklayabilir. Yani yeni gereksinimler kırpılırsa, ben sadece DataObj nesnesine başka bir öznitelik olarak ekleyeceğim (ki benim kodumda iletiyorum).

Bununla birlikte, son zamanlarda (FP programcıları tarafından) bunun çok kötü bir uygulama olduğu beni etkiledi, çünkü kodu okumak çok zorlaştırıyor. Bir DataObj aslında ne nitelikleri bulmak için tüm kodu geçmek zorunda.

Soru : Esneklikten ödün vermeden daha fazla sürdürülebilirlik için bunu nasıl yeniden yazabilirim?

İşlevsel programlamadan benimseyebileceğim fikirler var mı?

Orada en iyi uygulamaları arıyorum.

Not : bir fikir, sınıfın karşılaşmayı beklediği tüm niteliklerle önceden başlatılmasıdır, örn.

class DataObj:
    "Catch-all data object"
    def __init__(self):
        data.a = 0
        data.b = ""
        data.c = []

def processData(inputs):
    data = DataObj()
    data.a = 1
    data.b = "sym"
    data.c = [2,5,2,1]

Bu gerçekten iyi bir fikir mi? Niteliklerimin a priori olduğunu bilmiyorsam ne olur?


Veri yapılarınız o kadar değişkendir ki, bunların sürdürülebilirliği ile ilgileniyorsunuz. Bol bol serbest zamanınızda, değişmez veri modelleri hakkında bu makaleyi okumaya çalışın . Verilerle ilgili düşünme şeklinizi tamamen değiştirebilir.
9000

@ 9000 Böyle bir makale zaten ikna olmuş olanı yeniden ikna eder. Bana göre neden daha çok nasıl yapılır gibi görünüyordu. Bana göre, VB'de faturaları güncelleyen birini, fatura nesnesinin sürekli olarak yeni kopyalarını oluşturmak zorunda kalmanın mantıklı olduğuna ikna etmiyor (ödeme ekle, yeni fatura nesnesi; parça ekle, yeni fatura nesnesi).
Paul

Yanıtlar:


10

Esneklikten ödün vermeden daha fazla bakım için bunu nasıl yeniden yazabilirim?

Yapmazsın. Esneklik, soruna neden olan şeydir. Herhangi bir yerdeki herhangi bir kod bir nesnenin sahip olduğu özellikleri değiştirebilirse, sürdürülebilirlik zaten parçalara ayrılmıştır. İdeal olarak, her sınıf, __init__her örnek için aynı ve aynı şekilde ayarlanmış bir dizi özelliğe sahiptir . Her zaman mümkün veya mantıklı değil, ancak bundan kaçınmak için gerçekten iyi nedenleriniz olmadığında durum böyle olmalıdır .

bir fikir, sınıfın karşılaşmayı beklediği tüm niteliklerle önceden başlatılmasıdır

Bu iyi bir fikir değil. Elbette, öznitelik oradadır, ancak sahte bir değere veya değeri atamayan kod (veya yanlış yazılmış bir) için geçerli olan geçerli bir değere sahip olabilir. AttributeErrorkorkutucu, ancak yanlış sonuç almak daha kötü. Varsayılan değerler genel olarak iyidir, ancak mantıklı bir varsayılan seçmek (ve neyin gerekli olduğuna karar vermek) için nesnenin ne için kullanıldığını bilmeniz gerekir.

Niteliklerimin a priori olduğunu bilmiyorsam ne olur?

Sonra her durumda mahvoldunuz ve sabit kodlama özellik adları yerine bir diksiyon veya liste kullanmalısınız. Ama anladım ki "... kap sınıfını yazdığım zaman". O zaman cevap: "Dosyaları kilit adımında düzenleyebilirsiniz, duh." Yeni bir özelliğe mi ihtiyacınız var? Kap sınıfına bir ayıklama özniteliği ekleyin. Bu sınıfı kullanan daha fazla kod var ve bu niteliğe ihtiyacı yok mu? İşleri iki ayrı sınıfa ayırmayı düşünün (KURU kalmak için karışımları kullanın), bu yüzden mantıklıysa isteğe bağlı yapın.

Tekrarlayan kapsayıcı sınıfları yazmaktan korkuyorsanız: Meta programlamayı akıllıca uygulayın veya oluşturduktan collections.namedtuplesonra üyeleri değiştirmeniz gerekmiyorsa kullanın (FP arkadaşlarınız memnun olacaktır).


7

Alex Martelli'nin Bunch sınıfını her zaman kullanabilirsiniz . Senin durumunda:

class DataObj:
    "Catch-all data object"
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

def processData(inputs):
    data = DataObj(a=1, b="sym", c=[2,5,2,1])

Bu şekilde, en azından okuyucu için, verilerin sadece aptal bir veri deposu olduğu açıktır ve biri hangi değerlerin hangi adda saklandığını hemen görebilir, çünkü hepsi tek bir satırda gerçekleşir.

Ve evet, işleri bu şekilde yapmak bazen iyi bir fikirdir.


1

Muhtemelen Nonegeçersiz verileri belirtmek için kullanarak muhtemelen ikinci yaklaşımı kullanırdım . Daha sonra nitelik eklerseniz okumak / sürdürmek zor olduğu doğrudur. Ancak, bu sınıfın / nesnenin amacı hakkında daha fazla bilgi, ilk fikrin neden kötü bir tasarım olduğu konusunda fikir verecektir: Nerede yöntem veya varsayılan veri olmadan tamamen boş bir sınıfınız olurdu? Neden sınıfın hangi niteliklerine sahip olduğunu bilmiyorsun?

O var mümkün olduğu processDatabir yöntem (daha iyi olabilir process_datao sınıfın üzerine hareket ediyorsa, piton adlandırma kuralları takip etmek). Örnek göz önüne alındığında, bir veri yapısı olarak daha iyi görünebilir ( dicta'nın yeterli olabileceği yerlerde ).

Gerçek bir örnek verildiğinde, soruyu kodu yeniden düzenlemeye yardımcı olabilecek CodeReview'a yönlendirmeyi düşünebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.