it-swarm-eu.dev

Mám se vrátit z funkce brzy nebo použít příkaz if?

Často jsem psal tento druh funkce v obou formátech a přemýšlel jsem, jestli je jeden formát preferován před druhým a proč.

public void SomeFunction(bool someCondition)
{
    if (someCondition)
    {
        // Do Something
    }
}

nebo

public void SomeFunction(bool someCondition)
{
    if (!someCondition)
        return;

    // Do Something
}

Obvykle kóduji první, protože to je způsob, jakým můj mozek pracuje při kódování, i když si myslím, že dávám přednost tomu druhému, protože se okamžitě postará o jakoukoli manipulaci s chybami a je pro mě snadnější číst

302
Rachel

Dávám přednost druhému stylu. Nejprve zlikvidujte neplatné případy, buď jednoduše ukončete nebo zvyšte výjimky, vložte tam prázdný řádek a poté přidejte „skutečné“ tělo metody. Je pro mě snazší číst.

400
Mason Wheeler

Rozhodně to druhé. Ten první teď nevypadá špatně, ale když získáte složitější kód, neumím si představit, že by si někdo myslel:

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    int retval = SUCCESS;
    if (someCondition)
    {
        if (name != null && name != "")
        {
            if (value != 0)
            {
                if (perms.allow(name)
                {
                    // Do Something
                }
                else
                {
                    reval = PERM_DENY;
                }
            }
            else
            {
                retval = BAD_VALUE;
            }
        }
        else
        {
            retval = BAD_NAME;
        }
    }
    else
    {
        retval = BAD_COND;
    }
    return retval;
}

je čitelnější než

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    if (!someCondition)
        return BAD_COND;

    if (name == null || name == "")
        return BAD_NAME;

    if (value == 0)
        return BAD_VALUE;

    if (!perms.allow(name))
        return PERM_DENY;

    // Do something
    return SUCCESS;
}

Plně přiznávám, že jsem nikdy nepochopil výhodu jednotlivých výstupních bodů.

169
Jason Viers

Závisí to - Obecně se nebudu snažit přesunout spoustu kódu kolem, aby se funkce brzy vymanila - kompilátor se o to obvykle postará mě. To však říká, že pokud existují nějaké základní parametry na vrcholu, které potřebuji a nemůžu pokračovat jinak, budu útěk brzy. Stejně tak, pokud podmínka generuje obrovský if blok ve funkci, budu mít útěk brzy také v důsledku toho.

To však znamená, že pokud funkce vyžaduje určitá data, když se volá, obvykle budu házet výjimku (viz příklad), na rozdíl od právě návratu.

public int myFunction(string parameterOne, string parameterTwo) {
  // Can't work without a value
  if (string.IsNullOrEmpty(parameterOne)) {
    throw new ArgumentNullException("parameterOne");
  } 
  if (string.IsNullOrEmpty(parameterTwo)) {
    throw new ArgumentNullException("parameterTwo");
  }

  // ...      
  // Do some work
  // ...

  return value;
}
32
rjzii

Dávám přednost předčasnému návratu.

Pokud máte jeden vstupní bod a jeden výstupní bod, musíte vždy sledovat celý kód ve vaší hlavě až dolů k výstupnímu bodu (nikdy nevíte, zda nějaký jiný kód uvedený níže nevede k výsledku něco jiného, ​​takže vy musí to sledovat, dokud neexistují). Uděláte to, že žádný materiál, který větev určuje konečný výsledek. To je těžké sledovat.

S jedním záznamem a více existuje, vrátíte se, až budete mít svůj výsledek, a neobtěžujte to sledovat až dolů, abyste zjistili, že s tím nikdo nedělá nic jiného (protože od návratu už nic jiného nebude). Je to jako rozdělit tělo metody na více kroků, které každý krok s možností vrátit výsledek nebo nechat další krok zkusit štěstí.

24
user7197

V programování v C, kde musíte ručně vyčistit, je třeba říci hodně pro jednobodový návrat. I když teď není třeba něco vyčistit, někdo by mohl upravit vaši funkci, přidělit něco a je třeba ji před návratem vyčistit. Pokud k tomu dojde, bude to noční můra, která prohlédne všechny prohlášení o návratu.

V programování v C++ máte destruktory a dokonce i nyní chrániče výstupu a výstupu. To vše musí být zde, aby se zajistilo, že kód bude v první řadě bezpečný, takže kód je dobře chráněn před předčasným odchodem, a proto nemá žádnou logickou nevýhodu a je čistě stylovou záležitostí.

Nejsem dostatečně obeznámen s Javou, ať už se zavolá „konečně“ blokový kód a zda finalizátoři zvládnou situaci, kdy je třeba zajistit, aby se něco stalo.

C # Určitě nemůžu odpovědět.

Jazyk D vám poskytuje správné vestavěné stráže rozsahu a výstupu, a proto je dobře připraven na předčasný výstup, a proto by neměl představovat jiný problém než styl.

