Bir işlevin kabul etmesi gereken kaç parametre hakkında kurallar var mı?


114

Çalıştığım birkaç işlevi farkettim, 6 veya daha fazla parametre var, oysa çoğu kütüphanede 3'ten fazla süren bir işlev bulmak nadirdir.

Genellikle bu ekstra parametrelerin çoğu, fonksiyon davranışını değiştirmek için ikili opsiyonlardır. Bence umpteen parametresi olan işlevlerin bazıları muhtemelen yeniden düzeltilmelidir. Hangi sayının fazla olduğuna dair bir kılavuz var mı?


4
@Ominus: Fikir, sınıflarınızı odaklanmış tutmak istediğinizdir. Odaklanmış sınıflar genellikle çok fazla bağımlılığa / niteliğe sahip değildir, bu nedenle yapıcı için daha az parametreniz olacaktır. Bu noktada ortaya atılan bazı vızıltı sözcüğü insanlar bu noktada yüksek uyum ve tek sorumluluk ilkesidir . Bunların ihlal edilmediğini ve hala çok fazla paragrafa ihtiyacı olduğunu düşünüyorsanız, Oluşturucu desenini kullanmayı düşünün.
c_maker

2
Kesinlikle 12 parametre alan MPI_Sendrecv () örneğini takip etmeyin !
chrisaycock

6
Şu anda üzerinde çalışmakta olduğum proje, 10+ parametresi olan yöntemlerin yaygın olduğu belirli bir çerçeve kullanıyor. Birkaç yerde 27 parametreli belirli bir yöntemi arıyorum. Her gördüğümde biraz içeride ölüyorum.
12'de per

3
İşlev davranışını değiştirmek için asla boolean anahtarlar eklemeyin. Bunun yerine işlevi bölün. Ortak davranışı yeni işlevlere ayırın.
kevin cline

2
@Ominus Ne? Sadece 10 parametre mi? Bu hiçbir şey, daha fazlasına ihtiyaç var . : D
maaartinus

Yanıtlar:


106

Hiç bir kılavuz görmedim, ancak deneyimlerime göre üç veya dörtten fazla parametre alan bir işlev iki problemden birini gösteriyor:

  1. İşlev çok fazla şey yapıyor. Her biri daha küçük bir parametre setine sahip olan birkaç küçük fonksiyona bölünmelidir.
  2. Orada saklanan başka bir nesne var. Bu parametreleri içeren başka bir nesne veya veri yapısı oluşturmanız gerekebilir. Daha fazla bilgi için Parametre Nesnesi modeli ile ilgili bu makaleye bakın .

Daha fazla bilgi olmadan neye baktığını söylemek zor. Muhtemel yapmanız gereken refactoring, işlevi, o anda işleve gönderilen bayraklara bağlı olarak, üst öğeden çağrılan küçük işlevlere bölmektir.

Bunu yaparak elde edilecek bazı iyi kazançlar var:

  • Kodunuzun okunmasını kolaylaştırır. Şahsen if, tanımlayıcı adlara sahip birçok yöntemi çağıran bir yapıdan oluşan bir kural listesinin okunmasını kişisel olarak çok daha kolay buluyorum .
  • Daha fazla test edilebilir. Sorununuzu, bireysel olarak çok basit olan birkaç küçük işe ayırdınız. Birim test koleksiyonu, daha sonra her bir prosedür için ana yöntem ve yolları daha küçük testlerden oluşan bir topluluğu kontrol eden davranışsal bir test grubundan oluşacaktır.

5
Parametre soyutlama bir tasarım modeline dönüştürülmüş mü? 3 parametre sınıfınız varsa ne olur? Farklı olası parametre kombinasyonlarını işlemek için 9 yöntem aşırı yüklemesi ekliyor musunuz? Kötü bir O (n ^ 2) parametre bildirimi sorunu gibi geliyor. Bekle, Java / C # 'da sadece 1 sınıfı miras alabilirsin, böylece pratikte çalışması için biraz daha fazla biyo-plaka (belki biraz daha alt sınıflama) gerektirecektir. Üzgünüm ikna olmadım. Bir dilin karmaşıklık lehine sunabileceği daha etkileyici yaklaşımları görmezden gelmek, kendini yanlış hissettirir.
Evan Plaice

