Je třeba, aby Nette\String byla třída?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8111
+
0
-

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)
Lopo
Člen | 277
+
0
-

mno neviem … osobne mi to zapuzdrene v triede pripada prirodzenejsie, samotne funkcie v NS som myslim este nikdy nikde nevidel

bene
Člen | 82
+
0
-

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)

jtousek
Člen | 951
+
0
-

Jsem proti předělání třídy String na funkce.

David Grudl
Nette Core | 8111
+
0
-

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?)

Aurielle
Člen | 1281
+
0
-

–1; Nette je OOP framework, když namespace tak se třídou…

Editoval gmvasek (2. 12. 2010 14:46)

paranoiq
Člen | 392
+
0
-

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:

  1. má vůbec smysl implementovat objektový String (a Array?) tak jak to mají jiné jazyky?
  2. patří to do Nette? (patří to do jazyka, ale tam se toho nejspíš nedočkáme)
  3. 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 | 8111
+
0
-

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
+
0
-

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?

srigi
Nette Blogger | 558
+
0
-

Som proti namespacovanym funkciam. Zvyknem si zapis skracovat pomocou use a v pripade kolizie pouzivat aj use as. Neviem ci som toto mohol pouzivat pri namespacovanej funkcii.

use Nette\String as ToolString,
    Nette\Application\Presenter;

class Foo extends Presenter
{
  public function renderBar()
  {
    $s = ToolString::trim($s)
  }
}
redhead
Člen | 1313
+
0
-

Jsem proti.

Navíc use nejde udělat na funkce. Takže se musí vždy uvádět celý namespace.

Editoval redhead (2. 12. 2010 19:44)

Nilp
Člen | 65
+
0
-

Lepší by asi bylo se statických „helper“ funkcí zbavovat.

LM
Člen | 206
+
0
-

redhead napsal(a):

Navíc use nejde udělat na funkce. Takže se musí vždy uvádět celý namespace.

A na metodu to use udělat jde? Nevidím rozdíl String\ vs String::.

redhead
Člen | 1313
+
0
-

Nilp napsal(a):

Lepší by asi bylo se statických „helper“ funkcí zbavovat.

Geniální.. Jak by si to, prosím, chtěl v PHP udělat?

Navíc i Java, která je objektová používá hodně i statické helper metody/třídy (např. třída Arrays)

redhead
Člen | 1313
+
0
-

LM napsal(a):

Bavíme se o statické třídě vs. namespace fce (nikdo neříkal nic o metodách)

use Nette\String as String;

String::trim();

V případě zjemnění namespaců:

use Nette\Tools\String as String;
//nebo
use Nette\Helper\String as String;

String::trim();

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 | 2634
+
0
-

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)

paranoiq
Člen | 392
+
0
-

Navíc use nejde udělat na funkce. Takže se musí vždy uvádět celý namespace.

je to experimentálně ověřeno? (zrovna nemám po ruce pracovní počitadlo. chjo)

v PHP manuálu je tohle (zkráceno):

use My\Full\NSname;
NSname\subns\func(); // calls function My\Full\NSname\subns\func          <-------

@Šaman: naslouchat a poslouchat není totéž

redhead
Člen | 1313
+
0
-

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
+
0
-

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 aj use as. Neviem ci som toto mohol pouzivat pri namespacovanej funkcii.

use Nette\String as ToolString,
    Nette\Application\Presenter;

class Foo extends Presenter
{
  public function renderBar()
  {
    $s = ToolString::trim($s)
  }
}
use Nette\String as ToolString,
	Nette\Application\Presenter;

class Foo extends Presenter
{
	public function renderBar()
	{
		$s = ToolString\trim($s)
	}
}

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

@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
+
0
-

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
+
0
-

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.

pekelnik
Člen | 462
+
0
-

Mně se to líbí.

Editoval pekelnik (2. 12. 2010 21:53)

PaBi3
Bronze Partner | 62
+
0
-

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řídy func

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
+
0
-

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

norbe
Backer | 405
+
0
-

PaBi3: Už teď se na fóru množí dotazy na mnohem známější konstrukce a jelikož i sám David pokud vím podporuje učení se rovnou na nette místo samotného php, tak jsem na to jen chtěl upozornit. Osobně s návrhem problém nemám, jelikož si můžu php5.2 dovolit odstříhnout..

PetrP
Člen | 587
+
0
-

Další nevýhoda je horší podpora v ide. Možná používám špatné, ale \Nette\String\<ctrl>+<space> mi nic nenapovídá.

Jo a jsem proti světovému míru. ;]

HonzaMac
Člen | 40
+
0
-

a také výhoda, že se v IDE pro danou třídu vypíšou dostupné metody :-)

jiriknesl
Člen | 56
+
0
-

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
+
0
-
use Nette\Tools;

Tools\String("Řetězec")->lower()->startsWith("ř");

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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.

Jan Tvrdík
Nette guru | 2595
+
0
-

Jsem pro zachování současného stavu.

redhead
Člen | 1313
+
0
-

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..

jasir
Člen | 746
+
0
-

Také jsem pro zachování současného stavu + odstranění final u helperů. Výhody změny moc nevidím, naopak nevýhoda 5.2 vs 5.3 je skutečně protivná.

vrana
Člen | 131
+
0
-

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 | 8111
+
0
-

Š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 | 8111
+
0
-

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.

paranoiq
Člen | 392
+
0
-

ale PHP má obdobu __toArray – Traversable interface

bene
Člen | 82
+
0
-

paranoiq napsal(a):

ale PHP má obdobu __toArray – Traversable interface

To není to samé. __toArray() by měl být spojen s přetypováním $arr = (array) $object;.

paranoiq
Člen | 392
+
0
-

skutečně?! že mě to nanapadlo! přetypování objektu na pole je celkem jasně definováno a funguje obstojně. a pokud chci objekt na pole převést jinak, mohu použít iterátor.

měla by metoda __toArray navázaná pouze na přetypování vůbec nějaké praktické využití?

bene
Člen | 82
+
0
-

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 | 8111
+
0
-

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
+
0
-

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:

  1. pole
  2. traversable object
  3. 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 | 8111
+
0
-

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.