Matzova keynote na RubyConf 2007

Posted by Jan Kubr Sun, 11 Nov 2007 13:14:00 GMT

Tento článek shrnuje Matzovu (tvůrce Ruby) keynote na RubyConf 2007. Dříve jsem psal o prvním a druhém dni.

Matz se na začátku rozpovídal na téma "Zaleží na použitém jazyce?" a začal s tím, že přeci ne. Že všechny (běžné) jazyky jsou Turing-kompletní a tudíž mají stejnou sílu. A že Twitter zvýšil výkonnost desetinásobně bez změny platformy, tudíž na jazyce nezáleží. Nebo ano? Ale jistě, důležitý je podle něj přístup. Ruby má příjemnou syntaxi a je kolem něj velmi entuziastická komunita a to znamená mnoho. Zde byla vhodná chvíle na úklon a poděkovaní všem v sále za jejich nadšení. Související poznámkou bylo, že 42% výdělku ThoughtWorks v USA pochází z Ruby projektů (o tom jsme se zde již zmiňovali) a že to prý jejich šéfovi pěkně zavařil, protože málokdo z jeho firmy chce dělat cokoliv jiného než Ruby. Jak říká Martin Fowler "There is business value in fun". Na konec první části přednášky Matz úkazal jakousi vtipnou tabulku vyjadřující poměr láska/nenávist pro různé jazyky vycházející z prý reálné ankety, ve které byli programátoři dotázáni, jestli daný programovací jazyk milují nebo nenávidí. Ruby vyšlo jako spolehlivý vítěz s poměrem 7,18, následoval Perl s 4,53 a Python s 4,35. Bral jsem to spíš jako žert, Ruby se pořádně rozšiřuje teprve v poslední době, a tak většina jeho programátorů si ho spíše sama vybrala, než že by jim byl "přidělen" zaměstnavatelem. Plus další důvody. A to byl konec sektářského úvodu.

Druhá část se věnovala nové verze Ruby - 1.9. Ta prý vyjde o letošních Vánocích, i když nebude tak stabilní, jak si autoři původně představovali. Bude obsahovat vlastnosti nekompatibilní s verzemi 1.8.x, tři z nich jsou podle Matze zásadní:

  1. Odlišná práce s argumenty bloku. Argument bloku již nemůže být globální proměnná ani členská proměnná objektu. Tedy žádné |$global| nebo |object.member|. Proměnné bloku také budou zastiňovat lokalní proměnné vně bloku, tj. x uvnitř bloku je jiné, než x vně:
    irb(main):022:0> x = 10
    => 10
    irb(main):023:0> [1,2,3].each {|i| x = i} 
    => [1, 2, 3]
    irb(main):024:0> x
    => 3
    
    Takhle to fuguje nyní, v 1.9 už x zůstane 10. Tohle mi přijde jako dost marginální změna, protože v podstatě byly odstraněny možnosti, které žádný rozumný programátor nepoužije..
  2. Řetězce již neobsahují Enumerable. Řetězce tedy již nepůjde iterovat metodou each. Ta ve stávající verzi iteruje přes jeho řádky, což evidentně nejen mně přišlo trochu neintuitivní. Matz podotkl, že vlastně není jasné, přes co by měla tato metoda iterovat, a proto místo ní přibydou metody lines, chars, bytes, které budou vracet příslušná pole (které se dají bez problému iterovat přes each, tj. "česky".chars.each pojede po jednotlivých znacích).
  3. Řetězce vědí o svém kódování a prvky řetězce vrací znaky. Řetězce už znají kódování, defaultně tuším UTF-8, ale při různých operacích to půjde předefinovat. Napříkad při otevírání souboru půjde určit, v jakém kódování očekáváme obsah. Související změnou je, že přístup na jednotlivé znaky řetězce bude vracet daný znak (řetězec o délce jedna) a ne jeho ASCII kód, jak je tomu nyní ("ahoj"[1] nevrátí 104, ale "h").

Další nekompatibility jsou prý již nezásadní, Matz rychle ukázal slajd se spoustou změněných metod. Vypíchnuta byla jen neexistence File.exists? ve prospěch File.exist?, protože den předtím si na to někdo stězoval..

