Jak rozdělit Nette do samostatných projektů

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

NDB si o to doslova říká ;-)

hrach
Člen | 1838
+
0
-

Namespace

IMO zachovat vse v zakladnim namespace Nette. Jednou to vzniklo pod Nette, tak neni duvod to presouvat ven jenom kvuli tomu, ze by pak nekdo pouzival jen cast Nette. Typicky treba takova Symfony Console. Taky by se to mohlo obejit bez namespace a „mosty“ mit jen pod namespace. Dulezita vec je odebrat zavislosti a vytvorit male baliky, nicmene roztristit komponenty je skoda. Dale, jednotlive makra (ale ted spis bridge, v obecnem smyslu) by si mely pridavat jednotlive komponenty, ne samotna knihovna. Mam kacirsky nazor, ze UIMacros ma byt distribuovano s presenterem (tzn. s Nette\Application(\UI))

Pokud jde o konrektni priklad, tak treba u Latte:

  • zachovat hlavni namespace Nette\Latte
  • makra:
    • CacheMacro → Nette\Cache\Bridges\Latte\CacheMacro
    • CoreMacros → nechat, ale presunout {dump } do noveho macra
    • FormMacros → Nette\Forms\Bridges\Latte\FormMacro
    • UIMacros → Nette\Application\Bridges\Latte\UIMacro

Poznamky k navrhovanemu:

  • Cilove namespace uzvazuji aktualni stav, ne diskutovane (jine) zmeny.
  • Pokud dojde k teoretickemu dalsimu deleni nette a vznike neco jako nette/core a nette/application, zachoval bych logiku, ze namespace Bridges bude v „rootu“ balicku.
  • composer.sh require latte/latte vypada proste blbe. Totalne se vytraci duch nette.

Nette\Database

Navrhuji jako prvni balicek osamostatnit Nette\Database.

  • Je to jedna z min core knihoven, ne kazdy ji pouziva. (Neda se rict o debugu, formech, latte)
  • Jeji zavislosti jsou velmi jednoduche
  • Predpokladam, ze ji nikdo nepouziva mimo Nette\Application, respektive nette samotne.

Z vyse uvedenych duvodu se domnivam, ze je to nejlepsi kandidat:

  • na nacviceni oddeleni
  • require samozrejme musi zustat na nette/nette, kvuli Strings, atp, nicmene do budoucna by melo byt treba jen nette/core a volitelne nette/cache.

Otazka na Davida

V cem ti muzeme pomoci? Mam se poustet do upravy build-scriptu? Atp? Je nutne s tim trochu pohnout. Diky.

enumag
Člen | 2118
+
0
-

S těmi UI makry v rámci nette/application naprosto souhlasím. Přesto by ale nette/application nemělo mít přímou závislost na nette/latte, spíše definovat suggest a v ApplicationExtension detekovat přítomnost Latte, makra instalovat pouze pokud latte existuje. Podobně makra pro formuláře, cache, dump.

U toho oddělení databáze je ale jeden problém. Bude mít nette/nette závislost na nette/database nebo opačně? @hrach navrhuje opačně, ale v tom bych si dovolil nesouhlasit. (Pochybuji že by composer zvládl cyklickou závislost a i kdyby ano tak považuji za nesmysl ji vytářet.) Balíček nette/nette by dle mého názoru měl obsahovat celé Nette, v budoucnu bych jej nejraději viděl pouze jako metapackage. Z tohoto důvodu jsem toho názoru že jako první by se mělo vyčlenit nette/core, jako druhé nette/cache a pak teprve databáze.

Další věc je, že oddělení nám poněkud změní zápis v neonu, protože každý balíček bude mít své CompilerExtension, které bude zřejmě také v bridges jako most na balíček nette/di (zde asi opět suggest, určitě ne přímou závislost).

Dnešní zápis:

nette:
	latte:
		#...
	database:
		#...

Nový zápis:

nette.latte:
	#...
nette.database:
	#...

Tento zápis se někomu možná nebude líbit natolik jako stávající. Mně ale připadá lepší, protože je i zde jasné že ta extensions jsou samostatná, proto myslím že bude lepší tuto změnu neřešit tj. nesnažit se za každou cenu zachovat původní syntaxi.

