Temiz Kod: Çok az parametreli fonksiyonlar [kapalı]


48

Temiz Kod'un ilk bölümlerini Robert C. Martin tarafından okudum ve bana göre oldukça iyi, ama bir şüphem var ki, bir kısımda, fonksiyonların bu kadar az parametreye sahip olması gerektiğinin iyi (bilişsel olarak) olduğu belirtildi. Mümkün olduğunca 3 veya daha fazla parametrenin bir işlev için çok fazla olduğunu bile gösteriyor (ki bu çok abartılı ve idealist buluyorum), bu yüzden merak etmeye başladım ...

Hem global değişkenleri kullanma uygulamaları hem de işlevler üzerine birçok argüman iletme kötü programlama uygulamaları olacaktır, ancak küresel değişkenlerin kullanımı, işlevlerdeki parametre sayısını büyük ölçüde azaltabilir ...

Bu yüzden ne düşündüğünüzü duymak istedim, fonksiyonların parametre sayısını azaltmak için global değişkenleri kullanmaya değer mi yoksa değer mi? Hangi durumlarda olabilir?

Benim düşüncem bunun birkaç faktöre bağlı olduğudur:

  • Kaynak kodu boyutu.
  • Fonksiyonların ortalama parametre sayısı.
  • Fonksiyonların sayısı.
  • Aynı değişkenlerin kullanıldığı frekans.

Bence kaynak kodu boyutu göreceli olarak küçükse (600 satırdan az kod gibi), birçok fonksiyon vardır, aynı değişkenler parametre olarak iletilir ve fonksiyonlar birçok parametreye sahiptir, o zaman global değişkenleri kullanmaya değecekti ama ben Bilmek istemek...

  • Fikrimi paylaşıyor musun?
  • Kaynak kodun daha büyük olduğu diğer durumlar hakkında ne düşünüyorsunuz?

PS . Gördüğüm bu yazı başlıkları çok benzer, ama ben bilmek istiyorum istemez.


144
Alternatifin küresel olacağını düşünmüyorum, bunun yerine argümanları nesnelerle birleştiriyoruz. Muhtemelen postLetter(string country, string town, string postcode, string streetAddress, int appartmentNumber, string careOf)kokulu bir versiyonu olan bir öneri daha fazla postLetter(Address address). Kitabı okumaya devam edin, umarım böyle bir şey söyleyecektir.
Nathan Cooper,

3
@DocBrown Bob Amca gibi daha fazla param kullanmıyor diyor gibi bir şey demek için soruyu aldım, bu yüzden genel değişkenleri doğru kullanarak bu sorunu aşmak? :-) Muhtemelen yazarın bu sorunu çözmenin daha iyi yolları olduğunu bilmediğini düşünüyorum - aşağıdaki cevaplarda belirtildiği gibi.
bytedev

9
N parametresinden daha fazla değil, bir pırlanta üzerinde çizilmemiş (bir n değeri için) bir kuraldır . Görev için iyi tavsiyelerde bulunmayın. Çok sayıda parametre genellikle tek bir fonksiyonda / yöntemde çok fazla şey yaşattığınızın bir kod kokusudur. İnsanlar, ekstra görüşmelerin ek yükünü atlatmak için birden fazla işleve bölmekten kaçınırlardı. Çok az sayıda uygulama artık bu kadar yoğun ve profiler size ne zaman ve nerede fazladan arama yapmaktan kaçınmanız gerektiğini söyleyebilir.
Jared Smith,

14
Bu, bu tür yargılama yasağı kuralında neyin yanlış olduğunu gösterir: Yargılamayan 'çözümlere' kapıyı açar. Bir işlevin birçok argümanı varsa, genellikle sadece işlevin değil, aynı zamanda kullanıldığı bağlamın alt düzey bir tasarımını gösterebilir. Çözüm (gerekirse) kodu yeniden denemek için arama yapmaktır. Size nasıl yapılacağına dair basit, genel ve yargılamayan bir kural veremem, ancak bu, 'N argümanından daha fazlasının' iyi bir kural olduğu anlamına gelmez.
sdenham

4
Bir fonksiyon için çok fazla parametreniz varsa, olasılıklar bunlardan bazıları ilişkilidir ve daha sonra birçok veri parçasını içeren tek bir parametre haline gelen bir nesneye gruplandırılmalıdır. Burada üçüncü bir seçenek var.

Yanıtlar:


113

Fikrini paylaşmıyorum. Benim görüşüme göre, global değişkenleri kullanmak, tarif ettiğiniz niteliklerden bağımsız olarak daha fazla parametreden daha kötü bir uygulamadır. Benim akıl yürütme, daha fazla parametrenin anlaşılmasını zorlaştırabilir, ancak global değişkenler kod için zayıf test edilebilirlik, eşzamanlılık hataları ve sıkı bağlantı gibi birçok soruna neden olabilir. Bir fonksiyonun kaç parametresi olursa olsun, doğal değişkenlerle aynı sorunları yaşamayacaktır.

... aynı değişkenler parametre olarak iletilir

