Má znak @ nějaký hlubší význam?
- tomve
- Člen | 11
Zdravím,
všiml jsem si, že v určitých funkcích se používá @.
Ze zvědavosti se chci zeptat, zda to má hlubší význam než umlčení.
Např. read() v Filesystem
public static function read($file)
{
$content = @file_get_contents($file); // @ is escalated to exception
if ($content === false) {
throw new Nette\IOException("Unable to read file '$file'.");
}
return $content;
}
Osobně bych použil nejprve file_exists() a file_get_contents() až s return. Ale chápu, že file_get_contents() má pár nevýhod, i když…
- false pro symlinks, mohl by nastat problém,
- false s zapnutým safe_mode(), který není od 5.4,
- někdy false pro soubory 2+ GB na 32bit, moc jich dnes nebude.
Tak nevím, zda @ je legacy kód nebo je v tom něco víc, jelikož mi přijde trochu „tvrdé“ použit hned file_get_contents(). (Kdysi mi neexistuji soubory, které jsem hned četl, „zavařily“ vps.)
- duke
- Člen | 650
tomve napsal(a):
Osobně bych použil nejprve file_exists() a file_get_contents() až s return.
Tam bys ale mohl narazit na problém, že v momentu, kdy voláš file_exists() ještě soubor existuje a v momentu, kdy voláš file_get_contents() už ne (jiný skript mohl soubor mezi tím smazat), takže bys to musel stejně znovu řešit i pro file_get_contents().
- tomve
- Člen | 11
duke napsal(a):
tomve napsal(a):
Osobně bych použil nejprve file_exists() a file_get_contents() až s return.
Tam bys ale mohl narazit na problém, že v momentu, kdy voláš file_exists() ještě soubor existuje a v momentu, kdy voláš file_get_contents() už ne (jiný skript mohl soubor mezi tím smazat), takže bys to musel stejně znovu řešit i pro file_get_contents().
Nebo obsah se získá, mezitím se soubor smaže a return vrátí „neexistující“ obsah.
Asi jsem haklivější na neověřování a umlčování. Just saying.
- tomve
- Člen | 11
GEpic napsal(a):
Můžeš to checkovat jak chceš, ale někdo ti může do
file_get_contents
dát klidně URL. A mě se zde líbí, že místo warningu dostaneš exception, s tou se vypořádává daleko lépe. Než nastavovat navíc ještě nějaké error handlery a podobně.
String se dá vždy vyřešit / ověřit.
Avšak díky za diskusi, jsem se chtěl dozvědět něco a skončil jsem v mínusu.
- tomve
- Člen | 11
@CZechBoY To chápu, avšak u read() to jde použít tuto logiku naopak (psal jsem nahoře) – file_get_contents() získá obsah, mezitím se soubor smaže a return vrátí „neexistující“ / „cache“ obsah.
@GEpic String se dá ověřit, zda je url nebo cesta – dokonce je tam isAbsolute().
Napadlo mě napsat něco jako safe_read() a exists() – v Filesystem nic takového nevidím, ale zase bych skončil u read() s @ (kdybych nechtěl psát další file_get_contents()) . :D
Editoval tomve (22. 7. 2018 14:18)
- tomve
- Člen | 11
@GEpic Uznávám, že si mě s tím URL dostal a mělo mi to dojít dřív. Pokud dáš před file_get_contents() funkci file_exists() a string bude URL, tak file_exists() vrátí false (pracuje pouze s lokálem) a do file_get_contents() se to nikdy nedostáne.
Editoval tomve (23. 7. 2018 11:33)
- David Matějka
- Moderator | 6445
hlavni problem, jak zminoval @duke, je s tou atomicitou. pokud bys
pred tim mel file_exists a nasledne file_get_contents bez @
, tak by
ti nahodne mohly vyskakovat warningy
jelikoz se potlaceny warning eskaluje na exception, tak je pouziti
@
zcela legitimni.
- hacafrakus
- Člen | 14
To, že metoda read()
může vrátit smazaná data není
problém (protože to není její účel) a kontrola přes
file_exists()
by tomu nijak nezabránila. Vydedukovat z toho, že
Nette programátor neumí programovat, mi připadá
fascinující.
Editoval hacafrakus (28. 7. 2018 17:27)
- tomve
- Člen | 11
hacafrakus napsal(a):
To, že metoda
read()
může vrátit smazaná data není problém (protože to není její účel) a kontrola přesfile_exists()
by tomu nijak nezabránila. Vydedukovat z toho, že Nette programátor neumí programovat, mi připadá fascinující.
To nebylo napsáno jen kvůli read() funkci.
Mě osobně přijde neskutečný fakt, že nette je nejpoužívanější framework v ČR, ale komunita okolo něj není schopná nette vyvíjet. Pak se musí udělat crowfunding.
Tyhle a další věci mě přijdouá fascinující a přesvědčují mě pořád dookola, že většina nettistů neumí programovat.
Editoval tomve (29. 7. 2018 11:07)
- Mysteria
- Člen | 797
Děláš jako kdyby ostatní frameworky peníze na vývoj nevybíraly. Sice to nedělají jako Nette, ale tečou tam třeba přes školení a dalšími způsoby.
A co se týká komunity a toho, že není schopná Nette vyvíjet, tak to je nesmysl, protože to že Nette používáš ještě neznamená, že si rovnou můžeš troufnout ho vyvíjet. Nebo ty snad taky když jezdíš autem, tak si schopnej ho i vyrábět? Já teda ne.
A co se týká @ v kódu, tak můžeš začít třeba se Symfony, zeptat se jich proč je taky používají, když je to nepřekonatelný problém. :)
- David Grudl
- Nette Core | 8227
@tonve, ty se podílíš na vývoji nějakého frameworku, nebo neumíš programovat? ;-)
- tomve
- Člen | 11
@Mysteria Pokud si nikdo netroufne, tak vývoj bude vždy stát na několika osobách, které budou muset být placení.
@DavidGrudl Roky jsem programoval v čistém PHP (a pokukoval po
Nette, jak si vede). Pak jsem před 2 lety skončil u Laravelu a teď jsem si
řekl, že se podívám blíže na Nette (proto ten dotaz) – nedávno jsem
viděl paskvil stvořen nettistou, který půlku kódu udělal natvrdo.
Jinak se na tvorbě frameworku nepodílím.
- tomve
- Člen | 11
@Milo Nějakou představu jsem tady už napsal:
- https://forum.nette.org/…lubsi-vyznam#… (poslední odstavec, odpověď pro je @GEpic blbost)
- https://forum.nette.org/…lubsi-vyznam#…
Zbytek jsou písmena a řádky.
@DavidGrudl Možná by bylo dobré u těch mínusových příspěvků, které „zešediví“, aby hoverem zpět „zčernalý“ – blbě se to čte (osobně mi to nevadí).
Editoval tomve (29. 7. 2018 17:09)
- tomve
- Člen | 11
Až se k tomu dostanu, tak to jsem napíšu.
Včera jsem zkoušel na localhostu s php7.2.7 co to udělá s 10k requestů na (ne)existujicí soubory – čisté php, v nette jsem to ještě netestoval.
U neexistujících souborů trvál:
- file_exists() s clearstatfile() cca 0.016s
- @file_get_contents bez file_exists() cca 0.12s
U existujících souborů:
- file_exists() s clearstatfile() cca 0.015s
- @file_get_contents() cca 0.17s
- file_exists() s clearstatfile() a s @file_get_contents() cca 0.19s
btw: Existující soubor byl FileSystem.php
Editoval tomve (30. 7. 2018 12:44)
- hacafrakus
- Člen | 14
Co takový test vlastně měří a jak souvisí s implementací metody určené ke čtení? Zkusím znovu popsat, proč není kontrolována existence souboru:
file_get_contents()
načte obsah souboru a vrátíFALSE
, pokud se to z libovolného důvodu nepodařífile_exists()
následovanýfile_get_contents()
je sice teoreticky rychlejší při čtení velkého počtu neexistujících souborů, jenomže to není atomická operace – mezi těmito dvěma voláními může dojít ke smazání souboru, ve webové aplikaci to není zrovna nepravděpodobný scénář. Taková metoda by naopak byla špatná, protože by klidně vrátilaFALSE
a produkovala warning a pokud by to programátor neošetřil (k čemuž jej výjimka nutí), vůbec by se o problému nedozvěděl.- Implementace s
file_exists()
by musela kontrolovat také oprávnění, klidně to můžete zahrnout do toho testu – ať už měříte cokoliv. Mimochodem, nepřekvapivě v něm v případě čtení existujícího souboru dojde k tomu, že nejdříve provedete všechny kontroly existence a oprávnění, aby je následněfile_get_contents()
svým způsobem provedl také (sice to, pokud vím, nedělá, ale při čtení existujících souborů – což je podle mě nejčastější – bude taková metoda vždy pomalejší).
To, že metoda vrátí obsah souboru, který vzápětí někdo smaže, je
sice možné, ale file_exists()
to nijak neřeší. Kromě toho
smyslem metody read()
je soubor přečíst a vrátit obsah, ne
zajistit, aby vrácený obsah stále existoval.
Samozřejmě se rád nechám vyvést z omylu a ocením kód, který bude naplňovat poslání dané metody, zajistí atomicky bezpečné čtení a bude navíc výkonnější. Momentálně žiji v přesvědčení, že takový způsob neexistuje.
Editoval hacafrakus (30. 7. 2018 13:03)
- tomve
- Člen | 11
Pointa toho vše je / má být, aby se zbytečně nedělaly requesty na neeexistující soubory (můj původní příspěvek), a taky jsem se ze zvědavosti ptál na @.
Pak se, zde začlo argumentovat, že v té době file_exists může vrátit true a contents warning (bez @, což bych tedy brál, i když jsem nikdy nedostál warning u contents bez @ po file_exists) a já zase protiargumentoval, že read() může vrátit obsah souboru, který se mezitím může smazat.
- hacafrakus
- Člen | 14
Pokud vám vadí zbytečné requesty na neexistující soubory, doporučil bych je asi nedělat – zbytek byl snad vysvětlen.
Ještě k STFU operátoru – file_get_contents()
generuje
při chybě warning, který metoda přeloží na exception. Důvod je
prostý – warning nezastaví kód, exception ano – tak automaticky donutí
programátora podobný stav ošetřit, nebo alespoň nenapáchá nějaké
kolaterální škody.
- tomve
- Člen | 11
hacafrakus napsal(a):
Pokud vám vadí zbytečné requesty na neexistující soubory, doporučil bych je asi nedělat – zbytek byl snad vysvětlen.
Ještě k STFU operátoru –
file_get_contents()
generuje při chybě warning, který metoda přeloží na exception. Důvod je prostý – warning nezastaví kód, exception ano – tak automaticky donutí programátora podobný stav ošetřit, nebo alespoň nenapáchá nějaké kolaterální škody.
To je taky určitá možnost.
Díky za diskusi. Více k tématu již nemám co napsát.
- Milo
- Nette Core | 1283
@tomve Pokud měl být příspěvek o tom, aby se nedělaly zbytečné filesystem operace, dovolím si konstatovat, že to z nadpisu ani prvního příspěvku, nikdo tak nepochopil :o)
Podle uvedeného měření file_exists()
(IMHO by ale mělo být
is_file()
) by se dala asi mikrooptimalizace udělat. Nicméně,
shut-up operátor se stejně s file_get_contnents()
musí
použít.
- duke
- Člen | 650
tomve napsal:
Pointa toho vše je / má být, aby se zbytečně nedělaly requesty na neeexistující soubory (můj původní příspěvek), a taky jsem se ze zvědavosti ptál na @.
Pak se, zde začlo argumentovat, že v té době file_exists může vrátit true a contents warning (bez @, což bych tedy brál, i když jsem nikdy nedostál warning u contents bez @ po file_exists) a já zase protiargumentoval, že read() může vrátit obsah souboru, který se mezitím může smazat.
Stále mám za to, že řešení použité v Nette, je nejrozumější. Extrémní „pesimistický“ scénář, který jsi zmínil (tj. obrovské množství neexistujících souborů, které chceš tímto způsobem číst), lze kdykoli zoptimalizovat vlastním voláním is_file. Ale ruku na srdce, jak často k takovému scénáři může dojít? Daleko běžnější je „optimistický“ scénář, kdy soubor existuje, a pak je naopak optimálnější is_file nevolat, neboť stejnou kontrolu stejně musí řešit interně metoda file_get_contents, a navíc odpadá problém s neatomicitou (jehož nejelegantnější řešení by si stejně vynutilo použít operátor @).
Co se týče tvého protiargumentu, že read() může vrátit obsah souboru, který je v momentu návratu funkce read() již smazán, zajímalo by mě, jak bys chtěl zajistit opak. Nicméně souhlasím s názorem těch, kteří tvrdí, že není úkolem read() toto zajistit, ale prostě přečíst obsah a pak ho vrátit bez ohledu na to, co se následně děje s jeho zdrojem.