Úspornost Scaly

Příběh odtučňovací kúry jedné Java třídy.

Nedávno jsem potřeboval v Play aplikaci vyrobit klasický stránkovaný seznam položek:

Neměl jsem zrovna náladu znovu objevovat kolo, takže jsem sáhnul po existujícím řešení z našeho webového frameworku pro Javu. Díky tomu, že v Play používáme stejný (náš vlastní) šablonovací systém jako v našich Java řešeních, to šlo až překvapivě snadno.

Šablonu toho, co vidíte na obrázku, jsem v podstatě zkopíroval. Ta šablona je sama o sobě jednoduchá (ani ne 40 řádek), potřebuje ale podstrčit objekt, který jí dodá všechny informace a provádí různé aritmetické gymnastiky.

I tuto Java třídu jsem bezostyšně zkopíroval do Play aplikace. Fungovalo to, jak se říká, na první zapojení. Nicméně po rozmazlení Scalou už kód, který používá tuto třídu, moc oku nelahodí:

Třídu samotnou si můžete prohlédnout zde. Vyznačuje se především, v Javě všudypřítomným, JavaBean stylem a je samozřejmě mutable. Ne, že by to v Javě nešlo (IMHO) lépe, ale zdá se mi, že většině Java programátorů je tento styl nejbližší.

Proto jsem neodolal pokušení přepsat původní Java třídu do Scaly a získat tím možnost přímého srovnání na jedné konkrétní úloze. Výsledek mé snahy si můžete prohlédnout zde. Všechny užitečné funkce původní třídy jsem zachoval, takže šablonu nebylo potřeba měnit. Hlavní rozdíl je v tom, že Scala implementace je immutable (až na to cachování, které se mi zdá jako předčasná optimalizace a možná ho ještě odstraním).

Oproti Java verzi jsem stejného cíle dosáhl na cca třetinovém počtu řádků, což považuji za úspěch. Navíc je (alespoň pro mě) výsledný kód přehlednější. Inicializace objektu před předáním do šablony nyní vypadá takto:

Pár věcí, které stojí ve Scala implementaci za povšimnutí:

  • case classes, kromě jiného ideální datové kontejnery (místo JavaBeans)
  • výchozí hodnoty parametrů metod/konstruktorů
    • proto při inicializaci Pagination nemusím udávat všechny parametry a nepotřebuji k tomu settery
  • možnost při volání metod použít jména parametrů
    • výrazně zpřehledňuje volání metod s více parametry
  • použití funkcí místo jednoúčelových rozhraní s jednou metodou - zdravíme Javu 8 :)

Článek obsahuje 4 komentáře

  • Tomáš Záluský

    1
    Hezké. Na Scale se mi líbí její stručnost, ale na náš současný projekt jsme ji nenasadili. Případy, kdy mi taky dost vadí ukecanost Javy, řeším Guavou. Je tam taky značná úspora, i když takové redukce počtu řádek jako u Scaly se nedosáhne a ani to není žádoucí. Zajímalo by mě, jak by Tvůj kód vypadal v Guavě - taky jsou tam cache, nějaká aritmetika, Ranges a samozřejmě funkce a predikáty emulující funkce vyšších řádů. Jinak Javu 8 zdravím taky :-)
  • Vlastimil Menčík

    2
    Guavu používám cca 2 roky na Java projektech. Dokud nemáme tu Javu 8 (resp. literály funkcí), tak je Guava nejlepší "zpříjemnění" Javy, co znám. Scala je ale prostě o několik levelů dál.
  • Natix

    3
    Já mám trochu problém se zápisem primárního konstruktoru zde: https://gist.github.com/vmencik/5019145

    Při takhle velkém množství, navíc s defaultními hodnotami, bych jednotlivé fieldy zapisoval každý na samostatnou řádku. Takhle to působí jako zeď kódu.
  • Vlastimil Menčík

    4
    OK, dobrá připomínka. Scala Style guide (http://docs.scala-lang.org/style/declarations.html) doporučuje to samé.