Sunday, August 13, 2006

Hivemind #1

ช่วงสองสามเดือนมานี่ ชีวิตขลุกอยู่กับ Tapestry
แน่นอนเมื่อโปรเจคใหญ่ขึ้น ซับซ้อนขึ้น
ก็หลีกเลี่ยงไม่ได้ที่จะต้องลงไปแตะ Architecture ที่เป็นฐานรากของ Tapestry
ซึ่งก็คือ Hivemind

Hivemind เรียกตัวเองว่า Service and Configuration MicroKernel
โดย Service ก็คือ POJO ที่สามารถร้อยเข้าหากันด้วยวิธี Dependency Injection เช่นเดียวกับ Spring
ส่วน Configuration ก็คือ การ define data ที่ service ต้องการใช้

ลองดูตัวอย่างการ configuration ของ hivemind

เริ่มด้วยการ define service

<service-point id="foo" interface="Foo">
...
</service-point>


เทียบกับ Spring ที่ใช้ concept เป็น Bean
<bean id="foo" class="test.impl.FooImpl">
...
</bean>

ความแตกต่างในเบื้องต้น จะเห็นได้ว่า bean ใน spring เราจะระบุชื่อที่รวม package name ด้วย
ส่วน hivemind ชื่อ package จะถูก define ไว้ที่ระดับ document root ของ xml

ส่วนประเด็นที่สอง hivemine นิยมประกาศให้ชัดไปเลยว่า
service ที่ expose นั้นมี interface เป็นอย่างไร
ซึ่ง client ที่ต้องการใช้ service สามารถ query ตามชื่อของ service ได้
IPreferenceService svr = (IPreferenceService) registry
.getService(IPreferenceService.class);


ทีนี้ลองไปดูวิธีร้อย service เข้าหากันบ้าง
เอาวิธีร้อยแบบ declarative (ไม่ได้ใช้ autowire)
ในส่วนของ Hivemind
<service-point id="dao" interface="IPreferenceDao">
<create-instance class="impl.PreferenceDapImpl"/>
</service-point>

<service-point id="preferenceService" interface="IPreferenceService">
<invoke-factory>
<construct class="impl.PreferenceServiceImpl">
<set-service property="dao" service-id="dao"/>
</construct>
</invoke-factory>
</service-point>

เทียบกับ spring
<bean id="dao" class="test.impl.PreferenceDaoImpl"/>

<bean id="preferenceService" class="test.impl.PreferenceServiceImpl">
<property name="">
<ref bean="dao"/>
</property>
</bean>


จะเห็นว่าถึงตอนนี้ hivemind กับ spring ก็ดูเหมือนๆกัน
ต่างกันตรงที่ใช้ wording กันคนละแบบ
แต่จริงๆแล้วพอถึงจุดนี้ มันเริ่มเกิดความแตกต่างในวิธี implement แล้ว
ใน Hivemind ถ้าเราลอง get service ขึ้นมา
object ที่เราได้จะมี class เป้น SingletonProxy
ส่วนของ Spring ถ้า get bean ขึ้นมา object ที่ได้
จะเป็น class ตรงตามที่ define ไว้
// hivemind
System.out.println(registry.getService(PreferenceServiceImpl.class);
// => <SingletonProxy for test.preferenceService(test.IPreferenceService)>

// spring
System.out.println(factory.getBean("preferenceService"));
// => test.impl.PreferenceServiceImpl

ดูอย่างนี้แล้ว Hivemind จะออกไปในแนว Lazy initialize มากกว่า
คือถ้า proxy ยังไม่ถูกใช้งาน object จริงๆ ก็จะยังไม่ถูกสร้างขึ้น
แต่ในกรณี spring bean ลูกๆที่ถูกอ้างถึง ต้องมีการ initialize สร้างเป็น object
ก่อนที่จะถูก set ให้กับ bean แม่

พักอยู่ที่จุดนี้ก่อน
ไว้ถ้ามีเวลา จะลงไปลึกถึงเรื่อง interceptor,
configuration point, service management

Related link from Roti

No comments: