Bir fonksiyondaki parametreleri sipariş etmek için en iyi uygulama nedir?


52

Bazen (nadiren), makul miktarda parametre alan bir işlev yaratmanın en iyi yol olduğu görülmektedir. Ancak, yaptığım zaman, sık sık parametrelerin sıralamasını rastgele seçtiğimi hissediyorum. Genelde en önemli parametre olan ilk önce "önem sırasına" bakarım.

Bunu yapmanın daha iyi bir yolu var mı? Netliği artıran parametreleri sipariş etmenin "en iyi uygulama" yolu var mı?


5
Adlandırılmış parametreler bunu bir sorundan daha az yapar. Python uç noktalara götürür, içine bakar. İyi bir örnek C # 'da - aramanın birçok yolu MessageBox.Show. Buna da bak.
İş

8
Haskell'de, kısmi işlev uygulamasının olası kullanışlılığı genellikle doğal bir argüman sırası önerir.
tdammers

Uygun miktarda parametre düşünürsünüz?
Chris

2> 'de düşünüyordum da, sıralamanın aynı 2 parametreye uygulandığını sanıyordum.
Casey Patton

3
tdammers bu aynı zamanda köri- leme için doğrudan desteği olan herhangi bir dil için de geçerlidir
jk.

Yanıtlar:


55

Genel olarak: kullanın .

İşleviniz için bir test yazın, gerçek bir dünya testi. Aslında bu işlevle yapmak istediğiniz bir
şey .

Ve bunları ne sırayla yaptığını gör.

Zaten benzer bir şey yapan bazı fonksiyonlara sahip değilseniz (veya bilmediğiniz sürece).
Bu durumda: uygun en az ilk argümanlar için, zaten ne kadar.

örneğin hepsi ilk argüman (lar) olarak bir belge / nesne / dosya işaretçisi / değer dizisi / koordinatlarını alıyor mu? Tanrı aşkına bu iddialara uymak .

İş arkadaşlarınızı ve gelecekteki benliğinizi karıştırmaktan kaçının .


12
Genel olarak iyi bir felsefe gibi "kafa karıştırmaktan kaçının ... gelecekteki benliğiniz" sesi
Jeanne Pindar

28

Her zaman aynı önceliğe sahip olmasam da, genellikle bu kurallara uyuyorum. Sanırım artık otomatik bir düşünce süreci ve genel API tasarımı dışında fazla düşünmüyorum .

Seçim hunisi

  1. semantik
  2. Önem / Alaka Düzeyi
  3. Kullanım sıklığı
  4. G / Ç Endişeleri

1. Önce Anlambilim

Özellikle OOP'de, eylem veya mesaj için anlamsal önemlerine göre parametreleri seçin . İyi adlandırılmış bir yönteme sahip iyi adlandırılmış bir yöntemin imzası:

  • aramak için doğal hissediyorum
  • niyet ve davranış açısından kendi kendini tanımlayıcı olmak.

(Bu nedenlerden dolayı, bazen ilkeller yerine özel türler veya takma adlar kullanılması imzanızın etkililiğini artırabilir.)

2. Sonra Önemi

En "önemli" parametre önce gelir (veya sonra ...)

3. Sonra Frekans

Frekans, özellikle adlandırılmış parametrelerinizin olmadığı ancak konumsal parametrelerde varsayılan değerlere sahip olabileceğiniz bir dilde önemlidir. Bu, parametrelerin sırasının değişmediği anlamına gelir ve Nth parametresinin varsayılan değerini zorlamak istiyorsanız N + 1 parametrelerini ayarlayamazsınız (dilinizde bir yer tutucu parametre kavramı varsa hariç) ).

Sizin için iyi haber, genellikle, sıklığın önemle ilgili olduğudur, bu da önceki noktayla el ele gider. Ve sonra, uygun semantikaya sahip olması için API'nizi oluşturmak muhtemelen sizin sorumluluğunuzdadır.

4. G / Ç'yi Unutmayalım