Pozn. Latte bych raději viděl jako balíček nette/latte než latte/latte.

EDIT:
Ještě jedna věc, speciálně pro @hracha, který nebyl na lednové posobotě. David prozatím nechce mít žádné nette/core, kde by byl Object a Strings a to z toho důvodu že composer-based instalace ještě není úplně standard – až to nastane může Nette\Object opět být jen jeden v nette/core, to už se dá udělat kdykoli celkem bezbolestně.

Další problém je třída Strings. Např. laděnka má na této třídě závislost, ale pouze kvůli funkci fixEncoding. V tomto případě bude podle Davida (a já s ním souhlasím) lepší tu jednu funkci zkopírovat než vytvářet zbytečnou závislost. Obzvlášť laděnka by měla být trochu stand-alone aby ji mohl použít kdokoli kdekoli, tj. bez composeru, bez nette.

Nevím teď jak moc je na Strings závislá NDB, je-li ta závislost podobně slabá, tak by též mohlo být lepší potřebné metody zkopírovat.

Editoval enumag (26. 2. 2013 13:58)

hrach
Člen | 1838
+
0
-

Smer zavislosti

Je snad naprosto jasne, ze nette/database zavisi na nette/nette. Nechapu, jak to mohl napadnou opak. Ted tady, v tuto chvili je to takhle. Ze se do budoucna stane nette/nette metabalickem, a zavislost se zmeni na nette/core je nanjevys zrejme. O cyklickym zavislostech tu nikdo nemluvi.


„Chybejici“ zavislosti

Ze ve jmenem prosto Nette\...\Bridges budou pouzity zavislosti, ktere budou jenom jako suggested je dle me naprosto korektni.


CompilerExtension

Tuto vec jsem si neuvedomil. Tvuj navrh mi prijde v poradku. Opet to dava logiku. Compiler pro Latte bude dostupny v Nette\Latte\Bridges\Config\ treba jako LatteExtension.php.

Editoval hrach (26. 2. 2013 13:54)

hrach
Člen | 1838
+
0
-

Takze pridavam reakci jeste ne edit:

  • ackoliv sem tuto informaci jsem nevedel, muj navrh je plne s timto v souladu.
  • nevim, jestli jsi to dobre interpretoval, ale ten nazor je mimo. Existuji dve kategorie, pouzivaci novych technologii a ti zpomaleni (v neutralnim slova smyslu). Ti, co si nette klonovali, tak davno pouzivaji composer. Ta stara kategorie stale pouziva … ? No preci stazeni archivu z nette.org. Zavedeni nette/core by samozrejme nic nezpusobilo s archivem na nette.org. Ten by se kompiloval samozrejme porad stejne.
  • podbodem na zamysleni je moznost mit v repozitar nette/nette duplikovane changesety, misto metabalicku. (proste opak split subtree)
enumag
Člen | 2118
+
0
-
  • O cyklické závislosti jsem se zmínil jen „aby taková blbost nikoho nenapadla“.
  • Pokud se závislosti v budoucnu obrátí tak OK, NDB může jít první. :-)
  • S tím názorem přišel David, argumentoval jsem mu na to naprosto stejně jako nyní ty, ale neměl jsem pocit že bych ho přesvědčil.
  • Těmi duplikovanými changesety myslíš co? (Split subtree neznám.)

Editoval enumag (26. 2. 2013 15:10)

castamir
Člen | 629
+
0
-

Má představa:

  • nette/core – jádro
  • nette/database
  • nette/cache
  • nette/latte
  • nette/nette
    • vyžaduje
      • nette/core
      • nette/latte
      • nette/core
    • volitelné
      • nette/database
      • nette/dibi – (nějaký sjednocený mechanismus i pro DibiExtension načítající dg/dibi)
Honza Marek
Člen | 1664
+
0
-

hrach napsal(a):

Je snad naprosto jasne, ze nette/database zavisi na nette/nette.

Ne. Když chceš requirovat composerem nette/nette, tak chceš, aby se ti nainstalovalo včetně nette database.

enumag
Člen | 2118
+
0
-

