Ještě jednou a lépe: zjišťování (ne)prázdnosti vráceného kontejneru

Od Petr Zemek, 2014-02-16

V příspěvku se podíváme na vhodnější alternativu za kód stylu if (obj->getItems().size() > 0) či if (!obj->getItems().empty()).

Původní kód

Dejme tomu, že máme třídu Directory, která má metodu getSubdirectories(). Ta vrátí seznam podadresářů. Dále mějme nějaký konkrétní adresář:

Directory *dir = new Directory("/path/to/directory");

Chcete pak v kódu zjistit, zda má daný adresář podadresáře. Obvykle vídávám jeden z takovýchto kódů:

if (dir->getSubdirectories().size() > 0)
if (dir->getSubdirectories().size() >= 1)
if (dir->getSubdirectories().size() != 0)
if (!dir->getSubdirectories().empty())

Proč takto raději ne?

Z několika důvodů:

  • Čitelnost. Abyste pochopili záměr kódu, musíte jej analyzovat. Nejdříve se získají všechny podadresáře. Pak se na podadresářích volá size(), což by mělo získat jejich počet. Ten se pak porovná s danou konstantou. Výsledkem je, že se if provede, pokud je velikost nenulová. Kód s empty() je na tom o něco lépe, ale i tak je tam ono získávání všech podadresářů. Navíc je tam pak negace, která pochopení opět ztíží.
  • Duplicitní kód. Podobných kontrol budete mít v kódu více. Na každém místě musíte zopakovat tentýž kód, tedy získání podadresářů a zjištění jejich velikosti.
  • Výkonnost. V případě, kdy getSubdirectories() vrací výsledný kontejner hodnotou, tak se musí zkopírovat, jenom aby se na něm zavolalo size() či empty(). Výsledná kopie se pak ihned zahodí. To může být zbytečně neefektivní.
  • Spoléhání se na implementaci. V ono kódu se spoléháte na to, že navrácený objekt má metodu size() či empty(). Pokud se změní implementace, máte problém. V neposlední řadě se jedná o porušení Deméteřina zákona.

Mimochodem, tento příklad ilustruje porušení principu Tell, don't ask, o kterém jsem psal nedávno.

Jak to udělat lépe?

Přidejte do třídy Directory metodu hasSubdirectories(). Kód uživatelů této třídy pak bude vypadat takto:

if (dir->hasSubdirectories())

Nádhera. Čitelné, jasné, krásné. Přesně tak, jak to mám rád.

Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
6 + 0 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.