Funkce by samozřejmě neměly být v první řadě tak dlouhé, a pokud máte obrovské přepínací prohlášení, váš kód je pravděpodobně také špatně faktorován.

13
CashCow

používám oba.

Pokud DoSomething je 3 až 5 řádků kódu, kód bude vypadat krásně pomocí první metody formátování.

Ale pokud má mnohem více řádků než to, dávám přednost druhému formátu. Nelíbí se mi, když otevírací a zavírací závorky nejsou na stejné obrazovce.

9
azheglov

Včasné návraty za vítězství. Mohou se zdát ošklivé, ale mnohem méně ošklivé než velké obaly if, zejména pokud existuje více podmínek ke kontrole.

9
STW

Klasický důvod pro single-entry-single-exit je to, že jinak se formální sémantika stane nevýslovně ošklivou jinak (stejný důvod byl GOTO považován za škodlivý).

Jinými slovy, je snazší uvažovat o tom, kdy váš software ukončí rutinu, pokud máte pouze 1 návrat. Což je také argument proti výjimkám.

Obvykle minimalizuji přístup předčasného návratu.

8
Paul Nathan

Osobně upřednostňuji na začátku kontrolu stavu úspěšnosti/neúspěchu. To mi umožňuje seskupit většinu nejčastějších selhání v horní části funkce se zbytkem logiky.

7
nathan

Záleží.

Brzy se vraťte, pokud existují zjevné podmínky slepé uličky, abyste mohli okamžitě zkontrolovat, že by zbytečné spuštění zbývající funkce nebylo možné. *

Nastavit Retval + jeden návrat, pokud je funkce složitější a jinak by mohla mít více výstupních bodů (problém s čitelností).

* To může často znamenat problém s designem. Pokud zjistíte, že mnoho vašich metod musí před spuštěním zbytku kódu zkontrolovat nějaký externí/paramaterský stav nebo podobně, pravděpodobně by to měl vyřešit volající. .

6
Bobby Tables

Použijte If

V knize Dona Knutha o GOTO je jsem si ho přečetl důvod, proč mít vždy nejpravděpodobnější stav na prvním místě v prohlášení if. Za předpokladu, že se jedná o rozumnou myšlenku (a nikoliv o čistě zohlednění rychlosti éry). Řekl bych, že předčasné návraty nejsou dobrým programovacím postupem, zejména s ohledem na skutečnost, že jsou častěji než používány pro zpracování chyb, ledaže by váš kód pravděpodobně selhal než selhal :-)

Pokud budete postupovat podle výše uvedené rady, budete muset dát tento návrat do dolní části funkce a pak byste jej také nemuseli ani nazývat návratem, stačí nastavit chybový kód a vrátit jej tedy dva řádky. Tím je dosaženo ideálního výstupu 1 vstupu 1.

Delphi specifické ...

Mám na mysli, že je to dobrá programovací praxe pro programátory Delphi, i když nemám žádný důkaz. Před D2009, nemáme atomový způsob, jak vrátit hodnotu, máme exit; a result := foo; nebo bychom mohli jen hodit výjimky.

Kdybys musel nahradit

if (true) {
 return foo;
} 

for

if true then 
begin
  result := foo; 
  exit; 
end;

možná bys jen onemocněl, když to uvidíš v horní části každé své funkce a budeš raději

if false then 
begin
  result := bar;

   ... 
end
else
   result := foo;

a úplně se vyhněte exit.

3
Peter Turner

Souhlasím s tímto prohlášením:

Osobně jsem fanouškem ochranných doložek (druhý příklad), protože snižuje odsazení funkce. Někteří lidé je nemají rádi, protože to má za následek více návratových bodů z funkce, ale myslím, že je to s nimi jasnější.

Převzato z tato otázka v stackoverflow .

2
Toto

Raději bych napsal:

if(someCondition)
{
    SomeFunction();
}
1
Josh K

Jako ty, obvykle píšu první, ale raději ten poslední. Pokud mám spoustu vnořených kontrol, obvykle odkazuji na druhou metodu.

Nelíbí se mi, jak je zpracování chyb přesunuto z kontroly.

if not error A
  if not error B
    if not error C
      // do something
    else handle error C
  else handle error B
else handle error A

Dávám přednost tomu:

if error A
  handle error A; return
if error B
  handle error B; return
if error C
  handle error C; return

// do something
1
jolt

Včasné návraty používám téměř výhradně v těchto dnech, do extrému. Píšu to

self = [super init];

if (self != nil)
{
    // your code here
}

return self;

tak jako

self = [super init];
if (!self)
    return;

// your code here

return self;

ale na tom opravdu nezáleží. Pokud máte ve svých funkcích více než jednu nebo dvě úrovně vnoření, je třeba je rozdělit.

1
Dan Rosenstark

Podmínky v horní části se nazývají „předpoklady“. Vložením if(!precond) return; vidíte seznam všech předpokladů.

Použití velkého bloku „if-else“ může zvýšit režii odsazení (zapomněl jsem citát o třech úrovních odsazení).

0
Ming-Tang