Kromě zpětně nekompatibilních změn přibyde i nová funkcionalita. Anonymní (lambda) funkce lze vytvořit novou syntaxí za pomocí "->". Vtipálek Matz ukázal sérii obrázku, ve které se znak lambdy nakláněl a postupně měnil v tuto dvojici znaků, jakože to je podobné.. Nový zápis dělá "->(a, b) {puts a+b}" ekvivalentní s "lambda {|a,b| puts a+b}". Parametry navíc můžou mít výchozí hodnoty. Lambdy půjdou zavolat i s vynecháním jména metody call: lambda.(1,2) bude stejné jako lambda.call(1, 2).

Přibyly iterátory či enumerátory. Tj. lze si z iterovatelného objektu "vytáhnout" pomocný objekt a iterovat pak přes něj. e = [1, 2, 3].each. Opakovaným voláním e.next pak dostaneme jednotlivé prvky pole. Javisté budou znát. Může se asi někdy hodit. Matz ukázal následujicí kousek kódu:

e1 = [1, 2, 3].each
e2 = [3, 4, 5, 6].each

loop {
  p e1.next + e2.next
}

Toto není nekonečná smyčka, normálně to vytiskne postupně 4, 6 a 8. Metoda next totiž vyhodí nějakou výjimku (EndOfLoopException či co), která způsobí vyskočení z cyklu. Nějak se mi to moc nelibí, chování není jasné na první pohled. Taky jsem si myslel, že výjimky se použivají na výjimečné stavy, ne na vyskočení z cyklu. Anyway.

Další podivností je možnost mít povinné argumenty za nepovinnými. Doteď pokud nějaké argumenty byly nepovinné (tj. měly výchozí hodnotu), nešlo za ně přidat žádné povinné. Tj. def method(a, b=1, c=2, d) nebylo povoleno. V Ruby 1.9 je. Jestli se ptáte, jak tedy vlastně budou hodnoty ve volání metody do proměnných přiřazovány, nejste samy. Byl kolem toho v sále docela rozruch. Matz uvedl pár příkladů:

def m(a, b=24, c)
m(1,2)
a -> 1
b -> 24
c -> 2

def m(1, b=1, c=2, d)
m(1, 2, 3)
a -> 1
b -> 2
c -> 2
d -> 3

Celkem jsem pochopil, jak si rychle uvědomit, co přijde kam: Nejdřív se přiřadí všechny povinné na začátku, poté všechny povinné na konci a pak se berou zbylé mezi tím a přiřazují se odleva, jak tomu bylo doteď (na které se nedostane, dostanou výchozí hodnotu). Problém je, že i Matzovi kolikrát vteřinu trvalo, než to vymyslel. A to on ten jazyk navrhuje.. Doufám, že nic takového se neobjeví v žádném programu, se kterým přijdu do styku; já sám to nepoužiju určitě. Matz vysvětloval, že je to nutný mezikrok pro pojmenované argumenty (které budou v Ruby 2), což se mi moc nezdá. Že by nešlo tohle zakázat a stejně pojmenované parametry umožnit?

Dalšími změnou je používání nativních vláken (co to znamená poznamenává David Majda v komentáři k minulému článku), odlišné bude také nakládání s členskými proměnnými třídy. Jak odlišné jsme se nedozvěděli, ale našel jsem článek, který mluví nejen o tom, ale zmiňuje a vysvětluje i další připravované změny.

Implementace jazyka se bude jmenovat YARV a nedělal ji Matz (někteří jásají), měla by být znatelně rychlejší a konzumovat o něco méně paměti. Matz vtipkoval, že Rubinius je rychlejší než MRI, JRuby je rychlejší než MRI, IronRuby je rychlejší než MRI a že tedy už byl čas předat implementaci někomu jinému. Někdo se zeptal, jestli množství implementací nemůže Ruby uškodit. Matz říkal, že mnoho jich nebude, protože Ruby je naštěstí těžké naimplementovat. On že to zkusil jednou a již nikdy více.

Závěr patřil filozofování na téma současnost a budoucnost jazyka. V klasickém schématu tragédie - nesmělý začátek -> úspěch -> pýcha -> konflikt/válka -> úpadek - se nacházíme v stadiu úspěch a snad to tak prý nějaký čas zůstane. Prý ať chceme nebo ne (Matz že on ne, ale nedá se nic dělat), Ruby si najde cestu do velkých firem (usuzuje podle "the suits people that are surrounding us"). Na podobné téma jsem shlédnul velmi zajímavou prezentaci Kena Auera z Ruby Hoedown 2007, která srovnává historii Smalltalku s Ruby a vůbec obecně mluví o tom, za jakých podmínek se technologie rozšiřují z pár nadšenců mezi masy. Zajímavé, doporučuji.