Bu olabilir tasarım kokusu olabilir. Sisteminizdeki birçok fonksiyona aynı parametreler iletiliyorsa, yeni bir bileşen tanıtılarak ele alınması gereken bir kesişme endişesi olabilir. Global değişkenleri tanıtmak için aynı değişkenleri birçok fonksiyona geçirmenin sağlıklı bir mantıklı olduğunu düşünmüyorum.

Sorunuzun bir düzenlemesinde, global değişkenleri tanıtmanın kodun okunabilirliğini artırabileceğini belirtti. Katılmıyorum. Genel değişkenlerin kullanımı uygulama kodunda gizli iken, işlev parametreleri imzada belirtilmiştir. İşlevler ideal olarak saf olmalıdır. Sadece parametreleri üzerinde çalışmalı ve herhangi bir yan etkisi olmamalıdır. Saf bir işleve sahipseniz, sadece bir işleve bakarak işlev hakkında bir sebep olabilirsiniz. Eğer işleviniz saf değilse, diğer bileşenlerin durumunu göz önünde bulundurmalısınız ve bunun hakkında düşünmesi çok daha zor hale gelir.


Tamam, başka görüşler duymak güzel, ama tasarım kokusu hakkında, yapay zeka yöntemleriyle çözülen C problemlerinde programlama yapıyorum ve hemen hemen her zaman aynı matrisleri, dizileri veya değişkenleri kullanan birçok işlevi kullanma eğilimindeyim. Fonksiyonlara parametre olarak geçiyorum), bunu söylüyorum çünkü bu değişkenleri bir yapı veya sendika gibi ortak bir kavramın / nesnenin içine koyabileceğimi hissetmiyorum çünkü daha iyi bir tasarım yapmayı bilemem, Bu yüzden bu durumda küresel değişkenlerin kullanımının faydalı olacağını düşünüyorum, ama büyük olasılıkla yanılıyorum.
OiciTrap

1
Bu bir tasarım sorunu gibi gelmiyor. Parametrelerin fonksiyonlara geçirilmesinin hala en iyi tasarım olduğunu düşünüyorum. Tarif ettiğiniz gibi bir AI sisteminde, sistemin parçalarını test etmek için birim testleri yazmanın ve bunun en kolay yolunun parametrelerle yapılmasını yararlı bulacağım.
Samuel,

96
Daha fazla parametre alt yordamın anlaşılmasını zorlaştırır, genel değişkenler tüm programı, yani tüm alt yordamların anlaşılmasını zorlaştırır.
Jörg W Mittag

2
Bazı fonksiyonların bir düzine parametreden daha fazlasını aldığı bir kod tabanı tutuyorum. Çok büyük bir zaman kaybı - fonksiyonu çağırmam gerektiğinde, bu dosyayı başka bir pencerede açmam gerekiyor, böylece parametrelerin hangi sırada belirtilmesi gerektiğini bilirim. Bana intellisense gibi bir şey veren bir IDE kullandıysam veya parametre ismini taşıyan bir dil kullandıysam o kadar da kötü olmazdı ama bu fonksiyonlar için bir düzine parametrenin hangi sırada olduğunu kim bilebilirdi?
Jerry Jeremiah,

6
Cevap, söylediklerinde doğrudur, ancak yine de OP'lerin verilen “Temiz Kod” undaki önerileri hakkında yanlış anlamalarına neden olur. Fonksiyon parametrelerinin o kitaptaki globaller tarafından değiştirilmesinin tavsiye edilmediğinden eminim.
Doktor Brown,

68

Veba gibi global değişkenlerden kaçınmalısınız .

I (3 veya 4 gibi) bağımsız değişkenlerin sayısı için bir sabit sınır koymak olmaz, ama sen do mümkünse minimumda tutmak istiyoruz.

Kullanım structs (ya da C ++ nesneleri) tek bir varlık grup birlikte değişkenlerine ve (referans ile bu) olup geçmesi fonksiyonlar ile ilgilidir. Genellikle bir işlev, içinde bir şeyler yapmasını söyleyen bir kaç parametre ile birlikte (içinde birkaç farklı şey bulunan) bir yapı veya nesne alır struct.

Kokulu, temiz, modüler kod için, tek sorumluluk ilkesine bağlı kalmaya çalışın . Bunu yapılarınız (veya nesneleriniz), fonksiyonlarınız ve kaynak dosyalarınızla yapın. Bunu yaparsanız, bir işleve iletilen doğal parametre sayısı açık olacaktır.


5
Bir yapı içinde gizlenmiş onlarca parametreyi geçmek ile bunları açıkça iletmek arasındaki temel fark nedir?
Ruslan

21
@Ruslan Yapıştırma.
abuzittin gillifirca

9
Fonksiyonu daha küçük fonksiyonlara yeniden yerleştirme olasılığınız daha yüksektir, çünkü onlarca parametre yerine sadece bir parametreyi alt fonksiyonlara aktarabilirsiniz. Konumsal argümanlar kullanıyorsanız ve parametreleri karıştırma riski daha azdır.
Hans Olsson,

8
Sorun değil, ancak Yapılardaki tutarlılığı sağlamak zorundasınız - bir Yapıda gruplanan parametrelerin 'ilişkili' olduğundan emin olun. Bazı durumlarda birden fazla Yapı kullanabilirsiniz.
Andrew Dodds

