it-swarm.asia

Çok fazla özel işleve / yönteme sahip olmak gibi bir şey var mı?

İyi belgelenmiş kodun önemini anlıyorum. Ancak kendi kendini belgeleyen kodun önemini de anlıyorum. Belirli bir işlevi görsel olarak okumak ne kadar kolay olursa, yazılım bakımı sırasında o kadar hızlı ilerleyebiliriz.

Bununla birlikte, büyük işlevleri diğer küçük işlevlere ayırmak istiyorum. Ama bunu bir sınıfın beş taneden daha fazlasına sahip olabileceği bir noktaya sadece bir kamusal yönteme hizmet etmek için yapıyorum. Şimdi beş özel yöntemi beş genel yöntemle çarpın ve muhtemelen bu genel yöntemlerle yalnızca bir kez çağrılacak yaklaşık yirmi beş gizli yöntem elde edersiniz.

Elbette, bu genel yöntemleri okumak artık daha kolay, ama çok fazla işleve sahip olmanın kötü bir uygulama olduğunu düşünmekten yardım edemem.

[Düzenleme]

İnsanlar bana neden çok fazla işleve sahip olmanın kötü bir uygulama olduğunu düşündüğümü soruyorlar.

Basit cevap: Bağırsak hissi.

İnancım, bir kere, herhangi bir saat yazılım mühendisliği deneyimi ile desteklenmiyor. Bu bana bir "yazar bloğu" veren bir belirsizlik, ama bir programcı için.

Geçmişte sadece kişisel projeleri programlıyordum. Kısa süre önce ekip tabanlı projelere geçtim. Şimdi, başkalarının kodumu okuyup anlayabilmesini sağlamak istiyorum.

Okunabilirliği neyin geliştireceğinden emin değildim. Bir yandan, büyük bir işlevi anlaşılır isimlerle diğer küçük işlevlere ayırmayı düşünüyordum. Ama başka bir tarafı daha fazla olduğunu söyledi.

Bu yüzden, doğru yolu seçmek için kendimi aydınlatmasını istiyorum.

[Düzenleme]

