Finální konstruktor PresenterComponent

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Ondřej Mirtes
Člen | 1536
+
0
-

Ahoj,
lidi mají neustále problémy s tím, že přepisují konstruktor (např. v potomku Controlu či Presenteru) a aplikace jim pak nefunguje (komponenta nepřijímá signály, Presenter taky zlobí). Navrhuji tedy, aby byl konstruktor v PresenterComponent nastaven jako finální, aby k těmto situacím nedocházelo.

pekelnik
Člen | 462
+
0
-

Ondřej Mirtes napsal(a):

Ahoj,
lidi mají neustále problémy s tím, že přepisují konstruktor (např. v potomku Controlu či Presenteru) a aplikace jim pak nefunguje (komponenta nepřijímá signály, Presenter taky zlobí). Navrhuji tedy, aby byl konstruktor v PresenterComponent nastaven jako finální, aby k těmto situacím nedocházelo.

To je dobrý nápad – zároveň by to chtělo nějaký mechanismus jako init() nebo setup() automaticky volaný z konstruktoru. Defaultně prázdná metoda.

Mikulas Dite
Člen | 756
+
0
-

Souhlasím.

pekelnik napsal(a):
zároveň by to chtělo nějaký mechanismus jako init() nebo setup() automaticky volaný z konstruktoru. Defaultně prázdná metoda.

Ta už existuje, je to metoda startup();

Majkl578
Moderator | 1364
+
0
-

Ondřej Mirtes: Co by bylo náhražkou? Byla by to poměrně velká zpětně nekompatibilní změna.

Mikulas Dite: To je sice hezké, ale funguje to pouze v presenteru.

pekelnik
Člen | 462
+
0
-

Mikulas Dite napsal(a):

Souhlasím.

pekelnik napsal(a):
zároveň by to chtělo nějaký mechanismus jako init() nebo setup() automaticky volaný z konstruktoru. Defaultně prázdná metoda.

Ta už existuje, je to metoda startup();

startup() je specifická metoda presenteru (určitá fáze zpracování požadavku)

zatímco setup by se volala v konstruktoru a byla by ve všech komponentách

já využívám konstruktory hojně především pro formuláře a další komponenty

Majkl578
Moderator | 1364
+
0
-

Podle mě je to takhle ideální. Špatné překrytí je čistě chyba programátora (z nepozornosti).

pekelnik napsal(a):

startup() je specifická metoda presenteru (určitá fáze zpracování požadavku)

zatímco setup by se volala v konstruktoru a byla by ve všech komponentách

To se mi ani trochu nelíbí. V tom by byl pěkný bordel.

Ondřej Mirtes
Člen | 1536
+
0
-

Nějaká metoda init() anebo přesunout startup() už do Controlu (s tím, že by si ho Presenter přepisoval).

Honza Marek
Člen | 1664
+
0
-

Ondřej Mirtes napsal(a):

Ahoj,
lidi mají neustále problémy s tím, že přepisují konstruktor (např. v potomku Controlu či Presenteru) a aplikace jim pak nefunguje (komponenta nepřijímá signály, Presenter taky zlobí). Navrhuji tedy, aby byl konstruktor v PresenterComponent nastaven jako finální, aby k těmto situacím nedocházelo.

Já bych byl asi pro, ale překvapuje mě, že s tímhle požadavkem přicházíš zrovna ty :)

Ondřej Mirtes
Člen | 1536
+
0
-

Já vím, to je fail :o) Naštěstí ta komponenta nemusí přijímat žádné signály, takže všechno funguje :o) Pokud se to do Nette dostane, holt udělám BC break a ten konstruktor zruším. Settery tam na ty věci jsou.

v6ak
Člen | 206
+
0
-

Přijde mi to trošku zvláštní. V Javě je toto vyřešené mnohem lépe, tam všechny konstruktory všech tříd (kromě java.lang.Object) musí volat buď jiný svůj konstruktor, nebo konstruktor předka. Dokonce je to AFAIK kontrolováno při tzv. verifikaci bytecode. (Jednou jsem na to nejspíš zapomněl a hned mi JVM nadávala.) Dokonce to asi musí proběhnout před prací s metodami rodiče, předáváním this apod. Toto by se tedy nestalo.

Celkově filozofie konstruktorů je IMHO taková, že každé třídě je houby po tom, jaké konstruktory mají potomci. Ať si třeba přijímají něco dalšího. Jen ať prvně inicializují rodičovskou třídu jejím konstruktorem a pak s ní pracují. (Protože předtím by to znamenalo práci s neinicializovanou třídou a tudíž nedefinovaný výsledek.)

Pravda, Presentery jsou trošku specifické tím, že jsou instanciovány nejspíš přes Reflection a tedy mají učitou pevnou strukturu API konstruktoru.

Ondřej Mirtes
Člen | 1536
+
0
-

Nojono, ale PHP tohle nevyžaduje a od toho pramení problémy.

v6ak
Člen | 206
+
0
-