3 comments |

RubyConf 2007 - den druhý

Posted by Jan Kubr Sun, 04 Nov 2007 17:58:00 GMT

Tento článek shrnuje druhý den RubyConf 2007. Dojmy z prvního dne lze nalézt zde.

Den zahájila přednáška o IronRuby, což je implementace Ruby pro .Net. Nejzajímavější na ní pro mě bylo, že na IronRuby pracuje můj kolega z MFF UK Tomáš Matoušek. Jelikož byl i osobně přítomen, tahal jsem z něj později odpoledne různé zajímavosti. Například jak moc v Redmondu prší (v létě prý naštěstí málo) a jak se mu tam líbí. Nejvíc mě ale zajímalo, co je pravdy na tom, že se zaměstnanci Microsoftu nesmějí podívat na open source kód, tedy ani vývojáři IronRuby nemají možnost spatřit zdrojové kódy jazyka, jehož implementaci vytváří. Prý je to pravda a důvodem je obava právníků Microsoftu, že by jejich nahlížením na cizí kód ovlivněná implementace byla důvodem žaloby. A že se to prý děje často (že je Microsoft žalován za podobné věci). Eh?

Druhá přednáška byla o JRuby. Pozor jsem dával asi jako při té první, zajímavé ale bylo, že parser Ruby pro JRuby napsaný umožňuje novým Netbeansům (a potenciálně dalším v Javě napsaným IDE nástrojům) implementovat různé vychytávky (byla předvedeno zvýrazňování lokální proměnné v metodě spolu s případným upozorěním, že není použitá). Nové Netbeans chci určite vyzkoušet (už jsem to tedy zkoušel instalovat, ale nezabralo mi to pět minut, tak jsem to odložil). JRuby má problém s implementací Object space (možností Ruby přistoupit na libovolný objekt v systému) související s garbage collectingem Javy. Umožnit Object space JRuby neúměrně zpomaluje, a tak je to ve výchozím režimu vypnuto. Interpret se musí spustit se speciálním flagem, aby byl umožněn. Byla kolem toho vášnivá debata, že by to mělo být defaultně zapnuto (protože jinak to není kompatibilní s původní implementací) and all that, kterou jsem nepochopil. Pokud někdo tuhle věc používá, bude dostatečně informovaný, že si to musí zapnout. JRuby využívá stejná vlákna jako Java (tj. převážně nativní či co, moc se v tom moc nevyznám). Na JRuby spustíte Rails (kdybyste to chtěli udělat..)

Třetí dopolední přednáška byla o další alternativní implementaci jazyka - Rubinius. To už byla jiná káva, dočkali jsme se skutečně zajímavé prezentace. Evan Phoenix působil zdravě sebevedomě a měl k tomu důvod, Rubinius je opravdu zajímavý projekt. Jeho přednáška začala skromným prohlášením, že důvodem, proč práci na alternativní implementaci začal, je, že chce aby Ruby dosáhlo světové dominance. Milé.. Poté postupně procházel jednotlivé stávající implementace a ukazoval, kolik v nich je řádku Ruby: MRI: 0, JRuby: 0, IronRuby: 0. Autoři JRuby se z davu ozvali, a tak jim poté velkoryse přiznal nějakých tisíc řádků. Nicméně MRI nazval Ruby pro C prográmátory, JRuby Ruby pro Java programátory a - modří už vědí - IronRuby Ruby pro C# programátory. Rubinius pak vykazoval poměr 1:2 mezi Ruby a céčkem a byl proto označen za Ruby pro Ruby programátora. Proč je to důležité? Pokud chce někdo přispět k lepší implementaci jeho oblíbeného jazyka, nejen musel do uvedení Rubinia umět některý z těch ostatních jazyků, ale musel být ochoten v něm i hodně pracovat. Rubinius umožňuje Ruby nadšencům zůstat u Ruby (plán týmu Rubinia je zvyšovat poměr Ruby v projektu). Rubinius je navíc více než otevřený přispěvatelům: komukoliv, jehož patch bude zařazen do projektu, bude úložiště kódu zpřístupněno k zápisu (commit right). V tuto chvíli do projektu přispělo 57 programátorů a podle Evana jsou všichni považováni za rovnocenní, tj. ne žádní "rovnější" (narážka na Rails core tým).

