Java x Groovy: improve your java development life

3,573 views

Published on

slides for Oracle java developer workshop #2

Published in: Technology, News & Politics
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,573
On SlideShare
0
From Embeds
0
Number of Embeds
651
Actions
Shares
0
Downloads
25
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Java x Groovy: improve your java development life

  1. 1. Java x Groovyで 開発効率を高めよう Java Developer Workshop #2 日本Grails Groovyユーザ会 上原 潤二 2011.12.12011年12月1日木曜日
  2. 2. 自己紹介 上原潤二(@uehaj) NTTソフトウェア株式会社 JGGUG運営委員 プログラミングGROOVY(技術評 論社)共著 Grails徹底入門(翔泳社)共著 ブログ「Grな日々」 GroovyServ, LispBuilder, GVM 開発者2011年12月1日木曜日
  3. 3. 本日皆さんに伝えたいこと Groovyとは何か? Groovyは簡単なのか? Groovyは便利なのか? JavaプログラマにとってGroovyと は何か? 32011年12月1日木曜日
  4. 4. Groovyとは何か Java VM上で動作する動的なスクリプト言語 構文はJavaと 上位互換 ほぼ プラットフォームやセキュリティモデルは全く 同じ ユニークな特徴: Javaと共存・併用するための言語 主要開発者はVMWare社(Spring Source)に所属 42011年12月1日木曜日
  5. 5. コード例1: HelloWorld.java __ public class HelloWorld {     public static void main(String[] args) {         System.out.println("Hello world");     } } 52011年12月1日木曜日
  6. 6. コード例1: HelloWorld.groovy public class HelloWorld {     public static void main(String[] args) {         System.out.println("Hello world");     } } 62011年12月1日木曜日
  7. 7. コード例1: HelloWorld.groovy public class HelloWorld {     public static void main(String[] args) {         System.out.println("Hello world");     } } Javaソースコードの拡張子.java を.groovyに変更するだけで groovyコードとして実行できる。 62011年12月1日木曜日
  8. 8. コード例1: hello.groovy println "hello world" 72011年12月1日木曜日
  9. 9. コード例1: hello.groovy println "hello world" Groovyでは以下が省略可能: main,クラス定義,文末のセミコロ ン, System.out,メソッド呼び出し の括弧,(例外宣言,静的型宣言, import宣言) etc.. 72011年12月1日木曜日
  10. 10. Groovyは何で無いか 82011年12月1日木曜日
  11. 11. Groovyは何で無いか 別言語をJVMにポーティングしたもので はない 82011年12月1日木曜日
  12. 12. Groovyは何で無いか 別言語をJVMにポーティングしたもので はない ➡JVM以外では動かない 82011年12月1日木曜日
  13. 13. Groovyは何で無いか 別言語をJVMにポーティングしたもので はない ➡JVM以外では動かない Next Javaではない 82011年12月1日木曜日
  14. 14. Groovyは何で無いか 別言語をJVMにポーティングしたもので はない ➡JVM以外では動かない Next Javaではない ➡Javaを駆逐しない・パラダイムシフトしない 82011年12月1日木曜日
  15. 15. Groovyは何で無いか 別言語をJVMにポーティングしたもので はない ➡JVM以外では動かない Next Javaではない ➡Javaを駆逐しない・パラダイムシフトしない 過去のOSSプロジェクトではない 82011年12月1日木曜日
  16. 16. Groovyは何で無いか 別言語をJVMにポーティングしたもので はない ➡JVM以外では動かない Next Javaではない ➡Javaを駆逐しない・パラダイムシフトしない 過去のOSSプロジェクトではない ➡活発な開発と意欲的な機能拡張が続いている 82011年12月1日木曜日
  17. 17. Groovyの特徴4つ Javaと親和性 簡潔 が高い 高機能 柔軟 92011年12月1日木曜日
  18. 18. Groovyの特徴4つ Javaと親和性 簡潔 が高い 本日は上記2つの特徴を中心に紹介し ます。 高機能 柔軟 102011年12月1日木曜日
  19. 19. 簡潔 11 http://www.flickr.com/photos/dan_culleton/4905300673/2011年12月1日木曜日
  20. 20. 例:ワードカウント処理 テキストファイル中の単語の出現回数 を数える $ cat input.txt That that is is that that is not is not is that it it is $ java WordCount input.txt 1: That 2: not 2: it 4: that 6: is 122011年12月1日木曜日
  21. 21. ワードカウント処理(Java) import java.util.Comparator;      Object[] list = entrySet.toArray(); import java.util.HashMap;     Comparator comp = new Comparator(){ import java.util.Map;        public int compare(Object o1, Object o2) import java.util.Set; { import java.util.List;          Map.Entry<String, Integer> e1 = import java.util.Arrays; (Map.Entry<String, Integer>) o1; import java.io.FileReader;          Map.Entry<String, Integer> e2 = import java.io.BufferedReader; (Map.Entry<String, Integer>) o2; import java.io.FileNotFoundException;         return e1.getValue() - e2.getValue(); import java.io.IOException;         }       }; public class WordCount {       Arrays.sort(list, comp);   @SuppressWarnings(value = "unchecked")       for (Object it: list) {   public static void main(String[] args) {         Map.Entry<String, Integer> entry =     FileReader fis = null; (Map.Entry<String, Integer>)it;     BufferedReader br = null;         System.out.println(entry.getValue() + ":     try { "+entry.getKey());       HashMap<String, Integer> map = new       } HashMap<String, Integer>();     }       fis = new FileReader(args[0]);     catch (IOException e) {       br = new BufferedReader(fis);       try {if (br != null) br.close();}catch       String line; (IOException ioe){}       while ((line = br.readLine()) != null) {       try {if (fis != null)fis.close();}catch         for (String it: line.split("W+")) { (IOException ioe){}          map.put(it, (map.get(it)==null) ? 1 :       e.printStackTrace(); (map.get(it) + 1));     }         }   }       }      Set<Map.Entry<String, Integer>> entrySet = } 48行 map.entrySet(); 132011年12月1日木曜日
  22. 22. ワードカウント処理(Groovy)def words = new File(args[0]).text.split(/W+/)words.countBy{it}.entrySet().sort{it.value}.each { println "${it.value}: ${it.key}"} 4行 142011年12月1日木曜日
  23. 23. .textdef words = new File(args[0]).text.split(/W+/)words.countBy{it}.entrySet().sort{it.value}.each { .getText()の略記法 println "${it.value}: ${it.key}"} File#getText()はJava APIに 対して追加されたGDKメソッド ファイル内容の全体を1つの Stringとして返す2011年12月1日木曜日
  24. 24. GDKメソッド Java標準APIクラスにメソッドを追加 java.lang.Stringを例にとると、 Java標準APIは、65個メソッド GDKでは、91個のメソッド追加 asType(Class c) execute(List envp, getAt(Collection padLeft(Number replaceFirst(Pattern toInteger() bitwiseNegate() File dir) indices) numberOfChars) pattern, Closure toList() capitalize() expand() getChars() padRight(Number closure) toLong() center(Number expand(int tabStop) isAllWhitespace() numberOfChars, reverse() toSet() numberOfChars, expandLine(int isBigDecimal() String padding) size() toShort() String padding) tabStop) isBigInteger() padRight(Number split() toURI() center(Number find(String regex) isCase(Object numberOfChars) splitEachLine(String toURL() numberOfChars) find(Pattern pattern) switchValue) plus(Object value) regex, Closure tokenize(String contains(String text) find(String regex, isDouble() previous() closure) token) count(String text) Closure closure) isFloat() readLines() splitEachLine tokenize(Character decodeBase64() find(Pattern pattern, isInteger() replaceAll(Pattern (Pattern pattern, token) denormalize() Closure closure) isLong() pattern, String Closure closure) tokenize() eachLine(Closure findAll(String regex) isNumber() replacement) stripIndent() tr(String sourceSet, closure) findAll(Pattern leftShift(Object replaceAll(String stripIndent(int String eachLine(int pattern) value) regex, Closure numChars) replacementSet) firstLine, Closure findAll(String regex, matches(Pattern closure) stripMargin() unexpand() closure) Closure closure) pattern) replaceAll(Pattern stripMargin(String unexpand(int eachMatch(String findAll(Pattern minus(Object target) pattern, Closure marginChar) tabStop) regex, Closure pattern, Closure multiply(Number closure) stripMargin(char unexpandLine(int closure) closure) factor) replaceFirst(Pattern marginChar) tabStop) eachMatch(Pattern getAt(int index) next() pattern, String toBigDecimal() pattern, Closure getAt(IntRange normalize() replacement) toBigInteger() closure) range) padLeft(Number replaceFirst(String toBoolean() execute() getAt(EmptyRange numberOfChars, regex, Closure toCharacter() execute(String[] range) String padding) closure) toDouble() envp, File dir) getAt(Range range) toFloat() 162011年12月1日木曜日
  25. 25. GDKメソッド Java標準APIクラスにメソッドを追加 java.lang.Stringを例にとると、 Java標準APIは、65個メソッド GDKでは、91個のメソッド追加 asType(Class c) execute(List envp, getAt(Collection padLeft(Number replaceFirst(Pattern toInteger() bitwiseNegate() File dir) indices) numberOfChars) pattern, Closure toList() capitalize() expand() getChars() padRight(Number closure) toLong() center(Number expand(int tabStop) isAllWhitespace() numberOfChars, reverse() toSet() “ls”.execute() numberOfChars, String padding) center(Number expandLine(int tabStop) find(String regex) isBigDecimal() isBigInteger() isCase(Object String padding) padRight(Number numberOfChars) size() split() splitEachLine(String toShort() toURI() toURL() " lsコマンドを実行(Processが返る) numberOfChars) find(Pattern pattern) switchValue) plus(Object value) regex, Closure tokenize(String contains(String text) find(String regex, isDouble() previous() closure) token) count(String text) Closure closure) isFloat() readLines() splitEachLine tokenize(Character decodeBase64() find(Pattern pattern, isInteger() replaceAll(Pattern (Pattern pattern, token) denormalize() Closure closure) isLong() pattern, String Closure closure) tokenize() eachLine(Closure findAll(String regex) isNumber() replacement) stripIndent() tr(String sourceSet, closure) findAll(Pattern leftShift(Object replaceAll(String stripIndent(int String eachLine(int pattern) value) regex, Closure numChars) replacementSet) firstLine, Closure findAll(String regex, matches(Pattern closure) stripMargin() unexpand() closure) Closure closure) pattern) replaceAll(Pattern stripMargin(String unexpand(int eachMatch(String findAll(Pattern minus(Object target) pattern, Closure marginChar) tabStop) regex, Closure pattern, Closure multiply(Number closure) stripMargin(char unexpandLine(int closure) closure) factor) replaceFirst(Pattern marginChar) tabStop) eachMatch(Pattern getAt(int index) next() pattern, String toBigDecimal() pattern, Closure getAt(IntRange normalize() replacement) toBigInteger() closure) range) padLeft(Number replaceFirst(String toBoolean() execute() getAt(EmptyRange numberOfChars, regex, Closure toCharacter() execute(String[] range) String padding) closure) toDouble() envp, File dir) getAt(Range range) toFloat() 162011年12月1日木曜日
  26. 26. GDKメソッド Java標準APIクラスにメソッドを追加 java.lang.Stringを例にとると、 Java標準APIは、65個メソッド GDKでは、91個のメソッド追加 asType(Class c) execute(List envp, getAt(Collection padLeft(Number replaceFirst(Pattern toInteger() bitwiseNegate() File dir) indices) numberOfChars) pattern, Closure toList() capitalize() expand() getChars() padRight(Number closure) toLong() center(Number expand(int tabStop) isAllWhitespace() numberOfChars, reverse() toSet() “ls”.execute() numberOfChars, String padding) center(Number expandLine(int tabStop) find(String regex) isBigDecimal() isBigInteger() isCase(Object String padding) padRight(Number numberOfChars) size() split() splitEachLine(String toShort() toURI() toURL() " lsコマンドを実行(Processが返る) numberOfChars) find(Pattern pattern) switchValue) plus(Object value) regex, Closure tokenize(String contains(String text) find(String regex, isDouble() previous() closure) token) count(String text) Closure closure) isFloat() readLines() splitEachLine tokenize(Character decodeBase64() find(Pattern pattern, isInteger() replaceAll(Pattern (Pattern pattern, token) denormalize() Closure closure) isLong() pattern, String Closure closure) tokenize() eachLine(Closure findAll(String regex) isNumber() replacement) stripIndent() tr(String sourceSet, closure) findAll(Pattern leftShift(Object replaceAll(String stripIndent(int String eachLine(int pattern) value) regex, Closure numChars) replacementSet) firstLine, Closure findAll(String regex, matches(Pattern closure) stripMargin() unexpand() closure) Closure closure) pattern) replaceAll(Pattern stripMargin(String unexpand(int “あいうえお”.tr(“あ-ん”,”ア-ン”) eachMatch(String regex, Closure closure) findAll(Pattern pattern, Closure closure) minus(Object target) multiply(Number factor) pattern, Closure closure) replaceFirst(Pattern marginChar) stripMargin(char marginChar) tabStop) unexpandLine(int tabStop) eachMatch(Pattern getAt(int index) next() pattern, String toBigDecimal() " “アイウエオ” pattern, Closure getAt(IntRange normalize() replacement) toBigInteger() closure) range) padLeft(Number replaceFirst(String toBoolean() execute() getAt(EmptyRange numberOfChars, regex, Closure toCharacter() execute(String[] range) String padding) closure) toDouble() envp, File dir) getAt(Range range) toFloat() 162011年12月1日木曜日
  27. 27. .split(/正規表現/)def words = new File(args[0]).text.split(/W+/)words.countBy{it}.entrySet().sort{it.value}.each { println "${it.value}: ${it.key}"} /∼/は文字列定数の記法。ただし 文字’’を特別扱いしない “W” == /W/ Java APIの String#split(String)2011年12月1日木曜日
  28. 28. .countBy{}def words = new File(args[0]).text.split(/W+/)words.countBy{it}.entrySet().sort{it.value}.each { println "${it.value}: ${it.key}"} countByはコレクション・イテレータに対 して追加されたGDKメソッド 分類基準に基づいて要素をグルーピングし た上でグループごとの要素数をカウントする2011年12月1日木曜日
  29. 29. .countBy{} リスト “ABC” “ABC” “DEF” “GHI” “ABC” “GHI” countBy{it} 分類基準をクロージャで与える マップ “ABC” : 3 “DEF” : 1 “GHI” : 2 コレクションやイテレータに対してcountByを適用する と、分類基準で分類されたグループをキー、そのグループの 要素数をバリューとするマップが得られる。(c.f. groupBy) 192011年12月1日木曜日
  30. 30. .entrySet().sort{}def words = new File(args[0]).text.split(/W+/)words.countBy{it}.entrySet().sort{it.value}.each { println "${it.value}: ${it.key}"} entrySet()はJava API sortはクロージャで比較するソート(GDKメ ソッド)2011年12月1日木曜日
  31. 31. each, GStringdef words = new File(args[0]).text.split(/W+/)words.countBy{it}.entrySet().sort{it.value}.each { println "${it.value}: ${it.key}"} eachはそれぞれに対して処理(クロージャ) 文字列中の$変数名、${ブロック}はその値 に置換される(GString) 212011年12月1日木曜日
  32. 32. 簡潔さをもたらしたもの 各種の省略 言語機能 高機能ライブラリ 222011年12月1日木曜日
  33. 33. 短かさの意味 Javaに比してコード量は1/5∼1/3 短かければ良いわけではない 短くて分かりにくくなることもある 重要なのは「やりたい事(what)/コード量」 のSN比 232011年12月1日木曜日
  34. 34. これは何でしょう?       Set<Map.Entry<String, Integer>> entrySet =import java.util.Comparator; map.entrySet();import java.util.HashMap;       Object[] list = entrySet.toArray();import java.util.Map;       Comparator comp = new Comparator(){import java.util.Set;         public int compare(Object o1, Object o2) {import java.util.List;           Map.Entry<String, Integer> e1 =import java.util.Arrays; (Map.Entry<String, Integer>) o1;import java.io.FileReader;           Map.Entry<String, Integer> e2 =import java.io.BufferedReader; (Map.Entry<String, Integer>) o2;import java.io.FileNotFoundException;           return e1.getValue() - e2.getValue();import java.io.IOException;         }       };public class WordCount {       Arrays.sort(list, comp);  @SuppressWarnings(value = "unchecked")       for (Object it: list) {  public static void main(String[] args) {         Map.Entry<String, Integer> entry =    FileReader fis = null; (Map.Entry<String, Integer>)it;    BufferedReader br = null;         System.out.println(entry.getValue() + ":    try { ["+entry.getKey()+"]");      HashMap<String, Integer> map = new       }HashMap<String, Integer>();     }      fis = new FileReader(args[0]);     catch (IOException e) {      br = new BufferedReader(fis);       try {if (br != null) br.close();}catch      String line; (IOException ioe){}      while ((line = br.readLine()) != null) {       try {if (fis != null)fis.close();}catch        for (String it: line.split("s+")) { (IOException ioe){}          map.put(it, (map.get(it)==null) ? 1 :       e.printStackTrace();(map.get(it) + 1));     }        }   }     } } 242011年12月1日木曜日
  35. 35. これは何でしょう?       Set<Map.Entry<String, Integer>> entrySet =import java.util.Comparator; map.entrySet();import java.util.HashMap;       Object[] list = entrySet.toArray();importimport 答:Java版ワードカウントから「処理 java.util.Map; java.util.Set;       Comparator comp = new Comparator(){         public int compare(Object o1, Object o2) {import java.util.List;           Map.Entry<String, Integer> e1 = の記述」を抜き出したもの。import java.util.Arrays; (Map.Entry<String, Integer>) o1;import java.io.FileReader;           Map.Entry<String, Integer> e2 =import java.io.BufferedReader; (Map.Entry<String, Integer>) o2;import java.io.FileNotFoundException;           return e1.getValue() - e2.getValue();import java.io.IOException;         }       };public class WordCount {       Arrays.sort(list, comp);  @SuppressWarnings(value = "unchecked")       for (Object it: list) {  public static void main(String[] args) {         Map.Entry<String, Integer> entry =    FileReader fis = null; (Map.Entry<String, Integer>)it;    BufferedReader br = null;         System.out.println(entry.getValue() + ":    try { ["+entry.getKey()+"]");      HashMap<String, Integer> map = new       }HashMap<String, Integer>();     }      fis = new FileReader(args[0]);     catch (IOException e) {      br = new BufferedReader(fis);       try {if (br != null) br.close();}catch      String line; (IOException ioe){}      while ((line = br.readLine()) != null) {       try {if (fis != null)fis.close();}catch        for (String it: line.split("s+")) { (IOException ioe){}          map.put(it, (map.get(it)==null) ? 1 :       e.printStackTrace();(map.get(it) + 1));     }        }   }     } } 242011年12月1日木曜日
  36. 36. 短かさの効用 Groovyの記述レベルは人間の認知 レベルでの「やって欲しいこと」の 記述に近い ➡理解性向上 ➡リファクタリングの頻度減少 252011年12月1日木曜日
  37. 37. Javaと親和性が高い 262011年12月1日木曜日
  38. 38. Java親和性(1):文法 正しいJavaコードは、正しいGroovyコード (ほぼ上位互換) 以下を含めて アノテーション,enum, Generics Java7機能(一部未対応) 272011年12月1日木曜日
  39. 39. Java親和性(2):API Java APIをそのままもしくは拡張して使う 例えばGroovy独自のコレクションクラス 群というものはない GDK(Groovy Development Kit) Java APIにメソッドを追加 282011年12月1日木曜日
  40. 40. Java親和性(3):相互運用 Groovyコードは常にJavaクラスに変換された上 で実行される。(次項) Java VMから見てGroovyコードは普通のJava クラス ラッパークラスは無い スクリプト(mainメソッドやクラス定義がな いGroovyコード)も内部的にクラスが生成さ れて実行される 292011年12月1日木曜日
  41. 41. Javaコードの実行 Javaソース javac .classファイル javaコマンド JVM 標準クラスローダ Javaクラス 302011年12月1日木曜日
  42. 42. Groovyコードの実行 Javaソース Groovyコード javac .classファイル javaコマンド groovyコマンド JVM 標準クラスローダ Groovyクラスローダ (オンメモリ実行時コンパイラ) Javaクラス Javaクラス 312011年12月1日木曜日
  43. 43. Groovyコードの実行 Javaソース Groovyコード javac groovyc .classファイル .classファイル javaコマンド groovyコマンド JVM 標準クラスローダ Groovyクラスローダ (オンメモリ実行時コンパイラ) Javaクラス Javaクラス Javaクラス 312011年12月1日木曜日
  44. 44. Groovyコードの実行 Javaソース Groovyコード javac groovyc .classファイル .classファイル javaコマンド groovyコマンド JVM 標準クラスローダ Groovyクラスローダ (オンメモリ実行時コンパイラ) Javaクラス Javaクラス Javaクラス 31 呼び出し・継承自由2011年12月1日木曜日
  45. 45. Java開発への取り込み方 7つの利用パターンを元にして http://www.flickr.com/photos/holeymoon/1634408365/ 322011年12月1日木曜日
  46. 46. Groovy「7つの利用パターン」 by Dierk König 万能接着剤(Super Glue): Javaのコンポーネントやフレームワークを Groovyを糊(glue)としてつなぐ やわらかな心臓部(Liquid Heart): 中核となるロジックだけをGroovy/ DSLで書けるようにする お化粧(Lipstick): Javaのライブラリを簡潔に利用できる層をもうけ る。 内視鏡手術(Keyhole Surgery): 実行時にGroovyスクリプトを接続で きる小さな口を用意しておく 無制限の開放(Unlimited Openness): 全部Groovyで書く 小人さんスクリプト(House-elf Script): 周辺の各種支援スクリプト をGroovyで書く ゴーストライター(Ghost Writer): 裏でコード生成 332011年12月1日木曜日
  47. 47. Groovyの利用パターン(1 of 7) 万能接着剤(Super Glue): Javaのコンポーネントやフレー ムワークをGroovyが糊(glue)としてつなぐ Groovy Java Java Java JavaAPI Java VM 342011年12月1日木曜日
  48. 48. 万能接着剤(Super Glue)の例 やりたいこと: 指定ファイルをbzip2圧縮して httpファイルアップロード Groovy ant HttpUnit 352011年12月1日木曜日
  49. 49. ant+HtmlUnit @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") def url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" def page = new WebClient().getPage(url) def fileField = page.getElementById(_p_attach_file) fileField.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() 362011年12月1日木曜日
  50. 50. ant+HtmlUnit @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") def url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" def page = new WebClient().getPage(url) def fileField = page.getElementById(_p_attach_file) fileField.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() 依存ライブ ラリの実行時 自動取得 362011年12月1日木曜日
  51. 51. ant+HtmlUnit @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; new AntBuilder().bzip2(src:args[0], zipfile:args[0]+".bz2") def url = "http://pukiwiki.example.com/index.php? plugin=attach&pcmd=upload&page=test" def page = new WebClient().getPage(url) def fileField = page.getElementById(_p_attach_file) fileField.valueAttribute = args[0]+".bz2" page.getByXPath("//input[@value=アップロード]")[0].click() Java資産の有 依存ライブ 効活用 ラリの実行時 (HtmlUnit, Ant) 自動取得 362011年12月1日木曜日
  52. 52. @Grab/Grape @Grab(net.sourceforge.htmlunit:htmlunit:2.8) import com.gargoylesoftware.htmlunit.WebClient; group指定 module指定 versoin指定 Grape Groovyスクリプト用の依存Jar管理機構 Apache Ivyベース/Maven互換 スクリプトを初回実行時に依存jarを自 動ダウンロード 372011年12月1日木曜日
  53. 53. Groovyの利用パターン (2 of 7) やわらかな心臓部(Liquid Heart): 中核となるロジックだ けをGroovy/DSLで書けるようにする 頻繁な変更 Groovy/DSL Java JavaAPI Java VM 382011年12月1日木曜日
  54. 54. やわらかな心臓部(LiquidHeart)の例 JavaからGroovyを呼びだす Binding binding = new Binding(); GroovyShell shell = new GroovyShell(binding); File script = new File(filename); shell.evaluate(script); 392011年12月1日木曜日
  55. 55. Groovyの利用パターン (3 of 7) お化粧(Lipstick): Javaのライブラリ・コンポーネントを 簡潔に利用できる層をもうける。 Groovy Wrapper Javaコンポーネント JavaAPI Java VM2011年12月1日木曜日
  56. 56. お化粧(Lipstick)の例 GroovyFX JavaFX Grails Spring FW Hibernate Geb Gant/AntBuilder Selenium Ant 412011年12月1日木曜日
  57. 57. GroovyFX Scene Graph DSL: 画面部品のツリー構造を Groovyのビルダーで記述 new SceneGraphBuilder(). stage(title:"Title",width:400,height:300,visible:true,resizable:true) { scene(fill: groovyblue) { rectangle x: 20, y: 20, width: 100, height: 50, fill: blue   onMouseClicked { println "hello" } } } Timeline DSL: 時間軸制御 timeline {     at(2.s) {         change(myCircle, layoutX){ to 500 } } } 422011年12月1日木曜日
  58. 58. Groovyの利用パターン (4 of 7) 内視鏡手術(Keyhole Surgery): 実行時にGroovyスクリ プトを接続できる小さな口を用意しておく 外部から Groovyコードを 注入 GroovyShell Java JavaAPI Java VM 432011年12月1日木曜日
  59. 59. 内視鏡手術(Keyhole Surgery) の例 Jenkinsのスクリプトコンソール Jenkins CLI Grails Console Plugin 442011年12月1日木曜日
  60. 60. Groovyの利用パターン (6 of 7) 小人さんスクリプト(House-elf Script): 周辺の各種支援 スクリプトをGroovyで書く 周辺スクリプト 開発対象のシステム Java Groovy JavaAPI JavaAPI Java VM Java VM1 45 2011年12月1日木曜日
  61. 61. Groovyの利用パターン (7 of 7) ゴーストライター(Ghost Writer): 裏でコード生成 Groovyコード 自動生成されるバイトコード JavaAPI Java VM1 32 46 2011年12月1日木曜日
  62. 62. ゴーストライターの例 やりたいこと:イミュータブル(不変)クラスを定 義しよう! クラスはfinalに 全フィールドをfinalかつprivate getter定義 Mutableなフィールド (配列やStringBufferや Dateなど) の取得に対しては「防御的コピー」 全フィールドをコンストラクタで初期化するコン ストラクタを定義 フィールドの値に基づくequals, hashCode, toStringを定義する 参考: Effective Java (2nd Edition), p73: Item15 Minimize mutability2011年12月1日木曜日
  63. 63. Java版 イミュータブルクラス: 57行 public final class Person { if (getClass() != obj.getClass()) private final String firstName; return false; private final String lastName; Person other = (Person) obj; if (firstName == null) { public Person(String firstName, String lastName) { if (other.firstName != null) this.firstName = firstName; return false; this.lastName = lastName; } else if (!firstName.equals(other.firstName)) } return false; if (lastName == null) { public String getFirstName() { if (other.lastName != null) return firstName; return false; } } else if (!lastName.equals(other.lastName)) return false; public String getLastName() { return true; return lastName; } } @Override @Override public String toString() { public int hashCode() { return "Person(firstName:" + firstName final int prime = 31; + ", lastName:" + lastName + ")"; int result = 1; } result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); } result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); return result; } @Override public boolean equals(Object obj) { やすく、 if (this == obj) 、ミスが混入し return true; 作成が大変 はない ド上明確で if (obj == null) return false; 意図がコー 参考: http://groovy.codehaus.org/Immutable+AST+Macro 482011年12月1日木曜日
  64. 64. Groovy版イミュータブルクラス: 4行 これ だけ です @Immutable よ!こ れだ class Person { け String firstName, lastName } 492011年12月1日木曜日
  65. 65. Groovy版イミュータブルクラス: 4行 これ だけ です @Immutable よ!こ れだ class Person { け String firstName, lastName } x = new Person("Junji","Uehara") assert x.lastName == "Uehara" x.firstName = "abc" //==> groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: firstName for class: Person 492011年12月1日木曜日
  66. 66. 強力なゴースト執筆陣 @Immutable, @ListenerList, @ToString, @Equals, @EqualsAndHashcode, @AutoClone, @TimedInterrupt, @Lazy, @Mixin, @Singleton, @InheritConsructors,@WithReadLock, @WithWriteLock, @Log, @Delegate, @Lazy, @Singleton, @Bindable, ほか 上記は「AST変換」を起動するアノテーション。 502011年12月1日木曜日
  67. 67. 最新動向 http://www.flickr.com/photos/realbreadcampaign/5534567421/ 512011年12月1日木曜日
  68. 68. Groovy 2.0へ 安定版最新 Groovy 1.8.4 開発版最新 Groovy 2.0.0-beta1 (=1.9-beta5相当) 2012年初頭に正式版登場予定 522011年12月1日木曜日
  69. 69. Groovyの新機能 Java 7のProject Coin対応(2.0以降) 二進リテラル リテラル中の下線 マルチキャッチ InvokeDynamic対応(2.0以降) try-with-resourceなどはいまのところ未 Groovy自体のモジュール化(1.8以降) 静的型チェック(2.0.0 beta1で実験的実装) 静的コンパイル(2.0以降) 532011年12月1日木曜日
  70. 70. まとめ http://www.flickr.com/photos/limonada/214375219/ 542011年12月1日木曜日
  71. 71. 本日伝えたかったこと Groovyとは何か? Groovyは簡単なのか? Java開発者にとってYES! 通常のJava開発と地続き Groovyは便利なのか? Java開発者にとってYES! 簡潔さと高機能さが 今、手はいる。 JavaプログラマにとってGroovyとは何か? Java x Groovyを実現するもの! 552011年12月1日木曜日
  72. 72. 本日伝えたかったこと Groovyとは何か? Groovyは簡単なのか? Java開発者にとってYES! 通常のJava開発と地続き Groovyは便利なのか? Java開発者にとってYES! 簡潔さと高機能さが 今、手はいる。 JavaプログラマにとってGroovyとは何か? Java x Groovyを実現するもの! 552011年12月1日木曜日
  73. 73. 本日伝えたかったこと Groovyとは何か? Groovyは簡単なのか? Java開発者にとってYES! 通常のJava開発と地続き Groovyは便利なのか? Java開発者にとってYES! 簡潔さと高機能さが 今、手はいる。 JavaプログラマにとってGroovyとは何か? Java x Groovyを実現するもの! 552011年12月1日木曜日
  74. 74. 本日伝えたかったこと Groovyとは何か? Groovyは簡単なのか? Java開発者にとってYES! 通常のJava開発と地続き Groovyは便利なのか? Java開発者にとってYES! 簡潔さと高機能さが 今、手はいる。 JavaプログラマにとってGroovyとは何か? Java x Groovyを実現するもの! 552011年12月1日木曜日
  75. 75. Java x Groovy GroovyはJavaの弱点を補う 組み合わせて使うことで相乗効果を発揮 Java開発者にとって修得・導入がごく容易 Java x Groovy (DIxAOP的な意味で) Groovy利用をJava開発と組み合わせることで、 Java開発を加速する! 562011年12月1日木曜日
  76. 76. ご静聴ありがとうご ざいました 572011年12月1日木曜日
  77. 77. コミュニティもよろしく 活発な国内コミュニティ 電子雑誌 G*マガジン 月1定例勉強会 G*ワークショップ 年1恒例合宿 その他企画 582011年12月1日木曜日

×