Bir nesne örneğindeki değişkenleri paketlemek ve bunu bir parametre olarak iletmek için Desen Nesnesi desenini kullanmazsanız. Ambalajlama için işe yarar, ancak sadece yöntem tanımını basitleştirmenin kolaylığı için farklı değişken sınıfları oluşturmak cazip gelebilir.
Evan Plaice

@EvanPlaice Birden fazla parametreye sahip olduğunuzda bu kalıbı kullanmanız gerektiğini söylemiyorum - ilk listeden bile daha nahoş hale gelmesi kesinlikle doğru. Gerçekten çok sayıda parametreye ihtiyaç duyduğunuz durumlar olabilir ve bunları bir nesneye sarmak işe yaramaz. Henüz kurumsal gelişimde, cevabımda bahsettiğim iki kovadan birine girmeyen bir vakayı henüz karşılamadım - bu da birinin olmadığına işaret etmiyor.
Michael K,

@MichaelK Onları hiç kullanmadıysanız, 'nesne başlatıcıları' googling'i deneyin. Tanım kazanını önemli ölçüde azaltan oldukça yeni bir yaklaşım. Teorik olarak, bir sınıfta yapıcıları, parametreleri ve aşırı yüklemeleri ortadan kaldırabilirsiniz. Yine de pratikte, ortak bir kurucuyu korumak ve belirsiz / niş özelliklerinin geri kalanı için 'nesne başlatıcı' sözdizimine güvenmek genellikle iyidir. IMHO, dinamik olarak yazılmış dillerin statik olarak yazılmış bir dilde ifade edilmesine en yakın olanıdır.
Evan Plaice

@Evain Plaice: Dinamik olarak yazılmış diller ne zamandan beri etkileyicidir?
ThomasX

41

"Temiz Kod: Çevik Yazılım İşçiliği El Kitabı" na göre, sıfır idealdir, bir veya iki kabul edilebilir, özel durumlarda üç, dört veya daha fazla, asla!

Yazarın sözleri:

Bir fonksiyon için ideal argüman sayısı sıfırdır (niladik). Sonra bir (monadik), ardından iki (dyadic) yakından takip edilir. Mümkünse üç argümandan (üçlü) kaçınılmalıdır. Üçten fazla (polyadik) çok özel bir gerekçelendirme gerektirir - ve daha sonra kullanılmamalıdır.

Bu kitapta, sadece parametrelerin tartışıldığı fonksiyonlardan bahseden bir bölüm var, bu yüzden bu kitabın ihtiyaç duyduğunuz parametrelere ilişkin iyi bir rehber olabileceğini düşünüyorum.

Kişisel görüşüme göre, bir parametre kimseden daha iyidir çünkü bence neler olup bittiğinin daha açık olduğunu düşünüyorum.

Örneğin, bence ikinci seçenek daha iyi çünkü yöntemin ne işlediği daha açık:

LangDetector detector = new LangDetector(someText);
//lots of lines
String language = detector.detectLanguage();

vs.

LangDetector detector = new LangDetector();
//lots of lines
String language = detector.detectLanguage(someText);

Pek çok parametre hakkında, bu, bazı değişkenlerin tek bir nesnede gruplandırılabileceğinin bir işareti olabilir veya bu durumda, birçok boole, işlevin / yöntemin birden fazla şey yaptığını gösterebilir ve bu durumda, bu davranışın her birini farklı bir fonksiyonda yeniden canlandırmak daha iyidir.


8
"Özel durumlarda üç, dört veya daha fazla, asla!" BS. Matrix.Create (x1, x2, x3, x4, x5, x6, x7, x8, x9); ?
Lukasz Madon

71
Sıfır idealdir? Fonksiyonlar nasıl bilgi edinir? Küresel / örnek / statik / değişkenler ne? Yuck.
Peter C,

9
Bu kötü bir örnek. Bu sorunun cevabı açık olduğunu: String language = detectLanguage(someText);. Her iki durumda da aynı sayıda argüman ilettiniz, bu sadece işlev yürütmesini zayıf bir dil nedeniyle ikiye bölmüş olmanızdır.
Matthieu M.

8
@lukas, dilde nasıl, diziler ya da (kurar) listeleri gibi süslü yapıları destekleyen Matrix.Create(input);nerede input, diyelim ki, bir .NET olduğunu IEnumerable<SomeAppropriateType>? Bu şekilde, 9 yerine 10 element içeren bir matris oluşturmak istediğinizde ayrıca bir aşırı yüke gerek
duymazsınız