@Honza Marek: Hrach to myslel jako dočasné řešení, ale nemyslím že to projde. Kdyby náhodou jo, tak NDB lze vyčlenit jako první, jak @hrach navrhuje s tím že by se závislost na nette/database musela psát zvlášť. Pokud ne, bude to pořadí muset být tak jak jsem řekl, přičemž nad nette/core David vyvěsil otazník.

@castamir: S první částí souhlasím, ale nette/database by mělo být součástí nette/nette. Pokud NDB nechceš, definuj si vlastní meta package, to je trivka. DibiExtension může být součástí dg/dibi, do nette to nepatří.

Editoval enumag (26. 2. 2013 15:20)

hrach
Člen | 1838
+
0
-

Hm, vzhledem k tomu, co napsal Honza Marek (a to ma hlavu a patu), navhruji tento workflow:

  1. composer balicek nette/nette smazat
  2. vytvorit novy composer balicek nette/framework, ktery bude mirit do repozitare nette/nette
  3. vytvorit novy composer meta-balicek nette/nette, ktery bude mirit do repozitare nette/…, proste tam bude jen ten jeden composer soubor.
  4. >>> po techto krocich lze jednoduse oddelit cokoliv – nette/nette bude instalovat vse.

Dale je postup oddeleni dalsich veci vcelku jednoduchy.

pekelnik
Člen | 462
+
0
-

Souhlasim s hrachem v tom ze by bylo dobre aby vsechny baliky zustaly v namespace nette.

Nelibi se mi mnozna cisla u Bridges ale to je asi detail…

Milo
Nette Core | 1283
+
0
-

Téma od začátku sleduji a na Nováčkové posobotě jsem byl v kroužku, kde se o tom mluvilo. Padlo několik návrhů (stejně jako tady) co osamostatnit jako první a co má nejmíň závislostí. Osobně jsem odhadoval, že Nette\Object nic nepotřebuje. Chyba.

Jednoho večera poté jsem napsal jednoduchý nástroj pro extrahování třídy z balíku knihovny. Nakonec jsem se rozhodl vystavit Class Extractor na GitHub ikdyž k pěknému stavu má daleko. Použití je jednoduché:

php extract.php -s ../dev/nette/Nette/ -t tree.tmp -c 'Nette\Object'

aneb z knihovny Nette vytáhni třídu Nette\Object a všechny její závislosti (a pouze je vypiš). Závislostmi myslím, když třída:

  • extends OtherClass
  • implements Interfaces

anebo uvnitř metod třídy je:

  • instanceof OtherClass
  • new OtherClass
  • OtherClass::static_thing
  • function(TypeHintOtherClass $arg)

Jak jsem psal, k širší použitelnosti to má daleko, některé závislosti jsou sporné, ale přehled poskytne celkem pěkně.

Editoval Milo (28. 2. 2013 13:04)

David Grudl
Nette Core | 8218
+
0
-

Wow, dobrý tool!

Všech těch šílených závislostí se lze zbavit zrušením Object::getReflection (a asi Callback::toReflection). Což samozřejmě zase otevírá otázku kompatibility. Bez BC breaků tohle uskutečnitelné nebude.

enumag
Člen | 2118
+
0
-

Kdy nastává ten případ že nefunguje getDocComment a AnnotationsParser potřebuje Nette\Caching?

Editoval enumag (28. 2. 2013 15:29)

Filip Procházka
Moderator | 4668
+
0
-

Nette\Object::getReflection() můžeš doplnit pomocí extension method :)

Milo
Nette Core | 1283
+
0
-

@David Grudl: Díky. Dalším krokem po refaktoringu by měla být možnost přímo ukázat, odkud se ta závislost vzala.

@enumag: Moc jsem nepochopil, na co se ptáš.

enumag
Člen | 2118
+
0
-

@Milo: Nette\Object má závislost na Reflection, a Reflecion\AnnotationsParser a zase na Caching. Není mi jasné proč tam ta závislost na Cache je, protože se nepoužívá vždy, ale jen v určitém případě – jakém?

Milo
Nette Core | 1283
+
0
-

@enumag: Aha, už chápu. Řekl bych, že cache tam je z obecného důvodu. AnnotationsParser si prostě cachuje naparsované anotace.

enumag
Člen | 2118
+
0
-