8
@ abuzittingillifirca Otomatik olarak uyum elde edemezsiniz. Parametreleri bir yapıya koymanın tek nedeni, onları belirli bir işleve aktarmaksa, o zaman uyum muhtemelen yanıltıcıdır.
sdenham,

55

Bilişsel yükten söz ediyoruz, sözdizimi hakkında değil. Soru Yani ... Ne olduğunu bu bağlamda bir parametre?

Parametre, fonksiyonun davranışını etkileyen bir değerdir. Parametreler ne kadar fazla olursa, değerlerin olası kombinasyonları o kadar fazla olur, işlev hakkında o kadar zorlu mantık alır.

Bu anlamda, küresel değişkenler fonksiyon kullanımları olduğunu vardır parametreleri. İmzasında görünmeyen, yapım sırası, erişim kontrolü ve acil durum sorunları olan parametrelerdir.

Bahsedilen parametre, çapraz kesme kaygısı olarak adlandırılmadığı sürece , her şeyin kullandığı, programda kullanılan, hiçbir şeyin değişmediği (örneğin bir kayıt nesnesi) durumudur, fonksiyon parametrelerini global değişkenlerle değiştirmemelisiniz. Hala parametreler olurdu, ama daha acımasız.


11
Sana bir + 1, bir tuvaleti ya da bir komodin olsun onlar aynı kokuyor. Koyun kılığına girmiş kurdu işaret eden iyi bir iş.
Jared Smith,

1
Hem birçok parms hem de global değişkenlerin kötü olduğunu belirten +1. Ama bir şeyi açıklığa kavuşturmak istiyorum. Çoğu dilde, ilkel parametreler varsayılan olarak değere göre iletilir (Java) ve diğerlerinde bunları açıkça değere göre (PL / SQL) geçirebilirsiniz. Öte yandan, küresel ilkellere her zaman referans olarak erişilir (yani). Dolayısıyla, en azından ilkel tür olan parametreler, her zaman genel değişkenlerden daha güvenlidir. Elbette iki veya üçten fazla parametreye sahip olmak bir koku olsa da, on iki parametreye sahip olmak, shoule'nin yeniden yapılandırılması gereken büyük bir koku.
Tulains Córdova

4
Kesinlikle, genel bir değişken IS gizli bir parametredir.
Bill K,

+1 Amacınız, verileri aktarmak için global değişkenlere dayanan MATLAB simülasyonları gördüm. Sonuç tamamen okunamıyordu; çünkü hangi değişkenlerin hangi fonksiyonun parametresi olduğunu söylemek çok zordu.
Cort Ammon

34

IMHO sorunuz bir yanlış anlama dayanmaktadır. "Temiz Kod" ta, Bob Martin, tekrarlanan fonksiyon parametrelerinin globals ile değiştirilmesini önermez, bu gerçekten korkunç bir tavsiye olacaktır. Bunları , işlev sınıfının özel üye değişkenleriyle değiştirmeyi önerir . Ayrıca , küçük, yapışkan sınıflar (tipik olarak bahsettiğiniz 600 kod satırından daha küçük) önermektedir , bu nedenle bu üye değişkenleri kesinlikle küresel değildir.

Bu nedenle görüşünüz 600'den az çizgiyle “global değişkenleri kullanmak buna değecektir” bağlamında olduğunda , Bob Amca'nın fikrini mükemmel bir şekilde paylaşıyorsunuz. Elbette, "maksimum 3 parametre" ideal sayı ise ve bu kural bazen küçük sınıflarda bile çok fazla üye değişkenine yol açıyorsa tartışılabilir. IMHO bu bir takas, çizgiyi çekecek zor ve hızlı bir kural yok.


10
Neden birisinin sınıflarını sadece gerçek bir argümanla yaşamak yerine, bir kurucuya parametreler koyarak doldurmayı tercih ettiğini anlamadım. Bu her zaman beni karmaşıklıkta muazzam bir artış olarak gördü. (Ben bu gördüğüm gerçek yaşamdan bir örneği bağımlılık enjeksiyonu ile birleştirildiğinde neredeyse imkansız program sayesinde veritabanının durumunu izlemeye çalıştığınız yapılan bir veritabanı bağlantı nesnesi, budur.) Ama belki Temiz Kod söz konusu söyleyecek daha vardır konu, özne. Elbette, küreseller durumları daha iyi duruma getirme konusunda daha da kötü bir seçenektir.
jpmc26

2
@ jpmc26: eğer sınıflar çok büyük olursa ve çok fazla üye değişkeni elde ederse, sadece "muazzam bir karmaşıklık artışı" alır, bu nedenle sonuç artık tutarlı değildir.
Doktor Brown,