9
"İdeal" olarak sıfır argümanlar bir güveç ve Temiz Kod yol çok abartılı olduğunu düşünüyorum bir nedenidir.
user949300 28:17

24

Uygulamadaki etki alanı sınıfları doğru tasarlanırsa, bir işleve geçirdiğimiz parametre sayısı otomatik olarak azalacaktır - çünkü sınıflar işlerini nasıl yapacaklarını bilir ve işlerini yapmak için yeterli veriye sahiptirler.

Örneğin, ödevleri tamamlamak için 3. sınıf bir sınıf soran bir yönetici sınıfınız olduğunu varsayalım.

Eğer doğru manken yaparsanız,

3rdGradeClass.finishHomework(int lessonId) {
    result = students.assignHomework(lessonId, dueDate);
    teacher.verifyHomeWork(result);
}

Bu basit.

Doğru modeliniz yoksa, yöntem şöyle olacaktır:

Manager.finishHomework(grade, students, lessonId, teacher, ...) {
    // This is not good.
}

Doğru model, yöntem çağrıları arasındaki işlev parametrelerini daima azaltır, çünkü doğru işlevler kendi sınıflarına verilir (Tek sorumluluk) ve işlerini yapmak için yeterli veriye sahiptirler.

Parametrelerin sayısının arttığını gördüğümde, uygulama modelimi doğru tasarlayıp tasarlamadığımı görmek için modelimi kontrol ediyorum.

Yine de bazı istisnalar var: Bir transfer nesnesi veya config nesneleri yaratmam gerektiğinde, önce büyük bir config nesnesi oluşturmadan önce küçük inşa edilmiş nesneler üretmek için bir oluşturucu desen kullanacağım.


16

Diğer cevapların almadığı bir özellik performanstır.

Yeterince düşük bir dilde (C, C ++, montaj) programlama yapıyorsanız, çok sayıda parametre, özellikle de fonksiyona büyük miktarda denirse, bazı mimarilerde performansa zarar verebilir.

Bir işlev çağrısı, örneğin ARM yapıldığı zaman, ilk dört bağımsız değişken kayıt yerleştirilir r0için r3ve kalan argümanlar yığını üzerine itilmesi gerekir. Argüman sayısını beşin altında tutmak kritik fonksiyonlar için oldukça fark yaratabilir.

Son derece sık denir fonksiyonları program her çağrı performansını etkileyebilir (önce argümanlar kurmak zorunda olduğu bile aslında için r0için r3denilen işlevi tarafından üzerine yazılabilir ve bir sonraki görüşme öncesinde değiştirilmesi gerekecektir) bu yüzden bu konuda sıfır argümanlar en iyisidir.

Güncelleme:

KjMag ilginç satır içi konuyu gündeme getiriyor. Inlining, bazı şekillerde bunu hafifletecektir çünkü derleyicinin salt montajda yazarken yapabileceğiniz aynı optimizasyonları yapmasına izin verecektir. Başka bir deyişle, derleyici çağrılan işlev tarafından hangi parametrelerin ve değişkenlerin kullanıldığını görebilir ve yığın okuma / yazma işlemlerinin en aza indirilmesi için kayıt kullanımını optimize edebilir.

Ancak satır içi ile ilgili bazı sorunlar var.

  1. Inlining, derlenmiş ikilinin büyümesine, aynı kodun birden fazla yerden çağrılması durumunda ikili biçimde çoğaltılmasına neden olur. I-cache kullanımı söz konusu olduğunda bu zararlıdır.
  2. Derleyiciler genellikle sadece belirli bir seviyeye kadar inline izin verir (3 adım IIRC?). Satır içi bir işlevden bir satır içi işlevi çağırdığını hayal edin. inlineHer durumda zorunlu olarak ele alınırsa , ikili büyüme patlayabilir .
  3. Tamamen görmezden gelebilecek inlineya da karşılaştıklarında size hata yapacak çok sayıda derleyici var .