Metodunuz / fonksiyonunuz bir girdi alır ve bir çıktı üretirse, ikincisi "return" (bir return ifadesiyle) veya "atılmış" (bir istisna sistemi kullanarak) değilse, geçme seçeneğiniz kalmaz değerleri diğer parametrelerinizi (veya giriş parametresini) kullanarak arayan kişiye geri döndürün. Bu, anlamsallık ile ilgilidir ve çoğu durumda, ilk parametrelerin çıktıyı tanımlaması mantıklı olacaktır ve son parametreler çıktıyı alır.

Ek olarak, daha az parametreye sahip olmak ve anlambilimi en üst düzeye çıkarmak için başka bir yaklaşım, fonksiyonel bir yaklaşım kullanmak veya bir Oluşturucu deseni tanımlamaktır , böylece girdilerinizi açıkça biriktirebilir, çıktılarınızı tanımlayabilir ve gerektiğinde bunları alabilirsiniz.

(Genel değişkenlerden bahsetmiyorum, çünkü neden bir tane kullandınız?)


Dikkate Alınacak Bazı Şeyler

  • Kullanılabilirlik

    Eğer ZJR'nin tavsiyelerine uyursanız, yukarıdakilerin çoğu doğal olarak gösterilecektir : Use It!

  • Refactoring'i düşünün

    Parametre siparişi konusunda endişeleniyorsanız, belki de bu endişe, kökenini yukarıda ve API'nizin kötü bir şekilde tasarlandığı gerçeğini bulur. Çok fazla parametreniz varsa, bir şey büyük olasılıkla bileşenleştirilebilir / modüler hale getirilebilir ve yeniden düzeltilebilir .

  • Performansı düşünün

    Parametreleri kullanırken bazı dillerin uygulamalarının çalışma zamanı bellek yönetiminiz üzerinde çok önemli etkilere neden olacağını unutmayın. Bu nedenle birçok dilin stil kitaplarının parametre listesini basit ve kısa tutmasını önerme nedeni . Örneğin 4 parametrede. Nedenini bulmak için bir egzersiz olarak bırakıyorum.

  • Bevan'ın cevabı ve Temiz Kod'un tavsiyelerine değinmek de kesinlikle geçerlidir!


18

Saygılarımla, parametre siparişi için endişelenmenin yanlış şey hakkında endişelendiğini söylerdim.

Bob Amca'nın " Temiz Kod " kitabında , ikna edici olarak, yöntemlerin hiçbir zaman ikiden fazla argüman içermemesi gerektiğini - ve çoğunun varsa, sadece bir tanesinin olması gerektiğini savunuyor. Bu durumda, sipariş ya açık ya da önemsizdir.

Ancak, kusurlu bir şekilde, Bob Amca'nın tavsiyelerine uymaya çalışıyorum - ve kodumu geliştiriyor.

Bir yöntemin daha fazla bilgi gerektirdiği nadir durumlarda , bir parametre nesnesinin tanıtılması iyi bir fikirdir. Genellikle, bunun algoritmamın anahtarı olan yeni bir konseptin (nesne) keşfedilmesinin ilk adımı olduğunu anlıyorum.


Sana kesinlikle katılıyorum! İlk açıklamam bunun benim için tipik bir şey olmadığı noktasını hedeflemekti, haha. Ancak, bazı parametreler iletmem gerektiğine ve tüm programı yeniden düzenlemeye değmeyeceğini bulmam halinde, sipariş vermeyi merak ediyorum.
Casey Patton

3
öksürük PHP öksürük . Üzgünüm - parametrelerin sırası hakkında endişelenmeyeceğiniz hakkında bir şey mi söylediniz?
Craige

Daha sonra parametre nesneniz için bu kadar çok argüman alan bir kurucunuz olmaz mı?
12'de

Hayır - çünkü parametre nesnesi daha fazla okunabilir bir şekilde birkaç ifadede "oluşturulabilir".
Bevan,

2
@Bevan: Bu son derece tartışmalı. Nesneleri bu şekilde inşa etmek artık değiştirilemeyecekleri anlamına gelir; nesnelerinizi mümkün olduğunda değişmez kılmak ancak sürdürülebilirliği arttırmanın başka bir harika yoludur.
tdammers

10