To ovšem nemění cokoli na tom, že to je celkem drastický přístup.

Jinak u Presenterů by se to dalo ještě zkousnout (do Nette 1.0 by to asi nebyl jediný BCB), ale u Controlů nikoli.

Honza Marek
Člen | 1664
+
0
-

U controlů už to mělo dávno být. Podle mě přepsaný konstruktor controlu je prasárna, pač se pak nedá spolehnout na standardní chování.

Honza Kuchař
Člen | 1662
+
0
-

Honza Marek napsal(a):

U controlů už to mělo dávno být. Podle mě přepsaný konstruktor controlu je prasárna, pač se pak nedá spolehnout na standardní chování.

Něco na tom bude. I přes to, že je to BC break, jsem pro.

redhead
Člen | 1313
+
0
-

A co na to jít cestou, kterou se vydal před nějakou dobou startup? Musí prostě volat svého předka. Prostě podobnou kontrolu toho, že programátor napsal parent::__contruct(). Pokud to tedy vyřeší problém, páč úplně nevím, v čem je zakopaný pes s nefunkčností signálů atd.. (pokud si dobře vybavuju, tak v nějaké topicu o tomhle, volal parent a stejně mu to nefungovalo, tak nevím)

Honza Marek
Člen | 1664
+
0
-

Jo a Datagrid taky přepisuje konstruktor. Dost divoce a moc nerozumim tomu proč.

Honza Kuchař
Člen | 1662
+
0
-

Honza Marek napsal(a):

Jo a Datagrid taky přepisuje konstruktor. Dost divoce a moc nerozumim tomu proč.

Je to kvůli obnovování stavu datagridu ze session.

Editoval honzakuchar (5. 3. 2010 23:25)

v6ak
Člen | 206
+
0
-

Já v tom nevidím problém, hlavně že volá parent constructor.

Ještě je tu možnost udělat nějaký lint, který by (aspoň zjednodušeně, nemuselo by to být jak v Javě) kontrolovat volání parent konstruktoru. Asi by ho šlo pro vývoj nějak modulárně připojit k RoLo.

redhead
Člen | 1313
+
0
-

Dyť říkám – udělat to stejně jako u startupu.. Musí se volat předek. Tečka. „Interní“ konstruktor může plnit nějakou private proměnnou na TRUE a ta se bude kontrolovat ve startupu, pokud bude FALSE, vyhodí vyjímku, že se nevolá předek.

v6ak
Člen | 206
+
0
-

Jo, to je runtime varianta této kontroly. Já mám radši statické kontroly. Ale tady je to celkem jedno.

Honza Marek
Člen | 1664
+
0
-

redhead napsal(a):

Dyť říkám – udělat to stejně jako u startupu.. Musí se volat předek. Tečka. „Interní“ konstruktor může plnit nějakou private proměnnou na TRUE a ta se bude kontrolovat ve startupu, pokud bude FALSE, vyhodí vyjímku, že se nevolá předek.

Předek nepředek, to je jedno. Pro mě je důležitější, abych byl schopen komponentu připojit k nadkomponentě takhle:

new Komponenta($this, $name);

To ta tvoje kontrola vůbec neřeší.

redhead
Člen | 1313
+
0
-

Tak to už je věc toho člověka co bude chtít posílat do konstruktoru. Pokud nebude připojená přes konstruktor, udělá si to nette samo (pokud použiješ továrničku samozřejmě).

Co když chci, aby si to nette dělalo samo a do konstruktoru posílal jen svoje určitý parametry? Tak to tak udělám. Pak už je problém, že pokud nepoužiju továrničku, laděnka bude řvát, že není připojená k jiné komponentě, ale to už je chyba programátora. Šlo jen o to, jak zabránit programátorům udělat chybu nevolání předka. Když ho volat nebudu, žádná chyba řvát nebude a pak si někdo myslí, že komponenta funguje jak má i když nefunguje (signály).

v6ak
Člen | 206
+
0
-

Tady je hlavně IMHO velký rozdíl mezi Presenterem a komponentou. U Presenteru chceme, aby ten konstruktor měl nějaké rozhraní (trošku zvláštní přístup, ale asi jsem ještě neviděl lepší řešení) a použití final by… bylo možná trošku zvláštní a mělo mírné vedlejší následky, ale zabralo by to.

Obecné kompomnenty si ale instanciujeme sami, takže tady to nedává smysl. Konkrétní komponenta může chtít pro vytvoření vědět něco navíc.

Způsob zabránění (nebo spíše varování) nevolání parent konstruktoru jsem tu výše navrhoval a mohl by takto fungovat pro všechny třídy obecně. To je IMHO společné pro celé OOP, nejen pro Presenter a Component.

Honza Marek
Člen | 1664
+
0
-

Tak jsem v Griditu taky musel zrušit konstruktoru parametry. Když jsem je tam nechal a připojoval datagrid hned, tak blblo loadState. Celý strom komponent datagridu se totiž nepřipojil k presenteru najednou, ale postupně, a to dělalo neplechu.