Automatické načítání configů

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

Ahoj,

před nějakou dobou jsem dostal nápad úplně oddělit konfigurační soubory pro komponenty (tovární služby) od ostatních configů a přesunout je ke komponentám. Prakticky vše tvořím v komponentách a počet továren, které musím registrovat, samozřejmě roste a nutnost je registrovat v nějakém společném configu jde proti myšlence „vezmu složku s komponentou (a subkomponentami), nakopíruji do projektu a frčím“. Pokud komponentu z projektu odstraním, musím hledat, kde v jakém configu jsou její továrny, prostě opruz, znáte to ;-)

Proto se mi líbila myšlenka mít ve složce s komponentou také složku „config“, kam si zaregistruji potřebné továrny, a tím mít pohromadě vše, co spolu souvisí, jako takový znovupoužitelný balíček. Struktura by mohla vypadat třeba takto:

- app/
  - Components/
    - FileManager/
      - config/
        - FileManager.neon # zde jsou továrny pro komponentu a subkomponenty
      - FileList/ # složka se subkomponentou
        - FileListControl.php
        - IFileListFactory.php
      - FileManagerControl.php
      - IFileManagerFactory.php

Tahle myšlenka v základu je ale jen přechod z bláta do louže – místo továrny teď musím někam napsat cestu k novému configu, moc bych si nepomohl. Chtěl jsem něco víc „convention over configuration“, proto se mi jako řešení vyloženě nabídl skvělý nástroj Finder.

Do bootstrapu jsem si tedy přidal takový malý scriptík

$cacheJournal = new Nette\Caching\Storages\FileJournal($tempDir);
$cacheStorage = new Nette\Caching\Storages\FileStorage($tempDir . '/cache', $cacheJournal);
$cache = new Nette\Caching\Cache($cacheStorage, 'configFiles');
$files = $cache->load('configFiles');
if($files === NULL) {
    $files = [];
    foreach(Nette\Utils\Finder::findFiles('config/*.neon')->from($appDir) as $path => $file) {
        $files[] = $path;
    }
    $cache->save('configFiles', $files);
}
foreach($files as $config) {
    $configurator->addConfig($config);
}

Ve složce s aplikací se projdou všechny složky s názvem „config“, z nich se vytahají neony a zaregistrují se. Seznam nalezených configů se cachuje, aby to nebrzdilo načítání aplikace.

Toto používám už nějaký ten pátek a jsem s tím nadmíru spokojený. Překvapuje mě však, že nikdo nic podobného nepoužívá (AFAIK), přitom tento scriptík vznikl jako naprosto přirozený důsledek mé vrozené lenosti a totální neochoty ručně registrovat desítky configů, které jsou v různých (pod)složkách. Jediné co musím, je dodržet konvenci (název složky „config“) a při přidání nového configu smazat vygenerovaný seznam z cache.

No a mě by zajímalo, co si o tomto řešení myslíte? Prosím zejména o argumenty proti, prostě jaké vás napadají nevýhody tohoto řešení, případně jak by to šlo vylepšit? Jde o velmi důležitou část aplikace, proto bych byl rád, kdyby se na to podívalo co nejvíc očí, protože já mohu být zaslepen tím, že mi to už nějakou dobu šetří práci, a třeba nevidím nějaký zásadní (možná i nebezpečný) problém.

Jen tak namátkou pár drobných nevýhod, které mě napadají:

  • Je to magie (magii používáme právě proto, že nám ve finále ušetří spoustu repetitivních opruzů, ne?)
  • Může to překážet, pokud chceme některé configy načítat pouze na základě nějaké podmínky nebo v konkrétním pořadí (to se dá velmi snadno obejít porušením konvence)
  • Mírně to zpomaluje načítání aplikace (nic, co by bylo nějak znatelně cítit)
  • Teoreticky by mohl někdo podstrčit nějaký nebezpečný config (pokud ale smí někdo zapisovat do složky s aplikací, pak je asi jádro problému trochu někde jinde)
  • Nutnost smazat jednu složku v cache při přidání nového configu (je to vůbec nevýhoda ve srovnání s nutností někam připsat cestu?)
  • … (?)

Za všechny názory a připomínky předem moc děkuji. Pokud se tento script rozhodnete použít, pak vám přeji, ať vám slouží minimálně stejně dobře, jako mně.

Šaman
Člen | 2635
+
+3
-
  1. Oddělené configy jsou rozhodně dobrý nápad, teď jsem potkal jeden config, který má přes 1000 řádků a to je peklo.
  2. Nicméně v malých a středních aplikacích jsem si zatím vystačil s ručním includováním nového configu do vyššího. Jsem rád, že nad tím mám plnou kontrolu a trochu mi to přijde analogické s DI – všechny závislosti (a configy) jsou explicitně popsané.
  3. Na ten velký projekt by to mohlo být fajn, ale trochu by mohlo hrozit, že se budou konfigy navzájem ovlivňovat a pak nemáš kontrolu nad pořadím includování (poslední přepisuje předchozí). Pokud to používáš jen na servisy, tak by to ale nemělo nastat.

Za sebe tedy mohu říct, že už jsem potkal projekty, kde by výhody silně převážily nad nevýhodami (přehlednost vs. magie). Ale zatím zůstanu u ručního includování configů od sebe.

Editoval Šaman (23. 10. 2014 19:12)

Zax
Člen | 370
+
0
-

@Šaman Ten třetí bod je dobrá připomínka. Zatím jsem ten problém neměl, buď to používám na služby a nebo prostě píšu parametry tak, aby se neovlivnily, ale dokážu si představit situaci, kdy mám třeba parametry s nějakým defaultním nastavením a ty bych chtěl později přepsat v jiném configu.

Napadá mě, že bych si v každém configu mohl volitelně nastavit prioritu a podle ní ty configy seřadit ještě než je uložím do cache. Nejdřív by se do pole vložily configy bez priority a za ně pak configy s prioritou. Někdy to tam určitě zkusím naimplementovat.

Díky!