easy going groovy 2nd season on devlove

96
DevLOVE ぐるぐるGroovy ~Easy Going Groovy~ NTTソフトウェア株式会社 上原 潤二 2011.1.24

Upload: -

Post on 10-May-2015

3.271 views

Category:

Technology


0 download

DESCRIPTION

DevLOVE "grow-grow Groovy" seminar handout in Japan, TOKYO at 24 Jan 2011.

TRANSCRIPT

Page 1: Easy Going Groovy 2nd season on DevLOVE

DevLOVEぐるぐるGroovy~Easy Going Groovy~

NTTソフトウェア株式会社上原 潤二2011.1.24

Page 2: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

はじめに

2

Page 3: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

自己紹介上原潤二NTTソフトウェア株式会社JGGUG運営委員ブログ“Grな日々”“Grails徹底入門”2章執筆JavaWorld記事執筆

3

http://d.hatena.ne.jp/uehaj/

Page 4: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

本日の内容GroovyはやわかりGroovyを使うとこんなに便利Groovy導入に向けてGroovyServGroovy 1.8の新機能

4

new! JJUG CCC発表資料からの追加・更新update

Page 5: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Groovyはやわかり

5

Page 6: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

GroovyJVM上で動作するスクリプト言語簡潔・高機能

記述量Java比1/2~1/5Javaとの高い相互運用性

Groovy Class=Java ClassGroovy Object=Java Object

6

Page 7: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Javaimport java.io.*;import java.net.*;

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}

7

Page 8: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!import java.io.*;import java.net.*;

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}

8

Page 9: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!import java.io.*;import java.net.*;

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}ポイント: 正しいJavaコードは一般に正

しいGroovyコードでもある(例外もある)

8

Page 10: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!import java.io.*;import java.net.*;

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}

9

Page 11: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!import java.io.*;import java.net.*;

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}

ポイント: java.io.*, java.net.*などは暗黙にimport済み

9

Page 12: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}

10

Page 13: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

public class SocketAccess {

public static void main(String[] args) { Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} } }}

ポイント: クラス定義、mainメソッドは省略可

10

Page 14: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} }

11

Page 15: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

Socket soc = null; InputStream ins = null; OutputStream outs = null; try { soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); try { if (soc != null) soc.close(); } catch(IOException ex) {} }

ポイント: チェック例外も非チェック扱い

11

Page 16: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

Socket soc = null; InputStream ins = null; OutputStream outs = null; soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); }

if (soc != null) soc.close();

12

Page 17: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

Socket soc = null; InputStream ins = null; OutputStream outs = null; soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

BufferedReader bis = new BufferedReader(new InputStreamReader(ins)); String line; while ((line = bis.readLine()) != null) { System.out.println(line); }

if (soc != null) soc.close();

ポイント: 変数の型宣言は省略可能

12

Page 18: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

def soc = null; def ins = null; def outs = null; soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

bis = new BufferedReader(new InputStreamReader(ins)); def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); }

if (soc != null) soc.close();

13

Page 19: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

def soc = null; def ins = null; def outs = null; soc = new Socket("www.java-users.jp", 80); ins = soc.getInputStream(); outs = soc.getOutputStream(); outs.write("GET / HTTP/1.0\n\n".getBytes());

bis = new BufferedReader(new InputStreamReader(ins)); def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); }

if (soc != null) soc.close();

ポイント: 読み込みストリームの自動クローズなど

13

Page 20: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs ->

outs.write("GET / HTTP/1.0\n\n".getBytes());

bis = new BufferedReader(new InputStreamReader(ins)); def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); } }

14

Page 21: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs ->

outs.write("GET / HTTP/1.0\n\n".getBytes());

bis = new BufferedReader(new InputStreamReader(ins)); def line = null; while ((line = bis.readLine()) != null) { System.out.println(line); } }

ポイント: 行読み込みストリームに対する行単位の処理と、自動クローズ

14

Page 22: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs ->

outs.write("GET / HTTP/1.0\n\n".getBytes());

ins.eachLine{ line -> System.out.println(line); } }

15

Page 23: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".getBytes()); ins.eachLine { line -> System.out.println(line); } }

16

Page 24: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".getBytes()); ins.eachLine { line -> System.out.println(line); } }

