Bir metod argümanını adlandırmak için bir değişken tanımlamak iyi bir pratik mi?


73

Okunabilirlik uğruna sık sık kendimi aşağıdaki kod gibi fonksiyonlar ararken geçici değişkenler tanımlarken buluyorum

var preventUndo = true;
doSomething(preventUndo);

Bunun bunun kısa versiyonu,

doSomething(true);

Ama kod geri döndüğümde ne anlama geldiğini sık sık merak ediyorum true. Bu tür bir bilmece için bir kongre var mı?


5
Bir çeşit IDE kullanıyor musunuz? Birçoğunun, sizin yaptığınız işleve hangi parametrelerin girdiğini gösteren bir çeşit yolu olacak ve bu da bunu yapma ihtiyacını biraz azaltacaktır.
Matthew Scharley

4
Bir IDE kullanmıyorum, ama o zaman bile ipucunun bir çeşit hareket gerektireceğini farz ediyorum (fareye gitme veya hatta hareket etme). Kodumun sadece ona bakarak ne yaptığını bilmek hoşuma gidiyor.
Metodüksiyon

11
Dil destekliyorsa,doSomething( Undo.PREVENT )
James P.

4
Fakat tanımlayabilirsiniz Undo = { PREVENT = true, DONT_PREVENT = false }. Ancak, JavaScript’te sözleşme şu şekilde yapmaktır: function myFunction( mandatoryArg1, mandatoryArg2, otherArgs ) { /*...*/ }ve sonra myFunction( 1, 2, { option1: true, option2: false } ).
xavierm02

6
Kesinlikle dile bağlı. Eğer bu python olsaydı, mesela, sadece anahtar kelime argümanlarını kullanmanızı öneririm, örneğindoSomething(preventUndo=True)
Joel Cornett

Yanıtlar:


117

Değişkenleri Açıklamak

Davanız değişken yeniden düzenlemeyi açıklayan bir örnek . Kısacası, açıklayıcı bir değişken kesinlikle gerekmeyen fakat okunabilirliği artırmak amacıyla bir şeye net bir ad vermenize izin veren bir değişkendir.

Kaliteli kod okuyucuya niyet iletir ; ve profesyonel bir geliştirici olarak okunabilirlik ve bakım kolaylığı sizin # 1 hedeflerinizdir.

Bu nedenle, tavsiye edeceğim başparmak kuralı şudur: parametrenizin amacı hemen belli değilse, iyi bir isim vermek için bir değişken kullanmaktan çekinmeyin. Bunun genel olarak iyi bir uygulama olduğunu düşünüyorum (kötüye kullanmadıkça). İşte hızlı, tartışmalı bir örnek - düşünün:

editButton.Enabled = (_grid.SelectedRow != null && ((Person)_grid.SelectedRow).Status == PersonStatus.Active);

biraz daha uzun, ancak tartışmasız daha net:

bool personIsSelected = (_grid.SelectedRow != null);
bool selectedPersonIsEditable = (personIsSelected && ((Person)_grid.SelectedRow).Status == PersonStatus.Active)
editButton.Enabled = (personIsSelected && selectedPersonIsEditable);

Boole Parametreleri

Örneğiniz aslında API'lerde bulunan booleanların genellikle neden kötü bir fikir olduğunu vurgulamaktadır - arayan tarafta, neler olduğunu açıklamak için hiçbir şey yapmazlar. Düşünmek:

ParseFolder(true, false);

Bu parametrelerin ne anlama geldiğine bakmak gerekir; eğer enums olsaydı, çok daha net olurdu:

ParseFolder(ParseBehaviour.Recursive, CompatibilityOption.Strict);

Düzenle:

Çok fazla insan boolean parametreler kısmına odaklanarak çünkü, başlıklar eklendi ve iki ana paragraf sırasını takas (dürüst olmak gerekirse, o oldu aslen ilk paragraf). Ayrıca ilk bölüme bir örnek ekledi.