Co se týče stavu projektu, tak prý stále selhává v 500 testech specifikace, ale ještě před pěti týdny to bylo 1100, takže se postupuje rychle. Rychlejší než MRI je v 24 testech z 31. Někdo se Evana zeptal, na co jsem myslel už den předtím - jestli si myslí, že Rubinius jednou nahradí stávající implementaci - on poměrně diplomaticky řekl, že místo na slunci mají oba projekty. A že důležitá je přece hlavně ta světová dominance (doprovázeno upravenými plakáty sovětské propagandy, ehm).

V průběhu přednášky došlo na zajímavou anketu, ze které vzešlo, že skoro všichni v sále (asi 500 posluchačů) jsou placeni za každodenní práci s Ruby. Doplňující otázka upřesnila, že zhruba 80% z nich pracují s Ruby on Rails.

Odpoledne jsem zašel na Phila Hagelberga a jeho "Tightening the Feedback Loop", ve které připomněl, jak je důležité mít při práci rychlý feedback. Nejprve jsme testovali ručně (pomalé, nespolehlivé), pak automaticky a spouštěli jsme testy jednou za čas; poté začali používat autotest, který spustí okamžitě přesně ty testy, které jsou potřeba. Phil tuto myšlenku zobecnil a představil následující postup: 1. Identifikujete metriku, která je pro vás důležitá (přesnost testů, komplexita kódu, výkon programu). 2. Najdete nebo vytvoříte nástroj, který metriku bude měřit. 3. Zařídíte, abyste byli informováni, změní-li se měřená hodnota. Například sledujete každý den o půlnoci pokrytí kódu testy a pokud hodnota klesne pod 100%, budete informování e-mailem. Stejně jako Ryan o den dříve připomněl, že přílišná komplexita kódu je škodlivá (a že je snadné produkovat kód, kterému rozumí stroj, ale obtížné programovat tak, aby tomu snadno rozuměli lidé) a opět doporučil flog na její měření. Absolutní čísla z flogu vystupující je pak třeba porovnávat s výsledky jeho běhu nad částmi programu přínášející zhruba stejnou hodnotu, samotné moc informativní nejsou.

Phil navíc rád vizualizuje feedback autotestu, hecklu, flogu atp. přímo v editoru a jeho projekt augment tomu napomáhá.

Eric Hodel (autor autotestu) hned poté přednášel na obdobné téma: "Maximizing Productivity". V podstatě se to točilo kolem stejných věcí - automatizace, automatizace, automatizace. Zajímavější byl dlouhý seznam open source projektů, na kterých se Eric podílel. Prohlásil, že není žádná programátorská hvězda a že nakonec všechny projekty napsal primárně pro sebe. Eric působil jako člověk, do kterého se můžete bez problému vžít. Pro mě byl vývoj open source vždy něco, co je spíš pro nerdy věčně sedící u počítače nemající nic lepšího na práci (asi neprávem, ale takhle to bylo). Eric ale řekl, že open source projektům věnuje maximálně deset hodin týdně a to jenom, pokud má zrovna něco velmi zajímavého na práci. Jinak to jsou třeba jen tři čtyři týdně. To opravdu není mnoho. Navíc člověk nemusí hned začít vlastní projekty, stačí pomoci s těmi stávajícími, které používá. Inspirativní.

Zajímavé také bylo Ericovo rozložení oken při práci. Ta jsou čtyři: vlevo nahoře editor s metodou, pod ním editor s testem, vlevo nahoře (aby šel prodloužit) pak termínál s autotestem, dole pak volný terminál. Už Ryan den předtím oceňoval "pair programming" (programování ve dvojicích), Eric přidal tzv. ping-pong: první z dvojice napíše test, ke kterému musí ten druhý vytvořit implementaci (nejjednodušší, jaká je možná) takovou, aby test uspěl. Poté napíše další test a přehodí míček zpátky prvnímu.

