Sunday, October 09, 2005

Groovestry

Groovy เป็น script language ตัวหนึ่งที่เขียนด้วย java
เป็น script ที่น่าใช้ทีเดียว เพราะมี feature หลายอย่างที่ลอกมาจาก
ruby, python, smalltalk

วันนี้อ่านเจอใน Tapestry Mailing list ว่ามี project ที่ชื่อ Groovestry
ก็เลย load มาทดลองดู

เป็าหมายของโปรเจค ก็คือ นำ groovy เข้ามาช่วยเขียน code
ในส่วนของ Controller (MVC Pattern)
เพราะเดิมเวลาเราเขียน Web Application
เรามักจะมีขั้นตอนประมาณนี้
  1. start tomcat
  2. ใช้ browser เรียกทดสอบ programe
  3. โปรแกรมทำงานไม่ถูกต้อง
  4. แก้ไขโปรแกรม
  5. reload application
  6. วนกลับไปทำขั้นตอนที่ 2

ขั้นตอนที่น่าเบื่อ ก็คือตอนที่รอมัน reload application
ถ้า project ใหญ่ๆ มันจะช้าจนน่ารำคาญ
แน่นอน ถ้าทำ test case ไว้ดี ก็จะลดรอบ
ของการ iterate แบบที่ว่าไปได้เยอะ
แต่บางที เราก็อยากเขียนโปรแกรม
ในแบบของศิลปินบ้าง เขียนไป ดูผลลัพท์ไป ออกแบบไป
เหมือนช่างปั้น ที่ค่อยๆใส่ดินเข้าไป ตัดออก โปะเข้าไปใหม่ เกลี่ย ปาด..
(สำหรับคนที่ใช้ framework อื่น
tapestry ใช้วิธี dynamic enhance class
ในตอนที่ load controller ขึ้นมาทำงาน
ทำให้เราไม่สามารถใช้ feature reload class
ของ tomcat ได้)

เมื่อนำ Groovestry เข้ามาใช้
รอบ cycle การพัฒนาของเราก็จะเร็วขึ้น
เพราะสามารถตัดขั้นตอน การ reload application ออกไปได้

การใช้ Groovestry ก็ง่ายดาย
เพียงแค่ add jar เข้าไปใน WEB-INF/lib
แล้วก็กำหนดให้ page class เป็น ScriptPage
<page-specification class="org.apache.tapestry.contrib.script.ScriptPage">

เมื่อกำหนดแบบนี้แล้ว เวลา controller ถูกเรียกใช้งาน
มันก็จะมองหา groovy file ที่มีชื่อเดียวกับ page แต่มีนามสกุลเป็น
.groovy ให้เอง

ตัว controller ที่เขียนด้วย groovy จะมีหน้าตาประมาณนี้
package application.script

import org.apache.tapestry.contrib.script.ScriptObject

class Home extends ScriptObject {

void pageBeginRender(event) {
.....
}

public void submit(cycle) {
page2 = cycle.getPage("Page2");
page2.title = "< " + formTitle + " >";
page2.customerId = customerId;
cycle.activate(page2);
}
}

โดย script ของเราจะ extend จากScriptObject
(จริงๆไม่ extend ก็ได้ แต่จะขาด feature ของการ access
component, page property ไป)

เวลาใช้งานใน mode develope ก็ให้ set flag
-Dorg.apache.tapestry.disable-caching=true ด้วย
เพื่อไม่ให้ tapestry ทำ template-caching

หลังจากลองใช้ไปสักพักหนึ่ง
ก็พบว่า Groovestry มันขาด feature หนึ่งของ
tapestry ไป
feature ที่ว่า ก็คือการ binding ระหว่าง component กับ controller
ในลักษณะ ognl Expression
ยกตัวอย่าง
สมมติเรามี dynamic title อยู่อันหนึ่ง
<title>
<span jwcid="@Insert" value="ognl:title">xxx</span>
</title>

ถ้าเรา implement Controller ด้วย Java
เราก็ต้องมี method getTitle
ที่จะถูก bind เข้ากับ component Insert ใน html template
public class MyPage extends BasePage {
...
public String getTitle() {
return "my page title";
}
....
}

แต่พอมาใช้ Groovestry ก็พบว่าไม่สามารถ
เรียกข้ามไปใช้ method getTitle ที่เขียนไว้ใน groovy controller ได้
หลังจากแกะ code ดูสักพัก
ก็พบว่า จริงๆแล้ว มันพอที่จะทำได้เหมือนกัน
แต่ต้องแก้ code จำนวนหนึ่ง

สุดท้าย feature ที่เพิ่มเข้าไป ก็ทำให้สามารถเรียกใช้ ในลักษณะนี้ได้
<title>
<span jwcid="@Insert"
value="ognl:doAction('getTitle')">xxx</span>
</title>

ดูไม่ค่อยเนียนตานัก แต่ก็ทำงานได้
(java มันขาด feature แบบ ruby ที่สามารถ
implement missing method handler ได้
ไม่งั้น เราก็สามารถทำ dynamic method ได้เนียนกว่านี้)

Related link from Roti

No comments: