Koddaki anahtarı ortadan kaldırma yolları [kapalı]


175

Kodda anahtar kullanımını ortadan kaldırmanın yolları nelerdir?


18
Uygun şekilde kullanıldığında neden anahtarları ortadan kaldırmak istersiniz? Lütfen sorunuzu biraz açıklayabilir misiniz?
RB.

Bu soruyu topluluk düzenlenebilir hale getirmek için oy ediyorum çünkü herkes aynı şeyi söylüyor ve tüm fikirleri pekiştirmek güzel olabilir;)
Josh

2
Anahtar, diğer talimatlar gibi standart değildir. Örneğin, C ++ 'da' sonu 'unutmanız muhtemeldir ve daha sonra beklenmeyen sonuçlara sahip olursunuz. Ayrıca, bu 'kırılma' bir GOTO'ya çok benzer. Anahtarları hiçbir zaman ortadan kaldırmaya çalışmadım, ama kesinlikle en sevdiğim talimatlar değiller. ;)

2
Sanırım C ++ veya Java switch deyimine değil, switch konseptine atıfta bulunuyor. Bir anahtar ayrıca 'if-else if' blokları zinciri de olabilir.
Yasadışı Programcı

2
Eğlenceli olabilirsiniz: IF karşıtı kampanyaya katılan çevik topluluktan çok sayıda kayda değer programcı vardır: antiifcampaign.com/supporters.html
Mike

Yanıtlar:


267

Anahtar ifadeleri kendi başına bir antipattern değildir, ancak nesne yönelimli kodlama yapıyorsanız, bir anahtar kullanımının bir anahtar ifadesi kullanmak yerine polimorfizm ile daha iyi çözülüp çözülmediğini düşünmelisiniz .

Polimorfizm ile bu:

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

bu olur:

foreach (var animal in zoo) {
    echo animal.speak();
}

2
Stackoverflow.com/questions/374239/… benzer öneri nedeniyle bashed ediliyor Pek çok kişi polimorfizm inanmıyorum :) Çok iyi bir örnek.
Nazgob

30
-1: Daha önce hiç bir switch deyimi kullanmadım typeofve bu cevap diğer durumlarda switch deyimleri üzerinde çalışmanın yollarını veya nedenlerini önermiyor.
Kevin

3
@Kevin ile aynı fikirdeyim - verilen örnek, polimorfizmle geçişin nasıl ortadan kaldırılacağını gerçekten göstermiyor. Basit örnekler: değerlerini değiştirerek enum adını alın veya bir tür algoritmada uygun değerlerle bir kod gerçekleştirin.
HotJard

Belirli uygulamalara, yani bir fabrikaya güvenmeden önce nasıl ortadan kaldırılacağını merak ediyordum. Ve burada harika bir örnek buldum stackoverflow.com/a/3434505/711855
juanmf

1
çok önemsiz bir örnek.
GuardianX

239

Bkz. Anahtar İfadeleri Kokusu :

Tipik olarak, benzer anahtar ifadeleri bir program boyunca dağılmıştır. Bir anahtarda bir cümle ekler veya kaldırırsanız, genellikle diğerlerini de bulup onarmanız gerekir.

Hem Refactoring ve Patterns için Refactoring bu sorunu çözmek için yaklaşımlar var.

(Sahte) kodunuz aşağıdaki gibi görünüyorsa:

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

Bu kod Açık Kapalı Prensibi'ni ihlal eder ve ortaya çıkan her yeni eylem kodu türü için kırılgandır. Bunu düzeltmek için bir 'Komut' nesnesi getirebilirsiniz:

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

(Sahte) kodunuz aşağıdaki gibi görünüyorsa:

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

Sonra bir 'Devlet' nesnesi getirebilirsiniz.

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

Bu yardımcı olur umarım.


7
Kodu yeniden düzenleme konusundaki harika örnek için teşekkür ederiz. Başlangıçta söyleyebilirim ama okumak biraz zor (çünkü tamamen anlamak için birkaç dosya arasında geçiş yapmak zorunda)
rshimoda

8
Anahtarla ilgili argümanlar, polimorfik çözümün kod basitliğini feda ettiğini anladığınız sürece geçerlidir. Ayrıca, anahtar durumlarınızı her zaman numaralandırmalarda saklarsanız, bazı derleyiciler sizi durumun anahtarda eksik olduğu konusunda uyarır.
Harvey

1
Bu, tam / eksik işlemler ve elbette kodu OOP'ye yeniden yapılandırmak için harika bir örnektir. Bir ton teşekkürler. OOP / Tasarım Desenleri taraftarlarının OOP kavramlarını kavramlar yerine operatörler gibi ele almayı önermesi yararlı olacaktır . Demek istediğim "genişletmeler", "fabrika", "aletler" vb. Dosyalar, sınıflar, dallar arasında çok sık kullanılır. "+", "-", "+ =", "?:", "==", "->" gibi operatörler kadar basit olmalıdırlar. Bir programcı bunları sadece operatörler olarak kullandığında, sadece o zaman tüm sınıf kütüphanesinde program durumu ve (in) tam işlemleri hakkında düşünebilir.
ad alanı formu

13
SWITCH'in buna kıyasla çok daha anlaşılır ve mantıklı olduğunu düşünmeye başlıyorum. Ve genellikle OOP'u çok seviyorum, ama bu karar benim için çok soyut görünüyor
JK

1
Command nesnesiyle, oluşturulan kodun Map<Integer, Command>bir anahtara ihtiyacı olmaz mı?
ataulm

41

Anahtar, bir anahtar deyimiyle uygulanıp uygulanmadığına bakılmaksızın, başka bir zincir, arama tablosu, oop polimorfizmi, kalıp eşleştirme veya başka bir şeydir.

" Anahtar ifadesi " veya " anahtar düzeni " kullanımını ortadan kaldırmak istiyor musunuz ? Birincisi, ikincisi, yalnızca başka bir desen / algoritma kullanılabiliyorsa ve çoğu zaman mümkün olmayan veya bunu yapmak daha iyi bir yaklaşım değilse, ortadan kaldırılabilir.

Switch deyimini koddan kaldırmak istiyorsanız , sorulması gereken ilk soru , switch deyimini ortadan kaldırmanın ve başka bir teknik kullanmanın nerede mantıklı olduğudur. Ne yazık ki bu sorunun cevabı alan adına özgüdür.

Ve derleyicilerin deyimleri değiştirmek için çeşitli optimizasyonlar yapabileceğini unutmayın. Örneğin, mesaj işlemeyi verimli bir şekilde yapmak istiyorsanız, bir switch deyimi hemen hemen gitmenin yoludur. Ancak öte yandan, bir switch deyimine dayalı iş kurallarını çalıştırmak muhtemelen en iyi yol değildir ve uygulama yeniden araştırılmalıdır.

Şunu değiştirmek için bazı alternatifler:


1
Birisi, switch'i kullanarak mesaj işleme ile diğer alternatifleri karşılaştırabilir mi?
Mike A

37

Anahtarın kendisi o kadar da kötü değildir, ancak yöntemlerinizdeki nesnelerde çok fazla "anahtar" veya "if / else" varsa, tasarımınızın biraz "yordamsal" olduğuna ve nesnelerinizin sadece değer olduğuna dair bir işaret olabilir. kovalar. Mantığı nesnelerinize taşıyın, nesnelerinize bir yöntem çağırın ve bunun yerine nasıl yanıt vereceğine karar vermelerine izin verin.


Tabii ki, C ile yazmadığı varsayılarak
Bernard

1
C, (ab?) nesne benzeri bir şey oluşturmak için işlev işaretçileri ve yapıları kullanabilirsiniz;)
Tetha

FORT ^ H ^ H ^ H ^ H Java'yı herhangi bir dilde yazabilirsiniz. ; p
Bernard

Tamamen katılıyorum - anahtar, kod satırlarını azaltmanın harika bir yoludur, ancak onunla da oynamayın.
HotJard

21

Bence en iyi yol iyi bir harita kullanmaktır. Bir sözlük kullanarak hemen hemen her girdiyi başka bir değer / nesne / işlevle eşleyebilirsiniz.

kodunuz şöyle bir şey (psuedo) olurdu:

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}

4
Dile bağlıdır. Bir anahtardan çok daha az okunabilir
Vinko Vrsalovic

Bu doğru durumda güzel bir elegent çözümdür. Bu eşleme anahtar kodlarını son zamanlarda yaptım ve bu amaç için iyi gibi görünüyordu.
Bernard

Bu doğrudur, muhtemelen basit bir şey için kullanmazdım, ancak bir switch deyimi üzerinden yapılandırma açısından bir miktar esneklik sağlar. Bir anahtar her zaman sabit olarak kodlanırken, sözlük anında hazırlanabilir.
Josh

Bazı durumlarda daha temiz olabilir. Ayrıca daha yavaş, çünkü işlev çağrıları gerektiriyor.
Nick Johnson

1
Bu senin anahtarlarına bağlı. Derleyici, her iki durumda da herhangi bir işlev çağrısı gerektirmeden basit bir aramaya veya son derece hızlı bir statik ikili aramaya bir anahtar deyimi derleyebilir.
Nick Johnson

12

Herkes BÜYÜK if elseblokları sever . Okuması çok kolay! Yine de neden switch ifadelerini kaldırmak istediğinizi merak ediyorum. Bir switch deyimine ihtiyacınız varsa, muhtemelen bir switch deyimine ihtiyacınız vardır. Cidden olsa, kodun ne yaptığına bağlı olduğunu söyleyebilirim. Anahtarın yaptığı tüm işlevler (diyelim ki) işlevleri çağırıyorsa, işlev işaretçileri iletebilirsiniz. O olsun bir daha çözüm tartışmalıdır.

Dil burada da önemli bir faktör.


13
Im alaycı olduğunu varsayıyorum :)
Craig Day

6

Aradığın şeyin Strateji Örneği olduğunu düşünüyorum.

Bu, bu sorunun diğer cevaplarında belirtilen çeşitli şekillerde uygulanabilir, örneğin:

  • Değerlerin haritası -> fonksiyonlar
  • Polimorfizm. (bir nesnenin alt türü, belirli bir işlemi nasıl işleyeceğine karar verecektir).
  • Birinci sınıf fonksiyonlar.

5

switch ifadelere yeni durumlar veya yeni davranışlar eklediğinizi fark ederseniz, ifadeleri değiştirmek iyi olur:

int durumu;

Dize getString () {
   anahtar (durum) {
     case 0: // durum 0 için davranış
           dönüş "sıfır";
     durum 1: // durum 1 için davranış
           dönüş "bir";
   }
   yeni IllegalStateException () öğesi ata;
}

çift ​​getDouble () {

   switch (this.state) {
     case 0: // durum 0 için davranış
           dönüş 0d;
     durum 1: // durum 1 için davranış
           dönüş 1d;
   }
   yeni IllegalStateException () öğesi ata;
}

Yeni davranış eklemek, kopyalamanın switchve yeni durumların eklenmesi case, her switch ifadeye bir başkasının eklenmesi anlamına gelir .

Java'da, yalnızca çalışma zamanında değerlerini bildiğiniz çok sınırlı sayıda ilkel tür arasında geçiş yapabilirsiniz. Bu kendi başına bir sorun yaratır: durumlar sihirli sayılar veya karakterler olarak temsil edilir.

Örüntü eşleştirme ve birden çok if - elseblok kullanılabilir, ancak yeni davranışlar ve yeni durumlar eklerken gerçekten aynı sorunlara sahiptir.

Başkalarının "polimorfizm" olarak önerdiği çözüm, Devlet modelinin bir örneğidir :

Eyaletlerin her birini kendi sınıfıyla değiştirin. Her davranışın sınıfta kendi yöntemi vardır:

IState durumu;

Dize getString () {
   return state.getString ();
}

çift ​​getDouble () {
   return state.getDouble ();
}

Her yeni durum eklediğinizde, IStatearayüzün yeni bir uygulamasını eklemeniz gerekir . Bir switchdünyada, caseher birine bir eklersiniz switch.

