Friday, October 06, 2006

ผลการวิจัยจาก google code

Rubyist มี blog ที่พูดถึง Measuring programmer happiness?
วัดโดยใช้ข้อมูลจาก google code

Related link from Roti

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 ที่พิสดารมากอยู่จุดหนึ่ง ก็คือ
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 นั่นคือ
  • 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 ก่อน
  • 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