17

Page 25: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".getBytes()); ins.eachLine { line -> System.out.println(line); } } ポイント: プロパティア

クセス記法でgetterを呼び出せる

17

Page 26: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes); ins.eachLine { line -> System.out.println(line); } }

18

Page 27: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes); ins.eachLine { line -> System.out.println(line); } } ポイント: System.out.println,

Ssytem.out.printなどはprintln,printと書ける

18

Page 28: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes); ins.eachLine { line -> println(line); } }

19

Page 29: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes); ins.eachLine { line -> println(line); } } ポイント: クロージャの引数

が1つなら、暗黙のクロージャ引数itで参照できる。

19

Page 30: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes); ins.eachLine { println(it); } }

20

Page 31: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes); ins.eachLine { println(it); } } ポイント: 行末のセミコロ

ンは多くの場合省略可

20

Page 32: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes) ins.eachLine { println(it) } }

21

Page 33: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write("GET / HTTP/1.0\n\n".bytes) ins.eachLine { println(it) } } ポイント: 式文のトップレ

ベルがメソッド呼び出しなら引数の括弧は省略可能

21

Page 34: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

コード例: Groovy!

new Socket("www.java-users.jp", 80).withStreams { ins, outs -> outs.write "GET / HTTP/1.0\n\n".bytes ins.eachLine { println it } }

22

Page 35: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

HTTPに限ればprintln new URL("http://www.java-users.jp").text

23

Page 36: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

HTTPに限ればprintln new URL("http://www.java-users.jp").text

JavaからGroovyに書き直すと、大抵数分の1程度にはなる。

マップリテラル、リストリテラルなどもコードが短くなる要因として良く示されるが、Java 7で採用されるので割愛。

23

Page 37: Easy Going Groovy 2nd season on DevLOVE

設定ファイル記述/DSL

GantGradleSpock,EasyB

先進的な取り組み

GparsGroovy++

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Groovy Eco System

既存ツールへの組み込み

GMaven,Maven3HudsonFreeMind

付属ライブラリ群

GSQLSwingBuilderMarkupBuilder

フレームワーク

Grails(Web)GSP,GORM

Griffon(GUI)

Groovy

Gaelyk

JBoss

24

Page 38: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Groovyを使うとこんなに便利

25

Page 39: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

ケース1

開発時に使用するツールとしてメンバーの大半はJava開発者なのでJavaで書きたい

やりたいこと

指定ファイルをbzip2圧縮してhttpファイルアップロード

26

Page 40: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

でも…Javaだと作成したプログラムをメンバーに配布するのが面倒!コンパイルして

実行可能Jarに?依存Jar群(commonsのjarとか)をダウンロードしてもらって

いやいっそ、Mavenでpom書いて

いっそ、RubyやPerlで… orz

27

Page 41: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時こそGroovyですよ!@Grab('net.sourceforge.htmlunit:htmlunit:2.8')import com.gargoylesoftware.htmlunit.WebClient;

// AntのBzip2タスクを使って圧縮new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2")// HtmlUnitを使ってファイルアップロードurl = "http://pukiwiki.example.com/index.php?plugin=attach&pcmd=upload&page=test"page = new WebClient().getPage(url)file = page.getElementById('_p_attach_file')file.valueAttribute = args[0]+".bz2"page.getByXPath("//input[@value='アップロード']")[0].click()

28

Page 42: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時こそGroovyですよ!@Grab('net.sourceforge.htmlunit:htmlunit:2.8')import com.gargoylesoftware.htmlunit.WebClient;

// AntのBzip2タスクを使って圧縮new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2")// HtmlUnitを使ってファイルアップロードurl = "http://pukiwiki.example.com/index.php?plugin=attach&pcmd=upload&page=test"page = new WebClient().getPage(url)file = page.getElementById('_p_attach_file')file.valueAttribute = args[0]+".bz2"page.getByXPath("//input[@value='アップロード']")[0].click()

Java資産の有効活用

(HtmlUnit, Ant)28

Page 43: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時こそGroovyですよ!@Grab('net.sourceforge.htmlunit:htmlunit:2.8')import com.gargoylesoftware.htmlunit.WebClient;