Aşağıda, ( sorunumu nasıl çözebileceğimin iki versiyonunu ekledim. Birincisi bunu büyük kod parçalarını ayırarak ile çözer. İkincisi ayrı şeyler yapar .

İlk versiyon:

public static int Main()
{
    // Displays the menu.
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

İkinci versiyon:

public static int Main()
{
    DisplayMenu();
}

private static void DisplayMenu()
{
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Yukarıdaki örneklerde, ikincisi, programın tüm çalışma süresi boyunca yalnızca bir kez kullanılacak bir işlevi çağırır.

Not: Yukarıdaki kod genelleştirilmiştir, ancak sorunumla aynı niteliktedir.

Şimdi, sorum şu: hangisi? Birincisini mi yoksa ikincisini mi seçerim?

63
Sal

Şimdi beş özel yöntemi beş genel yöntemle çarpın ve muhtemelen bu genel yöntemlerle yalnızca bir kez çağrılacak yaklaşık yirmi beş gizli yöntem elde edersiniz.

Kapsülleme olarak bilinen, daha yüksek düzeyde bir Kontrol Soyutlama oluşturur. Bu iyi birşey.

Bu, kodunuzu okuyan herkesin, kodunuzdaki startTheEngine() yöntemine ulaştıklarında, openIgnitionModule(), turnDistributorMotor() gibi daha düşük tüm ayrıntıları göz ardı edebileceği anlamına gelir. , sendSparksToSparkPlugs(), injectFuelIntoCylinders(), activateStarterSolenoid() ve çok daha büyük, daha soyut işlevi kolaylaştırmak için çalıştırılması gereken tüm diğer karmaşık, küçük işlevler startTheEngine().

Kodunuzda karşılaştığınız sorun doğrudan bu bileşenlerden biriyle ilgilenmedikçe, kod koruyucular sanallaştırılmış, kapsüllenmiş işlevselliği yok sayarak devam edebilir.

Bu ayrıca kodunuzun test edilmesini kolaylaştırır . Örneğin, turnAlternatorMotor(int revolutionRate) için bir test durumu yazabilir ve işlevselliğini diğer sistemlerden tamamen bağımsız olarak test edebilirim. Bu işlevle ilgili bir sorun varsa ve çıktı beklediğim gibi değilse, sorunun ne olduğunu biliyorum.

Bileşenlere bölünmemiş kodun test edilmesi çok daha zordur. Aniden, koruyucularınız ölçülebilir bileşenlere inmek yerine sadece soyutlamaya bakıyorlar.

Tavsiyem, kodunuz ölçekleneceği, bakımı kolay olacağı ve gelecek yıllar boyunca kullanılabileceği ve güncellenebileceği için yaptıklarınızı yapmaya devam etmektir.

36
jmort253

Evet ve hayır. Temel prensip: bir yöntem sadece bir şey yapmalı

Yönteminizi daha küçük yöntemlere ayırmak doğrudur. Daha sonra, bu yöntemler optimal olarak yalnızca bu "büyük" yönteme hizmet etmeyecek kadar genel olmalı, ancak başka yerlerde yeniden kullanılabilir olmalıdır. Bazı durumlarda, yöntem InitializePlugins, InitializeInterface vb. Çağıran Initialize Yöntemi gibi basit bir ağaç yapısını izler.

Eğer gerçekten büyük bir yöntem/sınıf varsa, bu genellikle çok şey yaptığını bir işaret ve "damla" kırmak için bazı yeniden düzenleme yapmak gerekir. Perphaps bir soyutlama altında başka bir sınıftaki bazı karmaşıklığı gizler ve bağımlılık enjeksiyonu kullanır

22
Homde

Genel olarak, çok az değil, çok fazla fonksiyonun yanına koymak daha iyidir. Uygulamada gördüğüm bu kuralın iki istisnası KURU ve YAGNI = ilkeler. Neredeyse aynı işlevleriniz varsa, bunları birleştirmeli ve kendinizi tekrar etmemek için parametreleri kullanmalısınız. Bunları "her ihtimale karşı" oluşturduysanız ve kullanılmıyorsa çok fazla fonksiyonunuz da olabilir. Okunabilirlik ve bakım kolaylığı sağladığında yalnızca bir kez kullanılan bir işleve sahip olmanın kesinlikle yanlış bir şey olmadığını görüyorum.

17
Karl Bielefeldt

jmort253'ün harika cevabı bana "evet ama" cevabını takip etmem için ilham verdi ...

Çok sayıda küçük özel yönteme sahip olmak kötü bir şey değildir, ancak burada bir soru göndermenizi sağlayan bu niggling hissine dikkat edin :). Sadece özel yöntemlere odaklanmış testler yazdığınız bir noktaya gelirseniz (ya doğrudan arayarak veya sonucu test edebilmeniz için belirli bir şekilde çağrılacak bir senaryo oluşturarak) geri adım atmalısın.

Sahip olabileceğiniz kendi daha odaklanmış ortak arayüzü ile kaçmaya çalışan yeni bir sınıf. Bu noktada, mevcut sınıf işlevselliğinizin şu anda özel yöntemle yaşayan kısmını kapsamak için bir sınıf çıkarmayı düşünmek isteyebilirsiniz. Artık orijinal sınıfınız yeni sınıfınızı bağımlılık olarak kullanabilir ve doğrudan bu sınıfa daha fazla odaklanmış testler yazabilirsiniz.

10
Pete Hodgson

Hemen hemen her OO katıldığım proje çok büyük sınıflardan ve çok uzun metotlardan çok acı çekti.

Kodun sonraki bölümünü açıklayan bir yoruma ihtiyaç duyduğumda, o bölümü ayrı bir yönteme ayıklarım. Uzun vadede bu, kodu kısaltır. Bu küçük yöntemler başlangıçta beklediğinizden daha fazla yeniden kullanılır. Bir grup ayrı bir sınıfa toplamak için fırsatlar görmeye başlarsınız. Yakında probleminizi daha yüksek bir seviyede düşünüyorsunuz ve tüm çaba çok daha hızlı gidiyor. Yeni özelliklerin yazılması daha kolaydır, çünkü bu küçük yöntemlerden oluşturduğunuz küçük sınıflar üzerine inşa edebilirsiniz.

8
kevin cline

5 genel yöntem ve 25 özel yöntem içeren bir sınıf benim için o kadar büyük görünmüyor. Sadece sınıflarınızın iyi tanımlanmış sorumluluklara sahip olduğundan emin olun ve yöntem sayısı konusunda fazla endişelenmeyin.

Bununla birlikte, bu özel yöntemler tüm görevin belirli bir yönüne odaklanmalıdır, ancak "doSomethingPart1", "doSomethingPart2" tarzında değil. Bu özel yöntemler, keyfi olarak bölünmüş uzun bir hikayenin parçalarıysa, her biri tüm bağlamın dışında anlamsızsa hiçbir şey kazanmazsınız.

7
user281377

R. Martin'den alıntı Temiz Kod (s. 176):

Çoğaltma, kod ifadesi ve SRP'nin ortadan kaldırılması gibi temel kavramlar bile çok ileri götürülebilir. Sınıflarımızı ve yöntemlerimizi küçük yapmak için çok fazla küçük sınıf ve yöntem oluşturabiliriz. Dolayısıyla bu kural [sınıf ve yöntem sayısını en aza indirgeyin] fonksiyonumuzu ve sınıf sayımlarımızı da düşük tuttuğumuzu göstermektedir. Yüksek sınıf ve yöntem sayıları bazen anlamsız dogmatizmin sonucudur.

4
user2418306

Bazı seçenekler:

  1. Bu iyi. Özel yöntemleri ve genel yöntemlerinizi adlandırmanız yeterlidir. Ve genel yöntemlerinizi iyi adlandırın.

  2. Bu yardımcı yöntemlerden bazılarını yardımcı sınıflara veya yardımcı modüllere ayırın. Ve bu yardımcı sınıfların/modüllerin iyi adlandırıldığından ve kendi başlarına sağlam soyutlamalar olduğundan emin olun.

3
yfeldblum

Ben muhtemelen bu şekilde kötü kod mimarisinin bir belirtisi olduğunu hissediyorsa "çok fazla özel yöntem" bir sorun olduğunu sanmıyorum.

İşte böyle düşünüyorum ... Eğer mimari iyi tasarlanmışsa, X yapan kodun nerede olması gerektiği genel olarak açıktır. Bunun birkaç istisnası varsa kabul edilebilir - ancak bunların gerçekten istisnai olması gerekir, aksi takdirde bunları standart olarak ele almak için mimariyi yeniden düzenleyin.

Sorun, sınıfınızı açtığınızda, daha büyük kodları daha küçük kod parçalarına bölen özel yöntemlerle doluysa, belki de bu eksik mimarinin bir belirtisidir. Sınıflar ve mimarlık yerine, bu kod alanı bir sınıf içinde prosedürel bir şekilde uygulanmıştır.

Burada bir denge bulmak projeye ve gereksinimlerine bağlıdır. Buna karşı argüman, genç bir programcının bir mimar 50 sınıfını alan 50 kod satırında çözümü devirebileceğidir.

1
Michael Shaw

Çok fazla özel işleve/yönteme sahip olmak gibi bir şey var mı?

Evet.

Python "özel" kavramı (C++ tarafından kullanıldığı gibi, Java ve C #) gerçekten mevcut değildir.

"Bir çeşit özel" adlandırma kuralı var, ama hepsi bu.

Özel, test edilmesi zor koda yol açabilir. Ayrıca, kodu basitçe kapatarak "Açık-Kapalı Prensibi" ni de kırabilir.

Sonuç olarak, Python'u kullanan kişiler için özel işlevlerin değeri yoktur. Her şeyi herkese açık hale getirin ve onunla işlerinizi yapın.

0
S.Lott