Saturday, September 03, 2005

Link น่าสนใจ (2005-09-03)

Related link from Roti

Friday, September 02, 2005

ความหมายของคำว่า Maven

ใช้ Maven มาตั้งนาน พึ่งรู้ความหมายของคำนี้
People who love to acquire knowledge on all sorts of topics and, perhaps more importantly, love to tell others about what they've learned (in fact, the word maven comes from Yiddish and means someone who accumulates knowledge).


ไปได้มาจาก David Geary 's Weblog ในหัวข้อเรื่อง Tipping Rails
ที่เล่าถึงประเด็นที่เขาเชื่อว่า Rails จะถึงจุด tipping point ในไม่ช้า

Related link from Roti

Ruby กับการ parse binary file

ช่วงนี้มี project ที่จะลองใช้ ruby parse wtmp file
และทำการ generate Image ที่แสดงลักษณะการใช้งานของ user ออกมา
(จริงๆแล้วมันไม่ต้องเวอร์ขนาดนี้ก็ได้ แต่อยากลอง feature ต่างๆดู)

เริ่มแรกสิ่งที่ต้อง solve ก็คือการ parse wtmp file
ขอยกตัวอย่างเฉพาะเจาะจงลงไปที่ wtmp file ที่ได้จาก AIX แล้วกัน
ใน AIX wtmp file จะมี record size = 648 byte
(AIX version ใหม่ ของเก่าขนาดเล็กกว่านี้เยอะ)
วิธีการที่ผมใช้ก็คือ อ่าน file ทีละ 648 byte เป็น string จากนั้นก็ส่งไป
ให้ parseRecord ทำงาน

def parseFile(fileName)
list = Array.new
begin
File.open(fileName, 'r') do |file|
while (! file.eof)
tmp = parseRecord(file.read(648))
wtmp = Wtmp.new(tmp)
list << wtmp
end
end
rescue
end
return list
end

ตัว parseRecord ก็จะใช้ method unpack เข้ามาช่วย
method นี้จะ return Array ของ object โดยเราต้องกำหนด template
ที่จะใช้ในการ parse

def parseRecord(str)
str.unpack("A256A14A64x2Nnx6Nnna256x36")
end

ความหมายของ template ที่ใช้
  • A256 -> return String ที่ตัดเอา white space ออกแล้ว
    ส่วนค่า 256 ก็คือ ความยาวของ data ที่ต้องการอ่านขึ้นมา ในที่นี้คือ 256 byte
  • x2 -> skip ข้ามไป 2 byte
  • N -> integer ความยาว 4 byte
  • n -> short (2 byte)


Link
Document ของ unpack method ใน String class

Related link from Roti

Wednesday, August 31, 2005

เล่าให้ฟัง (48-08-31)

วันก่อนอ่านเจอตารางตัวเลข โครงสร้างแรงงานนอกระบบ
ในหนังสือมติชนรายสัปดาห์ มีจุดสะดุดตาที่หนึ่งก็คือ
ประกอบอาชีพอิสระ
- มีฝีมือสูง (วิศวกร/สถาปนิก/เภสัช)
- มีฝีมือปานกลาง (โปรแกรมเมอร์, สอนพิเศษ, นักร้อง, นักแสดง)
- มีฝึมือทั่วไป (ช่างเสริมสวย, แผงลอย, สาธิตสินค้า)

อืมม์ อาชีพเรานี่ใช้ฝีมือปานกลางเอง
กลับไปเป็นวิศวกรไฟฟ้าดีกว่าแฮะ

ช่วงนี้อ่านหนังสืออยู่เล่มหนึ่งชื่อ "ท้าวทองกีบม้า"
ของสำนักพิมพ์มติชน ขอบรรยายให้ฟังคร่าวๆ พอเป็นกระสัย

ชื่อ "ท้าวทองกีบม้า" เป็นชื่อบรรดาศักด์ิของข้าราชสำนักฝ่ายใน
มีหน้าที่ประกอบอาหารหวาน
ที่มาของชื่อนี้ก็มีคนสันนิษฐานไว้หลายแนว
แต่ที่หนังสือเล่มนี้ขยายความ ก็คือ ชื่อนี้เป็นชื่อที่ได้มาจากชื่อ
"แคทเทอริน เดอ ทอร์ควิมา" ซึ่งเป็นภรรยาของ
เจ้าพระยาวิชาเยนทร์ (คอนแสตนติน ฟอลคอน)
ในสมัยสมเด็จพระนารายณ์