// AntのBzip2タスクを使って圧縮new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2")// HtmlUnitを使ってファイルアップロードurl = "http://pukiwiki.example.com/index.php?plugin=attach&pcmd=upload&page=test"page = new WebClient().getPage(url)file = page.getElementById('_p_attach_file')file.valueAttribute = args[0]+".bz2"page.getByXPath("//input[@value='アップロード']")[0].click()

依存ライブラリの実行時自動取得

Java資産の有効活用

(HtmlUnit, Ant)28

Page 44: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時こそGroovyですよ!@Grab('net.sourceforge.htmlunit:htmlunit:2.8')import com.gargoylesoftware.htmlunit.WebClient;

// AntのBzip2タスクを使って圧縮new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2")// HtmlUnitを使ってファイルアップロードurl = "http://pukiwiki.example.com/index.php?plugin=attach&pcmd=upload&page=test"page = new WebClient().getPage(url)file = page.getElementById('_p_attach_file')file.valueAttribute = args[0]+".bz2"page.getByXPath("//input[@value='アップロード']")[0].click()

コンパイル不要

依存ライブラリの実行時自動取得

Java資産の有効活用

(HtmlUnit, Ant)28

Page 45: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

もうちょっと詳しくー1@Grab('net.sourceforge.htmlunit:htmlunit:2.8')import com.gargoylesoftware.htmlunit.WebClient;

GrapeGroovyスクリプト用の依存Jarのダウンロード・管理機構Apache IvyベースMavenリポジトリも扱える

module指定group指定 versoin指定

29

Page 46: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

もうちょっと詳しく-2// AntのBzip2タスクを使って圧縮new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2")

argsはコマンドライン引数を表す暗黙引数Antは組み込まれている他に、JUnit, commons-logging, commons-cli, jlineなどがGroovy配布パッケージに同梱

30

Page 47: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

ケース2

開発システムに含まれるJavaコードで処理した結果を投入する必要があるとする

やりたいこと

指定したCSVファイルの内容を処理してDBテーブルに投入DBにクエリをかける

31

Page 48: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

ケース2

開発システムに含まれるJavaコードで処理した結果を投入する必要があるとする

やりたいこと

指定したCSVファイルの内容を処理してDBテーブルに投入DBにクエリをかける

東京,35676000,日本 ニューヨーク,19040000,アメリカ合衆国 ブリッジポート=スタンフォード,1018000,アメリカ合衆国 フィラデルフィア,5492000,アメリカ合衆国

cities.csv

31

Page 49: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

ケース2

開発システムに含まれるJavaコードで処理した結果を投入する必要があるとする

やりたいこと

指定したCSVファイルの内容を処理してDBテーブルに投入DBにクエリをかける

東京,35676000,日本 ニューヨーク,19040000,アメリカ合衆国 ブリッジポート=スタンフォード,1018000,アメリカ合衆国 フィラデルフィア,5492000,アメリカ合衆国

cities.csv

都市名, 人口, 国名

31

Page 50: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時にはGroovyですよ!@Grab('com.h2database:h2:1.2.143')@GrabConfig(systemClassLoader=true)import groovy.sql.Sqlsql = Sql.newInstance("jdbc:h2:cities")sql.execute """ CREATE TABLE Cities (                  id INT IDENTITY PRIMARY KEY, name VARCHAR,                  population DECIMAL(10), country VARCHAR)"""cities = sql.dataSet("Cities")new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理  cities.add(name:f1, population:f2, country:f3)}assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

32

Page 51: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時にはGroovyですよ!@Grab('com.h2database:h2:1.2.143')@GrabConfig(systemClassLoader=true)import groovy.sql.Sqlsql = Sql.newInstance("jdbc:h2:cities")sql.execute """ CREATE TABLE Cities (                  id INT IDENTITY PRIMARY KEY, name VARCHAR,                  population DECIMAL(10), country VARCHAR)"""cities = sql.dataSet("Cities")new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理  cities.add(name:f1, population:f2, country:f3)}assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

32

H2 DBも自動でダウンロード

