it-swarm-eu.dev

Ternární operátor považován za škodlivý?

Například byste upřednostňovali tuto jednostrannou vložku

int median(int a, int b, int c) {
    return (a<b) ? (b<c) ? b : (a<c) ? c : a : (a<c) ? a : (b<c) ? c : b;
}

nebo řešení if/else zahrnující více prohlášení o návratu?

Je-li ?: vhodné a kdy tomu tak není? Měl by být učen nebo skryt před začátečníky?

82
fredoverflow

Je ternární operátor zlý?

Ne, je to požehnání.

Kdy je?: Vhodné?

Když je to něco tak jednoduchého, nechcete ztrácet mnoho linek.

a kdy tomu tak není?

Když trpí čitelnost a srozumitelnost kódu a zvyšuje se pravděpodobnost chyby díky nedostatečné pozornosti, například u mnoha zřetězených operátorů, stejně jako ve vašem příkladu.


Litmus test je, když začnete pochybovat, že váš kód je snadno čitelný a dlouhodobě udržovatelný. Tak to nedělej.

236
user8685

Myslím, že netestovaný ternární operátor (tj. Prohlášení, kde se používá pouze jednou), je v pořádku, ale pokud hnízdíte více než jeden, je to poněkud obtížné přečíst.

50
mipadi

Kdy je?: Vhodné

  • Když je váš kód stručnější a čitelnější.

a kdy tomu tak není?

  • Když je váš kód nečitelný.
  • Pokud to děláte jen proto, abyste potěšili refaktoringový nástroj, jako je ReSharper, a ne osobu, která musí kód udržovat

Pokud máte v ternárním výrazu nějaké logické nebo funkční volání, je pro vás strašné podívat se.

24
realworldcoder

Jeden rozdíl, který (myslím) nikdo neuvedl, je, že pokud-jinak nemůže vrátit hodnotu, zatímco ternární operátor může.

Pocházím z F #, někdy ráda používám ternárního operátora k napodobování vzorů.

match val with
| A -> 1
| B -> 3
| _ -> 0

vs

return val == A ? 1 : 
       val == B ? 3 : 
       0;
23
Benjol

Příklad (IMHO) platného použití:

printf("Success in %d %s\n", nr_of_tries, (nr_of_tries == 1 ? "try" : "tries"));

Výsledkem je čitelnější kód, než mít 2 odlišné tiskové příkazy. Vnořené příklady závisí: (pochopitelné? Ano: ne)

13
Henno Brandsma

Rozhodně ne zlé. Ve skutečnosti je to čistě , a pokud-pak-jinde, není.

Ve funkčních jazycích, jako je Haskell, F #, ML atd., Se jedná o příkazy if-then-else, které jsou považovány za zlé.

Důvodem je to, že jakákoli „akce“, jako je imperativní příkaz if-then-else, vyžaduje, abyste oddělili deklaraci proměnné od její definice, a do vaší funkce zavádí state .

Například v následujícím kódu:

const var x = n % 3 == 1
    ? Parity.Even
    : Parity.Odd;

vs.

Parity x;
if (n % 3 == 1)
    x = Parity.Even;
else
    x = Parity.Odd;

První z nich má dvě výhody kromě toho, že je kratší:

  1. x je konstanta, a tak nabízí mnohem menší šanci na zavedení chyb a může být potenciálně optimalizována tak, jak by druhá nemohla být.
  2. Typ je vyjasněn výrazem, takže kompilátor může bez námahy odvodit, že x musí být typu Parity.

Matoucí, ve funkčních jazycích, je ternární operátor často nazýván if-then-else. V Haskellu můžete říci x = if n mod 3 == 1 then Odd else Even.

7
Rei Miyasaka

Tento konkrétní výraz způsobuje bolení mých očí; Vyhodil bych každého vývojáře z mého týmu, který ho použil, protože je to neudržitelné.

