Jak rozdělit Nette do samostatných projektů
- hrach
- Člen | 1838
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
- CacheMacro →
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
anette/application
, zachoval bych logiku, ze namespaceBridges
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 jennette/core
a volitelnenette/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
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
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
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
- 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)
- Honza Marek
- Člen | 1664
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
@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
Hm, vzhledem k tomu, co napsal Honza Marek (a to ma hlavu a patu), navhruji tento workflow:
- composer balicek nette/nette smazat
- vytvorit novy composer balicek nette/framework, ktery bude mirit do repozitare nette/nette
- vytvorit novy composer meta-balicek nette/nette, ktery bude mirit do repozitare nette/…, proste tam bude jen ten jeden composer soubor.
- >>> po techto krocich lze jednoduse oddelit cokoliv – nette/nette bude instalovat vse.
Dale je postup oddeleni dalsich veci vcelku jednoduchy.
- Milo
- Nette Core | 1283
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
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.
- Filip Procházka
- Moderator | 4668
Nette\Object::getReflection()
můžeš doplnit pomocí extension
method :)
- enumag
- Člen | 2118
@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
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
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
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)
- Majkl578
- Moderator | 1364
mkoubik napsal(a):
Nejlepší by asi bylo, kdyby balík
nette/database
závisel nanette/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
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
Majkl578 napsal(a):
mkoubik napsal(a):
Nejlepší by asi bylo, kdyby balík
nette/database
závisel nanette/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.
- enumag
- Člen | 2118
Majkl578 napsal(a):
mkoubik napsal(a):
Nejlepší by asi bylo, kdyby balík
nette/database
závisel nanette/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ů.
- MartinitCZ
- Člen | 580
@**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 ;)
- castamir
- Člen | 629
@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)