Page 52: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時にはGroovyですよ!@Grab('com.h2database:h2:1.2.143')@GrabConfig(systemClassLoader=true)import groovy.sql.Sqlsql = Sql.newInstance("jdbc:h2:cities")sql.execute """ CREATE TABLE Cities (                  id INT IDENTITY PRIMARY KEY, name VARCHAR,                  population DECIMAL(10), country VARCHAR)"""cities = sql.dataSet("Cities")new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理  cities.add(name:f1, population:f2, country:f3)}assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

where句の自動生成

32

H2 DBも自動でダウンロード

Page 53: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時にはGroovyですよ!@Grab('com.h2database:h2:1.2.143')@GrabConfig(systemClassLoader=true)import groovy.sql.Sqlsql = Sql.newInstance("jdbc:h2:cities")sql.execute """ CREATE TABLE Cities (                  id INT IDENTITY PRIMARY KEY, name VARCHAR,                  population DECIMAL(10), country VARCHAR)"""cities = sql.dataSet("Cities")new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理  cities.add(name:f1, population:f2, country:f3)}assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

where句の自動生成

insertも簡単

32

H2 DBも自動でダウンロード

Page 54: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

そんな時にはGroovyですよ!@Grab('com.h2database:h2:1.2.143')@GrabConfig(systemClassLoader=true)import groovy.sql.Sqlsql = Sql.newInstance("jdbc:h2:cities")sql.execute """ CREATE TABLE Cities (                  id INT IDENTITY PRIMARY KEY, name VARCHAR,                  population DECIMAL(10), country VARCHAR)"""cities = sql.dataSet("Cities")new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理  cities.add(name:f1, population:f2, country:f3)}assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

where句の自動生成

insertも簡単

Javaコードは自由に呼べる

32

H2 DBも自動でダウンロード

Page 55: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

もうちょっと詳しく-3@Grab('com.h2database:h2:1.2.143')@GrabConfig(systemClassLoader=true)import groovy.sql.Sql

Grabは、実行時ダウンロード&クラスパスへの追加デフォルトだとGroovyClassLoaderで読み込まれるClass.forName()で読み込めるように、システムクラスローダーを指定

jdbcの初期化で必要

33

Page 56: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

もうちょっと詳しく-4cities = sql.dataSet("Cities")new File("cities.csv").splitEachLine(",") { f1, f2, f3 -> // 何らかの処理  cities.add(name:f1, population:f2, country:f3)}

DataSetは簡易なSQLインターフェースsplitEachLineはGDKメソッドaddでinsertフィールド名はMapのキーで指定

34

Page 57: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

もうちょっと詳しく-5cities = sql.dataSet("Cities") :assert cities.findAll{ it.country=="日本" && it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

上は以下と同じcities = sql.dataSet("Cities") :assert cities.findAll{ it.country=="日本" } .findAll{ it.population>1000000 }.rows()*.name == ['東京', '大阪=神戸 (阪神)', '京都', '名古屋', '福岡']

findAllの式は遅延評価されて最後にSelectが1回実行。

35

Page 58: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Groovy導入に向けて

36

Page 59: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.2437

Super Glue: Javaのコンポーネントやフレームワークを、Groovyを糊(glue)としてつなぐLiquid Heart: 中核となるロジックだけをGroovy/DSLで書けるようにするKeyhole Surgery: 実行時にGroovyスクリプトを接続できる小さな口を用意しておくSmart Configuration: 設定ファイルとしてGroovyスクリプトを使うUnlimited Openness: 全部Groovyで書いちゃう :)House-elf Script: 周辺の各種支援スクリプトをGroovyで書くPrototype: プロトタイプをGroovyで作る

7つのGroovy利用パターン

http://d.hatena.ne.jp/ksky/20090618/p1

update

Page 60: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.2437

Super Glue: Javaのコンポーネントやフレームワークを、Groovyを糊(glue)としてつなぐLiquid Heart: 中核となるロジックだけをGroovy/DSLで書けるようにするKeyhole Surgery: 実行時にGroovyスクリプトを接続できる小さな口を用意しておくSmart Configuration: 設定ファイルとしてGroovyスクリプトを使うUnlimited Openness: 全部Groovyで書いちゃう :)House-elf Script: 周辺の各種支援スクリプトをGroovyで書くPrototype: プロトタイプをGroovyで作る

