กำลังสาละวนอยู่กับโปรเจ็คนึงอยู่ และกำลังจะเริ่มเตรียมการทดสอบแบบอัตโนมัติ แต่พอดีไปสะดุดตาเข้ากับการประกาศ Spring Bean ด้วย bean builder แทนการใช้ XML ครับ เลยหยิบมาเป็นประเด็น ซึ่งคิดว่าน่าจะมีประโยชน์
โดยปกติผู้ใช้ Spring จะประกาศ bean ด้วย XML เพื่อเตรียม bean ที่ต้องการจะ inject เข้าสู่ตัวระบบงาน (อ่านเพิ่ม Dependency Injection Pattern)
ในเกรลส์เราทำได้ผ่าน resource.xml และถ้าไม่อยากเขียน XML (ซึ่งเป็นวิธีที่ผมกำลังจะเล่าให้ฟัง) ก็ทำได้โดยการระบุ Spring Bean เป็นภาษา Groovy ลงใน resource.groovy ครับ ภาษาที่ใช้กำหนด Spring Bean ก็เรียกกันว่า bean DSL
ถ้าเราเขียน XML แบบนี้
<bean id="myBean" class="my.company.MyBeanImpl"></bean>
ใน resource.groovy เราสามารถเขียนได้เป็น
myBean(my.company.MyBeanImpl)
จะเห็นว่า สั้นกระชับกว่าเยอะเลยครับ
ถ้าต้องการที่จะกำหนด property ลงใน bean ด้วยการโยงจาก bean อื่น ๆ เช่น
<bean id="myBean" class="my.company.MyBeanImpl"> <property name="bookService" ref="bookService" /> <property name="sessionFactory" ref="sessionFactory" /> </bean>
เราจะเขียนใน resource.groovy เป็น
myBean(my.company.MyBeanImpl) {
bookService = ref('bookService')
sessionFactory = ref('sessionFactory')
}
มาถึงตรงนี้ บางท่านอาจจะแย้งว่า ไม่เห็นมันจะมีประโยชน์อะไรเลย ก็แค่แปลง syntax จาก XML เป็น Groovy ธรรมดา ๆ ไม่ได้มีอะไรพิเศษ
แต่อย่าลืมครับว่า ด้วย Groovy แล้วนั้นหมายถึงเรากำลังใช้ภาษาโปรแกรมอยู่ นั่นคือเราสามารถทำอะไรหลาย ๆ อย่างได้มากกว่า XML เช่นในกรณีของผม ผมต้องใช้ mock object (วัตถุปลอมสำหรับใช้ทดสอบ) เพื่อการทดสอบ เนื่องจากเกิดปัญหาพอดีว่าผมไม่สามารถใช้ production environment สำหรับทดสอบได้ เพราะจะต้อง deploy ไปยังระบบที่เป็น Platform as a Service (ประเภท Google AppEngine ทำนองนั้นครับ) การรันเทสเลยต้องทำภายใต้การจำลองระบบโดยใช้ mock object ในหลาย ๆ จุด
มาถึงตรงนี้ bean DSL ในเกรลส์ช่วยได้มากเลยครับ
import grails.utils.GrailsUtil as gu
beans = {
def twUserId = 'myid'
def twPassword = 'mypassword'
switch(gu.environment) {
case 'development':
case 'test':
twitter(twitter4j.TwitterMock) {
userId = twUserId
password = twPassword
}
break
case 'production':
twitter(twitter4j.Twitter) {
userId = twUserId
password = twPassword
}
break
}
}
จากตัวอย่างจะเห็นว่ามีการใช้ switch case เพื่อตรวจสอบว่ากำลังรันอยู่ใน environment แบบไหน และถ้าเป็น test environment ก็ให้เตรียม bean ที่เป็น mock object แทน แต่ถ้าเป็น production ก็ให้ใช้ bean จริงเป็นต้นครับ
September 25th, 2008 at 11:08 am
ผมใช้แต่เป็น xml ยังไม่เคยลองใช้แบบ DSL เลยครับ
แต่ตรงที่ประยุกต์มาใช้งานตามแต่ละ env นี่มีประโยชน์ครับ เพราะว่าทางระบบที่ผมพัฒนามักจะติดปัญหาทำนองนี้เหมือนกันครับ [ out of control ]
October 3rd, 2008 at 1:45 pm
เห็นแล้ว ชื่นใจ ..