Her yeni davranış eklediğinizde, IStatearabirime ve uygulamaların her birine yeni bir yöntem eklemeniz gerekir . Bu, öncekiyle aynı yüktür, ancak şimdi derleyici, önceden var olan her durum üzerinde yeni davranış uygulamalarınız olup olmadığını kontrol edecektir.

Diğerleri zaten bunun çok ağır olabileceğini söylediler, bu yüzden elbette birinden diğerine geçtiğiniz bir nokta var. Şahsen, ikinci kez bir anahtar yazdığımda, refactor olduğum noktadır.


4

if-else

Anahtarın doğası gereği kötü olduğu fikrini çürütüyorum.


3

Birincisi, anahtarı kullanmanın bir anti-desen olduğunu bilmiyordum.

İkinci olarak, anahtar her zaman if / else if ifadeleri ile değiştirilebilir.


tam olarak - anahtar if / elsifs bir grup için sadece sözdizimsel metadon.
Mike A

3

Neden istiyorsun? İyi bir derleyicinin elinde, bir switch deyimi, / else bloklarından (okunması daha kolay olmasının yanı sıra) çok daha verimli olabilir ve herhangi bir türle değiştirildikleri takdirde yalnızca en büyük anahtarların hızlandırılması muhtemeldir. dolaylı arama veri yapısının


2
Bu noktada, derleyiciyi ikinci olarak tahmin edersiniz ve derleyici içlerine göre tasarımınızda değişiklikler yaparsınız. Tasarım, derleyicinin doğasını değil, sorunun doğasını izlemelidir.
Mike A

3

'geçiş' sadece bir dil yapısıdır ve tüm dil yapıları bir işi yapmak için araçlar olarak düşünülebilir. Gerçek araçlarda olduğu gibi, bazı araçlar bir göreve diğerinden daha uygundur (resim kancası koymak için bir kızak çekiç kullanmazsınız). Önemli olan 'işi bitirmenin' nasıl tanımlandığıdır. Sürdürülebilir olması gerekiyor mu, hızlı olması gerekiyor mu, ölçeklendirilmesi mi gerekiyor, genişletilebilir olması gerekiyor mu vb.

Programlama sürecinin her noktasında genellikle kullanılabilecek bir dizi yapı ve desen vardır: bir anahtar, bir if-if-series dizisi, sanal fonksiyonlar, atlama tabloları, fonksiyon işaretçileri olan haritalar vb. Tecrübe ile bir programcı belirli bir durum için doğru aracı içgüdüsel olarak bilir.

Herhangi bir yapının güvenle kullanılabilmesi için, kodu koruyan veya gözden geçiren herkesin en az orijinal yazar kadar yetenekli olduğu varsayılmalıdır.


Tamam, ama neden aynı şeyi yapmanın 5 farklı, gereksiz yoluna ihtiyacımız var - koşullu yürütme?
Mike A

@ mike.amy: Çünkü her yöntemin farklı faydaları ve maliyetleri vardır ve her şey en düşük maliyetle en fazla faydayı elde etmekle ilgilidir.
Skizz

1

Anahtar, çeşitli nesne türlerini ayırt etmek için oradaysa, muhtemelen bu nesneleri veya bazı sanal yöntemleri tam olarak tanımlamak için bazı sınıfları kaçırıyorsunuzdur ...


1

C ++ için

Yani bir AbstractFactory atıfta bulunuyorsanız, bir registerCreatorFunc (..) yönteminin genellikle gerekli olan her "yeni" deyim için bir vaka eklemeyi gerektirmekten daha iyi olduğunu düşünüyorum . Daha sonra tüm sınıfların bir makro ile kolayca uygulanabilecek bir creatorFunction (..) oluşturmasına ve kaydetmesine izin vermek (bahsetmeye cesaret edersem). Bunun birçok çerçevenin ortak bir yaklaşım olduğuna inanıyorum. İlk olarak ET ++ 'da gördüm ve bir DECL ve IMPL makrosu gerektiren birçok çerçevenin bunu kullandığını düşünüyorum.


1

C gibi prosedürel bir dilde, geçiş, alternatiflerden herhangi birinden daha iyi olacaktır.

Nesneye yönelik bir dilde, nesne yapısını, özellikle de polimorfizmi daha iyi kullanan neredeyse her zaman başka alternatifler vardır.

Anahtar ifadeleriyle ilgili sorun, uygulamanın birden çok yerinde çok benzer anahtar blokları oluştuğunda ve yeni bir değer desteğinin eklenmesi gerektiğinde ortaya çıkar. Bir geliştiricinin, uygulamanın etrafına dağılmış anahtar bloklarından birine yeni değer için destek eklemeyi unutması oldukça yaygındır.

Çok biçimlilik ile yeni değer yeni değerin yerini alır ve yeni davranış, yeni sınıfı eklemenin bir parçası olarak eklenir. Bu anahtar noktalarındaki davranış, ya üst sınıftan devralınır, yeni davranış sağlamak için geçersiz kılınır veya süper yöntem soyut olduğunda derleyici hatasını önlemek için uygulanır.

Belirgin bir polimorfizmin olmadığı yerlerde, Strateji modelini uygulamaya değer olabilir .

Ama alternatifiniz büyük bir EĞER ... SONRA ... ELSE bloğuysa, unutun.


1

Yerleşik anahtar deyimiyle birlikte gelmeyen bir dil kullanın. Perl 5 akla geliyor.

Cidden, neden bundan kaçınmak istersiniz? Ve bundan kaçınmak için iyi bir nedeniniz varsa, neden bundan kaçınmayasınız?


1

İşlev işaretçileri, büyük bir tıknaz anahtar ifadesinin yerini almanın bir yoludur, özellikle işlevleri adlarıyla yakalayabileceğiniz ve onlarla bir şeyler yapabileceğiniz dillerde iyidir.

Tabii ki, switch deyimlerini kodunuzdan zorlamamalısınız ve her zaman yanlış yapma şansınız vardır, bu da aptal gereksiz kod parçalarıyla sonuçlanır. (Bu bazen kaçınılmazdır, ancak iyi bir dil, temiz kalırken artıklığı kaldırmanıza izin vermelidir.)

Bu harika bir bölünme ve fethetme örneği:

Diyelim ki bir çeşit tercümanınız var.

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

Bunun yerine şunu kullanabilirsiniz:

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

C de opcode_table fazlalığını kaldırmak için nasıl bilmiyorum unutmayın. Belki de bu konuda bir soru yapmak gerekir. :)


0

En belirgin, dilden bağımsız cevap, bir dizi 'if' kullanmaktır.

Kullandığınız dilde işlev işaretçileri (C) varsa veya 1. sınıf değerleri (Lua) olan işlevlere sahipse, işlevlerden oluşan bir dizi (veya liste) kullanarak "geçiş" işlevine benzer sonuçlar elde edebilirsiniz.

Daha iyi cevaplar istiyorsanız dile daha açık olmalısınız.


0

Anahtar ifadeleri genellikle iyi bir OO tasarımı ile değiştirilebilir.

Örneğin, bir Hesap sınıfınız var ve hesap türüne göre farklı bir hesaplama yapmak için bir switch deyimi kullanıyorsunuz.

Bunun, farklı hesap türlerini temsil eden ve bir Hesap arabirimi uygulayan bir dizi hesap sınıfı ile değiştirilmesi gerektiğini öneririm.

Daha sonra anahtar gereksiz olur, çünkü tüm hesap türlerine aynı şekilde davranabilirsiniz ve polimorfizm sayesinde hesap türü için uygun hesaplama yapılır.


0

Neden değiştirmek istediğinize bağlı!

Birçok tercüman opcode yürütme için switch deyimleri yerine 'hesaplanmış gotos' kullanır.

C / C ++ anahtarı hakkında özlediğim Pascal 'in' ve aralıkları. Keşke dizeleri de açabilseydim. Ancak bunlar, bir derleyicinin yemek için önemsiz olmakla birlikte, yapılar ve yineleyiciler ve şeyler kullanılarak yapıldığında zor işlerdir. Aksine, sadece C'nin anahtarı () daha esnek olsaydı, bir anahtarla değiştirebilmeyi dilediğim birçok şey var!


0

Açma Prensibi'ni kırdığı için geçiş yapmak iyi bir yol değildir. Ben böyle yaparım.

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