Ternární operátoři nejsou zlí, když se používají dobře. Nemusí to být ani jediné řádky; Dlouhý formát, který je dobře naformátován, může být velmi jasný a snadno pochopitelný:

return
      ( 'a' == $s ) ? 1
    : ( 'b' == $s ) ? 2
    : ( 'c' == $s ) ? 3
    :                 4;

Líbí se mi to lepší než ekvivalent řetězce if/then/else:

if ( 'a' == $s ) {
    $retval = 1;
}
elsif ( 'b' == $s ) {
    $retval = 2;
}
elsif ( 'c' == $s ) {
    $retval = 3;
}
else {
    $retval = 4;
}

return $retval;

Přeformátuji je na:

if    ( 'a' == $s ) { $retval = 1; }
elsif ( 'b' == $s ) { $retval = 2; }
elsif ( 'c' == $s ) { $retval = 3; }
else                { $retval = 4; }

return $retval;

pokud podmínky a přiřazení umožňují snadné nastavení. Přesto dávám přednost ternární verzi, protože je kratší a kolem podmínek a přiřazení nemá tolik hluku.

7
the Tin Man

ReSharper ve VS.NET někdy navrhuje nahradit if...else s ?: operátor.

Zdá se, že ReSharper navrhuje pouze v případě, že podmínky/bloky jsou pod určitou úrovní složitosti, jinak se drží if...else.

3
Uwe Keim

Zde je příklad, kdy --- is zlo:

oldValue = newValue >= 0 ? newValue : oldValue;

Je to matoucí a zbytečné. Kompilátor mohl optimalizovat druhý výraz (oldValue = oldValue), ale proč to kodér dělal na prvním místě?

Další doozy:

thingie = otherThingie != null ? otherThingie : null;

Někteří lidé prostě nemají být kodéry ...

Greg říká, že ekvivalent, pokud je prohlášení „hlučné“. Je to, když to píšete hlučně. Ale to samé, pokud lze napsat jako:

if ('a' == $s) return 1;
if ('b' == $s) return 2;
if ('c' == $s) return 3;
return 4;

Což není hlučnější než ternár. Zajímalo by mě, jestli jsou ternární zkratky; vyhodnotí se všechny výrazy?

2
hapybrian

Ternární operátor není zdaleka zlý a je darem boha.

  • Je to nejužitečnější, když se chcete rozhodnout ve výrazu vnořený. Klasickým příkladem je volání funkce:

    printf("I see %d evil construct%s in this program\n", n, n == 1 ? "" : "s");
    
  • Ve vašem konkrétním příkladu je ternár téměř bezdůvodný, protože se jedná o výraz nejvyšší úrovně pod return. Podmíněnou úroveň můžete zvednout na úroveň výpisu, aniž byste duplikovali něco jiného než klíčové slovo return.

N.B. Nic takového algoritmu pro střední hodnotu nebude nikdy snadno číst.

2
Norman Ramsey
  1. Kromě „zlých“ argumentů jsem zjistil, že podle mých zkušeností existuje vysoká korelace mezi tím, jak programátor používá ternárního operátora a pravděpodobností, že jeho celý kódovací základna bude obtížně čitelná, sledovatelná a udržovatelná (pokud ne přímo nezdokumentovaná). Pokud se programátor více zajímá o záchranu několika 1-2 znakových řádků než někdo, kdo je schopen porozumět jeho kódu, pak jakýkoli menší zmatek chápající ternární prohlášení je obvykle špičkou ledovce.

  2. Ternární operátoři přitahují magická čísla jako s ** t přitahuje mouchy.

Kdybych hledal knihovnu Open Source, která by vyřešila konkrétní problém, a viděl jsem kód, jako jsou ternární operátoři původního odesílatele, v kandidátovi na uvedenou knihovnu, v mé hlavě by se začaly objevovat varovné zvonky a začal bych uvažovat o tom, do jiného projektu, od kterého si půjčit.

2
user8865

Zlo? Podívej, jsou prostě jiné.