4
Bence bu yanıt, birçok sınıfa yayılmış olan devlet yönetimindeki (hatta değişken olabilir) zorlukları görmezden geliyor. Bir işlev yalnızca argümanlara değil, aynı zamanda nesnenin nasıl yapılandırıldığına (veya ömrü boyunca bile değiştirildiğine) bağlı olduğunda, belirli bir çağrı yaptığınız zamanki durumunu anlamak zorlaşır. Şimdi aramanın ne yapacağını bulmak için başka bir nesnenin yapısını izlemeniz gerekiyor. Örnek değişkenleri eklemek, nesneyi yapıp hemen atmadığınız sürece, programın durum miktarını aktif olarak artırır mı?
jpmc26

3
@ jpmc26 Yeniden yapılanma sırasında düzenli olarak kullandığım bir desen, yapıcının bir bağlam ayarlamak gibi davranmasıdır, ardından yöntem argümanları bir eyleme özgüdür. Nesne tam olarak durumlu değildir, çünkü tuttuğu durum asla değişmez, ancak bu ortak eylemleri bu kapsayıcı yöntemlerine taşımak, kullanıldığı yerlerde okunabilirliği önemli ölçüde artırır (içerik yalnızca bir kez ayarlanır, python'un içerik yöneticilerine benzer şekilde) ve çoğaltmayı azaltır. nesnenin yöntemlerine birden çok çağrı yapılır.
Izkata

3
+1 Üye değişkenlerinin genel değişkenler olmadığını açıkça söylemek için. Birçok insan öyle olduğunu düşünüyor.
Tulains Córdova

34

Birçok parametreye sahip olmanın istenmeyen olduğu kabul edilir, ancak bunları alanlara veya global değişkenlere dönüştürmek çok daha kötüdür çünkü asıl sorunu çözmez fakat yeni problemler ortaya çıkarır.

Birçok parametreye sahip olmak kendi başına sorun değil, ancak bir sorun olabileceğinin bir belirtisidir . Bu yöntemi düşünün:

Graphics.PaintRectangle(left, top, length, height, red, green, blue, transparency);

7 parametreye sahip olmak kesin bir uyarı işaretidir. Asıl sorun, bu parametrelerin bağımsız olmaması ancak gruplara ait olmasıdır. leftve topbir şekilde birbirine ait Position-Elektroseramiklerde yapı, lengthve heightbir şekilde Sizeyapı ve red, blueve greenbir şekilde Colorbir yapı. Ve belki Colorve şeffaflık bir Brushyapıya ait? Belki Positionve Sizebir Rectangleyapıda bir araya geliyoruz, bu durumda onu nesnede bir Paintyönteme dönüştürmeyi bile düşünebiliriz Rectangle? Bu yüzden son bulabiliriz:

Rectangle.Paint(brush);

Görev tamamlandı! Ancak asıl önemli olan, aslında genel tasarımı geliştirmiş olduğumuzdur ve parametre sayısındaki azalma bunun bir sonucudur . Temel sorunları çözmeden sadece parametre sayısını azaltırsak, şöyle bir şey yapabiliriz:

Graphics.left = something;
Graphics.top = something;
Graphics.length = something;
...etc
Graphics.PaintRectangle();

Burada parametre sayısında aynı azalmayı sağladık, ancak aslında tasarımı daha da kötüleştirdik .

Alt satır: Herhangi bir programlama tavsiyesi ve temel kurallar için, altta yatan mantığı anlamak gerçekten önemlidir.


4
+1 güzel, yapıcı, anlaşılır, teorik olmayan cevap.
AnoE

1
Bahsetmiyorum bile, "kare" nin hem uzunluk hem de yükseklik özelliğine sahip olmasının sebebi. :)
Wildcard

1
Bazı cevapların ima ettiği üçüncü yolun (yani, işlev çağrısından önce bir yapıya / nesneye yapılan birçok atama) daha iyi olmadığını kabul etmek için +1.
benxyzzy

@Wildcard: Teşekkürler, sorunu karıştırmamak için "dikdörtgen" olarak değiştirdik!
JacquesB

7

fonksiyonların parametre sayısını azaltmak için global değişkenleri kullanmaya değer mi, değil mi?

Değil

Bu kitabın ilk bölümlerini okudum

Kitabın kalanını okudun mu?

Global sadece gizli bir parametredir. Farklı bir acıya neden olurlar. Ama bu hala acı. Bu kuralı aşmanın yollarını düşünmekten vazgeç. Nasıl takip edeceğinizi düşünün.

Parametre nedir?

Bu şeyler. Güzel etiketli bir kutuda. İçinde ne gibi şeyler koyabiliyorsan, kaç kutuya sahip olman neden önemli?

Nakliye ve taşıma maliyeti.

Move(1, 2, 3, 4)

Bunu okuyabildiğini söyle. Hadi dene.

Move(PointA, PointB)

Bu yüzden.

Bu numaraya, object parametresi adı verilir .

Ve evet, yaptığınız tek şey parametreleri saymak. Saymanız gereken şey FİKİRLER! Soyutlamalar! Beni bir kerede ne kadar düşündürüyorsun? Basit tut.

Şimdi bu aynı sayı:

Move(xyx, y)

Offf! Bu korkunç! Burada yanlış olan ne?

Fikir sayısını sınırlamak yeterli değil. Net fikirler olmalılar. Bir xyx halt nedir?