Francis Hwang se pak snažil ukázat, jak nepřesné definice mnoha věcí v Ruby (duck typing, neexistence specifikace) odpovídají našemu světu, protože mnoho jeho vlastností je na tom podobně: druh, rasa, pravda/lež, atd. Hmmm. Poměrně zajímavá ale byla úvaha, že jazyky, které vám davají méně volnosti (jeho příkladem byla překvapivě Java), jsou perfektní volbou pro firmy, které rády zůstávají v bezpečných vodách (nemají ambice být výjimečné, jen chtějí mít pár spokojených zákazníků). Už i u nás bylo totiž diskutováno, že Ruby je silný nástroj, který vám umožní nejen udělat mnoho výjimečného, ale také hodně věcí pořádně zkazit.

Večer pak byla velmi zajímavá Matzova keynote, o té v příštím článku. Ale co nevidět mizím do hor hledat místního yetiho, takže asi ne úplně brzy.

3 comments |

RubyConf 2007 - den první

Posted by Jan Kubr Sat, 03 Nov 2007 17:57:00 GMT

Rozhodl jsem se rozšířit si obzory návštěvou další konference. Tentokrát nebyla o Railsech, ale šla přímo ke zdroji - Ruby. Na RailsConf (ať už americkou nebo evropskou verzi) jsem nejel především kvůli její ceně a masovosti.

Ruby on Rails začínají být notoricky známá a hojně používaná věc (minimálně zde ve Státech), což je samozřejmě dobře, zároveň to ale dělá konference o tomto frameworku trochu přelidněné a působící tak trochu "enterprise" (= nudně).

Ne že bych na RailsConf někdy byl (někdo z čtenářů ano? - rád bych se dozvěděl váš názor), ale takový byl můj pocit a potvrdil mi ho Nathaniel Talbott ve své přednášce "Why Camping Matters". Camping je webový mikroframework, napsaný Why the Lucky Stiffem, pomocí něhož můžete vytvořit webovou aplikaci jedním souborems pár řádky. Ješte jsem nepříšel na to, na co by to bylo dobré.. Ale vzhledem k tomu, že Camping aplikace umí využívat ActiveRecord, mohly by se hodit na superrychlé pre-Rails prototypy. Důležité v Talbottově přednášce ale bylo, že Camping nám připomíná, že zde nejsou a nebudou jen Ruby on Rails a že to nejenom není jediný webový framework, ale že to není ani jediný webový framework napsaný v Ruby. Aneb snažil se sdělit, abychom nepřestávali zkoušet nové věci a inovovat a že diverzita nám jedině pomůže. Je důležité mít Vlad deployer vedle Capistrana, je důležité mít Camping vedle Ruby on Rails.

Ale vraťme se na začátek. Letošní RubyConf odehrávájící se v Charlotte v Severní Karolíně byla zahájena Marcelem Molinou a jeho prezentací nazvanou "What makes code beautiful". Musím se přiznat, že po celém jednom dnu bez internetu jsem musel vyřídit pár věci a moc jsem tedy Marcelův výlet do historie nesledoval; shrnout ji ale snad zvládnu. Jeho oblíbená definice krásy byla, že všechny aspekty něčeho krásného jsou vyvážené, nic nijak nevhodně nevyrůstá nebo nepřečnívá. Totéž aplikoval na kód programu (a na konkrétním příkladě i ukázal) - krásný je, pokud jsou všechny jeho důležité vlastnosti vybalancované - délka, čitelnost, rychlost atp. Zkrátka středně zajímavě podaná jednoduchá myšlenka.

Následovala přednáška Jima Weiricha, mimo jiné tvůrce nástrojů rake a XML Builder nazvaná "Advanced Ruby Class Design". Jim ukázal zajimavé příklady návrhů specifické pro Ruby.

Prvním byla ukázka, jak chceme-li vytvořit rozšíření nějaké standardní třídy (např. pole) se spíše vyplatí dodefinovat metodu to_* (např. to_ary pro pole) a příslušné operace na dané třídě (+, -, *, ..), než využít dědičnosti. Důvod pro to byl myslím podobný problém, o kterém jsem psal minule - (ne)komutativita operací. Další technikou bylo předefinování - nebo lépe schování - (téměř) všech metod nějaké třídy. To používá právě XML Builder, kde volání xml.cokoliv vytvoří XML element . Jim ukázal, jak vyřešit krajní případy související s flexibilitou Ruby. Dále se pokusil nahradit SQL fragmenty vstupující do ActiveRecord objektů čistým Ruby, tj. místo Person.find(:all, :conditions => ["name = ?", name]) psát Person.select {|p| p.name == name} se zachováním efektivity SQL - tedy ještě rozšířenějším překladem Ruby do SQL. Docela mu to šlo, ale narazilo to na nemožnost předefinování operátorů &&, || a !. Celá přednáška včera dávala dobrý smysl, ale určitě si slajdy projdu znovu (až budou k dispozici) a do jednotlivých triků se zahloubám více.

Odpoledne jsem slyšel kromě již zmíněného Nathaniel Talbotta dvojici Japonců povídat o AP4R - messaging middlewaru. Zajímavé jen středně. Eric Ivancich pak představil svoji implementaci Ropes - reprezentaci řetězců binárními stromy. Povídání o datových strukturách nepříliš objevné, v určitých aplikacích to ale může věci velmi urychlit. Zajímavější byla jeho poznámka o tom, co ho k napsání této knihovny vedlo. Na jakési mezinárodní soutěži v programování mnoho příznivců dynamických jazyků v průběhu hledání rešení "uteklo" k Ć++, protože problém vyžadoval mnoho operací nad řetězci a to bylo s použitím tradičních reprezentací velmi pomalé. Což Eric komentoval jako nedostatek důvěry v tyto jazyky. Problém ale nebyl v jazyce, nýbrž ve vybraných datových strukturách; použití něčeho jako Ropes a Ruby by bylo rychlé dostatečně (rychlější než něco středně hloupého v C).

Zlatým hřebem dne pro mě každopádně byl Ryan Davis a jeho přednáška "Hurting Code for Fun and Profit". Ryan stojí za mnou velmi oblíbenými nástroji zentest, heckle a flog (mimo jiných). Ryan skvěle ukázal, že nejhorší věc, která může programátora potkat je apatie. "Svůj kód buď milujete, nebo nenávidíte". Pokud ho nenávidíte, pracujete na jeho zlepšení, zlepšujete testy (jako já připomněl, že stoprocentní pokrytí testy nic neříká o jejich kvalitě), snižujete jeho komplexitu a děláte ho čitelnějším. K tomu patří i nedělání věcí zbytečně, programujete naprosté minimum potřebné k tomu, aby vaše testy uspěly. Zmínil i mou oblíbenou knihu 7 Habits of Highly Effective People a jak změnila jeho přístup k práci. Vysvětlení by bylo na další článek, ale v zásadě to podporuje testování, častou refaktorizaci a automatizaci opakujících se úkolů, aby se člověk mohl soustředit na důležité, ale neurgentní úkoly. Další zajimavostí byla definace "technického dluhu": zvyšováním komplexity kódu si jakoby půjčujete čas - uděláte něco rychleji, ale nakonec to stejně budete muset předělat a ten čas "vrátit". Navíc pokaždé, kdy s takovým kódem pracujete, platíte "úroky" tím, že vám úkony trvají déle, než by trvaly, kdyby byla daná část naimplementována čistě. Doporučoval, abychom hodně programovali, protože pouze praxí dosáhneme mistrovství (věc zde často opakovaná). A na závěr: čtete-li jednu knihu měsíčně, jste na dvanáctinásobku průměru v našem odvětví. Ryan byl velmi inspirující a všechny nadchnul k lepší a svědomitější práci.

Den zakončily "Otázky a odpovědi" s Matzem Matsumoto, tvůrcem Ruby. Z těch zajímavějších odpovědí bych zmínil informaci, že verze 1.9 by měla vyjít o těhle Vánocích. Zajímavé také bylo, že Ruby komunita v Japonsku prý závratně velká není a poměr lidí, kteří se Ruby živí, je menší než v USA. Někdo se Matze zeptal, jestli přijede na evropskou Ruby konferenci a on se tvářil, že toho má strašně moc a že se někdy v budoucnu pokusí. Koho zajímá, jaký Matz používá editor, tak je to .. Emacs. Old-schooler..

Příště další dny.

2 comments |

Case statement pod lupou

Posted by Jan Kubr Tue, 30 Oct 2007 21:40:00 GMT

Jak pozorní budete, když v knížce o Ruby narazíte na příkaz case? Jestli jako já, tak moc ne. Rozhodnutí, jakou větví se provádění programu vydá se řídí operátorem ===, tak co je nutné vědět více, že? Následující určitě někomu přijde jako stará známá věc, ale věřím, že ne všem. Až do nedávna jsem si myslel, že následující case:

case wifes
  when 0
     puts 'single'
  when 1
     puts 'married'
  else
     puts 'mormon'
