Preface
Groovy 程式語言在 2003 年問世,創造它的是 Apache Software Foundation 的軟體工程師 James Strachan,目前專案的負責人則是 Guillaume LaForge。Groovy 是自由軟體,它採用 Apache 2.0 開放原始碼授權,第一個正式版本 1.0 在 2007 年發佈,從 2012 年發佈 2.0 版本後,Groovy 的發展更活躍,預期在 2014 年就會出現 3.0 的新版本。
長久以來,許多 Java 開發者期待更好的語言,Java.next 一直是受到關注的議題。日漸成熟的 Groovy 帶來新希望,它讓開發 Java 的世界變得更加敏捷,我們不必再等待 Java 8 或 Java 9 實現的新功能,有許多現代語言的方便特性,開始用 Groovy 就能做到。
Groovy 的語法大致上和 Java 語言相似;但是卻比 Java 更容易學習與使用,也比更適合剛入門學習寫程式的初學者。已經熟悉 Java 的開發者,很快就能學會使用 Groovy 寫程式,有許多用 Java 寫起來很複雜的程式,改用 Groovy 就可以用更輕鬆簡單的方法完成,因此吸引不少 Java 開發者加入學習行列。
A First Look at Groovy
Groovy 可以當作 Scripting Language 執行,不必像 Java 至少需要定義主類別(Main-Class)與 main(String[] args) 方法提供主程式才能啟動。因此最簡單的 Hello World 程式用 Groovy 撰寫只需要一行,就像 Python 或 Ruby 這類語言一樣簡單易寫。
- println "Hello Groovy"
- class Person {
- def name, age
- }
- def p = new Person(name: 'John', age: 21)
- println "${p.name}: ${p.age}"
對學習者而言,入門 Groovy 比 Java 更容易,特別是剛開始接觸物件導向程式設計時,不必被又多又規則複雜的關鍵字混淆,較能專注在物件導向觀念的學習。如果是從 Groovy 開始入門,未來要學習 Java 程式設計並不難,使用 Java API 的方法也沒有什麼不同,只是 Java 寫起來就是比較麻煩一些。
Groovy 簡化字串的操作,可以類似 PHP 在使用雙引號「"」的字串中夾帶變數。
- println "現在月份:${new Date().month}"
- println "Square root of 199 is ${Math.sqrt(199)}"
- println "運動強度建議每分鐘心跳數不超過 ${(220 - p.age) * 0.9}"
- mailContent = """Dear ${p.name},
- Welcome to a world of Peace, Love and Grooviness!
- Best regards,
- Kyle
- ${new Date().format('yyyy/MM/dd')}
- """
函數型程式設計(Functional Programming,簡稱 FP)在 Java 世界不多見,過去的做法通常搭配 Funcation Library(如 Functional Java)使用。JDK 直到最新的 Java SE 8 推出,才有提供 Lambda Expression 的支援,但是卻使得觀念變得更多更複雜。在傳統的 Java 物件導向程式中,撰寫函數型的程式並不自然,也不容易學習或實際應用。Groovy 提供 Lambda 及 Closure 的特性,可以支援函數型程式設計。在撰寫 Groovy 程式時,使用 FP 很自然而且也很容易寫,開發者可以適時運用來「簡化」程式碼,而不是把程式碼變得更複雜。
例如一個比較兩個數字大小的程式,可以撰寫成多數人都熟悉的函式宣告形式。
- def max(a, b) {
- a > b ? a : b
- }
- max(18, 24) // return 24
- def max = { a, b ->
- a > b ? a : b
- }
- max(35, 24) // return 35
- def max = { a, b ->
- a > b ? a : b
- }
- def min = { a, b ->
- a < b ? a : b
- }
- [max, min].each {
- println it(2013, 2014)
- }
- func = "max"
- "${func}"(1024, 768) // return 102
Map 與 List 是 Java 程式常用的資料結構,但是遇到很簡單的資料處理時,Java 程式碼並無法像 PHP 或 Ruby 那樣簡潔。Groovy 的語法內建 Map 與 List 兩種資料結構,讓簡單的資料處理能有易讀易寫的做法。(Groovy - Collections)
宣告 List 的語法很像定義陣列。
- list1 = []
- list1 = [1, 2]
- list1 += [3, 4, 5] // [1,2,3,4,5]
- list1 << 6 // [1,2,3,4,5,6]
- list1.size() // => 6
- list1 == [1, 2, 3] + [4, 5, 6] // => true
- list1.each {
- println it
- }
- list1 = 1..5
- list2 = [1, 2, 3, 4, 5]
- list1 == list2 // => true
- (1..100).each { println it }
- ('a'..'z').each { println it }
- map1 = [:]
- map1 = [name: "book1", year: 2010]
- map1['name'] = "book1 2e"
- map1.year = 2013
- map1 << [author: "John"]
- map1.each { key, value ->
- println "${key} = ${value}"
- }
Groovy 適合用於多種類型的軟體開發,包括桌面視窗程式、網路服務程式、網站或資料庫應用程式等。以打造圖形介面(視窗)應用程式為例,Groovy 可以使用 Java 的 Swing GUI Toolkit,以下是使用 Groovy 撰寫的 Swing Hello World 範例。
- import javax.swing.*
- frame = new JFrame("HelloWorldSwing")
- label = new JLabel("Hello World")
- frame.contentPane << label
- frame.pack()
- frame.visible = true
從學習 Groovy 的那一刻起,就會開始不斷與 DSL 打交道。Groovy 有許多不同用途的 Builder,讓你輕鬆享受 DSL 帶來的好處。常見的 Groovy Builder 包括:
我們可以將 Swing Hello World 範例程式改用 SwingBuilder 重寫成 DSL 的風格。
- new groovy.swing.SwingBuilder().edt {
- frame(title: "HelloWorldSwing", pack: true, show: true) {
- label(text: "Hello World")
- }
- }
- def builder = new groovy.json.JsonBuilder()
- builder.people {
- person {
- firstName 'Kyle'
- lastName 'Lin'
- address(
- city: 'Taichung',
- country: 'Taiwan'
- )
- }
- }
- println builder.toPrettyString()
Groovy 支援靜態語言不容易做到的 Metaprogramming 功能,利用 metaClass 我們可以擴充一個已經定義好的類別,加入新的方法函式。例如基本的 Java API 的 String 類別,我們可以加入 String 的 hello() 方法,讓字串直接擁有新的功能。
- String.metaClass.hello = { "Hello ${delegate}" }
- "John".hello() // Say Hello to John
- // Execute external command and get results
- execResult = "echo hello".execute().text
- // Fetch html response from a url
- htmlText = new URL("http://google.com/").text
- String.metaClass.escapeHtml = {
- delegate
- .replaceAll('<', '<')
- .replaceAll('>', '>')
- .replaceAll(' ', ' ')
- }
- "
".escapeHtml()
TIOBE 提供程式語言熱門程度的排行榜,從這份統計資料不難發現 Java 始終名列前茅 (TIOBE Programming Community Index)。Java 不僅有眾多 Open Source 社群開發者的支持,也有多家跨國大型軟體公司力挺,形成的 Ecosystem 難以被其他開發平台取代;我們可以大膽預期 Java 在未來幾年仍會有舉足輕重的地位,在 Web-based 及 Cloud 應用成為主流的今日,Java 會在 Server-side 的開發扮演重要的角色。
從 1995 年誕生迄今,Java 已算是個邁入中年的程式語言,它被廣泛使用於各類型軟體開發,發展出豐富的 Java API 及大量的 Library 與 Framework,Java 的解決方案多能滿足企業級的開發需求。傳統的 Java 語言已經變得太過複雜;但儘管許多開發者渴望更時髦的 Java 語言,多年來一直無法如願以償,歷史的包袱使得 Java 語言不可能快速演化。如果期望有一天寫 Java 也能夠像 Ruby 或 Python 同樣愉悅,那肯定是在夢境裡才會實現。
Groovy 誕生的那一刻,已經為 Java 的世界重新打開一扇窗。
Groovy 受到其他程式語言的啟發,將許多語言的優點融合,像是 Smalltalk、Ruby 或 Python 等,甚至可以像 Perl 一樣直接在程式碼使用 Regular Expression。
- new File('.').eachFileMatch( ~/.*\.groovy/ ) {
- println it
- }
Polyglot Programming in the JVM
原來 Java 的世界不只有 Java 程式語言!?先談談什麼是 Polyglot Programming 吧? 以微軟的 .NET 開發平台為例,MSDN 文件提供 C# / C++ / F# / JScript / VB 等五種不同語言的使用範例。雖然使用不同的程式語言撰寫,但它們都使用相同的 .NET Framework API。
Java 虛擬機器(Java Virtual Machine,簡稱 JVM)的設計亦支援 Polyglot Programming,不管用什麼語言寫程式,只要編譯成 Java Bytecode,就可以在 JVM 虛擬機器執行。官方的 Java API 文件中,無法找到其他程式語言的範例,坊間一般的書籍也很少介紹 JVM 的其他語言。但實際上 Java 世界用其他語言寫程式,已盛行多年並且可用於產品的開發。
常見的 JVM Languages 包括:
Polyglot Programming 帶給 Java 程式設計師更多的語言選擇,例如下面的範例是一段 JavaScript 程式碼,它使用 Java Thread API 建立多執行緒。
- var obj = {
- run: function () {
- print(“Hello Thread\n"); }
- }
- var r = new java.lang.Runnable(obj);
- var t = new java.lang.Thread(r);
- t.start();
JVM Scripting Language
Ousterhout’s dichotomy 將程式語言分類為以下兩種:(Oursterhout, 1998,資料來源為 Wikipedia)
Groovy 兼顧上述兩種不同語言的特性,既可當作 Scripting Language 用直譯方式執行,也可以先編譯 Groovy 的類別程式碼變成 Java Bytecode;後者的執行方式和一般 Java Class 相同,也可以打包成 JAR 或 WAR 發佈。Java Scripting API 最早是從 Java SE 6 這個版本開始提供,它提供 ScriptEngine 介面類別,讓不同的 JVM Scripting Language 有一致的執行方式,以下是使用 ScriptEngine 執行 JavaScript 程式碼的範例。
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName("JavaScript");
- engine.eval("print('Hello');");
但是 Java Script 是 JDK 6 唯一內建支援的語言,JDK 並沒有提供 Groovy 或其他 JVM Scripting Language 的 ScriptEngine 實作。若要執行其他語言的 Scripting 程式碼,需要先將符合JSR-223 規範的 Library 加到 CLASSPATH 才能執行。
以下是 ScriptingEngine 執行 Groovy Scripting 程式碼的 Java 程式範例,執行前需要先取得 groovy-all-2.2.1.jar 檔案。
- import javax.script.*;
- public class RunGroovy {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName("groovy");
- engine.eval("println 'Hello'");
- }
- }
Why Groovy?
目前在 Java 世界已經四處可見 Groovy 的實際應用,不用擔心這只是曇花一現或是趕流行的新語言。Groovy 的出現不是為了取代 Java,而是讓那些原本在 Java 不容易做到的事情,能夠利用 Groovy 來達成,開發社群使用 Groovy 的開發應用將會愈來愈多。
iReport 與 JasperReport 是功能強大的報表設計工具,它利用 Groovy 簡化報表製作時的程式撰寫;在處理報表資料顯示時,可以利用 Groovy Scripting 進行資料的運算處理。
* iReport Designer – Groovy
Gradle 是新一代的 Java 專案自動化建置工具,它直接使用 Groovy Script 定義專案建置的各項任務,比起 Ant 或 Maven 採用 XML 格式的設定檔,Gradle 直接以程式碼撰寫設計建置流程讓功能更強大,Groovy DSL 的特性也讓 Gradle 設定檔看起來十分友善。
* Gradle The Enterprise Build Automation Tool
Gradle 目前也成為 Google 建議的 Android 專案建置工具。
* New Build System? > ?Gradle Plugin User Guide
Jenkins CI 是持續整合(Continuous Integration)的工具首選,它為軟體開發團隊提供二十四小時無休的專業管家服務,可以幫忙處理單元測試或每日自動化建置及發佈。Jenkins 提供的 Script Console 功能,就是利用 Groovy Script 進行遠端維護管理。
* Jenkins Script Console
Spock Framework 提供以更簡潔的 Groovy 語法撰寫測試案例,可以用於 Java 或 Groovy 程式的單元測試。Spock 提供 Specification 的描述語言,讓開發者用 Groovy DSL 的方式定義測試規格。
* Spock Enterprise-ready Testing and Specification Framework
Geb 是非常好用的 Web UI Testing 工具,它讓開發者使用 Groovy 撰寫簡單的 Script 程式來操作瀏覽器,完成網站各項畫面或表單的模擬操作。Geb 利用類似 jQuery 的語法取得畫面的內容加以驗證,還能夠將網頁測試結果及畫面截圖保存。Geb 對瀏覽器的自動化操作實際是透過 Selenium WebDriver 完成,它利用 Groovy DSL 的特性讓 Test Script 的撰寫變得十分容易。
* Geb – Very Groovy Browser Automation
Supplement
* 淺談 Groovy 與 Gradle
* Groovy 官方網站
* Guillaume Laforge’s Blog
* Koans the missing groovy tutorial
* Groovy Content on InfoQ
* Groovy Zone
沒有留言:
張貼留言