- Insects and Entropy
developer ทั้งหลายพึ่งอ่าน
Wednesday, October 12, 2005
Tuesday, October 11, 2005
LINQ
LINQ ย่อจาก Language INtegrated Query
เป็น feature หนึ่งใน .net version ใหม่
ดูตัวอย่าง snippet ของการใช้ LINQ
integrate ได้เนียนดีมาก
ลองมาดู java บ้าง
ถ้าต้องการ feature แบบนี้ เราต้องใช้ JoSQL เข้ามาช่วย
เนื่องจากเป็นแค่ api ก็เลยดูไม่เนียนตาเท่า LINQ ที่เป็น language extension
เป็น feature หนึ่งใน .net version ใหม่
The LINQ Project is a codename for a set of extensions to the .NET Framework that encompass language-integrated query, set, and transform operations. It extends C# and Visual Basic with native language syntax for queries and provides class libraries to take advantage of these capabilities.
ดูตัวอย่าง snippet ของการใช้ LINQ
using System;
using System.Query;
using Danielfe;
class Program
{
static void Main(string[] args)
{
string[] aBunchOfWords = {"One","Two", "Hello",
"World", "Four", "Five"};
var result =
from s in aBunchOfWords // query the string array
where s.Length == 5 // for all words with length = 5
select s; // and return the string
//PrintToConsole is an Extension method that prints the value
result.Print();
}
}
integrate ได้เนียนดีมาก
ลองมาดู java บ้าง
ถ้าต้องการ feature แบบนี้ เราต้องใช้ JoSQL เข้ามาช่วย
public static void main(String[] args) throws
QueryParseException,
QueryExecutionException {
List list = new ArrayList();
list.add("one");
list.add("two");
list.add("Hello");
list.add("world");
list.add("four");
list.add("five");
Query q = new Query();
q.parse("select * from java.lang.String " +
"where length = 5 ");
QueryResults qr = q.execute(list);
List results = qr.getResults();
for (Iterator iter = results.iterator(); iter.hasNext();) {
String tmp = (String) iter.next();
System.out.println(tmp);
}
}
เนื่องจากเป็นแค่ api ก็เลยดูไม่เนียนตาเท่า LINQ ที่เป็น language extension
Related link from Roti
Monday, October 10, 2005
Develop Rails with vim
ช่วงหลังๆนี้เริ่มทดลองเขียน ruby(rails) เยอะขึ้น
ก็เริ่มมองหา editor ที่ใช้เขียน ว่าจะใช้อะไรเขียนดี
เริ่มตั้งแต่ RDT ที่ใช้ eclipse เป็น platform
,BBEdit, JEdit
สุดท้ายสูงสุดคืนสู่สามัญ
กลับมาใช้ vi เป็น editor หลัก
มูลเหตุที่ใช้ vi ก็เพราะว่า พึ่งจะฉลาดรู้ว่า
vi ที่เป็น vim version นั้น มันมี feature แพรวพราวไม่เบาเลย
(เมื่อก่อนใช้ vi ดัั้งเดิม ใน hp เป็นหลัก
เลยไม่นึกว่าเวลาเปลี่ยน แล้ว vi จะเปลี่ยนด้วย)
ลองมาดูว่าผมทำอะไรลงไปบ้าง เพื่อให้ใช้ vim กับ ruby
ได้อย่างสบายใจ
เริ่มดูการไป copy VimExtension จาก rubyforge ก่อน
ใน package นี้มี vim extension อยู่ 4 ส่วนคือ
เพื่อให้ใช้งาน extension ตามข้างบน ก็ต้องมีการ
set .vimrc ดังนี้
ด้วยเหตุผลอะไรก็ไม่ทราบ
(คิดว่าคงเนื่องจากไม่รู้จัก vim ดีพอมากกว่า)
ทำให้ function compiler บนเครื่องผมไม่ work
ผมก็เลยต้อง copy command ที่อยู่ใน compiler/ruby.vim
ไปไว้ใน ftplugin/ruby.vim แทน
และเพื่อให้สะดวกในการ Run
โดยให้มัน save ก่อน run
ผมก็เลยเพิ่ม map key เข้าไปดังนี้
ได้ข้างบนมาก็ช่วยได้ระดับหนึ่งแล้ว
ก็ต้องเพิ่มความสามารถด้วยการทำ folding
โดยกำหนด ให้ใช้ toggle การแสดง folder guild line
ส่วน tab key ก็ใช้ให้เป็นตัว toggle show/hidden fold
จากนั้นก็ map ให้เป็น key ที่ใช้ toggle การแสดง linenumber
สุดท้ายก็ลง script winmanager เพื่อช่วยให้ access file
กับ switch buffer ได้ง่ายขึ้น
ก็เริ่มมองหา editor ที่ใช้เขียน ว่าจะใช้อะไรเขียนดี
เริ่มตั้งแต่ RDT ที่ใช้ eclipse เป็น platform
,BBEdit, JEdit
สุดท้ายสูงสุดคืนสู่สามัญ
กลับมาใช้ vi เป็น editor หลัก
มูลเหตุที่ใช้ vi ก็เพราะว่า พึ่งจะฉลาดรู้ว่า
vi ที่เป็น vim version นั้น มันมี feature แพรวพราวไม่เบาเลย
(เมื่อก่อนใช้ vi ดัั้งเดิม ใน hp เป็นหลัก
เลยไม่นึกว่าเวลาเปลี่ยน แล้ว vi จะเปลี่ยนด้วย)
ลองมาดูว่าผมทำอะไรลงไปบ้าง เพื่อให้ใช้ vim กับ ruby
ได้อย่างสบายใจ
เริ่มดูการไป copy VimExtension จาก rubyforge ก่อน
ใน package นี้มี vim extension อยู่ 4 ส่วนคือ
- Systax Highlighting อันนี้ไม่ต้องอธิบาย
- Smart Indenting อันนี้ก็ไม่ต้องอธิบายเช่นเดียวกัน
- Compiler อันนี้ช่วย map คำสั่ง make กับ error format
ทำให้เรา run และแก้ไข error ที่เกิด ขณะอยู่ใน vim ได้
เพื่อให้ใช้งาน extension ตามข้างบน ก็ต้องมีการ
set .vimrc ดังนี้
set nocompatible " We're running Vim, not Vi!
syntax on " Enable syntax highlighting
filetype on " Enable filetype detection
filetype indent on " Enable filetype-specific indenting
filetype plugin on " Enable filetype-specific plugins
ด้วยเหตุผลอะไรก็ไม่ทราบ
(คิดว่าคงเนื่องจากไม่รู้จัก vim ดีพอมากกว่า)
ทำให้ function compiler บนเครื่องผมไม่ work
ผมก็เลยต้อง copy command ที่อยู่ใน compiler/ruby.vim
ไปไว้ใน ftplugin/ruby.vim แทน
และเพื่อให้สะดวกในการ Run
โดยให้มัน save ก่อน run
ผมก็เลยเพิ่ม map key เข้าไปดังนี้
function! RunRuby()
w
make %
endfunction
map <C-R> :call RunRuby()<CR>
ได้ข้างบนมาก็ช่วยได้ระดับหนึ่งแล้ว
ก็ต้องเพิ่มความสามารถด้วยการทำ folding
โดยกำหนด
ส่วน tab key ก็ใช้ให้เป็นตัว toggle show/hidden fold
set fdm=syntax
set foldtext=getline(v:foldstart)
set foldcolumn=3
set fillchars=fold:\ "follow by white space
map <TAB> za
function! ToggleFoldColumn()
if &foldcolumn == 3
set foldcolumn=0
else
set foldcolumn=3
endif
endfunction
map <F3> :call ToggleFoldColumn()<CR>
จากนั้นก็ map
map:call ToggleNumber()
function! ToggleNumber()
if &number
set nonumber
else
set number
endif
endfunction
สุดท้ายก็ลง script winmanager เพื่อช่วยให้ access file
กับ switch buffer ได้ง่ายขึ้น
Related link from Roti
Sunday, October 09, 2005
บทความน่าสนใจ [2005-10-9]
- Urban performance legends, revisited
Pop quiz: Which language boasts faster raw allocation performance, the Java language, or C/C++? The answer may surprise you -- allocation in modern JVMs is far faster than the best performing malloc implementations.
Related link from Roti
Groovestry
Groovy เป็น script language ตัวหนึ่งที่เขียนด้วย java
เป็น script ที่น่าใช้ทีเดียว เพราะมี feature หลายอย่างที่ลอกมาจาก
ruby, python, smalltalk
วันนี้อ่านเจอใน Tapestry Mailing list ว่ามี project ที่ชื่อ Groovestry
ก็เลย load มาทดลองดู
เป็าหมายของโปรเจค ก็คือ นำ groovy เข้ามาช่วยเขียน code
ในส่วนของ Controller (MVC Pattern)
เพราะเดิมเวลาเราเขียน Web Application
เรามักจะมีขั้นตอนประมาณนี้
ขั้นตอนที่น่าเบื่อ ก็คือตอนที่รอมัน 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 เป็น
เมื่อกำหนดแบบนี้แล้ว เวลา controller ถูกเรียกใช้งาน
มันก็จะมองหา groovy file ที่มีชื่อเดียวกับ page แต่มีนามสกุลเป็น
ตัว controller ที่เขียนด้วย groovy จะมีหน้าตาประมาณนี้
โดย script ของเราจะ extend จาก
(จริงๆไม่ extend ก็ได้ แต่จะขาด feature ของการ access
component, page property ไป)
เวลาใช้งานใน mode develope ก็ให้ set flag
เพื่อไม่ให้ tapestry ทำ template-caching
หลังจากลองใช้ไปสักพักหนึ่ง
ก็พบว่า Groovestry มันขาด feature หนึ่งของ
tapestry ไป
feature ที่ว่า ก็คือการ binding ระหว่าง component กับ controller
ในลักษณะ ognl Expression
ยกตัวอย่าง
สมมติเรามี dynamic title อยู่อันหนึ่ง
ถ้าเรา implement Controller ด้วย Java
เราก็ต้องมี method
ที่จะถูก bind เข้ากับ component Insert ใน html template
แต่พอมาใช้ Groovestry ก็พบว่าไม่สามารถ
เรียกข้ามไปใช้ method getTitle ที่เขียนไว้ใน groovy controller ได้
หลังจากแกะ code ดูสักพัก
ก็พบว่า จริงๆแล้ว มันพอที่จะทำได้เหมือนกัน
แต่ต้องแก้ code จำนวนหนึ่ง
สุดท้าย feature ที่เพิ่มเข้าไป ก็ทำให้สามารถเรียกใช้ ในลักษณะนี้ได้
ดูไม่ค่อยเนียนตานัก แต่ก็ทำงานได้
(java มันขาด feature แบบ ruby ที่สามารถ
implement missing method handler ได้
ไม่งั้น เราก็สามารถทำ dynamic method ได้เนียนกว่านี้)
เป็น script ที่น่าใช้ทีเดียว เพราะมี feature หลายอย่างที่ลอกมาจาก
ruby, python, smalltalk
วันนี้อ่านเจอใน Tapestry Mailing list ว่ามี project ที่ชื่อ Groovestry
ก็เลย load มาทดลองดู
เป็าหมายของโปรเจค ก็คือ นำ groovy เข้ามาช่วยเขียน code
ในส่วนของ Controller (MVC Pattern)
เพราะเดิมเวลาเราเขียน Web Application
เรามักจะมีขั้นตอนประมาณนี้
- start tomcat
- ใช้ browser เรียกทดสอบ programe
- โปรแกรมทำงานไม่ถูกต้อง
- แก้ไขโปรแกรม
- reload application
- วนกลับไปทำขั้นตอนที่ 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
JBI Interface Name & Service Name
ในการ implement JBI component
จะมีศัพท์พื้นฐานที่ต้องทำความเข้าใจอยู่จำนวนหนึ่ง
ไม่เช่นนั้นอาจจะต้องปวดหัวกับการ ส่ง message ไม่ได้
หรือ message วิ่งหายต๋อมไม่รู้ไปไหน
ศัพท์ตัวแรกก็คือคำว่า interface
เป็นศัพท์ที่ define ไว้ใน spec ของ WSDL 2.0
มีความหมายเดียวกับ คำว่า porttype ใน spec WSDL 1.1
10 ปากว่า ไม่เท่าตาเห็น
ลองดู WSDL 1.1 ของ google ดู
ถ้าเปรียบเทียบกับ OOP term
interface ใน WSDL 2.0 ก็มีความหมายเหมือนกัน interface ใน OOP
ศัพท์ตัวถัดไปก็คือ service
ความหมายก็คือ implementation ของ interface นั่นเอง
ศัพท์ตัวถัดไปก็คือ endpoint
endpoint คือจุดที่เกิดการเชื่อมต่อจริงๆ
คล้ายๆความหมายของ port ในเรื่อง socket (network)
ลองดูความหมายที่ WSDL 2.0 define ไว้ (JBI endpoint มีความหมายเดียวกับ WSDL endpoint)
ความสัมพันธ์ระหว่าง service กับ endpoint เป็น one-to-many ก็คือ
service หนึ่งๆมี endpoint ได้หลาย endpoint
เวลาเราส่ง Message ใน JBI
เราสามารถระบุ target ที่จะส่งได้ 2 วิธีคือ
ที่นี้ลองดูที่ jbi.xml จริงๆบ้าง
source ข้างบนก็คือ การ define service ของ provider
จะเห็นว่ามีการระบุ
ถ้าเราไปดู source code ของ Java Class ที่ implement service นี้
จะเห็นว่ามี method ที่ชื่อ
เวลาเราเขียน component ใน servicemix
เราสามารถเลือกวิธีเขียนได้ 2 วิธีคือ
ในที่นี้เราจะพูดถึงการเขียน component แบบที่ใช้ client-api เท่านั้น
เริ่มโดย เวลาเราเขียน component เราก็จะเขียน class ที่ implement
interface
ซึ่งใน interface นี้จะบังคับให้เรา implement method ที่ชื่อ
ส่วน service name และ endpoint name
คงจะใช้การ lookup จาก jbi.xml
กรณีที่เรามี endpoint มากกว่า 1 endpoint ใน 1 service
การ implement แค่
จะไม่เพียงพอ ต้องมีการ implement
interface นี้จะบังคับเราให้เรา implement method
กับ
จะมีศัพท์พื้นฐานที่ต้องทำความเข้าใจอยู่จำนวนหนึ่ง
ไม่เช่นนั้นอาจจะต้องปวดหัวกับการ ส่ง message ไม่ได้
หรือ message วิ่งหายต๋อมไม่รู้ไปไหน
ศัพท์ตัวแรกก็คือคำว่า interface
เป็นศัพท์ที่ define ไว้ใน spec ของ WSDL 2.0
มีความหมายเดียวกับ คำว่า porttype ใน spec WSDL 1.1
10 ปากว่า ไม่เท่าตาเห็น
ลองดู WSDL 1.1 ของ google ดู
<portType name="GoogleSearchPort">
<operation name="doGoogleSearch">
<input message="typens:doGoogleSearch"/>
<output message="typens:doGoogleSearchResponse"/>
</operation>
</portType>
ถ้าเปรียบเทียบกับ OOP term
interface ใน WSDL 2.0 ก็มีความหมายเหมือนกัน interface ใน OOP
ศัพท์ตัวถัดไปก็คือ service
ความหมายก็คือ implementation ของ interface นั่นเอง
ศัพท์ตัวถัดไปก็คือ endpoint
endpoint คือจุดที่เกิดการเชื่อมต่อจริงๆ
คล้ายๆความหมายของ port ในเรื่อง socket (network)
ลองดูความหมายที่ WSDL 2.0 define ไว้ (JBI endpoint มีความหมายเดียวกับ WSDL endpoint)
Endpoints, in WSDL 2.0, refer to a particular address, accessible by a particular protocol, used to access a
particular service
ความสัมพันธ์ระหว่าง service กับ endpoint เป็น one-to-many ก็คือ
service หนึ่งๆมี endpoint ได้หลาย endpoint
เวลาเราส่ง Message ใน JBI
เราสามารถระบุ target ที่จะส่งได้ 2 วิธีคือ
- ระบุแค่ service name
ถ้าระบุแค่นี้ ตัว JBI container จะตัดสินให้ว่า ควรจะส่งให้ endpoint ไหนดี - ระบุทั้ง service name และ endpoint name (มีศัพท์เรียกว่า service endpoint)
ที่นี้ลองดูที่ jbi.xml จริงๆบ้าง
<services binding-component="false"
xmlns:logger="http://pok/dblogger/">
<provides interface-name="logger:log-interface"
service-name="logger:log"/>
</services>
source ข้างบนก็คือ การ define service ของ provider
จะเห็นว่ามีการระบุ
interface-name
กับ service-name
ถ้าเราไปดู source code ของ Java Class ที่ implement service นี้
public class DbLoggerComponent implements
ServiceInterfaceImplementation,
ServiceEndPointImplementation {
public QName getInterfaceName() {
return new QName("http://pok/dblogger/",
"log-interface");
}
public void onMessage(MessageExchange msg) {
...
}
}
จะเห็นว่ามี method ที่ชื่อ
getInterfaceName
เวลาเราเขียน component ใน servicemix
เราสามารถเลือกวิธีเขียนได้ 2 วิธีคือ
- implment interface ของ JBI-api ด้วยตนเอง
- ใช้ client-api ของ ServiceMix
อันนี้จะสะดวกสบายขึ้นหน่อย จำนวนบรรทัดของ source code
ที่เขียน จะลดลงหน่อย
ในที่นี้เราจะพูดถึงการเขียน component แบบที่ใช้ client-api เท่านั้น
เริ่มโดย เวลาเราเขียน component เราก็จะเขียน class ที่ implement
interface
ServiceInterfaceImplementation
ซึ่งใน interface นี้จะบังคับให้เรา implement method ที่ชื่อ
getInterfaceName
ส่วน service name และ endpoint name
คงจะใช้การ lookup จาก jbi.xml
กรณีที่เรามี endpoint มากกว่า 1 endpoint ใน 1 service
การ implement แค่
ServiceInterfaceImplementation
จะไม่เพียงพอ ต้องมีการ implement
ServiceEndPointImplementation
interface นี้จะบังคับเราให้เรา implement method
getServiceName
กับ
getEndpointName
Related link from Roti
Subscribe to:
Posts (Atom)