Ve nasıl kullanılacağı (kodunuzu alarak):

foreach (var animal in zoo) 
{
    echo animal.speak();
}

Temel olarak yaptığımız şey, ebeveynin çocuklarla ne yapacağına karar vermesi yerine sorumluluğu çocuk sınıfına devretmektir.

Ayrıca "Liskov İkame İlkesi" ni okumak isteyebilirsiniz.


0

İlişkilendirilebilir dizi kullanan JavaScript'te:
bu:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

bu olur:

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

Nezaket


-12

İf / else için başka bir oy. Ben büyük bir dava veya anahtar ifadeleri hayranı değilim çünkü onları kullanmayan bazı insanlar var. Büyük / küçük harf veya anahtar kullanırsanız kod daha az okunabilir. Belki sizin için daha az okunabilir değil, ama komutu kullanmak için hiç ihtiyaç duymamış olanlar için.

Aynı şey nesne fabrikaları için de geçerli.

/ Else blokları herkesin aldığı basit bir yapı ise. Sorunlara neden olmadığınızdan emin olmak için yapabileceğiniz birkaç şey var.

Birincisi - İfadelerin birkaç kezden fazla olup olmadığını girintilemeyin. Kendinizi girintili buluyorsanız, yanlış yaparsınız.

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

Gerçekten kötü - bunun yerine bunu yapın.

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

Optimizasyon lanet olsun. Kodunuzun hızı konusunda o kadar büyük bir fark yaratmaz.

İkincisi, sürece belirli kod bloğu aracılığıyla dağınık açık hale getirmek için yeterli sonları ifadeleri olduğu sürece bir if bloğunu kırmak için sabırsızlanıyorum

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

EDIT : On Switch ve neden grok zor olduğunu düşünüyorum:

İşte bir anahtar ifadesi örneği ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

Benim için buradaki sorun, C benzeri dillerde uygulanan normal kontrol yapılarının tamamen kırılmış olmasıdır. Bir kontrol yapısının içine birden fazla kod satırı yerleştirmek istiyorsanız, kaşlı ayraçlar veya bir başlangıç ​​/ bitiş ifadesi kullanmanızın genel bir kuralı vardır.

Örneğin

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

Benim için (ve eğer yanlışsam beni düzeltebilirsiniz), Case deyimi bu kuralı pencereden dışarı atar. Koşullu olarak yürütülen bir kod bloğu bir başlangıç ​​/ bitiş yapısı içine yerleştirilmez. Bu nedenle, Case'in kavramsal olarak kullanılmayacak kadar farklı olduğuna inanıyorum.

Umarım sorunuzu cevaplamıştır.


Vay be - açıkça tartışmalı bir cevap. Neyin bu kadar yanlış yaptığımı bilmek isterdim.
seanyboy

Ee, geçiş çok karmaşık mı? Bilmiyorum ... Bana öyle geliyor ki, kullanabileceğiniz pek çok dil özelliği kalmazdı. :) Ayrıca, merkezi örneğinizde, (a == 1 || a == 2 || a == 3) bir şey yaparsanız yapmak daha akıllıca olmaz mı?
Lars Westergren

Ayrıca, son örneğinizde, "break" ifadesi çoğu dilde hiçbir şey yapmaz - en yakın bloktan (genellikle bir döngü) kopar ve durumunuz bir sonraki satırda (endif) zaten olur. Mola "dönüş" olan bir dil kullanırsanız, birçok dönüş de ("koruma ifadeleri" hariç) kaşlarını
çatırır

4
"Optimizasyon lanet olsun. Kodunuzun hızında o kadar büyük bir fark yaratmaz." Kodum mobil bir platformda çalışıyor. Optimizasyonlar önemlidir. Ayrıca, anahtarlar doğru kullanıldığında kodun çok temiz görünmesini sağlayabilir (if..elseif..elseif..elseif ... ile karşılaştırıldığında). Onları hiç görmedin mi? Öğrenin.
Swati

Anahtar hiç karmaşık değil, ama her zaman anlamada sürtünmeyi azaltmak için kodda kullanılan yapı sayısını en aza indirmeye çalıştım.
seanyboy
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.