28
Adlandırılmış parametreler kullanmıyorsanız (.NET Framework'te bağımsız değişkenler), bu durumda doSomething(preventUndo: true);yeterince açıktır. Ayrıca, API'nizdeki her bir boole için bir enum oluşturmak? Ciddi anlamda?
Arseni Mourzenko

12
@MainMa: Eğer kullandığınız dil isimlendirilmiş argümanları destekleyecek kadar soğuk değilse, enum kullanmak iyi bir seçenektir. Bu, sistematik olarak her yere enums eklemeniz gerektiği anlamına gelmez.
Giorgio

18
@MainMa - Bu soruyu cevaplamak için asıl mesele, API'lerde (en azından halka açık olanlarınız) booleanlara sahip olmamanız gerektiği. Muhtemelen aptalca olmayan (yazı yazarken) adlandırılmış bir argüman sözdizimine geçmeniz gerekir, ve her durumda, bir boolean parametresi hemen hemen her zaman yönteminizin iki şeyi yaptığını ve arayanın izin verdiğini gösterir. Seç. Fakat cevabımın amacı, kodunuzdaki değişkenleri açıklamakta yanlış bir şey olmamasıydı; bu aslında çok iyi bir uygulama.
Daniel B,

3
C # dilinin daimi bir parçası, daha ne "ana kabullenme" ihtiyacı var? Yapının farkında olmayan biri için bile (bu, C # dev'lerin C # doc'larını bile okumadığı anlamına gelir), ne yaptığı oldukça açıktır.
Nate CK

3
Bu nedenle, MS her sürümde ekledikleri tüm yeni şeylerin güzel özetlerini yayınlar, her birkaç yılda bir okumak için çok fazla iş yarattığını düşünmüyorum: msdn.microsoft.com/en- biz / kitaplık / bb383815% 28v = vs.100% 29.aspx
Nate CK

43

İhtiyacınız olmayan kod yazmayın.

Eğer bulursanız doSomething(true)anlamak zor, ya bir yorum eklemek gerekir:

// Do something and prevent the undo.
doSomething(true);

veya, eğer dil destekliyorsa, parametre adını ekleyin:

doSomething(preventUndo: true);

Aksi takdirde, çağrılan yöntemin imzasını size vermek için IDE'nize güvenin:

görüntü tanımını buraya girin

Yararlı olduğu durumlar

Ek bir değişken koymak yararlı olabilir:

  1. Hata ayıklama amacıyla:

    var productId = this.Data.GetLastProductId();
    this.Data.AddToCart(productId);
    

    Aynı kod tek bir satıra yazılabilir, ancak ürün kimliğinin doğru olup olmadığını görmek için bir ürün eklemeden önce bir kesme noktası koymak istiyorsanız, bir ürünün yerine iki satır yazmak iyi bir fikirdir.

  2. Çok fazla parametreli bir yönteminiz varsa ve her parametre bir değerlendirmeye tabi tutulursa. Bir satırda, bu tamamen okunamaz hale gelebilir.

    // Even with indentation, this is unreadable.
    var doSomething(
        isSomethingElse ? 0 : this.getAValue(),
        this.getAnotherOne() ?? this.default,
        (a + b + c + d + e) * f,
        this.hello ? this.world : (this.hello2 ? this.world2 : -1));
    
  3. Bir parametrenin değerlendirilmesi çok karmaşıksa. Gördüğüm bir kod örneği:

    // Wouldn't it be easier to have several if/else's (maybe even in a separate method)?
    do(something ? (hello ? world : -1) : (programmers ? stackexchange : (com ? -1 : 0)));
    

Neden diğer durumlarda değil?

Basit durumlarda neden ek değişkenler oluşturmuyorsunuz?

  1. Performans etkisinden dolayı değil. Bu, onun uygulamasını mikro-optimize eden yeni başlayan bir geliştiricinin çok yanlış bir varsayımı olurdu . Derleyici değişkeni satır içi olarak alacağından çoğu dilde performans etkisi yoktur . Derleyicinin bunu yapmadığı dillerde, buna değmeyerek birkaç mikrosaniye elde edebilirsin, ki buna değmez. Yapma bunu.

  2. Ancak, değişkene verdiğiniz adı parametre adıyla ayırma riski nedeniyle.

    Örnek:

    Diyelim ki orijinal kod:

    void doSomething(bool preventUndo)
    {
        // Does something very interesting.
        undoHistory.removeLast();
    }
    
    // Later in code:
    var preventUndo = true;
    doSomething(preventUndo);
    

    Daha sonra, doSomethinggeri alma tarihinin yakın zamanda, geri alma geçmişinin iki yeni yöntem getirdiğini fark eden bir geliştirici :

    undoHistory.clearAll() { ... }
    undoHistory.disable() { ... }
    

    Şimdi, preventUndoçok net değil gibi görünüyor. Bu sadece son eylemin önleneceği anlamına mı geliyor? Veya belki de kullanıcının artık geri alma özelliğini kullanamayacağı anlamına geliyor? Yoksa geri alma tarihi temizlenecek mi? Daha net isimler şöyle olurdu:

    doSomething(bool hideLastUndo) { ... }
    doSomething(bool removeAllUndo) { ... }
    doSomething(bool disableUndoFeature) { ... }
    

    Yani şimdi sahipsin:

    void doSomething(bool hideLastUndo)
    {
        // Does something very interesting.
        undoHistory.removeLast();
    }
    
    // Later in code, very error prone, while the signature of the method is clear:
    var preventUndo = true;
    doSomething(preventUndo);
    

Ya dişler?

Diğer bazı insanlar da enums kullanarak önerdi. Acil sorunu çözerken daha büyük bir problem yaratır. Hadi bir bakalım:

enum undoPrevention
{
    keepInHistory,
    prevent,
}

void doSomething(undoPrevention preventUndo)
{
    doTheJob();
    if (preventUndo == undoPrevention.prevent)
    {
        this.undoHistory.discardLastEntry();
    }
}

doSomething(undoPrevention.prevent);

Bununla ilgili sorunlar:

  1. Çok fazla kod var. if (preventUndo == undoPrevention.prevent)? Ciddi anlamda?! ifHer seferinde böyle şeyler yazmak istemiyorum .

  2. Başka bir yerde aynı Enum kullanıyorsanız, enum için bir öğe eklemek çok caziptir. Ya bu şekilde değiştirirsem:

    enum undoPrevention
    {
        keepInHistory,
        prevent,
        keepButDisable, // Keeps the entry in the history, but makes it disabled.
    }
    

    Ne olacak şimdi? Will doSomethingyöntem çalışması beklendiği gibi? Bunu önlemek için, bu yöntemi en baştan bu şekilde yazmak gerekir:

    void doSomething(undoPrevention preventUndo)
    {
        if (![undoPrevention.keepInHistory, undoPrevention.prevent].contains(preventUndo))
        {
            throw new ArgumentException('preventUndo');
        }
    
        doTheJob();
        if (preventUndo == undoPrevention.prevent)
        {
            this.undoHistory.discardLastEntry();
        }
    }
    

    Boole kullanan değişken, çok hoş görünmeye başlıyor!

    void doSomething(bool preventUndo)
    {
        doTheJob();
        if (preventUndo)
        {
            this.undoHistory.discardLastEntry();
        }
    }
    

3
"Çok fazla kod var. ((PrevUndo == undoPrevention.prevent)? Cidden mi ?! Her zaman böyle bir ifs yazmak istemiyorum.": Peki ya eski anahtar ifadesini kullanmaya ne dersiniz? Ayrıca, bir boole kullanıyorsanız, yine de bir if ifadesine ihtiyacınız var. Açıkçası, bu konudaki eleştiriniz bana biraz yapay görünüyor.
Giorgio

1
Burada alternatif bir çözümü özlüyorum. Diyor ki hiçbir şey düzüne sadık, doğru ve yanlış olmalı ve IDE'ye (ki kullanmadığı) güvenmeli mi? Bir yorum değişken ismi gibi çürümeye başlayabilir.
Güvenli

2
@superM: Yalnızca arama için kullanılan geçici bir değişkenin adını değiştirmek o kadar zor bulmuyorum. Bir numaralandırma adı değişirse, o zaman daha da iyidir, çünkü çağrı kodu artık çalışmaz ve yüzünüze bir hata atar. İşlevin işlevselliği bir enum uzantısı tarafından radikal bir şekilde değiştirilirse, yine de tüm çağrıları daha fazla doğruluk için tekrarlamanız gerekir, aksi halde mantıkla değil, umutla programlayın. Değerleri değiştirmeyi düşünmüyorsunuz, örneğin imzadakileri ihmal preventUndoetmek allowUndo...
Secure

4
@superM yorumların kodla senkronize edilmesini sağlamak gerçekten sorun yaratır, çünkü tutarsızlıklar aramanızdaki derleyicinizden hiç yardım alamazsınız.
Buhb

7
“... size çağrılan yöntemin imzasını vermek için IDE'nize güvenin” - bu kodu yazarken kullanışlıdır, ancak okurken çok değil. Bir sınıfın kodunu okuduğumda, sadece bakarak bakarak ne yaptığını bilmek istiyorum. Okunabilirlik için IDE'ye güvenmeniz gerekiyorsa, kodunuz kendi kendini belgelendirmiyor.
Phil

20

Her ikisinde de, boolean bayraklı yöntemler yazmamalısınız.

Robert C. Martin'den alıntı yapmak, Temiz Kod adlı kitabında (ISBN-13 978-0-13-235088-4), "Bir boole bir işleve geçmek gerçekten korkunç bir uygulamadır" diyor.

Onu ifade etmek için, mantık, doğru / yanlış anahtarına sahip olmanızın, yönteminizin büyük olasılıkla iki farklı şey yaptığı anlamına geldiği (yani "Geri al ile bir şey yap" ve "Geri al olmadan bir şey yap") anlamına gelmesidir ve bu nedenle iki farklı yönteme bölün (dahili olarak aynı şeyi arayabilir).

DoSomething()
{...

DoSomethingUndoable()
{....

7
Bu mantıkla, tek HotDog yapıcımın yaklaşık 16 farklı yöntem olması gerekir: HotDogWithMustardRelishKrautOnion (), HotDogWithMustardNorelishKrautOnion () ve benzeri. Veya, seçenekleri bit alanı olarak yorumladığım basit bir HotDogWithOptions (int options) olabilir, ancak daha sonra iddia edilen farklı şeyleri yapan bir yönteme geri dönüyoruz. Öyleyse, ilk seçeneğe gidersem, aksi takdirde Boolean parametreleri olacak olan şeylere dayanarak hangi kurucuyu arayacağımı belirlemek için büyük bir koşullu yazı yazmak zorunda mıyım? Eğer Q bir int kullanıyorsa, bu A Q'ya cevap vermez.
Caleb

4
Tüm cevapları okuduktan ve koduma baktıktan sonra, bunun doğru şekilde yapılacağı sonucuna varıyorum. doSomethingUndoable()değişiklikleri yakalamak ve sonra çağrıdoSomething()
metodofaction

1
Bu nedenle, çok fazla işlem yapan ve yapıldığında bir e-posta gönderme seçeneğine sahip bir işlevim varsa, e-postanın gönderilmesini engelleyebilecek bir boolean argüman olmamalı, ayrı bir işlev oluşturmalı mıyım?
yakatz

2
@Caleb Bu durumda bir sosisli yapardım ve malzemeleri birer birer eklerdim , ya da kesinlikle yazılmış bir dilde tüm boolean bayrakları koyacağım bir HotDogSettings nesnesi geçirirdim. Korumam için bir kabus olacak 15 farklı doğru / yanlış bayrakları olmazdı. Kodun bakım ile ilgili olmadığını unutmayın, çünkü bu uygulama maliyetinin% 80'i kadardır. var hd = MakeHotDog (); hd.Add (Soğan); ...
Nick B.

2
@Caleb Buradaki ayrım, örneğinizin booleanları gerçek bir veri alanı olarak kullandığı, bunun çoğu kullanımın yürütme akışını yönlendirdiği; dolayısıyla Bob Amca buna karşı korkuyor. Ayrıca, onun tavsiyesi biraz aşırıdır - kitaptaki sonraki birkaç satır, muhtemelen daha da aşırı bir duruş olan 2'den fazla parametreye sahip olmamanızı tavsiye eder. Yine de deliliğe bir yöntem var. Soruyu cevaplamaması konusunda kesinlikle haklısın, kendi cevabımda yaptığım bir hata.
Daniel B,

5

Olduklarını birleştiğinde nasıl olduğunu görmek için iki sınıf baktığımızda biri kategoriden olan veri bağlantısı için bir rapor istediğini ay gibi bir sınıf başka bir sınıfın yöntemlerini çağırmak ve sadece verilerde geçen kod anlamına gelir, ve başka kategori kontrol birleştirme , yöntemleri çağırmak ve yöntemin davranışını kontrol eden bir şeyi iletmektir. Sınıfta kullandığım örnek bir verbosebayrak veya reportTypebayrak, fakat preventUndoaynı zamanda harika bir örnek. Az önce göstermiş olduğunuz gibi, kontrol birleştirme arama kodunu okumayı ve ne olduğunu anlamanızı zorlaştırır. Ayrıca arama kodunu doSomething(), aynı geri alma ve arşivlemeyi kontrol etmek veya aynı anda başka bir parametre eklemek için aynı bayrağın kullanıldığı değişikliklere karşı hassas hale getirirdoSomething() arşivlemeyi kontrol etmek, böylece kodunuzu kırmak vb.

Sorun, kodun çok sıkı bağlanmış olmasıdır. Davranış kontrol etmek için bir bool geçirerek, bence, kötü bir API işaretidir. API’niz varsa, değiştirin. İki yöntem doSomething()ve doSomethingWithUndo()daha iyi olurdu. eğer sahip değilseniz, kendinize ait kodda iki sarmalayıcı yöntem yazın ve bunlardan birini arayın doSomething(true)ve diğerini arayın doSomething(false).


4

Argümanların rolünü tanımlamak, arayanın rolü değildir. Her zaman satır içi sürüm için giderim ve şüphem varsa çağrılan işlevin imzasını kontrol ederim.

Değişken, mevcut kapsamdaki rollerinden sonra adlandırılmalıdır. Değil Gönderildikleri kapsam.


1
Değişkenin mevcut kapsamdaki rolü ne için kullanıldığını anlatmaktır. Bunun OP'nin geçici değişken kullanmasıyla nasıl çelişdiğini anlamıyorum.
30'da

4

JavaScript'te yapacağım şey, bunun gibi bir parametre olarak bir nesneyi alma işlevidir:

function doSomething(settings) {
    var preventUndo = settings.hasOwnProperty('preventUndo') ? settings.preventUndo : false;
    // Deal with preventUndo in the normal way.
}

Öyleyse şununla ara:

doSomething({preventUndo: true});

HA!!! İkimiz de bir doSomething(x)yöntem yaptık ! lol ... Şimdiye kadar görevinizi bile farketmedim.
saat

"NoUndo" dizgisini geçirirsem ne olur ve imzanızı kullanan kişi için uygulamaya bakmadan hangi ayarları içermesi gerektiği açıktır?
Nick B.

1
Kodunuzu belgeleyin. Herkesin yaptığı budur. Kodunuzu okumayı kolaylaştırır, yalnızca bir kez olması gerektiğini yazmak.
ridecar2

1
@NickB. Kongre güçlüdür. Kodunuzun çoğu argüman içeren nesneleri kabul ederse, bu açıktır.
saat

4

Netliği sağlamak için dil özelliklerinden yararlanmaya bayılıyorum. Örneğin, C # ile parametreleri adıyla belirtebilirsiniz:

 CallSomething(name: "So and so", age: 12, description: "A random person.");

JavaScript'te genellikle bir seçenek nesnesini bu nedenle argüman olarak kullanmayı tercih ederim:

function doSomething(args) { /*...*/ }

doSomething({ name: 'So and so', age: 12, description: 'A random person.' });

Bu sadece benim tercihim. Sanırım bu, çağrılan yönteme ve IDE'nin geliştiricinin imzayı anlamalarına nasıl yardımcı olduğuna büyük ölçüde bağlı olacak.


1
Bu gevşek yazılmış dillerin "olumsuz". Bir onaylama olmadan bir imzayı gerçekten uygulayamazsınız. JS'de böyle isimler ekleyebileceğinizi bilmiyordum.
James P.

1
@JamesPoulson: Muhtemelen JS'de bunu yapabileceğinizi biliyordunuz ve henüz farkında değildiniz. $.ajax({url:'', data:''})
JQuery'de

Doğru. İlk bakışta olağandışı görünüyor, ancak bazı dillerde var olan satır içi sahte nesnelere benziyor.
James P.,

3

Bunun okunması en basit ve en kolay yol olduğunu biliyorum:

enum Undo { ALLOW, PREVENT }

doSomething(Undo u) {
    if (Undo.ALLOW == u) {
        // save stuff to undo later.
    }
    // do your thing
}

doSomething(Undo.ALLOW);

MainMa bundan hoşlanmaz. Kabul etmemeyi kabul etmemiz gerekebilir ya da Joshua Bloch'un önerdiği bir çözümü kullanabiliriz:

enum Undo {
    ALLOW {
        @Override
        public void createUndoBuffer() {
            // put undo code here
        }
    },
    PREVENT {
        @Override
        public void createUndoBuffer() {
            // do nothing
        }
    };

    public abstract void createUndoBuffer();
}

doSomething(Undo u) {
    u.createUndoBuffer();
    // do your thing
}

Şimdi bir Undo.LIMITED_UNDO eklerseniz, createUndoBuffer () yöntemini uygulamadığınız sürece kodunuz derlenmez. Ve doSomething () 'de if yoktur (Undo.ALLOW == u). Her iki yolu da yaptım ve ikinci yöntem oldukça ağır ve Undo enum kod sayfalarına ve kod sayfalarına genişlediğinde anlaşılması biraz zor, ama sizi düşündürüyor. Değiştirmek için bir nedenim olana kadar basit bir boole yerine 2 değerlik değerine sahip basit bir boole yöntemini kullanıyorum. Üçüncü bir değer eklediğimde IDE'mi "Find-usages" için kullanıyorum ve sonra her şeyi düzeltirim.


2

Çözümünüzün kodunuzu biraz daha okunaklı hale getirdiğini düşünüyorum, ancak işlev çağrınızı daha net hale getirmek için fazladan bir değişken tanımlamaktan kaçınırdım. Ayrıca, fazladan bir değişken kullanmak istiyorsanız, programlama diliniz destekliyorsa bunu sabit olarak işaretlerim.

Fazladan bir değişken içermeyen iki alternatif düşünebilirim:

1. Ekstra bir yorum kullanın

doSomething(/* preventUndo */ true);

2. Boole yerine iki değerli bir enum kullanın

enum Options
{
    PreventUndo,
    ...
}

...

doSomething(PreventUndo);

Diliniz numaraları destekliyorsa alternatif 2'yi kullanabilirsiniz.

DÜZENLE

Elbette, eğer dilinizi destekliyorsa, adlandırılmış argümanları kullanmak da bir seçenektir.

Enums'ın ihtiyaç duyduğu fazladan kodlama ile ilgili olarak, bu benim için gerçekten önemsiz görünüyor. Onun yerine

if (preventUndo)
{
    ...
}

var

if (undoOption == PreventUndo)
{
    ...
}

veya

switch (undoOption)
{
  case PreventUndo:
  ...
}

Ve biraz daha tipik bir yazı olsa bile, kodun bir kez yazıldığını ve birçok kez okunduğunu unutmayın; bu yüzden altı ay sonra daha okunaklı bir kod bulmak için şimdi biraz daha fazla yazmaya değer olabilir.


2

@GlenPeterson'ın söylediklerine katılıyorum:

doSomething(Undo.ALLOW); // call using a self evident enum

ama aynı zamanda içgüdüsel bir yaklaşım olacaktır, çünkü bana öyle geliyor ki, sadece iki olasılık var (doğru ya da yanlış)

//Two methods    

doSomething()  // this method does something but doesn't prevent undo

doSomethingPreventUndo() // this method does something and prevents undo

2
Güzel fikir - Bunu düşünmemiştim. DoSomething (String, String, String, boolean, boolean, boolean) gibi daha karmaşık hale geldiğinde, adlandırılmış sabitler olarak adlandırılan tek makul çözümdür. Evet, Josh Bloch, aşağıdaki gibi bir fabrika ve yapıcı nesne önerir: MyThingMaker thingMaker = MyThingMaker.new (); thingMaker.setFirstString ( "Merhaba"); thingMaker.setSecondString ( "Orada"); etc ... Şey t = thingMaker.makeIt (); ) (t.doSomething; Bu sadece çok daha fazla iş, bu yüzden buna değse iyi olur.
GlenPeterson

İkinci yaklaşımla ilgili bir sorun doSomething, arayan bir kişinin geri almasına izin verip vermemeyi seçmesine izin veren bir yöntem yazmasını zorlaştırmasıdır . Bir çözüm, Boolean seçeneğini alan bir aşırı yüke sahip olmak olabilir, ancak aynı zamanda, eski sürümü her zaman doğru veya her zaman yanlış olan parametre ile çağıran sarma sürümlerine de sahip olabilir.
Supercat

@GlenPeterson Bir fabrika Javascript'te bir olasılıktır ve mümkündür (OP ile anılan).
James P.

2

Genelde javascript hakkında soru sorduğun için, coffeescript kullanarak sözdizimi, süper kolay gibi adlandırılmış bir tartışmaya sahip olabilirsin:

# declare method, ={} declares a default value to prevent null reference errors
doSomething = ({preventUndo} = {}) ->
  if preventUndo
    undo = no
  else
    undo = yes

#call method
doSomething preventUndo: yes
#or 
doSomething(preventUndo: yes)

derler

var doSomething;

doSomething = function(_arg) {
  var preventUndo, undo;
  preventUndo = (_arg != null ? _arg : {}).preventUndo;
  if (preventUndo) {
    return undo = false;
  } else {
    return undo = true;
  }
};

doSomething({
  preventUndo: true
});

doSomething({
  preventUndo: true
});

Olanakları denemek için http://js2coffee.org/ adresinde biraz eğlenin


CoffeeScript'i yalnızca javascript'in OOP deliliğinden kaçınmam gerektiğinde kullanırım. Bu, tek başına kodlarken kullanabileceğim güzel bir çözüm, iş arkadaşına okunabilirlik uğruna bir boole yerine bir nesneyi ilettiğimi haklı çıkarmak zor olurdu!
metodofaksiyon

1

Sadece daha az geleneksel bir çözüm için ve OP Javascript'ten bahsettiği için olasılık, eşleme değerleri için bir ilişkisel dizi kullanmaktır. Tek bir booleanın avantajı, istediğiniz kadar tartışmanız olabilir ve dizileri hakkında endişelenmenize gerek kalmaz.

var doSomethingOptions = new Array();

doSomethingOptions["PREVENTUNDO"] = true;
doSomethingOptions["TESTMODE"] = false;

doSomething( doSomethingOptions );

// ...

function doSomething( doSomethingOptions ){
    // Check for null here
    if( doSomethingOptions["PREVENTUNDO"] ) // ...
}

Bunun, kesinlikle yazılmış bir arka plandan birinin yansıması olduğunu ve o kadar pratik olmayabilir, fakat özgünlüğü düşünün.

Bir başka olasılık da bir nesneye sahip olmak ve Javascript'te de mümkündür. Bunun% 100 doğru olduğundan emin değilim. Daha fazla ilham almak için Fabrika gibi kalıplara bakın.

function SomethingDoer( preventUndo ) {
    this.preventUndo = preventUndo;
    this.doSomething = function() {
            if( this.preventUndo ){
                    // ...
            }
    };
}

mySomethingDoer = new SomethingDoer(true).doSomething();

1
Bunun doSomethingOptions.PREVENTUNDOdizi erişim notu yerine nokta notasyonunda ( ) yazılabileceğini düşünüyorum.
Paŭlo Ebermann

1

Sorunuzun ve diğer cevapların odak noktası, işlevin çağrıldığı okunabilirliği artırmaktır, ki bu da aynı fikirdeyim. Herhangi bir özel kural, "boolean argüman yok" olayı, her zaman bu amaç için bir işlev görmeli ve kendileri haline gelmemeli ve bitmemelidir.

Programlama dili, C # 4 ve Python'daki gibi adlandırılmış argümanları / anahtar kelime argümanlarını desteklediğinde veya Smalltalk veya Objective-C'de olduğu gibi, metod argümanlarının metot isminde birleştirildiği durumlarda, bu sorunun çoğunlukla önlendiğini not etmek faydalı olur.

Örnekler:

// C# 4
foo.doSomething(preventUndo: true);
# Python
foo.doSomething(preventUndo=True)
// Objective-C
[foo doSomethingWith:bar shouldPreventUndo:YES];

0

Boole değişkenlerini işlevlere argüman olarak iletmekten kaçınmak gerekir. Çünkü fonksiyonlar bir seferde bir şey yapmalı. Boolean değişkenini geçerek fonksiyonun iki davranışı vardır. Bu aynı zamanda daha sonraki bir aşamada veya kodunuzu görme eğilimindeki diğer programcılar için okunabilirlik problemi yaratır. Bu aynı zamanda işlevi test etmede sorun yaratır. Muhtemelen bu durumda iki test durumu oluşturmak zorundasınız. Anahtar ifadesine sahip ve işlevini anahtar türüne göre değiştiren bir işleve sahip olduğunuzu ve bunun için tanımlanmış çok sayıda farklı test durumunun olması gerektiğini hayal edin.

Ne zaman biri işlev için bir boolean argümanına sahip olursa, kodu boolean argümanı yazmayacak şekilde değiştirmek zorunda kalırlar.


Öyleyse, boolean argümanlı bir işlevi, kodlarının yalnızca küçük bir bölümünde farklı olan iki işlevde dönüştürürsünüz (orijinalin sahip olduğu yerde if(param) {...} else {...})?
Paŭlo Ebermann

-1
int preventUndo = true;
doSomething(preventUndo);

C ++ gibi düşük dil bilen diller için iyi bir derleyici, aşağıdaki gibi 2 satırın üzerindeki makine kodunu optimize edecektir:

doSomething(true); 

bu yüzden performans açısından önemli değil, okunabilirliği artıracak.

Ayrıca, daha sonra değişken olması ve diğer değerleri de kabul etmesi durumunda bir değişkenin kullanılması yararlı olacaktır.

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.