Şimdi bu hala zayıf. Bunun hakkında düşünmenin daha güçlü bir yolu nedir?

İşlevler küçük olmalıdır. Bundan daha küçük değil.

Bob Amca

Move(PointB)

Neden işlev gerçekten gerekenden daha fazlasını yapıyor? Tek sorumluluk ilkesi sadece sınıflar için değildir. Cidden, sadece bir fonksiyonun, bazıları başkalarıyla kullanılamayan 10 bazen ilgili parametrelerle aşırı yüklenmiş bir kabusa dönüşmesini durdurmak için bütün bir mimariyi değiştirmeye değer.

Bir fonksiyondaki en yaygın satır sayısının 1 olduğu bir kod gördüm. Cidden. Bu şekilde yazman gerektiğini söylemiyorum ama sheesh, bana bir küresel söyleme, bu kurala uymanın SADECE bir yol olduğunu söyleme. Bu işlevi yeniden düzenlemekten kurtulmaya çalışmayı bırakın. Yapabileceğini biliyorsun. Birkaç fonksiyona bölünebilir. Aslında birkaç nesneye dönüşebilir. Cehennem bile bunun bir kısmını tamamen farklı bir uygulamaya ayırabilirsin.

Kitap, parametrelerinizi saymanızı söylemiyor. Size neden olduğunuz acıya dikkat etmenizi söylüyor. Ağrıyı gideren her şey sorunu çözer. Sadece bir acıyı diğerine sattığınızın farkında olun.


3
"Kitabın kalanını okudun mu?" Sorunuz, gönderimin ilk 8 kelimesinde cevaplandı ...
OiciTrap

Tamamen katılıyorum - mesele sorunu küçük parçalara ayırmaktır. Nesneler, bu parçaları düzenlemeye ve gruplandırmaya gerçekten yardımcı olabilirler, aynı zamanda, birbirleriyle bağlantılı olmayan parçalardan ziyade, tek bir kavramsal birimin parametre olarak geçirilmesine izin verirler. 3 parametreden daha fazlasını içeren bir yöntem gördüğümde antsy olsun. 5, tasarımımın bozulmaya başladığının bir göstergesi ve başka bir yeniden düzenleme turuna ihtiyacım var. Parametre sayımı gibi tasarım sorunlarını çözmenin en iyi yolu, basitçe işleri daha küçük, basit birimlere (sınıflar / yöntemler) yeniden yansıtmaktır.
Bill K,

2
Bu cevabın tonu geliştirilebilir. Çok ani ve sert olarak okur. Örneğin: "Bunu okuyabildiğini söyle. Hadi, dene." çok agresif görünüyor ve "Yukarıdaki / aşağıdaki iki işlev çağrısından hangisinin okunması daha kolay?" olarak yeniden yazılabilir. Saldırı olmadan noktaya ulaşmaya çalışmalısınız. OP sadece öğrenmeye çalışıyor.
Kyle A

Unutma ki OP de uyanık kalmaya çalışıyor.
candied_orange

4

Parametreleri azaltmak için asla global değişkenleri kullanmam. Bunun nedeni, global değişkenlerin herhangi bir işlev / komut tarafından değiştirilebilmesidir, bu nedenle işlev girişini güvenilmez kılar ve işlevlerin yapabileceklerinin kapsamı dışındaki değerlere eğilimli hale getirir. Değişken, işlevin yürütülmesi sırasında değiştirilmişse ve işlevin yarısı diğer yarımdan farklı değerlere sahipse?

Diğer taraftan parametrelerin geçirilmesi, değişkenin kapsamını yalnızca kendi işlevi ile sınırlandırır, böylece yalnızca işlev çağrıldığında bir parametreyi değiştirebilir.

Bir parametre yerine global değişkenleri geçmeniz gerekiyorsa, kodu yeniden tasarlamak tercih edilir.

Sadece iki sentim.


“Parametreleri azaltmak için hiçbir zaman global değişken kullanmam” tamamen kabul etti. Gereksiz kuplaj yaratır.
bytedev

2

Bu konuda Bob Amca ile birlikteyim ve 3'ten fazla paramın kaçınılması gereken bir şey olduğuna katılıyorum (Çok nadiren bir fonksiyonda 3 paramdan fazla kullanırım). Tek bir fonksiyon üzerinde çok fazla parama sahip olmak daha büyük bir bakım problemi yaratır ve muhtemelen fonksiyonunuzun çok fazla yaptığı / çok fazla sorumluluğu olduğu kokusudur.

Bir OO dilinde bir yöntemde 3'ten fazlasını kullanıyorsanız, o zaman bir şekilde birbiriyle ilgili olmayan paramları göz önünde bulundurmalısınız ve bu nedenle bunun yerine gerçekten bir nesneyi geçiriyor olmalısınız.

Ayrıca, daha fazla (daha küçük) işlevler yaratırsanız, işlevlerin daha sık 3 parama veya daha az parazit gösterme eğiliminde olduğunu da fark edeceksiniz. Özü işlevi / yöntem arkadaşın :-).

Küresel değişkenleri, daha fazla paragrafa sahip olmaktan kurtulmanın bir yolu olarak kullanmayın! Bu, daha da kötüsü için kötü bir uygulamayı değiştiriyor!


