Na navigaci | Klávesové zkratky

Nejsi ve vleku cargo kultů?

Před mnoha lety jsem si uvědomil, že když v PHP ve funkci používám proměnnou obsahující předdefinovanou tabulku dat, tak při každém volání funkce musí být pole znovu „vytvořené“, což je překvapivě dost pomalé. Příklad:

function isSpecialName(string $name): bool
{
	$specialNames = ['foo' => 1, 'bar' => 1, 'baz' => 1, ...];
	return isset($specialNames[$name]);
}

A přišel jsem na jednoduchý trik, který znovuvytváření zabránil. Stačilo proměnnou definovat jako statickou:

function isSpecialName(string $name): bool
{
	static $specialNames = ['foo' => 1, 'bar' => 1, 'baz' => 1, ...];
	return isset($specialNames[$name]);
}

Zrychlení, pokud pole bylo trošku větší, se pohybovalo v několika řádech (jako třeba klidně 500×).

Takže od té doby jsem u konstantních polí vždy používal static. Je možné, že tento zvyk někdo následoval, a třeba ani netušil, jaký má skutečný důvod. Ale to nevím.


Před pár týdny jsem psal třídu, která nesla v několika properties velké tabulky předdefinovaných dat. Uvědomil jsem si, že to bude zpomalovat vytváření instancí, tedy že operátor new bude pokaždé „vytvářet“ pole, což jak víme je pomalé. Tudíž musím properties změnit na statické, nebo možná ještě lépe použít konstanty.

A tehdy jsem si položil otázku: Hele a nejsi jen ve vleku cargo kultu? Opravdu pořád platí, že bez static je to pomalé?

Těžko říct, PHP prošlo revolučním vývojem a staré pravdy nemusí být platné. Připravil jsem proto testovací vzorek a udělal pár měření. Samozřejmě jsem si potvrdil, že v PHP 5 použití static uvnitř funkce nebo u properties přineslo zrychlení o několik řádů. Ale pozor, v PHP 7.0 už šlo jen o jeden řád. Výborně, projev optimalizací v novém jádře, ale stále je rozdíl podstatný. Nicméně u dalších verzí PHP rozdíl dál klesal a až postupně téměř vymizel.

Dokonce jsem zjistil, že použití static uvnitř funkce v PHP 7.1 a 7.2 běh zpomalovalo. Zhruba 1,5–2×, tedy z pohledu řádů, o kterých se tu celou dobu bavíme, zcela zanedbatelně, ale byl to zajímavý paradox. Od PHP 7.3 rozdíl zmizel zcela.

Zvyklosti jsou dobrá věc, ale je nutné jejich smysl stále validovat.


Zbytečný static v těle funkcí už používat nebudu. Nicméně u oné třídy, která držela velké tabulky předdefinovaných dat v properties, jsem si řekl, že je programátorsky správné konstanty použít. Za chvíli jsem měl refaktoring hotový, ale už jak vznikal jsem naříkal nad tím, jak se kód stává ošklivým. Místo $this->ruleToNonTerminal nebo $this->actionLength se v kódu objevovalo řvoucí $this::RULE_TO_NON_TERMINAL a $this::ACTION_LENGTH a vypadalo to fakt hnusně. Zatuchlý závan ze sedmdesátých let.

Až jsem zaváhal, jestli vůbec chci koukat na tak hnusný kód, a jestli raději nezůstanu u proměnných, případně statických proměnných.

A tehdy mi to došlo: Hele nejsi jen ve vleku cargo kultu?

No jasně že jsem. Proč by měla konstanta řvát? Proč by měla na sebe upozorňovat v kódu, být vyčnívajícím elementem v toku programu? Fakt, že struktura slouží jen ke čtení, není důvod PRO ZASEKNUTÝ CAPSLOCK, AGRESIVNÍ TÓN A HORŠÍ ČITELNOST.