Önce IN parametrelerini, sonra OUT parametrelerini koymaya çalışıyorum. Ayrıca bazı doğal sıralamalar da vardır, örneğin createPoint(double x, double y), şiddetle tercih edilir createPoint(double y, double x).


5
Bazen tam tersi daha iyidir, örneğin, her zaman sadece bir OUT argümanı ve değişken sayıdaki argümanlarda olduğu gibi addAllTo(target, something1, something2).
maaartinus,

Aynı kuralı uygulasam da, mümkün olduğunda OUT parametrelerinden ve en iyi programcılardan da kaçınmaya çalışıyorum. Dolayısıyla, bu önerinin gerçekte OP'ye yardımcı olduğu işlevlerin sayısı oldukça küçük olmalıdır.
Doktor Brown

7
@DocBrown Gerçekten iyi programlayıcılardan kaçınmaya çalışmamalısınız, onlar etrafta olmanız için yararlı olabilir.
RyanfaeScotland

@RyanfaeScotland: kahretsin, yorumumu göndermeden önce iki kez okumalıyım (veya en azından beş dakika içinde değiştirebilirim) ;-)
Doc Brown

6

Bu konuyla ilgili belgelenmiş "en iyi uygulama" yı hiç görmedim, ancak kişisel standartlarım onları, kullanıldıkları yöntemde görünecekleri sırayla listelemek veya yöntem daha fazla Bir veri katmanına geçiş Bunları db şema veya veri katmanı yöntemlerinde görünecekleri sırayla listeleyeceğim.

Ayrıca, bir yöntemin birden fazla aşırı yüklemesi olduğunda, tipik yolun, yöntemlerin hepsinde (veya çoğunda) ortak olan parametrelerden başlayarak her bir yöntemin aşırı yüküne sonuna kadar eklenen her farklı yöntemin eklendiğini listelemek olduğuna dikkat edin. :

void func1(string param) { }
void func2(string param, int param2) { }
void func3(string param, string param3) { }
void func3(string param, int param2, string param3) { }


3

constParametreleri ilk önce (yani, değere göre girdiğiniz parametreler) ve daha sonra referans olarak girdiğiniz parametreleri yerleştirme konvansiyonunu sık sık takip ediyorum . Bu mutlaka çağrı işlevlerinin doğru bir yöntemi olmayabilir, ancak her derleyicinin parametreleri nasıl ele aldığına meraklıysanız, yöneten kurallar ve / veya parametrelerin yığına itildiği sıra için aşağıdaki bağlantılara bir göz atın.

http://msdn.microsoft.com/en-us/library/zthk2dkh%28v=vs.80%29.aspx

http://en.wikipedia.org/wiki/Calling_convention


İlginizi çekebilecek başka bir link msdn.microsoft.com/en-us/library/984x0h58%28v=vs.71%29.aspx Özyinelemeli fonksiyonlar için aşağıdaki bağlantıya bir göz atın. publications.gbdirect.co.uk/c_book/chapter4/… Unutmadım ama yeni bir kullanıcı olarak ikiden fazla bağlantısı olan bir yorum gönderemiyorum .... ne kadar sinir bozucu!
Bill

1

Ben genellikle sadece "daha az selektik görünen ne" parametre sıralaması ile giderim. Yöntem / işlev tanımına ne kadar az zaman gitmem gerekiyorsa o kadar iyidir. Ve ne için kullanıldıklarına ilişkin tanımlayıcı parametrelerin isimlendirilmesi güzel, bu şekilde küçük bir araç ipucu (VS) açıldığında daha da kolaylaşıyor.

Satır ve parametre satırınız varsa, farklı bir tasarım düşünebilirsiniz. Geri adım atın ve bunu daha fazla fonksiyon / yönteme nasıl ayırabileceğinizi görün. Sadece bir fikir, ancak fonksiyonumda bir düzine parametre bulunduğunda, neredeyse her zaman bir parametre sorunu değil, bir tasarım sorunu.


2
"cyprtic": konuyu ifade etmek için harika bir yol.
Bevan

2
Daha önce hiç yazım hatası yapmadın mı @Bevan?