เธอเป็นลูกครึ่งโปรตุเกส กับ ญี่ปุ่น
สืบเชื้อสายมาจาก ออกญาเสนาภิมุข (ยามาดา)
ที่รับราชการในสมัยพระเอกาทศรถ

หลังจากความวุ่นวายในช่วงเปลี่ยนราชวงศ์ในช่วงนั้น
ฟอลคอนถูกกำจัด (อาจรวมถึงพระนารายณ์ด้วย)
ตัวท้าวทองกีบม้า ถูกนำตัวไปเป็นทาสในวัง มีหน้าที่ทำอาหาร
ซึ่งช่วงนั้นแหล่ะที่เป็นที่มาของขนมหวาน
ที่มีไข่และน้ำตาลเป็นส่วนประกอบ (เป็นลักษณะของอาหารโปรตุเกส)
เช่น ทองหยิบ ทองหยอด ฝอยทอง ทองโปร่ง ทองพลุ ขนมหม้อแกง
สังขยา ....

เกริ่นแค่นี้พอแล้วกัน เล่มจริงอ่านแล้วเพลินดี
ใครสนใจลองหาอ่านดู
แถมกลอนให้อีกนิด

ทองหยิบทิพย์เทียมทัด สามหยิบชัดน่าเชยชม
หลงหยิบว่ายาดม ก้มหน้าเมินเขินขวนใจ
...
ทองหยอดทอดสนิท ทองม้วนมิดคิดความหลัง
สองปีสองปิดบัง แต่ลำพังสองต่อสอง

(กลอนของ ร.1)

Related link from Roti

ทดลอง Implement Business Rule ด้วย Drools

โดยปกติเวลาเรา implement business logic เรามัก
จะเขียน code ลงไปตรงๆ โดยใช้พวก control statement เป็นหลัก (พวก if statement)
ถ้าเป็นโปรแกรมที่มี bussiness logic ซับซ้อน ก็คงจะต้อง
เคยปวดหัวกับ if block อันมหาศาล โปรแกรมพวกนี้
ส่วนใหญ่จะเกี่ยวกับเงินๆทองๆ เช่น Module Doctor Fee (พวกหมอในโรงพยาบาลเอกชน
จะมีวิธีการคำนวณเงินที่ซับซ้อนมาก) หรือ Module การคำนวณเงินลงทะเบียนของนักศึกษา

ในโปรแกรมใหญ่ๆ ที่อยู่บน Mainframe มีอยู่จำนวนหนึ่งที่
นิยม implement business logic ด้วย Rule Engine
ถามว่าช่วยลดความซับซ้อนได้แค่ไหน
อันนี้ตอบไม่ได้เหมือนกัน เพราะยังไม่เคยลองเลย
แต่เท่าที่ดู ในกรณีที่มี Rule เยอะมาก ปัญหาที่เกิดก็คือ
Rule จะเกิด conflict กันได้ง่าย
ต้องมี Debugger หรือ Test Case ดีๆ ไว้ช่วย

ในส่วนของ Java ผมสนใจ Rule Engine อยู่หลายตัวเหมือนกัน
ช่วงนี้ได้ลองใช้ Drools ดู ก็พบว่าเข้าท่าดีเหมือนกัน
ตัว Drools เองใช้ Charles Forgy's Rete algorithm
ลองมาดูตัวอย่างการ Implement กันดู

สมมติว่าเราจะใช้ Rule Engine ในส่วนของการ คำนวณ Discount
ของ Sale Order
เริ่มด้วยการ define Domain ก่อน ทำง่ายๆดังนี้



ส่วน business rule ที่จะ implement มีดังนี้
  • ลูกค้าทุกคนที่ซื้อของ ในเบื้องต้นจะได้ส่วนลด 5 %
  • กรณีที่เป็นลูกค้าภาคเหนือ จะให้ส่วนลด 7 % แทน
  • กรณีที่ซื้อสินค้าเกิน 1500 บาท และซื้อเป็นเงินสด จะให้ส่วนลด 10 %
  • สินค้า "a-1" จะไม่มีส่วนลด (ไม่เอายอดไปคำนวณในส่วนลดรวม)


Drools ให้เรากำหนด Rule ผ่านทาง xml file
โดยรูปแบบของ file เป็นดังนี้
<?xml version="1.0"?>
<rule-set name="BusinessRulesSample"
xmlns="http://drools.org/rules"
xmlns:java="http://drools.org/semantics/java"
xmlns:xs
="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation
="http://drools.org/rules rules.xsd
http://drools.org/semantics/java java.xsd">
<!-- Import the Java Objects that we refer
to in our rules -->
<java:import>
pok.test.Order
</java:import>


<!-- Rule -->

</rule-set>

กฎข้อที่ 1 "ลูกค้าทุกคนที่ซื้อของ ในเบื้องต้นจะได้ส่วนลด 5 %"
เขียนได้ดังนี้
  <rule name="ในเบื้องต้น ลูกค้าทุกคนได้ส่วนลด 5 %" salience="100">
<parameter identifier="order">
<class>pok.test.Order</class>
</parameter>
<java:condition>
1 == 1
</java:condition>
<java:consequence>
order.setPercentDiscount(5.0);
</java:consequence>
</rule>
</rule-set>

กฎข้อที่ 2 "กรณีที่เป็นลูกค้าภาคเหนือ จะให้ส่วนลด 7 %"
  <rule name="ลูกค้าภาคเหนือได้ส่วนลด 7 %" salience="20">
<parameter identifier="customer">
<class>pok.test.Customer</class>
</parameter>
<parameter identifier="order">
<class>pok.test.Order</class>
</parameter>
<java:condition>
customer.getRegion() == Customer.NORTH
</java:condition>
<java:condition>
order.getCustomer() == customer
</java:condition>
<java:consequence>
order.setPercentDiscount(7.0);
</java:consequence>
</rule>

กฎข้อที่ 3 "กรณีที่ซื้อสินค้าเกิน 1500 บาท และซื้อเป็นเงินสด จะให้ส่วนลด 10 %"
  <rule name="สังซื้อมากกว่า 1500 บาท และเป็นเงินสด ได้ส่วนลด 10 %" salience="10
">
<parameter identifier="order">
<class>pok.test.Order</class>
</parameter>
<java:condition>
order.getAmount() > 1500.0
</java:condition>
<java:condition>
order.getPayType() == Order.CASH
</java:condition>
<java:consequence>
order.setPercentDiscount(10.0);
</java:consequence>
</rule>

กฎข้อที่ 4 "สินค้า "a-1" จะไม่มีส่วนลด"
  <rule name="สินค้า p-1 จะไม่ให้ส่วนลด" salience="0">
<parameter identifier="item">
<class>pok.test.OrderItem</class>
</parameter>
<java:condition>
item.getProduct().getProductCode().equals("p-1")
</java:condition>
<java:consequence>
item.setIncludeInTotalDiscount(false);
</java:consequence>
</rule>


ในการ run จะเขียน code ดังนี้
    RuleBase businessRules = RuleBaseLoader.loadFromUrl(BusinessLayer.class
.getResource("DiscountRules.xml"));
WorkingMemory workingMemory = businessRules.newWorkingMemory();
// Small ruleset, OK to add a debug listener
workingMemory.addEventListener(new DebugWorkingMemoryEventListener());

workingMemory.assertObject(order);
workingMemory.assertObject(order.getCustomer());
for (Iterator iter = order.getItems().iterator(); iter.hasNext();) {
OrderItem item = (OrderItem) iter.next();
workingMemory.assertObject(item);
}
workingMemory.fireAllRules();