TRADICE VELKÝCH PÍSMEN POCHÁZÍ Z JAZYKA C, KDE SE TAKTO OZNAČOVALY MAKROKONSTANTY PREPROCESORU. BYLO UŽITEČNÉ NEPŘEHLÉDNUTELNĚ ODLIŠIT KÓD PRO PARSER OD KÓDU PRO PREPROCESOR. V PHP SE ŽÁDNÉ PREPROCESORY NIKDY NEPOUŽÍVALY, TAKŽE NENÍ ANI DŮVOD psát konstanty velkými písmeny.

Ještě ten večer jsem je všude zrušil. A stále nemohl pochopil, proč mě to nenapadlo už před dvaceti lety. Čím větší blbost, tím tužší má kořínek.

Komentáře

  1. TT #1

    avatar

    Ahoj, jen názor do diskuze – mne osobně vůbec neuráží mít konstanty UPPER_CASE, není špatné vidět na první pohled, že se jedná o konstantu. Co mi ale trochu trhá oči, je přístup ke statickým prvkům přes referenci $this. Jsem zvyklý ke statickým prvkům přistupovat vždy přes self:: (nebo v případě potřeby přes static::). Díky za článek

    před 6 měsíci | odpovědět | reagoval [2] Zbynek [3] David Grudl [7] Taco
  2. Zbynek #2

    #1 TTe, přechod na camelcase by mě zas tak nvadil, ale pak mi tam zase chyběj mezery
    subjektivní dojem:
    hůře čitelné: ruleToNonTerminal
    lépe čitelné: rule_to_non_terminal

    před 6 měsíci | odpovědět
  3. David Grudl https://davidgrudl.com #3

    avatar

    #1 TTe, že se jedná o konstantu na první pohled vidět přece je stále, v tom se nic nemění. Stejně jako rozeznáš metodu od property. Nebo míváš obtíže rozeznat metody od properties?

    ad $this:: vs self::. První variantu nepoužívám, v článku to je omylem (používám to s jinými proměnnými). Ale asi to tam nechám, dává to důraz na tu část za ::.

    před 6 měsíci | odpovědět | reagoval [4] TT
  4. TT #4

    avatar

    #3 Davide Grudle, Ano, vidět to stále je. Jestli ale na první pohled, to už je asi věc názoru. Viz příklad:

    self::whatever
    self::$whatever

    Osobně mi tedy chvilku trvá než si uvědomím, že první řádek je konstanta a druhý statický atribut. Takhle je to za mě jasné:

    self::WHATEVER
    self::$whatever

    Roli samozřejmě hraje i zvýrazňování syntax v IDE. Jak jsem psal v prvním komentáři, osobně mi konstanty velkým písmem nevadí. Většinou jich v kódu nemáme příliš na to aby to ten kód vyloženě hyzdilo.

    před 6 měsíci | odpovědět | reagoval [5] David Grudl
  5. David Grudl https://davidgrudl.com #5

    avatar

    #4 TTe, Mně konstanty velkým písmem taky nevadily, dokud jsem je neměl v kódu :) Rozhodnutí pro změnu proto přišlo, až když jsem je trošku víc použil.

    před 6 měsíci | odpovědět
  6. Vojta #6

    avatar

    Jen detail, ve funkci

    isSpecialName(string $s);

    se v isset používá proměná $name pravděpodobně místo $s.

    před 6 měsíci | odpovědět
  7. Taco #7

    avatar

    #1 TTe, No, a není to ten klasický příběh podobně jako IFoo, nebo (v jiném jazyce):
    var item = GetFoo(…) versus Foo item = GetFoo(…)
    kde se argumentuje podobně – „není špatné vidět na první pohled, že se jedná o rozhraní, typ, etc“. A přitom to vlastně vůbec k ničemu není, nebo to dokonce škodí (šumí)?

    před 6 měsíci | odpovědět

Zanechat komentář

Text komentáře
Kontakt

(kvůli gravataru)



*kurzíva* **tučné** "odkaz":http://example.com /--php phpkod(); \--

phpFashion © 2004, 2022 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.