1
Ben yazım hataları her zaman var - yazma cyprtic ben öyle düşündüm çok iyi bilerek . Lütfen tekrar değiştirin, bir kaza olsa bile, amacınıza ulaşmaya yardımcı olur.
Bevan

1
@Bevan, haha ​​tamam ne dediğini anladım. İyi bir nokta! Geri değişti =)

1

Bazen (nadiren), makul miktarda parametre alan bir işlev yaratmanın en iyi yol olduğu görülmektedir.

Birkaç parametrenin kullanılması genellikle bu yöntemde SRP'yi ihlal ettiğinizin açık bir göstergesidir . Birçok parametreye ihtiyaç duyan bir yöntemin tek bir şeyi yapması pek mümkün değildir . Ekspetiyon, matematiksel bir fonksiyon veya aslında birkaç parametreye ihtiyaç duyulan bir konfigürasyon metodu olabilir . Şeytan kutsal sudan kaçınırken birden fazla parametreden kaçınırdım. Bir yöntem içinde ne kadar çok parametre kullanırsanız, yöntem o kadar yüksek, yöntemin karmaşık olması da o kadar olası; daha karmaşıklık şu anlama gelir: bakımı daha zor ve bu daha az arzu edilir.

Ancak, yaptığım zaman, sık sık parametrelerin sıralamasını rastgele seçtiğimi hissediyorum. Genelde en önemli parametre olan ilk önce "önem sırasına" bakarım.

Priniple'da rastgele seçiyorsunuz . Elbette , A parametresinin B parametresinden daha alakalı olduğunu düşünebilirsiniz ; ancak B'nin en alakalı parametre olduğunu düşünen API'nizin kullanıcıları için durum böyle olmayabilir . Öyleyse siparişi seçme konusunda dikkatli olsanız bile - diğerleri için rastgele görünebilir .

Bunu yapmanın daha iyi bir yolu var mı? Netliği artıran parametreleri sipariş etmenin "en iyi uygulama" yolu var mı?

Bunun birkaç yolu vardır:

a) Önemsiz durum: Birden fazla parametre kullanmayın.

b) Belirlemediğiniz gibi, hangi dili seçtiğiniz, adlandırılmış parametrelerle bir dil seçme şansınız var . Bu, paramters sıralamasının önemini gevşetmenize izin veren hoş sözdizimsel şekerdir :fn(name:"John Doe", age:36)

Her dil, bu tür güzellere izin vermez. O zaman ne?

c) Parametre olarak bir Dictionary / Hashmap / Associative Array kullanabilirsiniz : örneğin Javascript, aşağıdakilere izin verir: fn({"name":"John Doe", age:36})(b) den çok uzakta olmayan.

d) Elbette, Java gibi statik olarak yazılmış bir dille çalışıyorsanız. Bir Hashmap kullanabilirsiniz , ancak HashMap<String, Object>parametreler farklı türlere sahipken (ve kullanmanız gerektiğinde) tip bilgisi (örneğin birlikte çalışırken ) kaybedersiniz .

Bir sonraki mantıksal adım Object(Java kullanıyorsanız) uygun özelliklere sahip veya bir yapı gibi daha hafif bir şey (örneğin C # veya C / C ++ yazarsanız ) iletmek olacaktır .

Başparmak kuralı:

1) En iyi durum - yönteminiz hiç parametre gerektirmez

2) İyi durum - yönteminiz bir parametreye ihtiyaç duyar

3) Tolere edilebilir durum - yönteminiz iki parametreye ihtiyaç duyar

4) Diğer tüm davalar yeniden düzenlenmeli


0

Çoğu zaman parametre olarak karmaşık bir nesne daha iyidir - fakir bir adamın çoğu platformda çalışan adlandırılmış parametrelerin bir sürümü. Ve önyükleme davranışına sahip parametrelere giden kapıyı açar.

Yapmamanız gereken şeylerin bir örneği için PHP'nin standart kütüphane belgelerini okumayı denemek isteyebilirsiniz.


0

Bunları genellikle, önce ORDER BY required DESC, SOME_MAGIC_FEELING(importancy,frequency)herhangi bir özel uygulamaya göre değil , bir "his" e göre (görülebilir ) göre birleşik bir ithalat ve kullanım sıklığı ölçüsünden ziyade gerekli olarak sipariş ediyorum .