end

se přeloží do následující operace:

if wifes === 0
  puts 'single'
elsif wifes === 1
  puts 'married'
else
  puts 'mormon'
end

Chtěl jsem ale, aby můj test vlezl do všech těchto větví (to je takový dobrý testovací návyk;) a jal jsem se nahradit metodu === na objektu wifes něčím (mockem), co mi vrátí postupně všechny hodnoty. A ono to nefungovalo. Zkoumáním nalezené skutečnosti v irb jsem dospěl k různým zajimavostem, které jsem si předtím dostatečnš neuvědomil:

irb(main):001:0> String === ""
=> true
irb(main):002:0> "" === String
=> false
irb(main):003:0> /h/ === "hey"
=> true
irb(main):004:0> "hey" === /h/
=> false

Aneb potřeboval jsem si znova uvědomit, že === není žádný komutativní operátor, ale metoda a ta může (a je) v různých třídách implementována různě. A jak to navazuje na case statement? No ten příkaz se ve skutečnosti vykoná takhle:

if 0 === wifes
  puts 'single'
elsif 1 === wifes
  puts 'married'
else
  puts 'mormon'
end

Metoda === se tedy nevolá na objektu stojícím za klíčovým slovem case, ale na objektech za "whens" v jednotlivých větvích. Zajimavé to pak začíná být především v případech, kdy nejsou všechny objekty instance stejné třídy. Doufám, že to dává smysl. Objasňuje to i tyhle hojně využívané casy:

case extension.downcase
  when /jpg$/
    puts "picture"
  when /mp3$/
    puts "song"
end
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
 case res
  when Net::HTTPSuccess, Net::HTTPRedirection
    # OK
  else
    res.error!
 end

no comments |

Použití MemCache jako úložiště pro sessions

Posted by Kamil Kukura Thu, 18 Oct 2007 19:28:00 GMT

Railsy umí používat pro ukládání sessions různá uložiště, přičemž ve výchozím nastavení používá PStore, jenž je implicitním úložištěm, se kterým pracuje CGI::Session. To jsou ty malé soubory v adresáři tmp/sessions, které vlastně obsahují serializované proměnné, které jsou v danou dobu v konkrétní session uloženy. Dále je pak možné použít uložení těchto sessions do databáze (přes ActiveRecord) nebo taky přímo do obsahu cookie (CookieStore), což zvyšuje o něco traffic, ale na druhou stranu nejsou nutné dodateční pomalé IO operace.

Zajímavou možnosti je použití operační paměti přes speciální server memcached. Ten byl původně vyvinut pro zvládnutí zátěže na LiveJournal.com a dnes je k dispozici téměř na všech známých platformách. Na straně Ruby je potřeba gem memcache-client, který dokonce umí používat několik serverů zároveň. Protože všechny data jsou ukládany v páru klíč - hodnota, tak pomocí hashovací funkce dokáže rozhodit jednotlivé klíče (a samozřejmě jejich data) na více serverů. Jako úložiště je možné memcache použít i pro ukládání stránek, což může hodně pomoct odlehčit nápor na databázový server.

Zavedení pro ukládání sessions se děje obvykle v souboru environments/production.rb, který konfiguruje aplikaci v produkčním režimu. K tomu stačí vyrobit MemCache objekt a spolu se specifikací expirace ho napojit na ActionController:

CACHE = MemCache.new 'localhost:11211',
                     :namespace => "myapp-#{RAILS_ENV}"
ActionController::Base.session_options[:expires] = 1800
ActionController::Base.session_options[:cache] = CACHE

Samozřejmě v tomto případě musí na localhostu běžet memcache daemon na svém výchozím portu 11211. V případě, že nějaká masívně využívaná aplikace, resp. hodně navštěvovaný web běží v clusteru na více serverech, tak je logicky nutné vyhradit jeden nebo více serverů, kde bude běžet memcached daemon a na něj, resp. na ně nasměrovat všechny instance aplikace/webu.

Bohužel, v čase psaní v aktuální verzi Rails (1.2.5) je menší chyba, který způsobuje podivné chování při nasazení memcache úložiště v prostředí clusterů. Je nutné aplikovat tuhle opravu, která už bude zahrnutá do dalších verzí, je možné že to už bude přímo Rails 2.0

Posted in | no comments |

Older posts: 1 ... 3 4 5 6 7 ... 17