@Milo: Pokud jsem správně pochopil implementaci tak se nekešují ani tak anotace jako spíše „docblock“ komentáře pokud je nelze přečíst z reflexe. Na jednu stranu si říkám že důvodem může být něco jako eAccelertator který komentáře maže, na druhou stranu témata s nefunkčními perzistentními parametry kvůli tomu že eAccelertator mazal komentáře už tu byly. Tzn. buď to nefunguje tak jak bylo zamýšleno, anebo (a to je mnohem pravděpodobnější) jsem něco špatně pochopil.

Milo
Nette Core | 1283
+
0
-

Milo napsal(a):

Dalším krokem po refaktoringu by měla být možnost přímo ukázat, odkud se ta závislost vzala.

Detailnější popis závislostí lze nyní ukládat -r report.html

Report je plochá struktura ze které je patrné, odkud se závislost na třídě bere. Původně jsem to chtěl ukazovat přímo v konzoli, ale je to příliš nepřehledné. Taktéž jsem uvažoval nad reportem kompletní stromové struktury, ale ikdyž se to nezdá, strom závislostí je vždy hodně košatý a vymyslet přehledné znázornění chce víc času.

Milo
Nette Core | 1283
+
0
-

Přemýšlel jsem nad vyčleněním Database z Nette. První co se zdá těžké je závislost na Cache, ale co jsem prohlížel kód, tak cache je v NDB použita dost jednoduše. Postačila by celkem triviální implementace jako náhrada. Hlouběji se tím nezabývám, když jsem viděl že už vznikl nette/database repo… :)

V souvislosti s tím jsem ale přemýšlel nad tím, jak případně onu trivální cache nahradit full Cache z Nette. První co mě napadlo je implementace stejného interface. Nestálo by za to, udělat nějaký repozitář nette/interafces? Anebo to granulovat ještě víc na nette/cache-interfaces? Nehloubal jste nad tím někdo víc?

Majkl578
Moderator | 1364
+
0
-

Milo napsal(a):

V souvislosti s tím jsem ale přemýšlel nad tím, jak případně onu trivální cache nahradit full Cache z Nette.

Stačí mít nějaké interface pro vyměnitelnou implementaci. Pokud má rozumné API, není problém napojit ho na jakoukoliv keš (viz např. napojení Symfony Validator metadata keše na Nette Cache: https://github.com/…heBridge.php).

Nestálo by za to, udělat nějaký repozitář nette/interafces? Anebo to granulovat ještě víc na nette/cache-interfaces?

To mi přijde jako nesmysl, který není potřeba.

Editoval Majkl578 (20. 4. 2013 17:34)

mkoubik
Člen | 728
+
0
-

Nejlepší by asi bylo, kdyby balík nette/database závisel na nette/caching, ale to už je zase jiná pohádka.

enumag
Člen | 2118
+
0
-

@mkoubik: Není. Caching je potřeba vyčlenit tak jako tak a samozřejmě na něm budou závislé téměř všechny ostatní balíčky.

Majkl578
Moderator | 1364
+
0
-

mkoubik napsal(a):

Nejlepší by asi bylo, kdyby balík nette/database závisel na nette/caching, ale to už je zase jiná pohádka.

To si nemyslím. Představ si, že bys chtěl ndb použít třeba v Symfony, které má vlastní keš. Raději si napíšeš bridge než abys používal nějakou další alien keš a měl schizofrenní kešování.

castamir
Člen | 629
+
0
-

trošku offtopic: šlo by separovat robotloader? Zběžně jsem se díval, že závisí jen na nette/object a využívá jen cache storage.

Ještě dodám, že pokud by ses osamostatnil RobotLoader a pak ještě Nette\Object, byl bych happy (aneb nemusel bych si kvůli těmto dvěma třídám stahovat celé nette při použití v něčem jiném, než u webové aplikace).

Editoval castamir (20. 4. 2013 18:15)

mkoubik
Člen | 728
+
0
-

Majkl578 napsal(a):

mkoubik napsal(a):

Nejlepší by asi bylo, kdyby balík nette/database závisel na nette/caching, ale to už je zase jiná pohádka.

To si nemyslím. Představ si, že bys chtěl ndb použít třeba v Symfony, které má vlastní keš. Raději si napíšeš bridge než abys používal nějakou další alien keš a měl schizofrenní kešování.

Oproti situaci, kdy by nette/database měla vlastní „triviální implementaci“ to není žádný rozdíl. Nic by ti samozřejmě nebránilo použít jakoukoliv jinou cache, která by implementovala příslušné rozhraní (třeba tu ze symfony).

Ještě mě napadlo další řešení: inteface Nette\Caching\IStorage extends Nette\Database\Caching\IStorage, Nette\Latte\Cahing\IStorage, ... – nette/database by měla vlastní rozhraní pro cache a každý by si ho mohl implementovat aniž by k tomu potřeboval cokoliv z nette, přičemž standardní úložiště z Nette by tam pořád pasovaly.

castamir
Člen | 629
+
0
-

@mkoubik ale tím bys podmínil přítomnost NDB v případě, kdy bys chtěl použít cache z nette k úplně něčemu jinému, kde NDB nepotřebuješ

mkoubik
Člen | 728
+
0
-

castamir napsal(a):

Nojo, to mi nedošlo, beru zpátky.

enumag
Člen | 2118
+
0
-

Majkl578 napsal(a):

mkoubik napsal(a):

Nejlepší by asi bylo, kdyby balík nette/database závisel na nette/caching, ale to už je zase jiná pohádka.

To si nemyslím. Představ si, že bys chtěl ndb použít třeba v Symfony, které má vlastní keš. Raději si napíšeš bridge než abys používal nějakou další alien keš a měl schizofrenní kešování.

To se dá obejít vlastním balíčkem který by nahrazoval nette/caching (lze v composer.json dá snadno nastavit). Zda je to správné řešení je otázka, ale kdybychom to měli řešit tak aby takové „hacky“ nebyly třeba, znamenalo by to pravděpodobně rozbití Nette na ještě víc kousků.

castamir
Člen | 629
+
0
-

@enumag a to něčemu vadí? Já bych některé kousky uvítal ;)