7つのGroovy利用パターン

http://d.hatena.ne.jp/ksky/20090618/p1

オススメ!

update

Page 61: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

事例集…g100pon(1)実用スクリプト例の集成Groovyスクリプト100本切りJGGUG合宿2010の企画実用スクリプト群100本をよってたかって作っちゃえ!本成果は、2010/11/09 JGGUG主催G*ワークショップにて報告実施済み

38

http://kokucheese.com/event/index/5267/

Page 62: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

g100pon(2)

39

http://bit.ly/g5iE0m

Page 63: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

インストールも簡単

40

Page 64: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Windows Installer

41

Page 65: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

MacOSX / LinuxMacport install groovybrew install groovy

Linuxapt-get install groovy

42

update

Page 66: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

GroovyServhttp://kobo.github.com/groovyserv/

43

Page 67: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

GroovyServって何?Groovyスクリプト起動が爆速に!(x10~20)Groovy処理系を常駐起動(groovyserver)Groovyスクリプト実行は、処理をgroovyserverに移譲する小さなCプログラムで行う(groovyclient)server~client間はsocket通信Apache 2 Licenseでソース公開MacOS X/Linux/Windows用バイナリ有

44

Page 68: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

構成図

JavaVM

Shell Environment

TCP/IPgroovyserver

groovyclientCtrl-C

stdin

stdou

tstd

err

exit status

CLASSPATH env

cmd. line args

File System

AuthenticationCookie File

User GroovySrcipt

System.in System.outSYstem.err

45

Page 69: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

通常のGroovy実行Shell Environment

JavaVM

groovyCtrl-C

stdin

stdou

t

CLASSPATH env

cmd. line args

File System

User GroovySrcipt

System.in System.outSYstem.err

stderr

exit status

46

Page 70: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

起動速度向上効果(Win)

groovy -e “println ‘hello world’”実行時間(sec) 比率

normal groovy 3.041 1.0

Installer版groovy 1.262 2.4

groovyclient(C版) 0.155 19.6

groovyclient(Ruby版) 0.193 15.8

•Groovy 1.7.3, GroovyServ 0.4-SNAPSHOT, WinXP SP3,Core2Duo 2GHz,JDK1•timeコマンドでreal時間を計測。10回実行した平均。

19.6倍

Page 71: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

起動速度向上効果(Mac)

groovy -e “println ‘hello world’”実行時間(sec) 比率

normal groovy 1.112 1.0

Mac Ports版groovy(1.7.2) 0.321 3.5

groovyclient(C版) 0.031 35.8

groovyclient(Ruby版) 0.041 27.1•Groovy 1.7.3, GroovyServ 0.4-SNAPSHOT, MacOSX 10.6.3, MacBook Core2duo 2.53GHz, JDK1.6.0u20•timeコマンドでreal時間を計測。10回実行した平均。

35.8倍

48

Page 72: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

実行速度の向上効果(Win)

実行時間(msec)groovy(Client VM) 593.7

groovy(Server VM) 243.8

groovyclient(Client VM) 454.6

groovyclient(Server VM) 197.0

for (i=0; i<1000000; i++) {};

•Groovy 1.7.3, GroovyServ 0.4, Windows XP SP3(cygwin 1.7.5),Core2duo 2.00GHz, JDK1.6.0u13•time コマンドで real 時間を計測。十回実行した平均。

Server VMの良いところ取り利用

49

Page 73: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

応用例: scalacの高速化

実行時間(msec) scalacとの比率scalac 6.6 1.0

fsc 1.2 5.5

scalac/GroovyServ 1.1 6.6

fsc/GroovyServ 0.4 16.5

for (i=0; i<1000000; i++) {};

Groovy限定ではない

50

Page 74: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Groovyスクリプト開発Groovyは本来PerlやRubyにも対抗しうる機能を持ったスクリプト言語

ワンライナー用オプション(-e, -p, -n, -i.bak, -l)

フィルタ、パイプ

コンパイル不要

でも、レスポンス悪いとやる気が出ないトライ&エラーを繰り返すため

➡ そこで、GroovyServですよ

51

Page 75: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

groovy-flymake

GroovyServと組合せてgroovycをバックグラウンドで高速実行