1

Bir çok fonksiyon parametresinin geçerli bir alternatifi, bir parametre objesi tanıtmaktır . Bu, tüm parametrelerini bir grup başka yönteme aktaran (neredeyse) tümleşik bir yönteminiz varsa kullanışlıdır .

Basit durumlarda, bu özellik olarak eski parametreler dışında hiçbir şeye sahip olmayan basit bir DTO'dur.


1

Genel değişkenleri kullanmak her zaman (özellikle küçük bir programda) kodlamanın kolay bir yoludur, ancak kodunuzu genişletmeyi zorlaştıracaktır.

Evet, bir varlıktaki parametreleri bağlamak için bir dizi kullanarak işlevdeki parametre sayısını azaltabilirsiniz.

function <functionname>(var1,var2,var3,var4.....var(n)){}

Yukarıdaki işlev düzenlenecek ve [ilişkisel dizi kullanılarak] olarak değiştirilecektir -

data=array(var1->var1,
           var2->var2
           var3->var3..
           .....
           ); // data is an associative array

function <functionname>(data)

Robert bristow-johnson'un cevabına katılıyorum : Verileri tek bir varlıkta bağlamak için bir yapı bile kullanabilirsiniz.


1

PHP 4'ten bir örnek alarak, aşağıdaki işlev imzalarına bakın mktime():

  • int mktime ([ int $hour = date("H") [, int $minute = date("i") [, int $second = date("s") [, int $month = date("n") [, int $day = date("j") [, int $year = date("Y") [, int $is_dst = -1 ]]]]]]] )

Bunu kafa karıştırıcı bulmuyor musun? İşlev "time time" olarak adlandırılır ancak gün, ay ve yıl parametrelerinin yanı sıra üç zaman parametresini de alır. Hangi sıraya girdiklerini hatırlamak ne kadar kolay? Ya görürsen mktime(1, 2, 3, 4, 5, 2246);? Başka bir şeye atıfta bulunmak zorunda olmadan bunu anlayabiliyor musunuz? Is 224624 saat süre "22:46" olarak yorumlanır? Diğer parametreler ne anlama geliyor? Bir nesne olarak daha iyi olurdu.

PHP 5'e geçildiğinde, artık bir DateTime nesnesi var. Metotları arasında iki adında setDate()ve vardır setTime(). İmzaları aşağıdaki gibidir:

  • public DateTime setDate ( int $year , int $month , int $day )
  • public DateTime setTime ( int $hour , int $minute [, int $second = 0 ] )

Parametrelerin sırasının en büyüğünden en küçüğüne geçtiğini hatırlamak zorundasınız, ancak bu büyük bir gelişme. Altı parametrenin tümünü aynı anda ayarlamanıza izin veren tek bir yöntem olmadığını unutmayın. Bunu yapmak için iki ayrı arama yapmanız gerekir.

Bob Amca'nın bahsettiği şey düz bir yapıya sahip olmaktan kaçınmaktır. İlgili parametreler bir nesnede gruplandırılmalıdır ve üçten fazla parametreniz varsa, orada büyük olasılıkla sözde bir nesneye sahip olmanız, bu da size daha büyük bir ayırma için uygun bir nesne yaratma fırsatı verir. PHP'nin ayrı Dateve Timesınıfı olmamasına rağmen , bunun DateTimegerçekten bir Datenesne ve bir Timenesne içerdiğini düşünebilirsiniz .

Muhtemelen aşağıdaki yapıya sahip olabilirsiniz:

<?php
$my_date = new Date;
$my_date->setDay(5);
$my_date->setMonth(4);
$my_date->setYear(2246);

$my_time = new Time;
$my_time->setHour(1);
$my_time->setMinute(2);
$my_time->setSecond(3);

$my_date_time = new DateTime;
$my_date_time->setTime($my_time);
$my_date_time->setDate($my_date);
?>

Her seferinde iki veya üç parametre ayarlamak zorunlu mudur? Sadece bir saat veya sadece bir gün değiştirmek istiyorsanız, şimdi yapmak kolaydır. Evet, her parametrenin diğerleriyle birlikte çalıştığından emin olmak için nesnenin doğrulanması gerekir, ancak yine de böyle oldu.

En önemlisi, anlaşılması daha kolay ve bu yüzden de sürdürmek mi? Alt kısımdaki kod bloğu tek bir mktime()fonksiyondan daha büyük , ama bunun daha kolay anlaşılabileceğini savunuyorum; programcı olmayan bir kişi bile, ne yaptığını çözmekte zorlanmayacaktır. Amaç her zaman daha kısa kod veya daha akıllı kod değil, daha fazla korunabilir koddur.

Oh, ve globals kullanmayın!


1

Burada birçok iyi cevap var, ancak çoğu konuya değinmiyor. Neden bu kurallar? Kapsam ile ilgili, bağımlılıklar ile ilgili ve uygun modelleme ile ilgili.