enumag
Člen | 2118
+
0
-

@castamir: Samozřejmě nevadí, jen bude složitější udělat to rozdělení správně. ;-) …Teda vlastně mohlo by to vadit těm co nepoužívají composer (not my case).

Editoval enumag (20. 4. 2013 20:24)

castamir
Člen | 629
+
0
-

@enumag no, to by mohl řešit release skript, který to spojí a který vytvoří komplet balík, který se umístí na web nette. Pokud vím, tak nějak to funguje už teď…

enumag
Člen | 2118
+
0
-

@castamir: Jistě, o tom už se mluvilo. Problém by nastal v případě že by někdo chtěl bez composeru stáhnout nightly verzi jinou než aktuální. Imho nemá smysl to řešit, ale to je názor asi každého kdo používá composer.

MartinitCZ
Člen | 580
+
0
-

@**castamir**, @**enumag**: nějak se to tu zvrhlo. Zachvíli z toho uděláte co třída, to package.
A když jsme u toho, né každý používá composer ;)

enumag
Člen | 2118
+
0
-

@martinit: Ano, to je přesně stav do kterého bych se velmi nerad dostal. :-) Pokud jde o composer, jsem si vědom, že ne každý jej používá. Proto nepovažuji svůj názor v tomto případě za příliš relevantní – ale jak jinak ty nightly verze řešit?

castamir
Člen | 629
+
0
-

@martinit já nechci rozdělit nette úplně na jednotlivé třídy, jen vysekat 2 další (a k nim patřičné závislosti). Například při testování používám jen Robotloader a Debugger (+ volitelný CacheStorage) viz bootstrap pro testování jednoho mého projektu. Uznej, že stahovat kvůli tomu celý framework je trošku zbytečné…

Celkově se podle mě má cenu z nette vysekat pouze Debugger, Latte, NDB, CacheStorage, Object a RobotLoader (snad jsem na nic nezapomněl). To není až tolik částí…

co se nightly verzí bez composeru týče – to je vždy takové ehm komplikované. Ale asi jsem díky používání Composeru zaujatý. Composer totiž hrozně rozmazluje ;-)

Editoval castamir (21. 4. 2013 13:51)