http://gist.github.com/63099252

Page 76: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

利用者からの声(>▽<)Dierk König

thanks for the great work on groovyserv!I use it everyday and enjoy its performance.I also give it lots of credit in my workshops and talks.(you may have recognized the additional hackergarten screencast.)

53

Guillaume LaforgeThat sounds like a great release to me!Congratulations to the team!

Hamlet D’ArcyGreat work, this thing really helps.

Jochen “blackdrag” Theodorou

I was thinking about maybe making GroovyServ the

default way of how groovy executes a script.

new!

Page 77: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

利用者からの声(>▽<)Dierk König

thanks for the great work on groovyserv!I use it everyday and enjoy its performance.I also give it lots of credit in my workshops and talks.(you may have recognized the additional hackergarten screencast.)

53

Guillaume LaforgeThat sounds like a great release to me!Congratulations to the team!

Hamlet D’ArcyGreat work, this thing really helps.

Jochen “blackdrag” Theodorou

I was thinking about maybe making GroovyServ the

default way of how groovy executes a script.

※個人の感想です。実際の効果には差違が生じる可能性があります。

new!

Page 78: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

苦労しているところ本当は1つのJVMを、スクリプトごとに占有しているように見せかける並行実行は不可避(Groovyのフィルタスクリプトをpipeで繋いで実行)

異なるクラスローダで読み込ませる

stdin/stdout/strerrを多重化して1ソケットで相互転送

カレントディレクトリをJNA(Java Native Access)で変更

System.exit()をトラップしてexit statusをクライアントに転送

セキュリティ対策秘密のクッキーファイルをserver-clientで共有し、ファイルシステムのアクセス制御に基づいた保護

54

Page 79: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

効果が薄い用途サーバ開発GUIアプリケーションCUIアプリでシェルのように起動して操作するものcronで定期的に起動するもの

➡ 起動レスポンスが重要ではないもの

55

Page 80: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Groovy 1.8.0の新機能(予定含む)

56

Page 81: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

GEP3 ..メソッド呼び出しの括弧省略

Groovy 1.7.xm1(a1).m2(a2).m3(a3)

Groovy 1.8.xでは以下のように書けるm1 a1 m2 a2 m3 a3

57

GEP ‥ Groovy Enhancement Proposal

Page 82: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

日本語プログラミング言語Groovy(GEP3の応用例)

まず 100 の 平方根 を 表示するそして 1 と 2 と 3 のうち、 奇数 それぞれに 対して { それ ->  二倍にした それ を 表示する}ついでに 1 から 100 のうち、 二の倍数.かつ(三の倍数) を 表示する

最後に 1 から 100 のうち、 二の倍数.かつ(三の倍数) それぞれに 対して { それ ->  とりあえず それ + "は6の倍数です" を 表示する}それはそれとして "以上" を 表示する

10.026[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]6は6の倍数です12は6の倍数です

18は6の倍数です24は6の倍数です: 96は6の倍数です以上

http://d.hatena.ne.jp/uehaj/20100919/1284906117

58

Page 83: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

日本語プログラミング言語Groovy(GEP3なしの時)

まず(100).の(平方根).を(表示する)そして(1).と(2).と(3).のうち、(奇数).それぞれに(対して({それ ->  二倍にした(それ).を(表示する)}))ついでに(1).から(100).のうち、((二の倍数.かつ(三の倍数))).を(表示する)

最後に(1).から(100).のうち、(二の倍数.かつ(三の倍数)).それぞれに(対して({ それ ->  とりあえず(それ + "は6の倍数です").を(表示する)}))それはそれとして("以上").を(表示する)

59

Page 84: Easy Going Groovy 2nd season on DevLOVE

int fib (int n) {    if (n<=1) return 1    return fib(n-1) + fib(n-2)}

60Slide # DevLOVE ぐるぐるGroovy 2011.1.24

プリミティブ演算の高速化(1)groovycでコンパイル、

jadでデコンパイルしてみる

new

Page 85: Easy Going Groovy 2nd season on DevLOVE

int fib (int n) {    if (n<=1) return 1    return fib(n-1) + fib(n-2)}

60Slide # DevLOVE ぐるぐるGroovy 2011.1.24

