Odlišujete v aplikaci vývojové, testovací a produkční prostředí?

Tento článek píšu se záměrem zjistit, zda jsme k těmto závěrům dospěli sami, nebo je to evoluční záležitost, ke které časem dospěje každý tvůrce produktů sloužících k dalšímu vývoji. Ve Forrestu k realizaci webů a webových aplikací používáme interní CMS systém, který je nadstavbou nad vybranými Javovskými knihovnami a frameworky. Namátkou například Spring Framework, Freemarker, Groovy, Spring Security, Stripes, DWR, iBatis a řada dalších. Tím, že jsme CMS systém (ona už je to vlastně tak trochu programová platforma) postavili nad existujícími knihovnami jsme dosáhli toho, že můžeme využívat většiny jejich širokých možností a máme zdarma zajištěn i další vývoj, který nás v podstatě bezpracně posouvá zase dál.

Tím, že se systém sestává z takového množství dalších knihoven a frameworků, jsme začali narážet na problémy se složitostí konfigurace. Teď nemluvím o nastavení pro cílového zákazníka (zabezpečení url, nastavení rolí, definice aplikačních triggrů a maker, proměnné prostředí jako adresa SMTP serveru atd.), ale o vývojové záležitosti jako je konfigurace cache (Freemarker šablon, lokalizované zprávy, Groovy třídy), podrobnost chybového výstupu (pro vývoj plné stacktracy, na produkci nic neříkající HTTP 500), dostupnost debugovacích nástrojů (máme vlastní inspektor jako Firefox plugin) apod.

Řada z použitých knihoven a scénářů, které jsme používali, měla sadu možností pro úpravu svého chování, které bylo velmi užitečné využít. V celkovém součtu se jednalo o tucet (a stále přibývají ;-) ) nastavení, které bylo nutné nastavit a u jejichž nastavování musel člověk přemýšlet. Také bylo nutné tato nastavení rozlišovat podle režimu v jakém aplikace běží a nepoužívat konstanty ale proměnné.

Vcelku brzy jsme přišli na to, že, přestože je možné všechny nastavení relativně jednoduše editovat, většinou se nastavilo pouze něco a velice často konstantně tak, že se nám na produkci dostávaly i nastavení, které tam neměly co dělat (třeba nulová cache FTL šablon omylem ponechaná z vývoje).

U nás rozeznáváme tři režimy běhu (a myslím, že se jedná o vcelku běžný standard):

  • development (vývoj) - v tomto prostředí potřebujeme co největší možnosti manipulace se systémem, rychlou odezvu vůči změnám, maximální přístup k debugovacím a chybovým informacím
  • staging (test) - v tomto prostředí již aplikaci vidí zákazník, je tedy vhodné standardní programátorské záležitosti skrýt a neděsit ho plnou obrazovkou stacktraců - na druhou stranu potřebujeme stále výrazně upozornit pokud se někde vyskytne chyba, aby bylo možné ji odstranit před přechodem do produkce, chceme si zachovat nějakou rozumnou míru odezvy na změny v systému a přístup k debugovacím nástrojům
  • production (ostrý běh) - tady chceme maximální výkon, změny v systému za běhu budou minimální (stále si chceme nechat otevřená dvířka, ale upřednostňujeme explicitní refresh konfigurace), minimalizujeme debugovací možnosti (ty mají dopad na výkon), optimalizujeme případný chybový výstup ke koncovému uživateli (stacktracy opravdu nejsou nejlepší vizitka, že Filemone?)

Po nějaké době jsme se dohodli, že toto nepsané rozdělení instalací zformalizujeme a umožníme je definovat na jednom místě v konfiguraci CMS a přizpůsobíme všechny moduly, aby svá běhová nastavení odvodila od aktuálního běhového prostředí. Konfigurace je velmi jednoduchá - např.:


<environment>
  <test hostname="nasserver.fg.cz"/>
  <development hostname="novoj.fg.cz"/>
  <development os="windows"/>
</environment>

Tímto jednotně říkáme, že všechna prostředí s operačním systémem Windows a stroj se jménem "novoj.fg.cz" mají být považována za vývojová, stroj "nasserver.fg.cz" má být považován za testovací prostředí. Všechny ostatní prostředí, které neodpovídají těmto pravidlům jsou považovány za produkční.

Všechny moduly i standardní web aplikace si potom může ze systému vytáhnout identifikaci aktuálního běhového prostředí (voláním metody isProduction(), isStaging(), isDevelopment() na jádrové třídě) a načíst defaultní nastavení pro tento režim běhu. Pokud by kdokoliv jevil zájem tyto výchozí nastavení přepsat, může - nicméně jak praxe ukázala, nikdo to nedělá, protože toto rozlišení defaultních nastavení pro naše potřeby plně postačuje. Integrační vrstva nad knihovnami jako je Freemarker, Groovy atd. také obsahuje trojí sadu defaultních nastavení optimalizovaných pro jednotlivé režimy běhu.

Takto jednoduše jsme se zbavili poměrně velké bolesti, kterou jsme nějakou dobu trpěli. Jedním nastavením vcelku rozumně nyní ovládáme chování celého systému - navíc je to něco, s čím dokáže pracovat kdokoliv i bez hlubší znalosti modulů a knihoven v dané instalaci použitých.

Myšlenka, ke které jsme dospěli, mi s odstupem času nepřijde ani moc geniální jako spíš evoluční. Pozitivní dopady jsou ovšem pro výslednou použitelnost citelně znatelné.

Skončím otázkou nakonec - pokud používáte pro svou práci nějakou infrastrukturní nadstavbu, dospěli jste k podobnému závěru? Jaká je Vaše motivace, řešení a zkušenosti?