Tartışmalar için globals daha kötü, çünkü sadece basitleştirmiş gibisin, ama aslında sadece karmaşıklığı sakladın. Artık prototipte görmüyorsunuz ama yine de farkında olmak zorundasınız (ki bu artık görmeniz için orada olmadığından zordur) ve başınızı fonksiyonun mantığı etrafında dolaştırmanız size yardımcı olmaz çünkü arkanıza müdahale eden diğer gizli mantıklardan biri olun. Kapsamınız her yere yayıldı ve neye bağımlı oldunuz çünkü artık değişkeninizle neyin karışabileceğini. İyi değil.

Bir fonksiyon için korunacak en önemli şey prototip ve çağrıya bakarak ne yaptığını anlayabilmenizdir. Bu yüzden isim açık ve net olmalıdır. Ancak, ne kadar fazla argüman varsa, ne yaptığını kavramak o kadar zor olacaktır. Kafanızdaki kapsamı genişletiyor, çok fazla şey oluyor, bu yüzden sayıyı sınırlandırmak istiyorsunuz. Ne tür argümanlarla uğraştığınız önemli olsa da, bazıları diğerlerinden daha kötü. Büyük / küçük harf duyarsız işlemelere izin veren isteğe bağlı bir boolean, işlevi daha fazla anlamak zorunda kalmaz, bu yüzden bu konuda çok fazla şey yapmak istemezsiniz. Bir not olarak, numaralandırmalar booleanlardan daha iyi argümanlar yapar çünkü çağrıda bir enumun anlamı açıktır.

Tipik sorun, muazzam miktarda argüman içeren yeni bir fonksiyon yazmak değil, yalnızca birkaçı ile başlayacağınız, henüz çözmediğiniz problemin ne kadar karmaşık olduğunun farkına varacaksınız. Programınız geliştikçe, tartışma listeleri giderek uzama eğilimindedir. Bir model aklınızdan geçtikten sonra bunu saklamak istersiniz, çünkü bu sizin bildiğiniz güvenli bir referanstır. Ancak geçmişe bakıldığında model bu kadar iyi olmayabilir. Mantıkta bir veya daha fazla adımı kaçırdınız ve bir veya iki varlık tanıyamadınız. “Tamam… Baştan başlayıp kodumu yeniden gözden geçirerek bir veya iki günümü geçirebilirim veya… Bu argümanı ekleyebilirim, böylece sonuçta doğru olanı yapabilirim ve bununla bitirdim. Şimdilik. Bu senaryo için Yaptığım notu tabağımdan çıkarmak, böylece yapışkan notu bitirdim. "

İkinci çözümle ne kadar sık ​​giderseniz, daha pahalı olan bakım da o kadar artar ve bir refaktör zorlaşır ve çekici olmaz.

Mevcut bir fonksiyondaki argüman sayısını azaltmak için bir kazan plakası çözümü yoktur. Bunları sadece bileşikler halinde gruplamak işleri kolaylaştırmak değil, halının altındaki karmaşıklığı silmenin başka bir yoludur. Doğru yapmak, tüm çağrı yığınına tekrar bakmak ve neyin eksik olduğunu veya neyin yanlış yapıldığını tanımayı içerir.


0

Birkaç kez, birlikte gönderilen birçok parametrenin gruplandırılmasının işleri iyileştirdiğini fark ettim.

  • Birlikte kullanılan kavramların bu bozulmasına iyi bir isim vermeye zorlar. Bu parametreleri birlikte kullanırsanız, onların bir ilişkisi olabilir (veya birlikte kullanmamanız gerekebilir).

  • Bir zamanlar nesneyle genellikle bazı funtionality'lerin bu görünüşte stuypid nesnesi tarafından hareket ettirilebileceğini öğrendim. Genelde test edilmesi kolaydır ve mükemmel bir uyum ve düşük bağlantı özelliği sayesinde işleri daha da iyi hale getirir.

  • Bir dahaki sefere yeni bir parametre eklemem gerekecek, birçok yöntemin imzasını değiştirmeden eklemek için güzel bir yerim var.

Bu nedenle, zamanın% 100'ünde çalışmayabilir, ancak bu parametre listesinin bir nesnede gruplandırılıp gruplandırılmayacağını kendinize sorun. Ve lütfen. Nesneyi oluşturmaktan kaçınmak için Tuple gibi yazılmamış sınıfları kullanmayın. Nesne yönelimli programlama kullanıyorsunuz, ihtiyacınız olursa daha fazla nesne oluşturmaya aldırmayın.


0

Tüm saygımla, bir fonksiyonda az sayıda parametreye sahip olma noktasını tamamen kaçırdığınızdan eminim.

