Rubyist มี blog ที่พูดถึง Measuring programmer happiness?
วัดโดยใช้ข้อมูลจาก google code
Friday, October 06, 2006
Thursday, October 05, 2006
Magic in Rails Routing
Jamis Buck เขาเขียนอธิบาย กลไก routing ของ Rails ว่าทำงานอย่างไร
ตอนแรกพูดถึง
Under the hood: Rails' routing DSL
ว่าด้วยการทำงานภายใน เวลา rails เริ่มอ่าน file $RAIL_ROOT/config/route.rb
จะมีการทำงานภายในอย่างไร
ส่วนตอนสองพูดถึง
Under the hood: route recognition in Rails
อธิบายว่า ถ้ามี request วิ่งเข้ามาแล้ว
กลไก routing จะ recognize url ได้อย่างไร
ส่วนที่น่าสนใจในตอนที่ 1 ก็คือ
การ dynamic generate anonymous module
แล้วค่อย include มันเข้ากับ ActionController
ส่วนตอนที่ 2 มี code ที่พิสดารมากอยู่จุดหนึ่ง ก็คือ
ความพิสดารอยู่ที่มัน recursive เรียกตัวมันเอง
แต่ก่อนที่จะเรียกตัวมันเอง มันทำการ rewrite ตัวเองด้วย method
รูปแบบนี้เป็น lazy method แบบหนึ่ง
นั่นคือยังไม่เตรียมอะไร จนกว่าจะถูกเรียกใช้
ตอนแรกพูดถึง
Under the hood: Rails' routing DSL
ว่าด้วยการทำงานภายใน เวลา rails เริ่มอ่าน file $RAIL_ROOT/config/route.rb
จะมีการทำงานภายในอย่างไร
ส่วนตอนสองพูดถึง
Under the hood: route recognition in Rails
อธิบายว่า ถ้ามี request วิ่งเข้ามาแล้ว
กลไก routing จะ recognize url ได้อย่างไร
ส่วนที่น่าสนใจในตอนที่ 1 ก็คือ
การ dynamic generate anonymous module
แล้วค่อย include มันเข้ากับ ActionController
ส่วนตอนที่ 2 มี code ที่พิสดารมากอยู่จุดหนึ่ง ก็คือ
def recognize(path, environment={})
write_recognition
recognize path, environment
end
ความพิสดารอยู่ที่มัน recursive เรียกตัวมันเอง
แต่ก่อนที่จะเรียกตัวมันเอง มันทำการ rewrite ตัวเองด้วย method
write_recognition
รูปแบบนี้เป็น lazy method แบบหนึ่ง
นั่นคือยังไม่เตรียมอะไร จนกว่าจะถูกเรียกใช้
Related link from Roti
Training Professors
BitWorking เขาลง link เรื่อง video แสดงการฝึกปลาทอง ใน youtube
แต่ที่ผมชอบไม่ใช่เรื่องนี้หรอก แต่เป็นเรื่องที่เขาเล่าให้ฟัง
ในอีกแง่หนึ่ง เรื่องนี้เป็นเรื่องที่เกิดตลอดเวลา ทั้งที่ตั้งใจและไม่ตั้งใจ
แต่เรา(ผู้ที่อาจโดนกระทำอยู่)จะรู้ตัวหรือเปล่า?
แต่ที่ผมชอบไม่ใช่เรื่องนี้หรอก แต่เป็นเรื่องที่เขาเล่าให้ฟัง
She was taking a psychology class with a professor that really liked his students to take notes. He also liked to pace in front of the blackboard when he lectured. After finishing the section on Pavlov the class got together and decided to only take notes when the professor was in front of the left side of the blackboard. After a week he was only pacing there. So the next week they cut the left hand side in half and did it again. And again. They kept cutting his pacing space in half and in a month had him firmly planted on the left hand side of the blackboard.
ในอีกแง่หนึ่ง เรื่องนี้เป็นเรื่องที่เกิดตลอดเวลา ทั้งที่ตั้งใจและไม่ตั้งใจ
แต่เรา(ผู้ที่อาจโดนกระทำอยู่)จะรู้ตัวหรือเปล่า?
Related link from Roti
Wednesday, October 04, 2006
XQuery
ช่วงนี้มีโปรเจคที่ต้องยุ่งกับ XML เยอะๆอยู่ตัว
ก็เลยมองหา solution ที่มาช่วยจัดการ
หนึ่งใน solution นั้นก็คือ XQuery
query language ของ Relational Database คือ SQL
query language ของ XML ก็คือ XQuery
ตัว syntax ของ XQuery มีบางคนเรียกย่อๆว่า FLWOR
ซื่อย่อมาจาก causes หลักๆที่ XQuery support นั่นคือ
มาตรฐานของ XQuery จะ depend อยู่บน มาตรฐานของ XPath 2.0
นั่นคือการอ้างถึง element ต่างๆ จะทำผ่าน XPath expression
ใครอยากเห็นว่าหน้าตา syntax เป็นอย่างไร ให้ดูที่ link นี้
Blooming FLWOR - An Introduction to the XQuery FLWOR Expression
ตัว language เห็นบางคนก็บอกว่า มีแนวทางไปในทางเดียวกับ Functional Language
อ่านดูได้ใน XQuery: a typed functional language for querying XML
ส่วนบางคนก็บอกว่า XQuery is imperative
ถ้ามีสองความคิดเห็นอย่างนี้ แสดงว่า xquery มันน่าอยู่กลางๆ spectrum ที่ฝั่งซ้ายเป็น declarative
ส่วน ฝั่งขวาเป็น imperative
(ไม่ว่าจะเป็นอะไร ก็ช่างหัวมันเถิด ใช้งานได้ดีก็พอแล้ว)
ผมชอบความ powerful ของมัน ลองดูตัวอย่างนี้
สมมติเรามี xml ที่ present Part ในลักษณะ Flat อยู่
ถ้าเราต้องการ convert ให้เป็นแบบนี้
เราสามารถทำได้ โดยเขียน XQuery ในแบบนี้
ช่วงนี้เพื่อทดสอบความเป็นไปได้ต่างๆ ผมก็เลยลองหา Opensource มาเล่นก่อน
ตัวที่น่าสนใจก็คือ eXist
ซึ่งเจ้านี้ claim ว่า XQuery ของเขา test ตามมาตรฐานของ w3c ผ่านกว่า 80% แล้ว
Architecture ของ eXist (ในแง่ implement) ก็น่าสนใจ ตรงที่ Framework ที่เขาใช้เขียน server
base อยู่บน Cocoon ซึ่งเป็น Development Framework ที่อิงกับ XML อย่างแนบแน่น
ก็เลยมองหา solution ที่มาช่วยจัดการ
หนึ่งใน solution นั้นก็คือ XQuery
query language ของ Relational Database คือ SQL
query language ของ XML ก็คือ XQuery
ตัว syntax ของ XQuery มีบางคนเรียกย่อๆว่า FLWOR
ซื่อย่อมาจาก causes หลักๆที่ XQuery support นั่นคือ
- F -> For
- L -> Let
- W -> Where
- O -> Order by
- R -> Return
มาตรฐานของ XQuery จะ depend อยู่บน มาตรฐานของ XPath 2.0
นั่นคือการอ้างถึง element ต่างๆ จะทำผ่าน XPath expression
ใครอยากเห็นว่าหน้าตา syntax เป็นอย่างไร ให้ดูที่ link นี้
Blooming FLWOR - An Introduction to the XQuery FLWOR Expression
ตัว language เห็นบางคนก็บอกว่า มีแนวทางไปในทางเดียวกับ Functional Language
อ่านดูได้ใน XQuery: a typed functional language for querying XML
ส่วนบางคนก็บอกว่า XQuery is imperative
ถ้ามีสองความคิดเห็นอย่างนี้ แสดงว่า xquery มันน่าอยู่กลางๆ spectrum ที่ฝั่งซ้ายเป็น declarative
ส่วน ฝั่งขวาเป็น imperative
(ไม่ว่าจะเป็นอะไร ก็ช่างหัวมันเถิด ใช้งานได้ดีก็พอแล้ว)
ผมชอบความ powerful ของมัน ลองดูตัวอย่างนี้
สมมติเรามี xml ที่ present Part ในลักษณะ Flat อยู่
<?xml version="1.0" encoding="ISO-8859-1"?>
<partlist>
<part partid="0" name="car"/>
<part partid="1" partof="0" name="engine"/>
<part partid="2" partof="0" name="door"/>
<part partid="3" partof="1" name="piston"/>
<part partid="4" partof="2" name="window"/>
<part partid="5" partof="2" name="lock"/>
<part partid="10" name="skateboard"/>
<part partid="11" partof="10" name="board"/>
<part partid="12" partof="10" name="wheel"/>
<part partid="20" name="canoe"/>
</partlist>
ถ้าเราต้องการ convert ให้เป็นแบบนี้
<parttree>
<part partid="0" name="car">
<part partid="1" name="engine">
<part partid="3" name="piston"/>
</part>
<part partid="2" name="door">
<part partid="4" name="window"/>
<part partid="5" name="lock"/>
</part>
</part>
<part partid="10" name="skateboard">
<part partid="11" name="board"/>
<part partid="12" name="wheel"/>
</part>
<part partid="20" name="canoe"/>
</parttree>
เราสามารถทำได้ โดยเขียน XQuery ในแบบนี้
declare function local:one_level($p as element()) as element()
{
<part partid="{ $p/@partid }"
name="{ $p/@name }" >
{
for $s in doc("partlist.xml")//part
where $s/@partof = $p/@partid
return local:one_level($s)
}
</part>
};
<parttree>
{
for $p in doc("partlist.xml")//part[empty(@partof)]
return local:one_level($p)
}
</parttree>
ช่วงนี้เพื่อทดสอบความเป็นไปได้ต่างๆ ผมก็เลยลองหา Opensource มาเล่นก่อน
ตัวที่น่าสนใจก็คือ eXist
ซึ่งเจ้านี้ claim ว่า XQuery ของเขา test ตามมาตรฐานของ w3c ผ่านกว่า 80% แล้ว
Architecture ของ eXist (ในแง่ implement) ก็น่าสนใจ ตรงที่ Framework ที่เขาใช้เขียน server
base อยู่บน Cocoon ซึ่งเป็น Development Framework ที่อิงกับ XML อย่างแนบแน่น
Related link from Roti
Tuesday, October 03, 2006
IEs4Linux
ช่วงหลังๆนี่ ละเลย IE มาตลอด (2 ปีแล้ว)
อย่างบางโปรเจคที่บังคับให้ใช้ firefox ได้ ผมก็จะ implement โดยไม่สนใจ IE เลย
(แต่จะมีน้องๆที่เสียดาย IE มาคอย port ให้ IE ใช้ได้)
มีโปรเจคใหม่อยู่ตัว ที่ต้อง support IE แน่ๆ
แต่เนื่องจากเครื่องที่ใช้เป็น Linux กับ Mac
ก็เลยต้องขวนขวายมากกว่าปกติ
เดิมมองไว้ที่ vmware
แต่ลองแล้ว มันหนักไปหน่อย
สุดท้ายก็ไปลงตัวที่ IEs4Linux
ซึ่ง run โดยใช้ Wine
การติดตั้งก็ง่ายมาก (ผมใช้ fedora)
ลงทีเดียวได้ครบตั้งแต่ version 5, 5.5, 6
ใครสนใจก็ลองดูได้
Related link from Roti
Monday, October 02, 2006
Prevayler
มองหา Persistent Storage ที่เหมาะๆมานานแล้ว
วันนี้ได้ฤกษ์ลองเล่น Prevayler ดู
(จริงๆ แล้ว prevayler มีมานานมากแล้ว
แต่ด้วย nature ของผมที่เมื่อก่อนเป็นพวก emotionally attached to database
พอเห็นคำเปรยที่ว่า Memory Only ก็เดินหนีแล้ว
)
ลองดู Architecture ก่อน
ฟังดูแล้ว ก็น่าสนใจดี
ลองดูภาพการใช้งานจริง
สมมติ application ตัวอย่างเป็น Bank application
ที่ต้อง maintain account ของ customer
ใน prevayler ไม่มี concept เรื่อง table แบบ Relational DB
ข้อมูลที่จะเก็บลง Prevayler ต้องอยู่ในรูป Object
ดังนั้นเราจึง define Bank Class ขึ้นมา เพื่อใช้ maintain account object ของเรา
ตัว Account Class ก็เขียนง่ายๆดังนี้
เนื่องจากกลไกที่ prevayler ใช้ในการทำ snapshot
ก็คือ java serialize ธรรมดา (ตรงนี้สามารถเปลี่ยนวิธีได้ เช่นไปใช้ xml serialize)
ดังนั้น class Bank กับ Account ของเรา ก็เลยต้อง implement Serializable
การเริ่่มต้นใช้งาน prevayler จะเริ่มต้นดังนี้
ในการที่จะสร้าง Account ขึ้นมา, เราจะไม่ใช้วิธี access Bank Object ตรงๆ
แต่จะทำผ่าน Command Object
ลองดูตัวอย่าง Command Object ที่ใช้ create Account
เมื่อจะใช้งาน ก็สั่งผ่าน prevayler object
ที่นี้ก็มาถึงคำถามถึงจุดนี้ถ้าเราปิดโปรแกรมเราลงไป แล้วเปิดขึ้นมาใหม่
Bank Object เราจะยังมี Account Object ที่พึ่งสร้างอยู่หรือไม่
คำตอบก็คือ "มี"
เพราะเมื่อเราสั่ง execute Command Object เมื่อไร
prevayler จะทำการสร้าง journal file ขึ้นมา
(1 command ต่อ 1 journal file)
กลไกการเขียน journal ก็ใช้ java serialize ธรรมดา
ที่นี้การเก็บข้อมูลในรูป journal อย่างเดียวคงไม่เหมาะแน่
เพราะมันจะเยอะแยะไปหมด และน่าจะกินเวลา startup time
(prevayler cliam ว่าสามารถ execute journal ใน rate 6000 journal/sec.)
prevayler ก็เลยมีความสามารถในการทำ snapshot ด้วย
โดยการสั่ง
หลังจากทดลองเล่น + อ่าน Architecture แล้ว
ก็จัดการ add เข้า Collection Tools ของตัวเอง
โดย usecase ที่จะนำไปใช้ ก็คือ
ข้อเตือนใจ
วันนี้ได้ฤกษ์ลองเล่น Prevayler ดู
(จริงๆ แล้ว prevayler มีมานานมากแล้ว
แต่ด้วย nature ของผมที่เมื่อก่อนเป็นพวก emotionally attached to database
พอเห็นคำเปรยที่ว่า Memory Only ก็เดินหนีแล้ว
)
ลองดู Architecture ก่อน
- Prevayler maintain ข้อมูลใน Memory เท่านั้น
- ข้อมูลที่ maintain อยู่ในรูป Plain Old Java Object
- เนื่องจากข้อมูลเก็บอยู่บน Memory เป็นหลัก
เพื่อให้ persistent สามารถ keep state ได้
prevayler ใช้วิธีทำ snapshot ลงบน Disk - การแก้ไขข้อมูลจะต้องทำผ่าน Transaction
โดยใช้ pattern ที่เรียกว่า Command pattern - เมื่อเราสั่ง execute Command Object(Transaction)
Prevayler จะทำการ serialize Command Object ของเราลง Journal file ก่อนที่ update ข้อมูลใน memory
เพื่อทีในกรณีที่ system fail ก่อนที่จะทำ snapshot
จะได้สามารถทำ recover persistent state กลับมาได้
ฟังดูแล้ว ก็น่าสนใจดี
ลองดูภาพการใช้งานจริง
สมมติ application ตัวอย่างเป็น Bank application
ที่ต้อง maintain account ของ customer
ใน prevayler ไม่มี concept เรื่อง table แบบ Relational DB
ข้อมูลที่จะเก็บลง Prevayler ต้องอยู่ในรูป Object
ดังนั้นเราจึง define Bank Class ขึ้นมา เพื่อใช้ maintain account object ของเรา
public class Bank implements Serializable {
private static final long serialVersionUID = -3472784405094724103L;
public List<Account> accounts = new ArrayList<Account>();
public List<Account> getAccounts() {
return accounts;
}
public void addAccount(Account acct) {
accounts.add(acct);
}
}
ตัว Account Class ก็เขียนง่ายๆดังนี้
public class Account implements Serializable {
private static final long serialVersionUID = 5447177127896043827L;
private String code;
private BigDecimal amount;
public Account(String code, BigDecimal amount) {
this.code = code;
this.amount = amount;
}
... getter/setter here.
}
เนื่องจากกลไกที่ prevayler ใช้ในการทำ snapshot
ก็คือ java serialize ธรรมดา (ตรงนี้สามารถเปลี่ยนวิธีได้ เช่นไปใช้ xml serialize)
ดังนั้น class Bank กับ Account ของเรา ก็เลยต้อง implement Serializable
การเริ่่มต้นใช้งาน prevayler จะเริ่มต้นดังนี้
Prevayler prevayler = PrevaylerFactory.createPrevayler(new Bank(), "bank");
Bank bank = (Bank) prevayler.prevalentSystem();
ในการที่จะสร้าง Account ขึ้นมา, เราจะไม่ใช้วิธี access Bank Object ตรงๆ
แต่จะทำผ่าน Command Object
ลองดูตัวอย่าง Command Object ที่ใช้ create Account
public class CreateAccount implements Transaction {
private static final long serialVersionUID = 8524963860312931007L;
private Account account;
public CreateAccount(Account account) {
this.account = account;
}
public void executeOn(Object prevalentSystem, Date executionTime) {
Bank bank = (Bank) prevalentSystem;
bank.addAccount(account);
}
}
เมื่อจะใช้งาน ก็สั่งผ่าน prevayler object
prevayler.execute(new CreateAccount(new Account("11", new BigDecimal("200.00"))));
ที่นี้ก็มาถึงคำถามถึงจุดนี้ถ้าเราปิดโปรแกรมเราลงไป แล้วเปิดขึ้นมาใหม่
Bank Object เราจะยังมี Account Object ที่พึ่งสร้างอยู่หรือไม่
คำตอบก็คือ "มี"
เพราะเมื่อเราสั่ง execute Command Object เมื่อไร
prevayler จะทำการสร้าง journal file ขึ้นมา
(1 command ต่อ 1 journal file)
กลไกการเขียน journal ก็ใช้ java serialize ธรรมดา
ที่นี้การเก็บข้อมูลในรูป journal อย่างเดียวคงไม่เหมาะแน่
เพราะมันจะเยอะแยะไปหมด และน่าจะกินเวลา startup time
(prevayler cliam ว่าสามารถ execute journal ใน rate 6000 journal/sec.)
prevayler ก็เลยมีความสามารถในการทำ snapshot ด้วย
โดยการสั่ง
prevayler.takeSnapshot();
หลังจากทดลองเล่น + อ่าน Architecture แล้ว
ก็จัดการ add เข้า Collection Tools ของตัวเอง
โดย usecase ที่จะนำไปใช้ ก็คือ
- พวก Desktop Application ตัวเล็กๆ
- กลไก Data บางอย่างที่ขี้เกียจทำ ORM (เริ่มเบื่อแล้ว)
เช่น User preference ใน Web application - เอาไว้เก็บพวก workflow instance ก็ไม่เลว
- เก็บ Fact ของพวก rule base ก็น่าจะได้
ข้อเตือนใจ
- Prevayler maintain ทุกอย่างใน memory
snapshot เป็นแค่ backup
ดังนั้นต้องแน่ใจว่ามี Ram พอ, กับข้อมูลไม่เยอะจนเกินไป - อย่าไปนึกว่าจะมี กลไก Index แบบ Relational database
การ access object เป็นไปตาม java object ธรรมดา
ดังนั้นอะไรที่อยากให้ access เร็ว ก็ต้องใช้พวก Map - ถ้า Domain เราซับซ้อน
command object ก็จะมีปริมาณสูง ทำให้ maintain ลำบากขึ้น (อะไร,อยู่ที่ไหน)
Related link from Roti
Subscribe to:
Posts (Atom)