Je třeba, aby Nette\String byla třída?
- David Grudl
- Nette Core | 8254
V souvislosti s úpravou
jmenných prostorů přemýšlím nad tím, zda je vlastně ideální, aby
statické třídy jako Nette\Tools
, Nette\String
nebo
Nette\ArrayTools
byly třídy, jestli by nebylo šikovnější je
mít jako jmenné prostory obsahující funkce.
Výhody tříd:
- případná společná funkcionalita může být umístěna do privátní metody
- mohou využít autoloading (ne příliš podstatná výhoda, třídy lze načíst vždy)
- lze použít dědičnost (ale má smysl u těchto statických tříd?)
- objektový zápis
$s = Nette\String::trim($s)
(ačkoliv jde o globální funkce)
Výhody jmenných prostorů:
- nejsou uzavřené, lze přidávat další funkce (ale je to správné?)
- nezneužívá statických tříd pro vytvoření namespace (a zároveň by šlo třeba String použít pro objektový přístup)
- funkční zápis
$s = Nette\String\trim($s)
- bene
- Člen | 82
Kdysi jsem přemýšlel nad stejnou věcí a v podstatě bych byl pro. Problém ale nastavá u php < 5.3, které jsem nucen používat.
Osobně to řeším tak, že mám StringTools::trim()
nebo
Tools_String::trim()
pro „emulaci“ jmennych prostorů. Tímto
si nezaplácnu třídu String
pro klasický objekt.
Kvůli php < 5.3 bych to osobně udělal takto:
Nette\Tools\String::trim()
, Nette\Tools\Array::xxx()
.
Sice je to šílenější zápis, ale je jasně definováno, co je Tools.
Editoval bene (2. 12. 2010 13:12)
- David Grudl
- Nette Core | 8254
Já jsem zase pro světový mír.
(proč si myslíte, že ve vývoji frameworku existuje nebo má váhu nějaká demokracie?)
- paranoiq
- Člen | 392
nezneužívá statických tříd pro vytvoření namespace
co je na tom konkrétně špatného? statická třída a namespace jsou téměř to samé. proč upřednostňovat jedno před druhým? kvůli nějaké takzvané čistotě návrhu?
rozdrobit na funkce raději ne. takhle bychom ten objektivismus nevybudovali. přichází doba, kdy i bastliči budou umět OOP a Nette a střídání objektového a neobjektového přístupu by mohlo být zbytečně matoucí. lepší by možná bylo (krom výkonu samozřejmě) všechny nativní řetězcové funkce PHP zavrhnout (resp. zabalit) a napsat vlastní řešení řetězců (UTF-8 kompatibilní, bezpečné, s jednotným API)
otázka je:
- má vůbec smysl implementovat objektový String (a Array?) tak jak to mají jiné jazyky?
- patří to do Nette? (patří to do jazyka, ale tam se toho nejspíš nedočkáme)
- bylo by to používáno, když
"abc"
je jednodušší nežnew String("abc")
?
Editoval paranoiq (2. 12. 2010 21:47)
- David Grudl
- Nette Core | 8254
Objektový String nebo Array dle mého žádnou výhodu nemá a v Nette nebude. Což myslím s tématem nijak nesouvisí. Otázkou spíš je, co je na statické třídě objektového a zda nelpíme jen na klišé.
- westrem
- Člen | 398
Za triedy (pokial nebudu final) je jeden argument naviac – je mozne ich podedit. Sam mam par vlastnych pridavnych funkcii napr do Stringu, ale kedze nechcem zasahovat do Nette musim dedit (s minimalnym zasahom odmazania final).
David ma pravdu v tom, ze na statickych triedach ako je String a ArrayTools nie je takmer nic objektoveho, staticke veci sa v OOP beru a chapu inak. Mat funkcie zoskupene v statickej triede je tak trochu bad practise ludi co prechadzaju z proceduralneho na OOP sposob programovania.
Na druhej strane je to vcelku convenient, ked clovek vie, ze vsetko ma
v nejakej triede. Neslo by v pripade zavedenia Namespacovych funkcii namiesto
statickych tried spravit aspon fallback tried String a ArrayTools s
__callStatic
ako kompromis?
- redhead
- Člen | 1313
LM napsal(a):
Bavíme se o statické třídě vs. namespace fce (nikdo neříkal nic o metodách)
V případě zjemnění namespaců:
Už podle mě znát je. I když si nemyslím, že na toto zjemnění David přistoupí, jde mi o logiku. Proč by měla být jedna třída v celém Nette být tak výjimečná, že bude převedena do namespace. Jak si řekl nevidíš rozdíl mezi String\fce a String::fce. Tak proč? Mě se líbí konzistentnost, ne jedno tak, druhý tak.
Editoval redhead (2. 12. 2010 16:37)
- Šaman
- Člen | 2667
Je mi jasný, že demokracie bude v Nette jen tak dlouho, jak dlouho bude David chtít poslouchat hlas lidu, ale dávám jeden bezvýznamný hlas proti přepsání statických tříd na funkce.
Jako hlavní bezvýznamný argument poukazuji na (alespoň syntaktickou) objektovost a jednotný zápis s ostatními statickými funkcemi.
Editoval Šaman (3. 12. 2010 12:35)
- redhead
- Člen | 1313
Sám zatím namespace nepoužívám (až s novým projektem..), takže nevím. Narazil jsem na to myslím na StackOverflow.
V tomhle případě by to možná i šlo, protože use importuje jen část toho namespace. Ale nějaký parent namespace se asi uvést musí.
Editoval redhead (2. 12. 2010 18:29)
- Patrik Votoček
- Člen | 2221
Jsem pro světový mír. A jsem pro přesun pod namespace. Připadá mě to čistější (nechápu co je objektového na třídě se zakázaným konstruktorem a kolekcí statických metod – chápu jí za předpokladu použití PHP < 5.3).
srigi napsal(a):
Som proti namespacovanym funkciam. Zvyknem si zapis skracovat pomocou
use
a v pripade kolizie pouzivat ajuse as
. Neviem ci som toto mohol pouzivat pri namespacovanej funkcii.
redhead napsal(a):
Navíc use nejde udělat na funkce. Takže se musí vždy uvádět celý namespace.
On de snad dělat use na metody? Protože jinak tuhle narážku nechápu…
- arron
- Člen | 464
Zarazi me, ze vsichni omilate dokola namespace a nikdo z vas nezminil autoloading. David to sice zminil jako ne prilis dulezite nicmene si uz dneska fakt nedokazu predstavi, ze budu nekam psat nejake require apod. Cili pro Davida ne prilis dulezite, pro me osobne uplne nejdulezitejsi (ale ze by se Ti, Davide, chtelo myslet nekde na nejake require, to se mi nejak nezda;-)).
Jinak bych tu mohl psat i ostatni duvody jakoze cele Nette je objektove, tak proc tam mit vyjimky atd. ale uz je zminili ostatni:-)
Spis by me zajimalo, jestli je k tomuhle kroku nejake logicke oduvodneni ci spise, jake by to melo mit v konecnem dusledku vyhody…protoze nic z toho, co David zminuje jako vyhody jmennych prostoru mi vyhoda neprijde…
- Patrik Votoček
- Člen | 2221
arron napsal(a):
Zarazi me, ze vsichni omilate dokola namespace a nikdo z vas nezminil autoloading. David to sice zminil jako ne prilis dulezite nicmene si uz dneska fakt nedokazu predstavi, ze budu nekam psat nejake require apod.
David to zmiňuje (nejspíš) protože by se to loadovalo automaticky i nadále jenom by se to muselo řešit jinak (přidáním ke třídám které jsou načítány vždy)).
Spis by me zajimalo, jestli je k tomuhle kroku nejake logicke oduvodneni ci spise, jake by to melo mit v konecnem dusledku vyhody…protoze nic z toho, co David zminuje jako vyhody jmennych prostoru mi vyhoda neprijde…
Připadá mě že takové to odpovědi se poslední dobou hodně často opakují. A nejčastěji jsou to lidé kteří namespace nepoužívají. Zkuste si dva měsíce programovat s namespace a už se nikdy nebudete chtít vrátit zpět do pravěku. (Proč používat namespace ti nenapíšu protože každý k tomu má jiné důvody a hlavně to jsou často důvody které nejdou jen tak napsat do dvou vět)
- Ondřej Mirtes
- Člen | 1536
David Grudl napsal(a):
Objektový String nebo Array dle mého žádnou výhodu nemá a v Nette nebude. Což myslím s tématem nijak nesouvisí. Otázkou spíš je, co je na statické třídě objektového a zda nelpíme jen na klišé.
Mají tu výhodu, že si nemusíš pamatovat nelogické pořadí parametrů (ať žije http://php.net/…-replace.php), ale nevím, jestli to prosazovat na úrovni aplikačního frameworku. Ale možná jo, když už tu máme Nette\Image…
- redhead
- Člen | 1313
@vrtak-cz: beru zpět. Nedošlo mi, že jde importovat jen namespace (bez třídy nakonci).
Nicméně stále si myslím, že by to mohlo být ve třídě. Co se týče výhod namespace, nejsou zas až tak zásadní (stejně tak nevýhody třídy). V konečném důsledku to stejně bude jen změna z ::fce() na \fce(). Což mi oku zrovna nelahodí a jsem radši, když se vše používá stejně. Nepravidelnosti jsou fuj fuj (stejně tak nepravidelná slovesa v angličtině). Jen můj názor. Pokud se to přesune a já budu muset měnit :: na \, tak se z toho nezblázním.
Editoval redhead (2. 12. 2010 19:44)
- mm-marek
- Člen | 61
David Grudl napsal(a):
Otázkou spíš je, co je na statické třídě objektového a zda nelpíme jen na klišé.
Přesně tak, jde jen o to že to vypadá jako OOP super návrh. Nemyslím ale, že by statické metody ve třídě bez konstruktoru bylo nějaký super excelentní řešení. Jde jen o úlitbu OOP…
Jako poddaný v absolutistické monarchii uvítám přesun pod namespace :)
- norbe
- Backer | 405
Spíš se bojím, co na to řeknou začátečníci, jelikož uvidí něco
jako Nette\String\func()
, tak si řeknou ááá, tady se mi
vytváří instance třídy func
… Rozhodně by to vyžadovalo
nějaké hodně VÝRAZNÉ objasnění v dokumentaci, protože si troufám
tvrdit, že s touto konstrukcí se téměř nikdo běžně nesetká, ani na ní
nenarazí v nějakém OOP tutoriálu.
- PaBi3
- Bronze Partner | 62
norbe napsal(a):
Spíš se bojím, co na to řeknou začátečníci, jelikož uvidí něco jako
Nette\String\func()
, tak si řeknou ááá, tady se mi vytváří instance třídyfunc
…
To mi pripadá, akoby si sa snažil argumentovať tým, že Nette Framework
by mali vedieť aj ľudia, čo poriadne nevedia PHP jazyk.
Nette\String\func()
je normálny zápis. To, že ho niekto nevidel
je už jeho problém.
Editoval PaBi3 (2. 12. 2010 22:10)
- paranoiq
- Člen | 392
jde více o čistotu kódu nebo o praktičnost?
pokud bude Nette ve verzi pro PHP 5.3 využívat namespaceované funkce, pak pro verzi pro PHP 5.2 zbývají dvě možnosti: buďto musí vše zůstat tak jak je, nebo se funkce rozsypou do globálního jmenného prostoru (což už teď nejde kvůli kolizím). v každém případě to znemožní použití těchto funkcí v kódu, který by měl být kompatibilní s oběma verzemi Nette (např. pluginy) a zhorší to pracnost při přechodu z 5.2 na 5.3
nedávno tu zaznělo, že rozdílné názvy tříd lze na straně PHP 5.3 překonat pomocí aliasování. bohužel rozdílnou syntax zápisu („\“ vs „::“) takto překonat nejde! pokud má být Nette pro PHP 5.3 co nejvíce kompatibilní s Nette pro PHP 5.2, nemělo by se o namespacovaných funkcích vůbec uvažovat
- jiriknesl
- Člen | 56
Já si myslím, že statická třída nebo nebo funkce, obojí špatně.
Použij statickou factory funkci pro obyčejný objekt, jako to mám já v Googym http://bitbucket.org/…oogy/Str.php
- Honza Marek
- Člen | 1664
Není to špatné, ale pořád tam zůstává ten otravný jmenný prostor
před názvem funkce. Nebo se rovnou může zavést
String::fromString
.
- stekycz
- Člen | 152
Na namespacu by se mi líbila jedna věc a to, že bych si do něj mohl
přidat vlastní metodu. Jak již zde bylo napsáno, String
je
final
, takže bez alespoň drobného zásahu do Nette třídu
neupravím.
Naopak bylo by správné, abych si mohl přidat vlastní metodu do části frameworku? Když už, tak si na ni vytvořím namespace vlastní, ať v tom mám trochu větší přehled a pořádek. A to nemluvím o tom, pokud bych někomu dal nějaký menší projektík k prozkoumání a měl bych tam v jednom namespacu svojí metodu a ten dotyčný by se potom divil, proč jemu to nefunguje.
Třídu, klidně opět statickou, si buď vytvořím od základu a vím,
odkud jakou metodu používám, nebo pomocí odstranění final
třídu podědím a vím, že pracuji se svou upravenou třídou pro
String
.
- pracj3am
- Člen | 14
jiriknesl napsal(a):
Použij statickou factory funkci pro obyčejný objekt, jako to mám já v Googym http://bitbucket.org/…oogy/Str.php
To by byl zabiják výkonu kvůli každýmu řetězci instanciovat objekt.
- Honza Marek
- Člen | 1664
pracj3am napsal(a):
To by byl zabiják výkonu kvůli každýmu řetězci instanciovat objekt.
Objekt bys instancoval jen kvůli řetězci, kde chceš použít nějakou funkci Nette Stringu.
- juzna.cz
- Člen | 248
Konkretne String treba nepotrebuje zadne staticke promenne, ale jine tridy to mohou potrebovat – pro konfiguraci ci jine duvody. Tyto hypoteticke jine tridy proto budou muset zustat jako tridy se statickymi properties.
Z duvodu konzistence bych tedy i String nechal jako tridu.
Navic tridu je mozne podedit, udelat si MyApp\String v celem projektu pak pouzivat tuto vlastni tridu. A tam uz treba budu chtit nejakou statickou konfiguraci (i.e. staticke promenne). Diky tomu, ze to bude trida, se je budu moci klidne implementovat.
- redhead
- Člen | 1313
juzna.cz napsal(a):
Z duvodu konzistence bych tedy i String nechal jako tridu.
Navic tridu je mozne podedit, udelat si MyApp\String v celem projektu pak pouzivat tuto vlastni tridu. A tam uz treba budu chtit nejakou statickou konfiguraci (i.e. staticke promenne). Diky tomu, ze to bude trida, se je budu moci klidne implementovat.
V zásadě souhlasím, s tím poděděním by to bylo fajn, jen kdyby String nebyla nesmyslně final..
- vrana
- Člen | 131
Já jsem tenhle mírně provokativní dotaz vznesl už na konferenci WebCamp, kde měl někdo přednášku o návrhových vzorech. Ale to jen tak na okraj.
Zásadní problém předělání je v tom, že se nedají použít
namespacové proměnné. Takže zatímco můžu napsat
String::$validChars
, tak String\$validChars
napsat
nejde. Možná to Nette zatím na nic nepoužívá, ale časem tu potřebu
mít může.
- David Grudl
- Nette Core | 8254
Šaman napsal(a):
Je mi jasný, že demokracie bude v Nette jen tak dlouho…
Myslel jsem to tak, že jsem pro nebo jsem proti bez dalšího argumentu nemá žádnou váhu, ať jej řekne kdokoliv, třeba většina.
- David Grudl
- Nette Core | 8254
jiriknesl napsal(a):
Použij statickou factory funkci pro obyčejný objekt, jako to mám já v Googym http://bitbucket.org/…oogy/Str.php
Ačkoliv něco podobného se v Nette používá (callback), pro řetězce se mi to v praxi nikterak nevyplácí, ještě horší je to v případě polí (chybějící __toArray). PHP je prostě horší jazyk a některé aspekty fixnout nejdou.
- bene
- Člen | 82
Ironie? :-)
Ano praktické využití by to mělo. Kdysi jsem tento problém řešil.
Nedávno jsem ho řešil, když DibiObject
už nedědil
ArrayObject
.
Vem si že máš vlastní třídu pro práci s polem, kde klíče a hodnoty
neukládáš jako properties ale do nějaké vlastní struktury, což je celkem
běžné. Pak přetypování na array už nejde. Předpokládám, že David
narážel na toto ohledně projektu Googy od Jiřího Knesla. Konkrétně na
třídu Googy\ArrayClass
. Nelze použít
$a = (array) Goody\Arr(array('a', 'b'))->reverse();
, ale musíš
použít $a = Goody\Arr(array('a', 'b'))->reverse()->toArray();
Nevím jak to myslíš přes ten iterátor.
- David Grudl
- Nette Core | 8254
Přesně tak, Jirkova třída byl v praktickém využití přinášela víc
komplikací, než výhod. Jediná možnost by byla ji implementovat jinak, tak,
aby jednotlivé prvky pole rozkopírovala do properties objektu (a žádné
jiné neměla), a v ten okamžik (array)
bude fungovat a půjde ji
použít v řadě případů, kdy funkce očekává pole. Nebo ji udělat
potomkem ArrayObject.
(kdysi jsem s tím experimentoval a zjistil ještě jednu obtíž: zatímco
klíčem pole může být jakýkoliv řetězec, název property nesmí být
prázdný řetězec nebo řetězec začínající znakem \x00
)
- paranoiq
- Člen | 392
mě stále není jasné, k čemu je vlastně dobré explicitní
(array)
, v případě že očekávám pole nebo neznámý
polní objekt
pokud píšu funkci, která očekává nějaké obecné pole, tak rozděluji tři případy:
- pole
- traversable object
- vše ostatní vyhodí výjimku a šmitec
očekávat, že jakýkoliv objekt, který je mi předhozen můžu mávnutím proutku korektně převést na pole je naivní a nebezpečné. pokud objekt nemá/nevrací iterátor, je tomu tak nejspíš proto, že to tak jeho autor zamýšlel a má to nějaký důvod
samozřejmě by se mi líbilo, kdyby existovalo jednoduché řešení druhého případu – syntactic sugar, kterým bych vytáhl z objektu jeho polní verzi pomocí iterátorů, ale to už je detail. můžu použít jednoduchou funkci, která objekt převede
rozhraní k převodu objektu na pole existuje – Traversable interface. zavádět nějaké další, jiné rozhraní navíc (__toArray()) by byl zbytečný chaos
to jak Googy/ArrayClass ukládá data považuji za správné, jen mi vadí, že neimplementuje Iterator interface
UPDATE: a nepochopte mne prosím špatně. neprosazuji, aby byly v Nette třídy Array nebo String. imo by objektová náhrada řetězcových a polních funkcí byla příliš nafouklá na to, aby odpovídala filosofii Nette. nemyslím si ale, že je to obecně špatný přístup
Editoval paranoiq (7. 12. 2010 18:25)
- David Grudl
- Nette Core | 8254
Tady nejde o dobrý/špatný přístup, ale o praktický nástroj vs. nepoužitelný výsledek programátorského cvičení (nic ve zlém). Zkrátka boxing mi v PHP taky chybí, ale v userlandu to nelze obejít. To je vše.