プリミティブ演算の高速化(1)

Groovy 1.7.5public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(ScriptBytecodeAdapter.compareLessThanEqual(DefaultTypeTransformation.box(n), $const$0))        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType($const$0, $get$$class$java$lang$Integer()));    else        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call(DefaultTypeTransformation.box(n), $const$0)), acallsite[3].callCurrent(this, acallsite[4].call(DefaultTypeTransformation.box(n), $const$1))), $get$$class$java$lang$Integer()));}

groovycでコンパイル、jadでデコンパイルしてみる

new

Page 86: Easy Going Groovy 2nd season on DevLOVE

int fib (int n) {    if (n<=1) return 1    return fib(n-1) + fib(n-2)}

60Slide # DevLOVE ぐるぐるGroovy 2011.1.24

プリミティブ演算の高速化(1)

Groovy 1.7.5public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(ScriptBytecodeAdapter.compareLessThanEqual(DefaultTypeTransformation.box(n), $const$0))        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType($const$0, $get$$class$java$lang$Integer()));    else        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call(DefaultTypeTransformation.box(n), $const$0)), acallsite[3].callCurrent(this, acallsite[4].call(DefaultTypeTransformation.box(n), $const$1))), $get$$class$java$lang$Integer()));}

groovycでコンパイル、jadでデコンパイルしてみる

Groovy 1.8.0 beta 3public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(!ScriptBytecodeAdapter.isOrigInt())        if(ScriptBytecodeAdapter.compareLessThanEqual((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(1)))            return 1;        else            return DefaultTypeTransformation.intUnbox(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(1))), acallsite[3].callCurrent(this, acallsite[4].call((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(2)))));    if(n <= 1)        return 1;    else        return fib(n - 1) + fib(n - 2);}

new

Page 87: Easy Going Groovy 2nd season on DevLOVE

int fib (int n) {    if (n<=1) return 1    return fib(n-1) + fib(n-2)}

60Slide # DevLOVE ぐるぐるGroovy 2011.1.24

プリミティブ演算の高速化(1)

Groovy 1.7.5public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(ScriptBytecodeAdapter.compareLessThanEqual(DefaultTypeTransformation.box(n), $const$0))        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType($const$0, $get$$class$java$lang$Integer()));    else        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call(DefaultTypeTransformation.box(n), $const$0)), acallsite[3].callCurrent(this, acallsite[4].call(DefaultTypeTransformation.box(n), $const$1))), $get$$class$java$lang$Integer()));}

groovycでコンパイル、jadでデコンパイルしてみる

Groovy 1.8.0 beta 3public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(!ScriptBytecodeAdapter.isOrigInt())        if(ScriptBytecodeAdapter.compareLessThanEqual((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(1)))            return 1;        else            return DefaultTypeTransformation.intUnbox(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(1))), acallsite[3].callCurrent(this, acallsite[4].call((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(2)))));    if(n <= 1)        return 1;    else        return fib(n - 1) + fib(n - 2);}

new

Page 88: Easy Going Groovy 2nd season on DevLOVE

int fib (int n) {    if (n<=1) return 1    return fib(n-1) + fib(n-2)}

60Slide # DevLOVE ぐるぐるGroovy 2011.1.24

プリミティブ演算の高速化(1)

Groovy 1.7.5public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(ScriptBytecodeAdapter.compareLessThanEqual(DefaultTypeTransformation.box(n), $const$0))        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType($const$0, $get$$class$java$lang$Integer()));    else        return DefaultTypeTransformation.intUnbox((Integer)ScriptBytecodeAdapter.castToType(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call(DefaultTypeTransformation.box(n), $const$0)), acallsite[3].callCurrent(this, acallsite[4].call(DefaultTypeTransformation.box(n), $const$1))), $get$$class$java$lang$Integer()));}

groovycでコンパイル、jadでデコンパイルしてみる