Çok sayıda parametreyi geçmenin performans açısından iyi veya kötü olması alternatiflere bağlıdır. Bir yöntemin bir düzine bilgi parçasına ihtiyacı varsa ve biri onlardan biri için aynı değerlerle yüzlerce kez arayacaksa, yöntemin bir dizi alması bir düzine parametreyi almaktan daha hızlı olabilir. Öte yandan, her çağrı benzersiz bir on iki değer kümesine ihtiyaç duyarsa, her çağrı için dizi oluşturma ve doldurma, değerleri doğrudan doğrudan iletmekten daha yavaş olabilir.
supercat

Satır içi bu sorunu çözmüyor mu?
KjMag

@KjMag: Evet, bir dereceye kadar. Ancak derleyiciye bağlı olarak bir sürü kazanım var. İşlevler genellikle yalnızca belirli bir seviyeye kadar sıralanır (eğer bir sıralı işlevi çağıran bir sıralı işlevi çağıran bir sıralı işlevi çağırırsanız ....). İşlev büyükse ve birçok yerden çağrılırsa, her yere dizmek ikiliyi daha büyük yapar, bu da I-cache'de daha fazla özlüyor anlamına gelebilir. Yani iç içe geçme yardımcı olabilir, ama gümüş kurşun değildir. ( inline
Leo

7

Parametre listesi beşten fazla büyüdüğünde, "bağlam" yapısını veya nesnesini tanımlamayı düşünün.

Bu temelde, sadece bazı isteğe bağlı parametreleri belirlenmiş bazı varsayılan ayarlarla tutan bir yapıdır.

C prosedürel dünyada düz bir yapı olurdu. Java, C ++ 'da basit bir nesne yeterli olacaktır. Alıcılarla veya ayarlayıcılarla uğraşmayın, çünkü nesnenin tek amacı "genel" ayarlanan değerleri tutmaktır.


Katılıyorum, fonksiyon parametresi yapıları oldukça karmaşıklaşmaya başladığında bir içerik nesnesinin çok kullanışlı olduğu ortaya çıkabilir. Son zamanlarda ziyaretçi benzeri bir
Lukas Eder

5

Hayır, standart bir kılavuz yok

Ancak birçok parametreye sahip fonksiyonu daha katlanılabilir hale getirebilecek bazı teknikler var.

Bir list-if-args parametresini (args *) veya bir args sözlük parametresini (kwargs **) kullanabilirsiniz.

Örneğin, python'da:

// Example definition
def example_function(normalParam, args*, kwargs**):
  for i in args:
    print 'args' + i + ': ' + args[i] 
  for key in kwargs:
    print 'keyword: %s: %s' % (key, kwargs[key])
  somevar = kwargs.get('somevar','found')
  missingvar = kwargs.get('somevar','missing')
  print somevar
  print missingvar

// Example usage

    example_function('normal parameter', 'args1', args2, 
                      somevar='value', missingvar='novalue')

Çıktılar:

args1
args2
somevar:value
someothervar:novalue
value
missing

Veya nesne değişmez tanımı sözdizimini kullanabilirsiniz.

Örneğin, burada bir AJAX GET isteği başlatmak için bir JavaScript jQuery çağrısı:

$.ajax({
  type: 'GET',
  url: 'http://someurl.com/feed',
  data: data,
  success: success(),
  error: error(),
  complete: complete(),
  dataType: 'jsonp'
});

JQuery'nin ajax sınıfına bakarsanız, ayarlanabilecek çok (yaklaşık 30) özellik vardır; çoğunlukla, ajax iletişimi çok karmaşık olduğu için. Neyse ki, nesne değişmez sözdizimi hayatı kolaylaştırır.


C # intellisense parametrelerin aktif belgelenmesini sağlar, bu yüzden aşırı yüklenmiş yöntemlerin çok karmaşık düzenlemelerini görmek nadir değildir.

Dinamik olarak python / javascript gibi yazılan dillerin böyle bir yeteneği yoktur, bu nedenle anahtar kelime argümanlarını ve nesne değişmez tanımlarını görmek çok daha yaygındır.