Fikir beyin tek seferde bu kadar "aktif bilgiyi" tutabilir ve varsa yani n bir fonksiyonu parametreleri, sahip n ihtiyaçlar kolay ve doğru şekilde beyinde olmak olduğunu "aktif bilgi" nin daha fazla parçayı Kod parçasının ne yaptığını kavrar (Code Complete'teki Steve McConnell (çok daha iyi bir kitap, IMO), bir yöntemin gövdesindeki 7 değişkenle ilgili benzer bir şey söyler: nadiren buna ulaşırız, ancak daha fazlasını kaybedersiniz) yeteneği kafanızdaki her şeyi düz tutun).

Düşük sayıdaki değişkenlerin amacı, bu kodla çalışmanın bilişsel gereksinimlerini küçük tutabilmektir, böylece daha etkili çalışabilirsiniz (veya okuyabilirsiniz). Bunun bir yan nedeni, iyi faktörlü kodun daha az ve daha az parametreye sahip olma eğiliminde olacağıdır (örneğin, zayıf faktörlü kod bir karışıklığı gruplandırmaya meyillidir).

Değerler yerine nesneler geçirerek, belki de beyniniz için bir soyutlama düzeyi elde edersiniz, çünkü şimdi evet anlamam gerekiyor, bu arama bağlamında olabilecek 15 özelliği düşünmek yerine, burada çalışmak için bir SearchContext'e sahibim .

Global değişkenlerini kullanmaya çalıştığınızda tamamen yanlış yöne gittiniz. Şimdi sadece bir fonksiyon için çok fazla parametrenin bulunma problemini çözmediniz, o problemi aldınız ve şimdi aklınızda bulundurmanız gereken çok, daha iyi bir problemi atdınız!

Şimdi sadece işlev düzeyinde çalışmak yerine, projenizin küresel kapsamını da göz önünde bulundurmanız gerekir (hayret, ne kadar korkunç! Titreşim ...). İşlevdeki önünüzdeki tüm bilgileriniz bile yok (saçma, bu küresel değişken adı nedir?) (Umarım bu işlevi çağırdığımdan beri başka bir şey tarafından değiştirilmemiştir).

Küresel kapsamda yer alan değişkenler, bir projede (büyük veya küçük) görülecek en kötü şeylerden biridir. Programlama için oldukça temel bir beceri olan uygun kapsam yönetimi için bir engeli ifade ederler. Onlar. Are. Kötülük.

Parametreleri fonksiyonunuzun dışına taşıyarak ve onları kürelere yerleştirerek, kendinizi (ya da bacağınız ya da yüzünüz) çekiyorsunuz. Ve tanrı , karar vermenizi yasaklar hey, bu dünyayı başka bir şey için tekrar kullanabilirim ... zihnim düşüncede titriyor.

Bütün ideal, işlerin kolay yönetilmesini sağlamak ve küresel değişkenler bunu yapmayacak. Aksi yönde gitmek için yapabileceğiniz en kötü şeylerden biri olduklarını söyleyene kadar giderdim.


-1

Arayüzler arasındaki sürtünmeyi en aza indirmek için oldukça etkili bir yaklaşım (JavaScript'te) buldum: Tüm modüller için tek biçimli bir arayüz kullanın , özellikle: tek param fonksiyonları.

Birden fazla parametreye ihtiyaç duyduğunuzda: Tek bir Nesne / Karma veya Dizi kullanın.

Benimle ayı, ben trolling değilim söz veriyorum ...

“Tek bir param işlevi nedir?” Veya “1 Array ve çoklu argüman işlevleri arasında bir fark var mı?” Demeden önce

İyi evet. Belki görsel olarak ince, ama fark çok yönlü - Ben burada birçok faydaları araştırmak

Görünüşe göre bazı ppl 3 düşünüyorum argümanların doğru olduğunu. Bazıları 2 olduğunu düşünüyor. Peki, "Hangi param argümana giriyor [0]?" Arayüzü sınırlayan seçeneği seçmek yerine, daha katı bir beyanla.

Sanırım daha radikal bir konum için savunuyorum: konumsal tartışmalara dayanmayın. Sadece kırılgan olduğunu ve kahrolası tartışmaların konumu hakkında tartışmalara yol açtığını hissediyorum. Atlayın ve fonksiyonların ve değişkenlerin isimleri hakkında kaçınılmaz mücadeleye devam edin. 😉

Cidden, isimlendirdikten sonra, umarım pozisyona duyarlı olmayan ve gelecekteki param değişikliklerinin işlevin içinde ele alınmasını sağlayan aşağıdaki gibi bir kodla bitirdiniz:

function sendMessage({toUser, fromUser, subject, body}) { }

// And call the method like so:
sendMessage({toUser: this.parentUser, fromUser: this.currentUser, subject: ‘Example Alert’})


6
Adlandırılmış argümanları faktoring gerçekten sadece bir argüman geçmiyor.
JDługosz

Belirlediğim bir hedefe ulaşmam neden "sahtekarlık" yapıyor? Ben adlandırılmış bağımsız değişkenlere daha yüksek bir öncelik veriyorum. Konumsal hatalar çağıran kodda açık olmadığından ve adlandırılmış fonksiyonların sayısıyla bir dev ezberlemek zorunda olduğu için hangi paramların nerede ve hangi isteğe bağlı olduğunu hatırlamakta fayda yoktur. ... Sonunda, seçeneklerden sonra gerekli bir param eklemek istersiniz, kart evini belgelemek ve yükseltmek için iyi şanslar.
Dan Levy

2
Adlandırılmış paraşütler aynı zamanda pekiştirici bir öğrenme hilesidir - insanlar sözcük koleksiyonlarına daha fazla anlam katar.
Dan Levy
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.