Ancak, diğerlerinin de belirttiği gibi, bunu bir sorun haline getiren sorunun altında çok fazla parametre kullanılıyor (IMHO, herhangi bir şey> 3 çok fazla) ve bu sizin ele almanız gereken asıl sorun. Bir var ilginç sonrası Rebecca Murphey blogunda bununla ilgili.

Sadece 1-3 argüman olduğunda, doğru sıralamanın oldukça açık olduğunu ve sadece doğru olanı “hissettiğini” düşünüyorum.


0

@Wyatt Barnetts'ın cevabına benzer şekilde, birkaç parametreden başka herhangi bir şey veya yöntem için çok açık parametreler yerine, bunun yerine bir nesneyi geçirmenizi tavsiye ederim. Bu genellikle güncellemesi / bakımı daha kolay, okunması daha açık ve sipariş verme konusunda endişelenme gerekliliğini ortadan kaldırıyor . Ayrıca, bir yöntem için çok fazla parametre kod kokusudur ve düzeltmek için takip edebileceğiniz ortak yeniden düzenleme modelleri vardır .

Açık örnek:

public int add(int left, int right)
{
  return left + right;
}

Bu oldukça açık bir şekilde tanımlanmış bir örnek olduğundan ve ekleme değişmeli olduğundan (sipariş önemli değil) o zaman onunla devam edin.

Ancak, daha karmaşık bir şey eklerseniz:

public SomeComplexReturnValue Calculate(int i, float f, string s, object o)
{
  // do work here
}

Olacaktı:

public class SomeComplexInputForCalculation
{
  public int i; 
  public float f;
  public string s; 
  public object o;
}

public SomeComplexReturnValue Calculate(SomeComplexInputForCalculation input)
{
  // do work here
}

Bu yardımcı olur umarım...


0

Körlemenin en çok fayda sağlayacağını düşündüğünüz şekilde sipariş edin. Örneğin, önce işlev parametreleri.


0

"Önemli ilk" çok şey ifade etmiyor. Bazı sözleşmeler var.

Çağıran nesneyi (genellikle gönderen adında) geçerseniz, önce bu olur.

Listede biraz akıcılık olmalı , yani okuduğunuzda tartışmanın ne hakkında olduğunu bilmelisiniz. Örnek:

CopyFolder (dize yolu, özyinelemeli bool);

Önce özyinelemeyi koyacak olsaydın, kafa karıştırıcı olurdu, çünkü henüz bir bağlam yoktu. Şimdiden bir şey (1), bir klasör (2) kopyalamakla ilgiliyse, özyinelemeli argüman anlamlı olmaya başlar.

Bu da IntelliSense benzeri özelliklerin iyi çalışmasını sağlar: kullanıcı argümanları doldururken öğrenir, metodu ve ne yaptığını anlar. Benzer şekilde, aşırı yükler eşit olan parçalar için aynı sırayı korumalıdır.

O zaman hala bu konuda "eşit" argümanlar olduğunu bulabilirsiniz ve sıranın argümanın türüne bağlı olmasına izin vermeniz istenebilir. Sırf üst üste bir kaç ipin olması ve bir kaç boole daha iyi görünmesi yüzünden. Bir seviyede, bu bir beceriden çok bir sanat haline gelecektir.

Tek bir argümanla sona ermek için tüm argümanları bir nesneye sarmanız gerektiği ifadesine pek aldırmıyorum. Bu sadece kendinizi kandırıyor (yöntemi daha az karmaşık hale getirmiyor, hala tüm bu argümanlara sahip, onları saklıyorsunuz). Birkaç kez yöntemden yönteme yöntemine geçtiğinizde, yeniden düzenleme işlemi çok daha kolay hale gelir, ancak tasarım açısından bir fark yaratıyormuş gibi yapman yeterlidir. Bir şeyi temsil eden anlamlı bir nesneyle bitmeyecek gibi değil, yöntem bildirimindeki listeden farklı olmayan bir sürü argüman olacak. Bob Amca'yı mutlu etmeyecek.

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.