Bir nesnenin somutlaştırılması sırasında hangi özelliklerin ayarlandığını açıkça görebildiğiniz için karmaşık yöntemleri yönetmek için nesne değişmez tanımlarını ( C # bile) tercih ederim . Varsayılan argümanları ele almak için biraz daha iş yapmanız gerekecek, ancak uzun vadede kodunuz çok daha okunaklı olacaktır. Nesne değişmez tanımları ile, ilk bakışta kodunuzun ne yaptığını anlamak için belgelere bağımlılığınızı kırabilirsiniz.

IMHO, aşırı yüklenmiş yöntemler aşırı abartılıyor.

Not: Salt okunur hatırlıyorsam erişim kontrolü C # 'daki nesne değişmez yapıcıları için çalışmalıdır. Esasen yapıcıdaki ayar özellikleriyle aynı şekilde çalışırlar.


Dinamik olarak yazılmış (python) ve / veya fonksiyonel / prototip javaScript tabanlı bir dilde önemsiz olmayan bir kod hiç yazmadıysanız, denemenizi şiddetle tavsiye ederim. Aydınlatıcı bir deneyim olabilir.

Her şeyden önce, her şeyden önce işlevsellik yaklaşımı için parametrelere bağlılığınızı kırmak korkutucu olabilir, ancak gereksiz karmaşıklık eklemek zorunda kalmadan kodunuzla çok daha fazlasını yapmayı öğreneceksiniz.

Güncelleme:

Muhtemelen statik olarak yazılmış bir dilde kullanımı göstermek için örnekler vermeliydim ama şu anda statik olarak yazılmış bir bağlamda düşünmüyorum. Temelde, aniden geri dönmek için dinamik olarak yazılmış bir bağlamda çok fazla iş yapıyorum.

Ne yapmak biliyorum ben önce onları kullandık çünkü (en azından C # ve Java) literal tanım sözdizimi statik olarak yazılan dillerde tamamen mümkündür nesnesidir. Statik olarak yazılmış dillerde 'Nesne Başlatıcılar' olarak adlandırılırlar. Java ve C # kullanımlarını göstermek için bazı bağlantılar .


3
Bireysel parametrelerin kendi kendini belgeleme değerini kaybettiğiniz için bu yöntemi sevdiğimden emin değilim. Benzer öğelerin listeleri için bu mükemmel bir anlam ifade eder (örneğin, dizelerin listesini alan ve birleştiren bir yöntem) ancak isteğe bağlı bir parametre kümesi için bu, uzun yöntem çağrısından daha kötüdür.
Michael K

@MichaelK Nesne başlatıcılarına başka bir göz atın. Geleneksel yöntem / işlev parametrelerinde dolaylı olarak nasıl tanımlandıklarının aksine özellikleri açıkça tanımlamanıza izin verir. Ne demek istediğimi görmek için msdn.microsoft.com/en-us/library/bb397680.aspx adresini okuyun .
Evan Plaice

3
Sadece parametre listesini işlemek için yeni bir tür oluşturmak, tam olarak gereksiz karmaşıklığın tanımı gibi geliyor ... Elbette, dinamik diller bundan kaçınmanıza izin veriyor, ancak tek bir goo parametresi topunu elde ediyorsunuz. Ne olursa olsun, bu soruyu cevaplamıyor.
Telastyn

@Telastyn Ne hakkında konuşuyorsun? Yeni bir tür oluşturulmadı, nesne değişmez sözdizimini kullanarak doğrudan özellikleri ilan edersiniz. Anonim bir nesneyi tanımlamak gibi bir yöntem ancak yöntem onu ​​bir anahtar = değer parametre grubu olarak yorumluyor. Baktığınız şey bir yöntem örneği (nesneyi kapsayan bir parametre değil). Sığır eti parametre paketlemeliyse, diğer sorulardan birinde belirtilen Parametre Nesnesi modeline bir bakın, çünkü tam olarak budur.
Evan Plaice

@EvanPlaice - Statik programlama dillerinin büyük ve küçük olması dışında, Parametre Nesnesi desenine izin vermek için (genellikle yeni) ilan edilmiş bir tip gerektirir.
Telastyn

3

Şahsen, kodum kokusunun alarm tetiklediği 2'den fazla. İşlevlerin işlemler olduğunu düşünürseniz (yani, girdiden çıktıya bir çeviri), bir işlemde 2'den fazla parametrenin kullanılması nadir görülür. Prosedürler (bu, bir hedefe ulaşmak için bir dizi adımdır) daha fazla girdi alacaktır ve bazen en iyi yaklaşımdır, ancak çoğu dilde bu günler norm olmamalıdır.

Fakat yine de, bu bir kuraldan ziyade bir kılavuzdur. Alışılmadık durumlar veya kullanım kolaylığı nedeniyle çoğu zaman iki parametreden fazlasını alan fonksiyonlara sahibim.


2

Evan Plaice'nin dediği gibi, mümkün olduğunca ilişkisel dizileri (veya dilinizin karşılaştırılabilir veri yapısını) fonksiyonlara geçirmenin büyük bir hayranıyım.

Böylece, (örneğin) yerine:

<?php

createBlogPost('the title', 'the summary', 'the author', 'the date of publication, 'the keywords', 'the category', 'etc');

?>

İçin gitmek:

<?php

// create a hash of post data
$post_data = array(
  'title'    => 'the title',
  'summary'  => 'the summary',
  'author'   => 'the author',
  'pubdate'  => 'the publication date',
  'keywords' => 'the keywords',
  'category' => 'the category',
  'etc'      => 'etc',
);

// and pass it to the appropriate function
createBlogPost($post_data);

?>

Wordpress bu şekilde çok şey yapar ve bence iyi çalışıyor. (Yukarıdaki örnek kodum hayali olsa da, Wordpress'ten bir örnek değil.)

Bu teknik, çok sayıda veriyi işlevlerinize kolayca aktarmanıza olanak tanır, ancak her birinin geçmesi gereken sırayı hatırlamanıza gerek kalmaz.

Refaktör zamanı geldiğinde de bu tekniği takdir edeceksiniz - bir fonksiyonun argümanlarının sırasını değiştirmek zorunda kalmak yerine (örneğin Bir Başka Argümanı geçmeniz gerektiğini fark ettiğinizde), fonksiyonlarınızın parametresini değiştirmeniz gerekmez. hiç listesi.

Bu sadece sizi fonksiyon tanımınızı tekrar yazmaktan kurtarmaz, aynı zamanda fonksiyon her çağrıldığında argümanların sırasını değiştirmek zorunda kalmazsınız. Bu büyük bir kazanç.


Bu durumun yayınlandığını görmek, bir hash-pass yaklaşımının bir başka yararını vurgular: ilk kod örneğimin o kadar uzun olduğuna dikkat edin, ikincisi sayfaya temiz bir şekilde uyuyor. Aynısı kod editörünüzde de geçerli olacak.
Chris Allen Lane,

0

Önceki bir cevap , fonksiyonlarınızın ne kadar az parametreye sahip olduğunu, ne kadar iyi yaptığınızı belirten güvenilir bir yazardan bahsetti. Cevap nedenini açıklamadı ama kitaplar onu açıklıyor ve işte bu felsefeyi benimsemeniz ve kişisel olarak hemfikir olduğum gibi neden olarak ikna edici iki sebep:

  • Parametreler, fonksiyondan farklı bir soyutlama seviyesine aittir. Bu, kodunuzun okuyucusunun, işlevlerinizin parametrelerinin niteliği ve amacı hakkında düşünmesi gerektiği anlamına gelir: bu düşünme, isimlerinin ve karşılık gelen işlevlerinin amaçlarından daha düşük seviyededir.

  • Bir fonksiyon için mümkün olduğunca az parametreye sahip olmanın ikinci sebebi test yapmaktır: örneğin, 10 parametreli bir fonksiyonunuz varsa, tüm test durumlarını, örneğin bir ünite için ne kadar parametre kombinasyonunu kapsamanız gerektiğini düşünün Ölçek. Daha az parametre = daha az test.


0

Yazar, Robert Martin'in “Temiz Kod: Çevik Yazılım İşçiliği El Kitabı” ndaki ideal işlev argümanları için tavsiye konusunda daha fazla bağlam sağlamak amacıyla, yazar aşağıdaki hususlardan biri olarak şunları söylüyor:

Argümanlar zor. Çok fazla kavramsal güç alıyorlar. Bu yüzden örnekten neredeyse hepsini aştım. Örneğin, StringBufferörnekte olduğu gibi düşünün . Örnek değişken yapmak yerine onu bir argüman olarak iletebilirdik, ancak daha sonra okurlarımız onu her gördüklerinde yorumlamak zorunda kalacaktı. Modül tarafından anlatılan hikayeyi okurken, includeSetupPage() anlaşılması daha kolaydır includeSetupPageInto(newPageContent). Argüman, işlevin adı ve sizi StringBufferbu noktada özellikle önemli olmayan bir ayrıntıyı (başka bir deyişle ) bilmeye zorladığı farklı bir soyutlama düzeyindedir .

Onun için includeSetupPage()yukarıdaki örnekte, burada bölümün sonunda yaptığı refactored "temiz kod" küçük bir parçacık İşte:

// *** NOTE: Commments are mine, not the author's ***
//
// Java example
public class SetupTeardownIncluder {
    private StringBuffer newPageContent;

    // [...] (skipped over 4 other instance variables and many very small functions)

    // this is the zero-argument function in the example,
    // which calls a method that eventually uses the StringBuffer instance variable
    private void includeSetupPage() throws Exception {
        include("SetUp", "-setup");
    }

    private void include(String pageName, String arg) throws Exception {
        WikiPage inheritedPage = findInheritedPage(pageName);
        if (inheritedPage != null) {
            String pagePathName = getPathNameForPage(inheritedPage);
            buildIncludeDirective(pagePathName, arg);
        }
    }

    private void buildIncludeDirective(String pagePathName, String arg) {
        newPageContent
            .append("\n!include ")
            .append(arg)
            .append(" .")
            .append(pagePathName)
            .append("\n");
    }
}

Yazarın "düşünce okulu" küçük sınıflar, düşük (ideal olarak 0) fonksiyon argüman sayısı ve çok küçük fonksiyonlar olduğunu savunur. Ayrıca onunla tam olarak aynı fikirde olmasam da, bunu düşündürücü buldum ve bir ideal olarak sıfır fonksiyon argümanları fikrinin düşünmeye değer olacağını düşünüyorum. Ayrıca, yukarıdaki küçük kod parçacığının bile sıfır olmayan argüman işlevlerine sahip olduğuna dikkat edin, bu nedenle içeriğe bağlı olduğunu düşünüyorum.

(Diğerlerinin de belirttiği gibi, daha fazla tartışmanın onu test açısından daha zorlaştırdığını da iddia ediyor. Ama burada temel olarak yukarıdaki işlevi ve sıfır fonksiyon argümanları için gerekçesini vurgulamak istedim.)


-2

İdeal olarak sıfır. Bir ya da iki tamam, bazı durumlarda üç.
Dört veya daha fazla genellikle kötü bir uygulamadır.

Diğerlerinin belirttiği tek sorumluluk ilkelerinin yanı sıra, bunu test etme ve hata ayıklama bakış açılarından da düşünebilirsiniz.

Bir parametre varsa, değerlerini bilmek, bunları test etmek ve onlarla hata bulmak, yalnızca bir faktör olduğu için nispeten kolaydır. Faktörleri artırdıkça, toplam karmaşıklık hızla artar. Özet bir örnek için:

'Bu havada ne giymeli' programını düşünün. Bir girişle neler yapabileceğini düşünün - sıcaklık. Tahmin edebileceğiniz gibi, ne giyeceğinizin sonuçları o faktöre dayanarak oldukça basittir. Şimdi programın gerçekten sıcaklık, nem, çiğlenme noktası, yağış vb.


12
Bir işlevin sıfır parametresi varsa, ya sabit bir değer döndürür (bazı durumlarda yararlıdır, ancak bunun yerine sınırlayıcıdır) ya da daha iyi yapılmasını sağlayacak gizli bir durum kullanıyordur. (OO yönteminin çağrısında, bağlam nesnesi sorunlara yol
açmayacağı

4
-1 kaynak belirtmeden değil
Joshua Drake

Cidden ideal olarak tüm fonksiyonların parametre almayacağını mı söylüyorsunuz? Yoksa bu abartma mı?
GreenAsJade,

1
Bob Amca'nın argümanına bakınız: informit.com/articles/article.aspx?p=1375308 ve alt kısımda "İşlevler az sayıda argüman içermelidir. Üçten fazlası sorgulanabilir ve önyargılı olmaktan kaçınılmalıdır. ”
Michael Durrant 11

Ben kaynağı verdim. Komik o zamandan beri yorum yok. Ayrıca “rehber” kısmını cevaplamaya çalıştım, çünkü çoğu kişi Bob Amca ve Temizlik Kodunu rehber olarak kabul ediyor. İlginç bir şekilde en üstteki cevabın (şu anda) herhangi bir rehberin farkında olmadığını söylüyor. Bob amca vermedi niyetinde authorative olmak ama biraz ve bu cevabı en azından sorunun ayrıntılarına bir cevabı olmaya çalışır.
Michael Durrant
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.