if je příkaz. (test ? a : b) je výraz. Nejsou to totéž.

Pro vyjádření hodnot existují výrazy. Pro provádění akcí existují prohlášení. Výrazy se mohou objevit uvnitř příkazů, ale ne naopak. Takže můžete použít ternární výrazy v jiných výrazech, například pro výrazy v sumaci nebo pro argumenty k metodě atd. Nemáte musíte, ale můžete, pokud chcete. S tím není nic špatného. Někteří lidé by mohli říci, že je to zlé, ale to je jejich názor.

Jednou hodnotou ternárního výrazu je to, že vás nutí zpracovat pravdivé i nepravdivé případy. Příkazy if ne.

Pokud se obáváte čitelnosti, můžete je formátovat čitelně.

Nějak se „zlé“ vkradlo do programovací slovní zásoby. Rád bych věděl, kdo to poprvé upustil. (Vlastně mám podezřelého - je na MIT.) Raději bychom měli objektivní důvody pro hodnotící úsudky v této oblasti, nejen vkus lidí a vyvolávání jmen.

2
Mike Dunlavey

Toto může být přeformátováno tak, aby vypadalo stejně hezky jako kombinace if/else:

int median(int a, int b, int c)
{
    return
        (a<b)
        ?
            (b<c)
            ? b
            :
                (a<c)
                ? c
                : a
        :
            (a<c)
            ? a
            :
                (b<c)
                ? c
                : b;
}

Problém je však v tom, že si nejsem opravdu jistý, jestli mám odsazení právo reprezentovat to, co se ve skutečnosti stane. :-)

2
Zan Lynx

Mohu to říct? Nedokážu najít tuto konkrétní aplikaci ternární operace zlá:

  1. operace, kterou provádí, je docela triviální, a jakmile jste ji prošli, jakmile to je stěží možné, některé chyby vyjdou;
  2. to, co dělá, je jasně uvedeno v názvu funkce;
  3. brát> 1 řádek za něco tak zřejmého a to by se v budoucnu zjevně nezlepšilo (ledaže by magický mediánový algoritmus doposud zůstal nezjištěn).

Prosím, mějte slitování, moje pověst je už docela žalostná.

1
cbrandolino

Všechno, co způsobuje, že váš kód je ošklivější, je zlé.

Pokud používáte k vytvoření čistšího kódu ternár, určitě jej použijte. Někdy je jako php skvělé provádět inline substituce, např.

"Hello ".($Male?"Mr":"Ms")." $Name

To ušetří několik řádků, a je to docela jasné, ale váš příklad potřebuje alespoň lepší formátování, aby bylo jasné, a ternár není opravdu dobrý pro víceřádkové, pak můžete také použít, pokud/jinde.

1
user11134

Největší výhra: Ukazuje, že existuje jediný cíl akce.

if ( $is_whatever )
    $foo = 'A';
else
    $foo = 'B';

Existují dvě cesty kódu, které můžete sledovat, a čtenář si musí pozorně přečíst, aby zjistil, které dvě proměnné jsou nastaveny. V tomto případě je to pouze jedna proměnná, ale čtenář musí číst více, aby to zjistil. Nakonec to mohlo být toto:

if ( $is_whatever )
    $foo = 'A';
else
    $bar = 'B';

S ternárním operátorem je jasné, že se nastavuje pouze jedna proměnná.

$foo = $is_whatever ? 'A' : 'B';

Na nejnižší úrovni je to nejzákladnější princip DRY (Don't Repeat Yourself)). Pokud můžete zadat $foo pouze jednou.

1
Andy Lester

Má místo. Pracoval jsem v mnoha společnostech, kde úroveň znalostí vývojářů sahá od strašného po kouzelníka. Protože kód musí být zachován a já tam nebudu navždy, snažím se psát věci tak, aby to vypadalo, že tam patří (aniž bych se díval na komentáře s mými iniciálami, je pro vás velmi vzácné, abyste mohli podívejte se na kód, na kterém jsem pracoval, abych zjistil, kde jsem provedl změny) a že ho může udržovat někdo s méně dovednostmi než já.

Zatímco ternární operátor vypadá nitzifficky a je v pohodě, moje zkušenost je taková, že řádek kódu bude asi nemožné udržet. U mého současného zaměstnavatele máme výrobky, které dodáváme již téměř 20 let. Tento příklad bych nikde nepoužil.

1
Tangurena

Nemyslím si, že ternární operátor je zlý.

Tady je ale gotcha, která mě přisahala. Byl jsem programátorem C pro mnoho (10+) a na konci 90. let jsem se přestěhoval do programování webových aplikací. Jako webový programátor jsem brzy narazil na PHP, který má také ternárního operátora.) Měl jsem chybu v programu PHP= program, který jsem konečně vysledoval k řádku) kódu s vnořeným ternárním operátorem. Ukázalo se, že = terčový operátor PHP ternární operátor přiřazený zleva doprava, ale ternární operátor C, na který jsem byl zvyklý) se sdružuje zprava doleva.

1
leed25d

Kdy je to vhodné a kdy tomu tak není?

Myslím si, že při vývoji homogenní skupiny lidí není problém, ale když se musíte vypořádat s lidmi, kteří manipulují s různými úrovněmi, tento druh onelinerů vnáší do kódu pouze další úroveň komplexnosti. Moje politika v této věci tedy zní: kód je jasný a nevysvětluje spíše než kód krátký a vysvětluje 123123 krát.

Měl by být učen nebo skryt před začátečníky?

Neměl bych se učit začátečníkům, ale raději bych je měl vymyslet, až to bude potřeba, takže se použije pouze v případě potřeby a ne vždy, když potřebujete.

0
guiman

Obchod, který pravidelně píše 600 - 1200 řádkových metod neměl by, mi říká, že ternár je „těžko pochopitelný“. Jakýkoli obchod, který pravidelně umožňuje pět podmínek pro vyhodnocení větve kódu neměl by, mi řekne, že konkrétně shrnuté podmínky v ternáru jsou „těžko čitelné“.

0
Axeman

IMO, samotný operátor není zlý, ale syntaxe použitá v C (a C++) je příliš napjatá. IMO, ALGOL 60 to udělal lépe, takže něco takového:

A = x == y ? B : C;

bude vypadat spíš takto (ale obecně se bude držet syntaxe podobné C):

A = if (x==y) B else C;

I přes to může nadměrně hluboké hnízdění vést k problémům se čitelností, ale alespoň A) kdokoli, kdo provedl programování, to dokáže jednoduše a B) lidé, kteří tomu rozumějí, dokáží docela snadno hnízdo zvládnout. OTOH, také bych si všiml, že v LISP (například) cond je skoro jako ternární příkaz - ne množina příkazů, ale jediný výraz dává hodnotu (pak opět, většina z LISP je takový ...)

0
Jerry Coffin

Kdy je?: Vhodné a kdy není?

  • Pokud nedosáhnete zvýšení výkonu, nepoužívejte jej; ovlivňuje to čitelnost kódu.
  • Použijte jej jednou a nestohujte jej.
  • Je obtížnější ladit.

Měl by být učen nebo skryt před začátečníky?

Nezáleží na tom, ale nemělo by být úmyslně skryto, protože pro začátečníka to není příliš složité na to, aby se naučil.

0
Amir Rezaei

Pokud ... pak ... jinak má tendenci zdůrazňovat stav a proto de-zdůrazňovat operace, které jsou podmíněně prováděny.

ternární operátor je opak, má sklon skrývat stav a je proto užitečný, když je prováděná operace důležitější než samotná podmínka.

V některých jazycích existuje drobná technická niggle, že nejsou zcela zaměnitelná kvůli tomu, že jeden je příkaz a jeden výraz např. podmíněně inicializuje konstanty v C++

0
jk.