// Test Result
System.out.println("Discount = " + order.getPercentDiscount());
for (Iterator iter = order.getItems().iterator(); iter.hasNext();) {
OrderItem item = (OrderItem) iter.next();
if (! item.isIncludeInTotalDiscount()) {
System.out.println("\titem:" +item.getProduct().getProductCode() + "
is no discount");
}
}

จะเห็นว่าขั้นแรก เราต้อง load Rule จาก xml file ก่อน
จากนั้นก็ทำการ initialize Working Memory ขึ้นมา
ส่วน DebugListener ที่ใส่เข้าไป ก็เพื่อจะให้ Drools dump debug information
ออกมาให้เราดู
จากนั้นก็เป็นการ assert Fact เข้าไป
สุดท้ายก็สั่ง fireAllRules เพื่อให้ Rule Engine เริ่มคำนวณผลลัพท์

ข้อที่ต้องระวัง ก็คือ Conflict ของ Rule
อย่างในตัวอย่างของเรา สมมติให้ Data ที่จะทดสอบมี nature ดังนี้
  • customer อยู่ในภาคเหนือ
  • ซื้อของ 7000 บาท เป็นเงินสด

ถ้าดูที่ Rule ที่เรากำหนดขึ้นมา จะเห็นว่า
Conflict จะเกิดได้ที่ rule ข้อ 2 กับ ข้อ 3
โดยข้อ 2 จะให้ส่วนลด 7 % ส่วนข้อ 3 จะให้ส่วนลด 10 %
การ solve สามารถทำได้หลายวิธี
ในกรณีของเรา เราใช้การกำหนด salience เข้ามาช่วย
โดยให้ rule ข้อ 2 มี saliance = 20 ส่วนข้อ 3 = 10
ดังนั้น Drools จะตัดสินให้ข้อ 3 ชนะ (ค่าน้อยๆมันทำทีหลัง เลยชนะ)

เท่าที่ลองทดสอบดูในประเด็นเรื่อง performance
พบว่าขั้นที่กินเวลามากสุดก็คือตอนที่เรา load xml file
ใน case ที่ทดสอบดู พบว่า
  • load xml -> ~1800 millisec
  • assert -> ~76 millisec
  • fireRule -> ~5 millisec


ไว้คราวหน้าจะลอง integrate เข้ากับ Spring ดู

อ่านเพิ่มเติม

Related link from Roti

Tuesday, August 30, 2005

Link น่าสนใจ (2005-08-30)

  • Raycoaster
    Caustics are the optical effects that occur when light gets bent several times by some refractive material. You can observe them for example on the bottom of a swimming pool or when light shines through a glass bottle. I find the resulting shapes very attractive so I have tried to create a tool which allows me to create and explore caustics or rather pseudo-caustics.

  • An Illusrated Guide to IPSec
    Article นี้ใช้การอธิบายแบบ Bottom up
    ดูแล้วเข้าใจมากขึ้นเยอะเลย

Related link from Roti

Link น่าสนใจ (2005-08-29)

  • SteP 10 Limited
    site นี้มีบทความเกี่ยวกับการ Modeling ที่น่าสนใจทีเดียว
    (ในแง่ของ Bussiness Application)
  • Implementors plugin (Eclipse Plugin)
    ช่วยในการ navigate จาก interface ไปยัง Implement Class
    หรือจะกระโดดจาก implement class, method -> interface ก็ได้

Related link from Roti

Monday, August 29, 2005

Tagging with Rails

Y.o.m.b.a.r เขียน mixin ไว้ตัวหนึ่งที่ช่วยให้ ActiveRecord
handle เรื่อง tag ได้ง่ายขึ้น

ดูตัวอย่างการใช้งาน
class Photo < ActiveRecord::Base
acts_as_taggable
end

elephant = Photo.find(4437)
elephant.tag 'zoo animals nature'

elephant.tagged_by?('urban') # => false
elephant.tags.size # => 3
elephant.tag_names # => [ 'zoo', 'animals', 'nature' ]

วิธีการใช้ ก็คือให้เอา source ไปใส่ไว้ใต้ lib directory
แล้วก็แก้ config/environment.rb เพิ่มคำสั่ง require 'tagggale'

Related link from Roti

เรียนรู้ CLISP

สั่งซื้อหนังสือเกี่ยวกับ RUBY, RAILS จาก amazon มาอาทิตย์กว่าแล้ว
มันยังไม่ shpping เลย ก็เลยไปเดินร้านหนังสือที่ fortune มา
ได้หนังสือ Practical Common Lisp มาเล่มหนึ่ง

หนังสือเขียนดีใช้ได้เลย ชอบตรงที่เขาไม่เริ่มต้นด้วยการอธิบาย syntax
หรือ language feature แต่พยายามแสดงให้เห็นเลยว่า ถ้าเขียนกับโจทย์จริงๆแล้ว
จะต้องเขียนอย่างไรบ้าง

Environment ที่เขาแนะนำให้ใช้ ก็คือ ใช้ emacs ​+ slime
ซึ่งเท่าที่ลองใช้ดูก็ work ดีมาก เสียอย่างเดียว
ยังจำคำสั่ง emacs ไม่ได้ (การกด meta key ก็วุ่นวายไปนิด
ใน OS X ที่ผมใช้ มันต้องกด ESC ทำให้ต้องง้างนิ้วไกลไปหน่อย
)
ส่วนตัว CLISP ผมใช้ GNU CLISP

สำหรับคนที่ใช้ java ก็มี Armed Bear Common List
ตัวนี้เป็น ANSI Common Lisp ที่ run บน Java Virtual Machine
มีข้อเสียในการ build นิดหน่อย ก็คือ ต้องใช้ Common LISP ในการ build

Related link from Roti

Sunday, August 28, 2005

Link น่าสนใจ (2005-08-27)

Roumen 's Weblog เขาเขียนเล่าเรื่อง Usability Studies of NetBeans
อ่านเพลินดีเหมือนกัน ที่ตลกก็คือเขาเล่าว่า เขาสามารถบอกได้ว่า ใคร(คนที่มาทดสอบ)
เป็นคนที่ใช้ eclipse อยู่แล้วบ้าง โดยดูจากพฤติกรรมที่คนคนนั้นเห็น error
เท้าความนิดหนึ่ง ใน eclipse เวลาเกิด error จะมีรูปกากะบาทเกิดขึ้นด้านซ้าย
ส่วนใน netbeans ก็เช่นเดียวกันเป็นรูปกากะบาทเหมือนกัน
ถ้าเป็นคนที่ใช้ eclipse อยู่ เวลาเกิด error ก็จะมีพฤติกรรมเหมือนกันหมด
ก็คือใช้ mouse ไป click ที่กากะบาท ซึ่งแน่นอนใน Netbeans การทำเช่นนั้น
จะกลายเป็นการ add Breakpoint แทน ที่น่าสนใจก็คือพฤติกรรมนั้นค่อนข้างจะติดเป็นนิสัย คือ ถึงจะเรียนรู้แล้ว
ว่า click กากะบาทใน netbeans ไม่ได้เป็นการแสดง error แต่พอเกิด error ใหม่ ก็จะยัง
คงพยายาม click กากะบาทอยู่ดี
ฟังเขาเล่าถึงเรื่องนี้แล้วก็นึกถึงตัวเองเหมือนกัน เมื่ออาทิตย์ก่อน ก็ใช้ Netbeans
paint หน้าจอ UI เหมือนกัน (ปกติใช้ eclipse แต่ชอบ visual editor
ของ netbeans มากกว่า) จะหงุดหงิดมากเวลาเกิด error แล้วพยายาม click
กากะบาทแล้วดันกลายเป็นการ add Breakpoint แทนแล้วก็ไม่จำด้วย เกิดใหม่ก็เผลอไป click ใหม่

Extremely Successful Software
มีอยู่ part หนึ่งที่เขาพูดถึง Technology ที่เขาใช้
Interestingly, when we checked we found that a number of Fortune 1000 companies were using Lisp in critical applications such as on-line banking and airline reservation systems.

อืมม์ผมนี่โลกแคบเหมือนกันแฮะ ไม่รู้เลยว่ามีคนใช้ Lisp ใน Business Application
สงสัยต้องเรียนรู้ภาษานี้บ้างแล้ว

Gigayachts lure the mega-rich
อันนี้สำหรับผู้ที่ใช้ Oracle
จะได้รู้ว่า license ที่จ่ายไป สุดท้ายไปอยู่ที่ไหน
Ellison สั่งต่อเรือ yacht ความยาว 137 metres
ภายในประกอบด้วย 5 ชั้น, 82 ห้อง, ห้องเก็บ wine ขนาดเท่ากับ beach bungalow
มีเครื่องปั่นไฟที่ใหญ่พอสำหรับเมืองเล็กๆ
ราคาแค่ 453 millon dollars เท่านั้นเอง
ส่วนลำของ Paul Allen (co-founder of Microsoft.)
ถูกหน่อย แค่ 300 millon dollars
(Note: อ่านเจอในมติชนก่อน แล้วค่อยไป search หาใน internet)

Related link from Roti