Yoda conditions
A héten felmerült egy kérdés egyik kollégánktól, hogy mi értelme van annak, ha egy if utasítás feltételében megfordítjuk az operandusok sorrendjét? Nézzük meg!
Először is tisztázzuk, hogy mit is jelent, ha megfordítjuk az if utasítás feltételében az operandusok sorrendjét. Ez azt jelenti, hogy a megszokott:
if (változó == valami) {
//kód
}
helyett
if (valami == változó) {
//kód
}
módon írjuk meg a feltételeket, ahol a valami egy konstans, amihez hasonlítunk.
Ezt a programozói szaknyelv Yoda condition néven ismeri. A Yoda condition a nevét nem meglepő módon Yoda-ról kapta, pontosabban a beszédstílusáról.
Eredeti nyelven Yoda beszéde a hagyományos angoltól eltérően nem az alany-ige-tárgy sorrendet követi, hanem általában az alany-tárgy-ige sorrendet. Ezt a szósorrendet tipikusan egyébként akkor szokás használni, ha valamit hangsúlyozni szeretnénk.
Pl: „She wants to fight, and fight she will”.
Ennyi angol és nyelvtani felvezető után visszatérve a programozásra felmerülhet a kérdés, hogy mi értelme van ennek a szintaxisnak?
A rövid válasz az, hogy C# esetén semmi, csak annyi, hogy a kódunkat nehezebb lesz olvasni. Persze akkor felmerül a másik kérdés, hogy mégis milyen nyelvek esetén van értelme?
Például C/C++ esetén van haszna, mivel itt az if utasításban nem csak összehasonlítani tudunk, hanem értéket is tudunk adni a változóknak:
if (valtozo = 42) {
/*kód*/
}
A fenti C/C++ kódrészlet simán lefordul, de nem sok értelme van így a feltételnek. Viszont ha ezt a kifejezést Yoda condition-re alakítjuk, akkor a kód nem fog fordulni, mivel az = operátor bal oldalán kell állnia annak, aminek értéket adunk.
/*fordítási hiba*/
if (42 = valtozo) {
/*kód*/
}
Ezen felül Java és olyan nyelvek esetén is lehet értelme, ahol a == jel nem felüldefiniálható és mindig referenciát hasonlít össze. Nézzünk egy példát!
String x = null;
if (x.equals("foo")) {
//kivétel fog keletkezni.
}
A fenti kódrészletetből belátható, hogy egy kivétel fog keletkezni, mivel null objektumon nem hívható metódus és x változó értékét nem ellenőriztük le null-ra. Viszont ha megfordítjuk a sorrendet, akkor nem fog kivétel keletkezni:
String x = null;
if ("foo".equals(x)) {
//Nem keletkezik kivétel
}
Ebben az esetben a konstans, létező objektumon lesz meghívva a metódus, ami nem dob kivételt, mert lekezeli, hogy x lehet null értékű.
A fenti példákból látható, hogy C# esetén nem sok értelme van a Yoda condition használatának, mivel az if utasítás feltételeinek bool típusra kiértékelhetőnek kell lenniük, valamint a == felülírható (kifejezetten ajánlott egyébként, ha a típus implementálja az IEquatable<T> interfészt) és a ?. operátorral null ellenőrizve tudunk egy objektum tulajdonságához hozzáférni.
Egyetlen „előnye”, hogy növeli a kód kognitív komplexitását, vagyis több idő kell a megértéséhez és módosításához. Éppen ezért a fejlett refactor eszközök, mint a Roslinator, felismerik ezt a mintát és automatikusan át tudják írni a feltételt a megszokott formára.
Összegezve tehát a Yoda condition valamikor hasznos volt, de manapság egyre kevesebb értelme van. C/C++ esetén a feltételen belüli értékadásból adódó hibákat szinte bármelyik statikus kód analizátor meg tudja fogni. Statikus kód analizátort pedig projekt mérettől függetlenül érdemes használni.


2022.03.02. @ 10:47
(Az interface neve helyesen IEquatable.)
2022.03.02. @ 10:53
Köszi, javítottam.