Groovy 1.8.0 beta 3public int fib(int n){    CallSite acallsite[] = $getCallSiteArray();    if(!ScriptBytecodeAdapter.isOrigInt())        if(ScriptBytecodeAdapter.compareLessThanEqual((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(1)))            return 1;        else            return DefaultTypeTransformation.intUnbox(acallsite[0].call(acallsite[1].callCurrent(this, acallsite[2].call((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(1))), acallsite[3].callCurrent(this, acallsite[4].call((Integer)DefaultTypeTransformation.box(n), (Integer)DefaultTypeTransformation.box(2)))));    if(n <= 1)        return 1;    else        return fib(n - 1) + fib(n - 2);}

if(n <= 1)    return 1; else    return fib(n - 1) + fib(n - 2);

new

Page 89: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

プリミティブ演算の高速化(2)

61

所要時間(ns) Java を1とした比率

Groovy 1.7.5 1,639,852,000 66.46

Groovy 1.8.0 beta 3 65,497,000 2.65

Java(OpenJDK 1.7) 24,672,000 1.0

long begin = System.nanoTime();FibJava foo = new FibJava();int result = foo.fib(32); //インスタンスメソッドであることが今は重要long end = System.nanoTime();System.out.println("Elapsed time: " + (end - begin) + "ns");

• MacOSX 10.6.3, MacBook Core2duo 2.53GHz,openjdk version "1.7.0-internal"

new

Page 90: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

アノテーション引数にクロージャ指定

例)GContract…DbC(契約による設計)をGroovyに導入

http://github.com/andresteingress/gcontracts/wiki

@Invariant({ elements != null }) class Stack {      private List elements      @Ensures({ is_empty() })     public Stack()  {         elements = []     }      @Requires({ preElements?.size() > 0 })     @Ensures({ !is_empty() })     public Stack(List preElements)  {         elements = preElements     }

      def boolean is_empty()  {         elements.isEmpty()     }      @Requires({ !is_empty() })     def last_item()  {         elements.last()     }      def count() {         elements.size()     }

62

Page 91: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

多数のAST変換追加@Log/@Log4j/@Slf4j/@Commons,@Field,@PackageScope,@Synchronized,@InheritConstructors,@IndexedProperties,@AutoClone,@AutoExternalize,@Canonical,@EqualsAndHashCode,@ToString,@TupleConstructor,@ThreadInterrupt,@TimedInterrupt,@ConditionalInterrupt,@WithReadLock,@WithWriteLock

http://canoo.com/blog/2010/09/20/log-groovys-new-and-extensible-logging-conveniences/

63

update

Page 92: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

@Logアノテーション@Log … オーバーヘッドなしロガーのインジェクション(java.util.Logger)@Log4j…〃(Log4j)@Slf4j…〃(Slf4j)@Commons…〃(Commons Logger)

http://canoo.com/blog/2010/09/20/log-groovys-new-and-extensible-logging-conveniences/

import groovy.util.logging.Log @Log class MyClass {     def invoke() {         log.info('... an info message')         log.fine('... a fine message')     } }

64

ログレベルが一致しない場合、ログ出力されないだけではなく引数が評価されない

Page 93: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

その他

65

明示的末尾再帰Closure#trampoline()クロージャ合成a >> b // b(a())a << b // a(b())クロージャメモ化(Memoization)JSONサポート(Parser,Builder)

New!

Page 94: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

まとめ

66

JavaプログラマにとってGroovyは超便利Groovyは進化し続けている!

1/31のJGGUG G*ワークショップ@渋谷IBMイノベーション・センター 受付中!! http://kokucheese.com/event/index/5267/

「Groovy&Grails exchange 2010@Londonへ行ってきた報告!」by

tyama, tamada (ニューキャスト)

「GradleによるG*なビルドシステムの構築」 by 林政利(LITERAL-ICE)

Page 95: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

まとめ

66

JavaプログラマにとってGroovyは超便利Groovyは進化し続けている!

場合によっては「使ったほうが良い」を越え「 使うべき」レベルか

1/31のJGGUG G*ワークショップ@渋谷IBMイノベーション・センター 受付中!! http://kokucheese.com/event/index/5267/

「Groovy&Grails exchange 2010@Londonへ行ってきた報告!」by

tyama, tamada (ニューキャスト)

「GradleによるG*なビルドシステムの構築」 by 林政利(LITERAL-ICE)

Page 96: Easy Going Groovy 2nd season on DevLOVE

Slide # DevLOVE ぐるぐるGroovy 2011.1.24

Q&A

67