Monday, February 19, 2007

Any bug here?

Ridiculous fish เขียน post ดีๆอีกแล้ว
คราวนี้เขาแสดงให้ดูว่า
code ข้างล่างนี้มี bug ได้อย่างไร
(เพื่อความสนุกในการอ่าน, ให้พยายามไล่ดู code ก่อน
ว่ามันจะมี bug v2 > v1 ได้อย่างไร)
unsigned variable1 = 0;
unsigned variable2 = 0;

#define ITERATIONS 50000000

void *writer(void *unused) {
for (;;) {
variable1 = variable1 + 1;
variable2 = variable2 + 1;
}
}

void *reader(void *unused) {
struct timeval start, end;
gettimeofday(&start, NULL);
unsigned i, failureCount = 0;
for (i=0; i < ITERATIONS; i++) {
unsigned v2 = variable2;
unsigned v1 = variable1;
if (v2 > v1) failureCount++;
}
gettimeofday(&end, NULL);
double seconds = end.tv_sec + end.tv_usec / 1000000. - start.tv_sec - start.tv_usec / 1000000.;
printf(”%u failure%s (%2.1f percent of the time) in %2.1f seconds\n”,
failureCount, failureCount == 1 ? “” : “s”,
(100. * failureCount) / ITERATIONS, seconds);
exit(0);
return NULL;
}

int main(void) {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, writer, NULL);
pthread_create(&thread2, NULL, reader, NULL);
for (;;) sleep(1000000);
return 0;
}

Related link from Roti

Saturday, February 17, 2007

T-Bone in TK Park

วันนี้พาคุณลูกไปเที่ยว TK park
บังเอิญโชคดีว่า TK park เชิญ T-Bone มาแสดงพอดี
เลยมีบุญได้ฟังการแสดงสดอย่างไกล้ชิด
โดยไม่ต้องไปเสียสุขภาพ อดหลับอดนอนไปรอฟังที่ Saxophone
เนื่องจากสถานที่ไม่ใหญ่โต คนก็ไม่เยอะ
เลยได้นั่งฟังอย่างไกล้ชิด

ผมไม่ได้ฟังการแสดงสดมานานมากแล้ว
เลยรู้สึกดีเป็นพิเศษ
ส่วนคุณลูกด้วยความที่เล่นมาทั้งวัน
พอฟังได้เพลงครึ่งก็ซบพ่อหลับไป
(beat ขนาดนั้น, เสียงก็ดัง, มันยังหลับได้อีก)

ระหว่างเล่น ก็มีเสริมความรู้ให้ด้วยนะ
เช่น อธิบายว่า สกากับเร็คเก้ ต่างกันอย่างไร
มีความเป็นมาอย่างไร
เสร็จแล้วก็เล่นเพลงเดียวกันเปรียบเทียบให้ดู
เริ่มจากสไตล์ jazz ก่อน
จากนั้นก็ลองเล่นเป็น ska
สุดท้ายก็เล่นเป็นเร็คเก้

ช่วงกลางๆมีเล่นเพลง เธอเห็นท้องฟัานั่นไหม
ได้ยินแล้วรู้สึกตัวเองแก่ทันที
ในหัวมันมีประโยคหนึ่งผุดขึ้นมา
"กาลครั้งหนึ่ง นานมาแล้ว..."

Related link from Roti

Friday, February 16, 2007

Spring return LinkList

อาจารย์มะนาว พึ่งเขียน ชื่นชอบสุดๆ
ในนั้นมี link เรื่อง The departure of the hyper-enthusiasts
ที่วิจารณ์พวก ruby + rails ที่กำลังสนุกกันมากไปหน่อย

เรื่องศาสนา กับความชอบ ผมไม่สนใจเท่าไร
ที่สนใจก็คือใน post มี quote ที่พูดถึง container
ว่าทำไม interface ใน List ของ java ไม่มี getLast() แบบที่ ruby มีใน Array

วันนี้อ่าน Sanjiv Jivan 's Blog
เจอ post know how to iterate พูดถึง spingดframework jdbc helper
มัน return List ที่เป็น linkList ออกมา
ถ้าคนไม่รู้ ดันไปใช้คำสั่งพวก
for (int i = 0; i< list.size; i++) {
X x = (X) list.get(i)
}

ถ้า data เยอะมากๆ , แตะหลักแสนเมื่อไร รับรองว่าเจอฝันร้ายด้าน performance แน่นอน

ใน post ได้อ้างถึง benchmark
ลองดูเวลาระหว่าง ArrayList กับ LinkedList

--------------------- ArrayList ---------------------
size add get set iteradd insert remove
10 121 139 191 435 3952 446
100 72 141 191 247 3934 296
1000 98 141 194 839 2202 923
10000 122 144 190 6880 14042 7333
--------------------- LinkedList ---------------------
size add get set iteradd insert remove
10 182 164 198 658 366 262
100 106 202 230 457 108 201
1000 133 1289 1353 430 136 239
10000 172 13648 13187 435 255 23


ส่วนวิธีที่ถูกต้องในการ access LinkList คือใช้ iterator

Related link from Roti

Thursday, February 15, 2007

ProjectEuler

พักนี้ใน mailing list ของ Haskell
มี newbie ถามประเด็นคำถาม เกี่ยว program
ที่เกี่ยวข้องกับโจทย์ทางคณิตศาสตร์ ถี่ขึ้น (ถี่ในที่นี้ หมายถึงประมาณ 1-3 ฉบับต่อเดือน)
เมื่ออ่านรายละเอียดก็พบว่า โจทย์นั้นมีที่มาจาก ProjectEuler
ซึ่งเป็น site ที่มีการตั้งโจทย์ทางคณิตศาสตร์ แล้วให้เขียนโปรแกรม solve หาคำตอบ

หลังจากตาม mailing list ไปที่ site นี้เป็นครั้งที่ 3
ผมก็เลยตัดสินใจลองเล่นดูบ้าง
เพื่อจะได้ฝึก programing ด้วย haskell และ ฝึกใช้สมองที่มีจุดอ่อนในส่วนคณิตศาสตร์

หลังจาก register และ login แล้ว
จึงรู้ว่ามันมีหน้าสถิติให้ดูด้วย
ซึ่งสถิติที่ผมสนใจคือตัวนี้



จากจำนวน active user 2242 คน
มีคนระบุสัญชาติ 1555 คน
เป็นอเมริกันเสีย 338 คน -> 20 %
รองลงไปคือ สวีเดน 146 คน

ลองไล่ดูกลุ่มรองลงไปบ้าง

อังกฤษ 82
เยอรมัน 84
อินเดีย 85
แคนาดา 74

กลุ่มรองลงไปอีก

โปรตุเกส 52
ออสเตรเลีย 48
รัสเซีย 44
เนเธอร์แลนด์ 39

พวกข้างบนนี่ไม่ทำให้ผมแปลกใจอะไร
แต่ชาติที่ทำให้ผมแปลกใจ ก็คือ เวียดนาม
คือมีจำนวนคนที่ active อยู่ถึง 28 คน
เทียบกับเพื่อนบ้านเรา
อินโดเนเซีย 8
มาเลเซีย 2
สิงคโปร์ 2

ถ้าผมมองว่า คนที่เข้ามาเล่นใน site นี้
เป็นกลุ่มคนที่เป็น self learning
มีแรงจูงใจจากภายในของตนเอง
เพราะว่า site นี้เขาตั้งโจทย์เฉยๆ, มีช่องให้ใส่ตัวเลขเพื่อตรวจคำตอบ
และไม่มีเฉลยให้ดู

จำนวนคนที่มาจากเวียดนาม คงบ่งบอก อนาคต บางอย่างให้เห็นได้เลาๆ

Related link from Roti

Tuesday, February 13, 2007

Version Control

เห็นข้อมูลหนังสือ Ship It เขาอ้างว่า
ที่อเมริกา ยังมี project ที่ไม่ได้ใช้พวก SCM อยู่ประมาณ 40 %
อืมม์อยากรู้จังว่าบ้านเรา มีกี่เปอร์เซนต์
คงจะมากกว่า 40 อย่างแน่นอน

ในส่วนตัวผมในแง่งานที่บริษัทฯ, ใช้ SCM มาได้หลายปีอยู่
โดยเริ่มจาก CVS แล้วก็เปลี่ยนมาเป็น SVN
สถานะปัจจุบัน "ชีวิตนี้ขาด SCM ไม่ได้แล้ว"
(prototype บางอัน ทำแค่คนเดียว ยังอุตส่าห์ใส่ SCM ด้วย)

แน่นอนว่าหลังจากเปลี่ยนมาใช้ SCM แล้ว
คุณภาพชีวิตย่อมดีขึ้นแน่นอน
แต่ก็ยังมีประเด็นเล็กๆน้อยที่ยังต้องตามแก้ไขต่อ เช่น

  • การใช้อะไรที่มากกว่า trunk
    ข้อนี้พบว่า developer ที่บริษัทผม ใช้ SCM ในการ develop main trunk เพียงอย่างเดียว
    ไม่มีใครเคยใช้ branches แม้ว่าสภาพงานบางงานเอื้อให้เกิด branch เสียเหลือเกิน
    (โปรเจคที่บริษัทฯ ส่วนใหญ่ไม่มี release
    เพราะเป็นโปรเจคแบบลูกค้าคนเดียว
    แถมยัง evolve ไปเรื่อยๆด้วย)
  • นิสัยในการแก้ไข code
    มี developer หลายๆคนที่ยังติดความเคยชินเก่าๆ ในการแก้ไข source code อยู่ เช่น
    สมมติ เรามี
    x = 1.2 * y

    ถ้ามีการแก้ไขขึ้นมา เช่นเปลี่ยน constant ที่ใช้คูณ
    แทนที่จะแก้ตรงๆ ก็ดันไปทำแบบนี้แทน
    // x = 1.2 * y
    x = 1.3 * y

    คือยังทำเหมือนกับไม่ได้ใช้ SCM
    ส่งผลให้ทั้ง source code และผลลัพท์ที่เกิดจากการ diff version, ดูรกหูรกตา
  • วิธีการ commit
    บางคนยังชอบไล่ commit ที่ละ file
    แทนที่จะทำ commit เป็น set ของการเปลี่ยนแปลง
    (ซึ่งจะทำให้การไล่อ่าน history หรือ ตรวจติดตาม change มันง่ายกว่า)
  • การใส่คำอธิบาย ในส่วนของการ commit
    อันนี้ก็คงประเด็นต่อเนื่องมาจาก comment
    ก็คือ ในเมื่อ comment ใน code ยังใส่น้อยอยู่เลย
    นับประสาอะไรกับ comment ใน changeset

Related link from Roti

Monday, February 12, 2007

กรรม เป็นผลจากการกระทำ

ยิ่งเขียนโปรแกรม ผมก็ยิ่งซึ้งกับเรื่อง "กรรม"
ยิ่ง maintain โปรแกรมเก่าเรามากเท่าไร ก็ยิ่งซึ้งมากขึ้นเท่านั้น
quick fix นี่ตัวดีเลย,

ยกตัวอย่าง quick fix หนึ่งของผม
สมัยเมื่อนานมาแล้ว
มีโปรเจคอยู่โปรเจคหนึ่งซึ่งเป็นโปรเจค ลูกเมียน้อย
(หมายความว่า ไม่ได้ถูกให้ความสำคัญทั้งจากคนจ้างและคนรับจ้าง)
ซึ่งผมต้องทำ prototype ไปให้ user ใช้
มีอยู่หน้าจอหนึ่ง มันขาด field ไป field หนึ่ง
เผอิญใน table มันมี field หนึ่งที่พึ่งถูกตัดทิ้งไป
ก็เลยหยิบเอามาใช้ก่อนเลย ทั้งที่ naming,datatype มันคนละเรื่องคนละราวเลย

เผลอแป๊บเดียว โปรเจคลูกเมียน้อย
เกิดกลายเป็นทายาทมรดกร้อยล้านขึั้นมา
data วิ่งเข้าไปเป็นหลาย ล้าน record แล้ว
โปรแกรมก็มีหน้าจอเกินหลักร้อยไปเยอะแล้ว
การ refactor เปลี่ยนชื่อ column ใน table กลายเป็นเรื่องใหญ่

ช่วงนี้มีการ upgrade ตัวโปรแกรม
จากหน้าจอ terminal ขึ้นมาเป็น web application
ชื่อ column ที่ quick fix ไว้ก็เลยโผล่ขึ้นมาหลอกหลอน

จริงๆกรรมนี้ถือเป็นกรรมเล็กๆน้อยๆ
กรรมใหญ่กว่านั้นนี่ยังมีอีกหลายนัก

Note: เรื่อง กรรม นี้ คงใช้ได้กับบุคคลที่ไม่ได้เปลี่ยนงานบ่อย
ส่วนพวกเปลี่ยนงานหลังโปรเจคจบ ก็สบายตัวไป
(ไปได้กรรมอีกประเภทคือ ไม่เคยได้อยู่ดู feedback
ซึ่งถือว่าเป็นประสบการณ์ที่ช่วยพัฒนาตัวเองดีนักแล)

Related link from Roti

Friday, February 09, 2007

CAL, haskell(like) on JVM

CAL เป็นส่วนหนึ่งของ Open Quark Framework for Java
มี syntax และ feature ไกล้เคียงกับ haskell มาก
แต่ compile เป็น bytecode และ run บน java virtual machine

code ข้างล่างเป็นตัวอย่างการแปลง array เป็น java ArrayList
outputListWith :: [a] -> (a -> JObject) -> JList;
public outputListWith !list f =
let
javaList :: JList;
javaList = jArrayList_new;
outputListWithHelper :: [a] -> (a -> JObject) -> JList ->
JList;
outputListWithHelper !list elementMappingFunction !javaList =
case list of
[] -> javaList;
x : xs ->
if (jList_add javaList (elementMappingFunction x)) then
outputListWithHelper xs elementMappingFunction
javaList
else
error "Adding an element to a Java list failed.";
;
in
outputListWithHelper list f javaList;

ส่วน Quark Framework ยังอ่านไม่เข้าใจ
ดูเหมือนจะเป็นชุดเครื่องมือที่มุ่งเรื่อง reuse business logic
โดย define code unit เล็กๆที่เรียกว่า Gem (เขียนโดย CAL)
จากนั้นก็สามารถนำ Gem พวกนี้มาต่อๆกันเป็นสายของ process ได้

Related link from Roti

Thursday, February 08, 2007

Declarative with groovy

กำลังทำงานอยู่ชิ้นหนึ่ง งานนี้เป็นงานรับข้อมูลงบการเงินเข้ามา
แล้วทำการสรุปพวก financial ratio ต่างๆออกมา
โดยสูตรของการคำนวณขึ้นอยู่กับ context ของผู้ที่ส่งงบเข้ามาด้วย
(เช่น สูตร ratio ของงบการเงินของธนาคาร ย่อมต่างจาก งบการเงินของพวกโรงงาน)
รายละเอียดปลีกย่อยมียุบยับ แต่ละไว้แล้วกัน

ประเด็นก็คือ เราอยากเขียนโปรแกรมให้กำหนดสูตรในลักษณะ declarative ได้
แทนที่จะเขียนเป็น method หรือ class ใน java แบบปกติ
เมื่ออยากได้ solution ที่เป็น declarative ก็เลยต้องมองหาพวก script language เข้ามาช่วย
ก็เลยหยิบเอา groovy มาลองทดสอบดู

ในเบื้องต้น เรามีสูตรแบบนี้อยู่
current_ratio = สินทรัพย์หมุนเวียน / หนี้สินหมุนเวียน


เขียนเป็น groovy ตรงๆก็คือ
current_ratio = element('asset') / element('liabilities')

โดย method element คือ helper ที่ช่วยดึงข้อมูลจากงบการเงิน

แต่พอลองทดสอบดู ก็พบว่า เราไม่สามารถ bind method element เข้าไปตรงๆได้
ต้องแปลงสูตรให้เป็น
current_ratio = env.element('asset') / env.element('liabilities')

การ evaluate code นี้ทำได้โดย

Binding binding = new Binding();
binding.setVariable("env", helperObject);
GroovyShell shell = new GroovyShell(binding);
shell.evaluate(src);
float current_ratio = binding.getVariable("current_ratio");

ใช้งานได้ แต่ดูแล้ว การที่ต้องใช้ "env" ก่อนนั้นดูไม่งามเลย
นอกจากนี้ยังมีประเด็นเรื่อง fix ชื่อสูตรไว้ใน code ด้วย
ประกอบกับที่พอนำ idea ไปคุยกับ user, user บอกว่า
อยากให้ script มันสามารถ include กันได้ด้วย
เพราะว่า sector แต่ละ sector มันมี common ratio อยู่

ก็เลยออกแบบใหม่
เอา Closure เข้ามาช่วย
สุดท้ายได้หน้าตาประมาณนี้ออกมา
formulas.declare {
include 'common.script'

formula('current ratio') {
element('assets')/element('liabilities')
}

formula('quick ratio') {
element('cash') + .... / element('liabilities')
}
}

ซึ่งการ evaluate script นี้จะยังไม่ได้ผลลัพท์ทันที
แต่จะได้ Closure จำนวนหนึ่งออกมา ซึ่งเราจะเก็บไว้ก่อน
แล้วค่อยนำ Closure พวกนี้ไป run ใน context ใดๆที่เราต้องการ

code ที่ใช้อ่าน formula เข้ามา หน้าตาเป็นแบบนี้
พระเอกของเรื่องนี้คือ closure.setDelegate(..)
public FormulaSet load(String name) throws IOException {
final FormulaSet ret = new FormulaSet();
Binding binding = new Binding();
binding.setVariable("formulas", new Delegate() {

public void declare(Closure c) {
c.setDelegate(this);
c.call();
}

public void formula(String name, Closure c) {
Formula f = new FormulaImpl(name, c);
ret.put(name, f);
}

public void include(String name) throws IOException {
FormulaSet set = FormulaLoaderImpl.this.load(name);
ret.add(set);
}

});
GroovyShell shell = new GroovyShell(binding);
InputStream src = getClass().getClassLoader().
getResourceAsStream(scriptPath + name);
if (src == null) throw new IOException("script " + name + " not found!");
Script script = shell.parse(src);
script.run();
return ret;
}

Related link from Roti

Monday, February 05, 2007

ขั้นตอนการ compress javascript ของ dojo

มีคนเขียนมาถามว่า Dojo ใช้วิธีอะไรในการ compress javascript file
ลองไปดู build file ของเขากัน
<target name="-rhino-compress"
unless="nostrip">
<copy overwrite="true" file="${srcFile}" tofile="${dstFile}.uncompressed.js" />
<java jar="./lib/custom_rhino.jar" fork="true" output="${dstFile}">
<arg value="-c" />
<arg value="${srcFile}" />
</java>
</target>


จะเขาใช้ rhino เข้ามาช่วยครับ
แต่ไม่ใช่ rhino ธรรมดานะครับ เขาใช้ custom ของเขาเอง

คือตัว rhino มันคือ javascript interpreter
ซึ่งภายในต้องมี class ที่ทำหน้าที่ parse javascript อยู่แล้ว
เขาก็เลย hack เจ้า class นี้
เพิ่มส่วน writer ที่ write ออกมาในรูปแบบที่ต้องการ
(หลักการเดียวกันกับพวก pretty printer แต่แทนที่จะออกมาสวย
ก็ออกมาไม่สวยแทน)

เราสามารถเอา rhino-custom.jar ของเขามาใช้ใน project เรา
โดยเรียกใช้แบบนี้
java -jar custom_rhino.jar -c infile.js > outfile.js 2>&1


ลองดูตัวอย่าง code custom rhino ที่เขาเขียน
ตอนที่ print out เขาจะ check token ก่อน ว่าเป็นประเภทไหน
ถ้าเป็น NAME ก็จะทำการ compress
    case Token.NAME:

if(Token.OBJECTLIT == source.charAt(jumpPos)){
i = printSourceString(source, i + 1, false, result);
}else{
i = tm.printCompressed( source, i + 1, false, result, prevToken,
inArgsList, braceNesting);
}
continue;

case Token.STRING:
... # a lot of case

จะเห็นว่าเรียกใช้ method printCompressed
ตามไปดู printCompressed จะเห็นว่าเขาเช็คก่อน
ว่าตัวแปรที่กำลังจะ print นั้นเป็น ตัวแปรที่พึ่งประกาศใหม่
หรือตัวแปรที่ถูกอ้างใช้
public int printCompressed(String     source, 
int offset,
boolean asQuotedString,
StringBuffer sb,
int prevToken,
boolean inArgsList,
int currentLevel){

....
// ถ้ามี var นำหน้า หรือ อยู่ใน argement list
// ให้สร้าง mapping ขึ้นมาใหม่
if(((prevToken == Token.VAR)&&(!hasLocalTokenMapping(sourceStr)))||(inArgsList)){
newMapping = true;
}

str = this.getMappedToken(str, newMapping);
....


}


private String getMappedToken(String token, boolean newMapping){
String nt = null;
HashMap tokens = (HashMap)scopeReplacedTokens.get(scopeReplacedTokens.size()-1);
if(newMapping){
lastTokenCount++;
// ตั้งชื่อตัวแปร โดยมี _ นำหน้า
// แล้วตามด้วย เลข running ที่แปลงให้เป็น hex
nt = new String("_"+Integer.toHexString(lastTokenCount));
if(nt.length() >= token.length()){
nt = token;
}

tokens.put(token, nt);
return nt;
}
if(hasTokenMapping(token)){
return getTokenMapping(token);
}else{
return token;
}
}

Related link from Roti

Friday, February 02, 2007

ผ่านไปอีกหนึ่ง

เมื่อวันก่อน Application ที่เขียนโดยใช้ opensource ล้วนๆ
(เดิมก็ใช้ opensource แหล่ะครับ, แต่คราวนี้ไม่ต้องใช้ db2, websphere)
ได้ run production กับ load ที่มากสุดของช่วงปีนี้แล้ว (31 มกราคม)
วันนั้นมี transaction ใบเสร็จป้อนเข้ามา หมื่นกว่าใบ
ผ่านไปด้วยความสบายใจ

ลองดูว่า project นี้ใช้ opensource อะไรบ้าง
  • ในส่วนของ browser บังคับให้ใช้ Firefox
    (เขียนให้ใช้ได้ทั้ง IE และ Firefox, แต่พอเกิดปัญหา ก็จะใล่ให้ไปลง firefox ก่อน
    แล้วค่อยคุยกัน)
  • PDF Viewer ใช้ FoxIt
    ตัวเล็กดี
  • Server ใช้ OpenSUSE
  • Database ใช้ Ingres
  • App Server ใช้ Tomcat 5.5
    ต่อเป็น cluster 2 server
  • Web Server ใช้ Apache 2.x
  • Single Sign On ใช้ CAS
  • ORM ใช้ Hibernate 3.2
  • Container ใช้ Spring Framework 2.0
  • Presentation Layer ใช้ Tapestry 4.0.2 ผสมกับ Spring
  • Report ใช้ JasperReport
  • Javascript Framework ใช้ Dojo
  • build tool ใช้ maven 2
  • continuous build ใช้ CruiseControl
  • Unit Testing ใช้ TestNG กับ EasyMock
  • Integrated Test ใช้ Selenium + Ruby

ยังมีตัวเล็กตัวน้อยอีกจำนวนหนึ่ง แต่ไม่สำคัญเท่าไร

Related link from Roti

Thursday, February 01, 2007

paradox of the active user

paradox of the active user
เจอใน Signal vs. Noise

อ่านแล้วนึกถึงพฤติกรรมของตัวเอง
ยกตัวอย่างล่าสุด ก็คือการใช้ emacs ของตัวเอง
ที่พอใช้ถึงจุดหนึ่ง (คือทำงานได้แล้ว) ก็หยุดที่จะพัฒนาปรับปรุงการใช้ให้มีประสิทธิภาพขึ้น

อย่างเมื่อก่อนเวลาที่เปิดหลายหน้าต่างพร้อมๆกัน
เวลาอยากจะ scroll อีกหน้าต่างหนึี่ง ก็ต้อง switch ไปหน้าต่างนั้นก่อน
แล้วค่อยกดปุ่ม page down
ทั้งๆที่รู้ว่ามันมีคำสั่งที่ทำได้ แต่ก็ขี้เกียจเปิดคู่มือหา

มาเมื่อวาน ฮึดออกแรงค้นหาดู
ใช้เวลา 2 นาที
ก็เลยพบว่ามันทำได้ง่ายๆเพียงแค่กด Meta-pagedown แค่นั้นเอง

ชีวิตมันต่างกันเยอะเลยนะ เวลาที่รู้คำสั่งนี้แล้ว
ระหว่างกด 3 sequence ก็เหลือ sequence เดียว

Related link from Roti

Wednesday, January 31, 2007

เรียนรู้ Javaspaces โดยไม่ต้องเขียน Javaspaces

เห็น javaspaces มานานแล้ว แต่ก็ยังไม่เคยเข้าไปแตะสักที
เมื่อวันก่อนทดลองทำ distributed program ด้วย ruby
ก็เลยได้รู้จักเจ้า Rinda
ตอนแรกก็ยังไม่รู้หรอกว่า Rinda มีความเป็นมาอย่างไร
แค่เอามาใช้งานได้, ก็พอใจระดับหนึ่ง
จนเมื่อคุณ sugree post ถามใน codenone forums
ก็เลยเริ่มเกิดความสงสัย
ในที่สุดก็รู้ว่า Rinda เลียนแบบมาจาก Linda

ในเอกสารที่อธิบายถึง Linda ได้บอกไว้ด้วยว่า,
javaspace ก็เลียนแบบ pattern มาจาก Linda ด้วยเช่นกัน
เห็นเท่านี้ก็เลยเกิดอาการ satori นิดๆขึ้นมา

น่าสนใจนะ ประเด็นเรื่องการเรียนรู้ pattern ผ่านภาษาอื่น
แล้วนำกลับมา apply ทำความเข้าใจกับ implement ในภาษาหลักของตนเอง
เพราะถ้าให้ผมเริ่มทดลองกับ javaspace ก่อน
ผมคิดว่าผมก็คงไปได้ไม่ไกลถึงไหนหรอก
เพราะแค่ setup jini อย่างเดียว ก็คงเสียเวลาไปหลายวันแล้ว
กว่าจะผ่านพิธีรีตองแบบ java อีก (ทำให้พาลเบื่อเลิกไปเสียก่อน)

เทียบกับ ruby ที่ผมสามารถทดลองเขียน Rinda เพื่อทดลอง Matrix multiplication ง่ายๆได้ในวันเดียว
แถมยังได้ความรู้กลับมาทำความเข้าใจ javaspace ได้อีกด้วย

Related link from Roti

Tuesday, January 30, 2007

การสอนคณิตศาสตร์

ไม่ใช่บ้านเราเท่านั้นที่มีปัญหา
Only 43% U.S. math teachers arrived at the correct answer to: 1 3/4 divided by 1/2 compared to 100% of the Chinese teachers.

อ่านเบื้องต้นได้ที่นี่ East meets West: Fundamental Differences in Math Teaching

Related link from Roti

Monday, January 29, 2007

AOP in emacs

ตอนที่เริ่มรู้จัก AOP ใน java ก็รู้สึกว่ามันเจ๋งดี
มาวันนี้ระหว่างนั่งเปิดคู่มือ emacs-lisp หา function ที่ต้องการอยู่
สายตาก็เหลือบไปเห็นคำว่า advice, before, after, around
อ้าว นี่มัน AOP นี่หว่า

กลับบ้านมาก็เลยทดลองเสียหน่อย
เอาโจทย์ที่เคยตอบคุณ sugree ใน codenone
ตอนนั้นประเด็นคำถามก็คือ behavior ของ M-f มันไม่เหมือนกับ 'w' ใน vi
วิธีเดิมที่ผมตอบคุณ sugree ไป ก็คือใช้การ define function ใหม่
แล้วก็ re-define map key ให้ชี้ไปที่ function ใหม่เอา
(defun my-forward-word()
(interactive)
(forward-word)
(skip-chars-forward " ")
(set-mark-command nil)
(forward-char))

แต่ถ้าเปลี่ยนมาใช้ Advice ก็จะทำได้ดังนี้
(defadvice forward-word (after forward-like-vim (arg))
(skip-chars-forward " ")
(set-mark-command nil)
(forward-char))

การประกาศ defadivce นั้น, advice นั้นจะยังไม่ทำงานทันที
ต้องมีการสั่ง activate ก่อน
(ad-activate 'forward-word)


Note: อ่านดูใน file ของ emacs แล้วพบว่า feature นี้เขียนตั้งแต่ปี 1992

Related link from Roti

Wednesday, January 24, 2007

โปรแกรมเมอร์กับการเมือง

ไม่อยากใช้คำว่า "การเมือง" เลยเพราะมันกว้างไปหน่อย
การเมืองในที่นี่ หมายถึง สถานะ ความสัมพันธ์ระหว่างองค์กร ในแง่ อำนาจการต่อรอง

ช่วงนี้ผมได้รับคำขอร้องให้ช่วยแก้ไข application หนึ่ง
การแก้ไขนี้เกิดขึ้นเพราะ application ที่ต้องส่งมอบ ของบริษัทอีกบริษัทหนึ่งมันส่งมอบไม่ได้
(บริษัทที่ไม่ได้เป็นพวก developer ก็มักจะเป็นอย่างนี้แหล่ะ ไม่ค่อยจะอ่าน spec ให้ดีก่อน
,ส่วน spec ราชการก็สุดๆเหมือนกัน คลุมๆเหมาๆ)
แน่นอนในแง่การเมือง บริษัทฯผมมีอำนาจต่อรองในมือสูงมาก
แต่ทางบริษัทฯผมก็เลือกวิธีสบายๆ ก็คือไม่ได้ลูกเล่นอะไร อะไรพอช่วยได้ก็จะช่วยทำให้
แต่ถ้ามากไปก็ไม่ทำ (เพราะมันไม่ได้ตังค์)

การทำงานร่วมกัน ก็มีอยู่ 3 กลุ่ม
ผม, IBM, บริษัท A (บริษัทที่ส่งมอบไม่ได้)
ผมทำงานกับ IBM มาสักพัก ไม่เกิดปัญหาอะไร
งานในส่วนเขา แต่เขาทำไม่ได้
ผมพอจะทำอันไหนให้ได้ ก็ช่วยทำไป

มาวันนี้ บริษัท A หาโปรแกรมเมอร์ได้
ก็เลยต่อสายให้คุยประสานงานกับผม
คุยครั้งที่ 1 มาถึงคุณท่านก็สั่งเลย ผมจะทำอย่างนี้, ขอ file นี้, ขอ file นั้น
ผมพยายามอธิบาย แต่มันก็ไม่ค่อยจะยอมฟัง
สุดท้ายผมก็หาทางอธิบายได้ว่า solution ไม่ใช่อย่างที่คุณคิดหรอก มันง่ายกว่านั้น
จบการคุยครั้งที่ 1 ด้วยความตระหงิดๆของผม

คุยครั้งที่ 2 มาอีกหรอบเดิม ผมทำอย่างนี้แล้ว คุณทำอย่างนี้นะ
มาเป็นชุด ผมก็พยายามอธิบายเงื่อนไขให้ฟัง
มันก็ไม่ยอมฟัง สุดท้ายต้องตวาด "เงียบแล้วฟังผมพูด"
ได้ผลหน่อย ยอมฟังบ้าง
แต่ยอมได้ไม่นาน ก็เริ่มสั่งกลับมาอีกแล้ว
สุดท้ายผมก็ฟิวส์ขาด บอกไปว่า "ผมไม่คุยกับคุณแล้ว"
แล้วขอคุยกับ project manager แทน

ประเด็นจริงๆที่จะบอก ก็คือ ไม่ใช่ว่า programmer คนนั้นพูดไม่รู้เรื่อง
,ประเด็นเขามี, ความรู้เขามี
แต่สิ่งที่เขาขาดก็คือ การฟัง และท่าทีในการร่วมมือ
รวมทั้ง sense ในระดับภาพรวมด้วยว่า ขณะนี้ทิศทางการเมืองเป็นอย่างไร

หลังจากโมโหอยู่พักใหญ่ (ผ่านไป 4 ชั่วโมง ก็เริ่มส่งสัยว่าทำไมต้องโมโหด้วยวะ
สงสัยต่อม ego แตก) ก็นั่งดับโมโหด้วยการแก้โปรแกรม แล้วก็ส่งไปให้บริษัท A ซะ

เรื่องนี้สอนให้รู้ว่า "ผมเป็นโคนันทวิศาล"

Related link from Roti

Tuesday, January 23, 2007

Bug ข้าม Application

วันนี้ระบบที่ deploy production เกิดทำงานผิดผลาดขึ้นมา
ลูกค้าแจ้งว่า วันที่ที่แสดงในหลายๆหน้าจอ แสดงวันที่ผิดปี
ยุ่งหล่ะสิ ระบบนี้ไม่ใช่พึ่งใช้งานด้วย ใช้งานมาไม่ต่ำกว่า 2 เดือนแล้ว
โชคดีที่มี fallback, ระบบสำรอง ก็เลยปิดระบบใหม่บังคับให้ user ไปใช้ระบบเก่าไปก่อน

หลังจากนั่นค้นหา changeset ว่าเมื่อคืน มีใคร deploy อะไรใหม่ๆลงไปบ้าง,
ทดสอบระบบที่ test server, ทดสอบระบบที่เครื่องตัวเอง
กว่าจะหาสาเหตุเจอ ก็ผ่านไป 4 ชั่วโมง

สาเหตุนั้นน่าสนใจมาก ตรงประเด็นที่ว่า
เรามักจะมี assumption ว่า bug เกิดที่ระบบใด ส่วนที่ผิด ก็ควรจะอยู่ในระบบนั้น
แต่ bug ตัวนี้ดันเกิดจาก application อีกตัว ที่พึ่ง deploy ขึ้นไปเมื่อวาน
ภายในมัน set locale ให้เป็น "th"
โชคร้ายที่ application เก่า เรามี assumption ในการเขียนว่า
locale เป็น "en"
เมื่อ deploy บน virtual machine เดียวกัน ก็เลย conflict กัน

Related link from Roti

Monday, January 22, 2007

malbolge

malbolge เป็น programming language ตัวหนึ่ง
สิ่งที่น่าสนใจก็คือ มันถูกออกแบบมาให้ใช้งานได้ยาก (designed to be difficult)
ภาษานี้ถูก design ในปี 1998
แต่โปรแกรม helloworld ตัวแรก ถูก solve ได้ในปี 2000

ถ้าอยากรู้ว่ามันยากอย่างไร ลองดูการเขียน helloworld ได้ที่นี่ malbolge: hello world
ตัวโปรแกรม ยกมาให้ดู สำหรับคนที่ขี้เกียจตาม link
(=<`$9]7<5YXz7wT.3,+O/o'K%$H"'~D|#z@b=`{^Lx8%$Xmrkpohm-kNi;gsedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543s+O<oLm

(perl กรุณาชิดซ้ายด้วย)

สำหรับ implement ที่ยกมา คนเขียนเขาเขาต้องใช้ lisp ช่วยคำนวณก่อน
จากนั้นจึงค่อย generate code มันออกมา
แต่มีอยู่คนหนึ่ง (Antwon) เขา claim ว่า
I beat Malbolge with a stick and mastered its secrets.

แต่เขาก็ไม่ได้เปิดเผยเคล็ดลับนั้นออกมา

Links malbolge in wikipedia

Related link from Roti

Friday, January 19, 2007

code vs comment

ปกติเวลาเราเขียนโปรแกรม
source code คือเนื้อหาหลัก ส่วน comment คือเนื้อหารอง
,comment จะแทรกอยู่ใน source code โดยมี prefix พิเศษนำหน้า

haskell มันมี file format อยู่อันหนึ่งที่เรียกว่า "lhs"
ถ้าอยู่ใน format นี้ source code จะหลายเป็นเนื้อหารองแทน
(คือต้องมี prefix นำหน้า)
-------------------------------------------------------------------------------
Haskell code and test cases
for the non-monadic stages
-------------------------------------------------------------------------------

This file contains the Haskell code for the various non-monadic stages
in the derivation of a Gaussian Elimination program using the
methodology. The remaining programs are in other files in the same
directory.

It also contains 3 sets of test data. Typing "main" runs the programs
for each non-monadic stage on this data and prints the results.

It needs modules which provide finite sequences:

> import SeqFinSeq
> import ParFinSeq
> import Cyclic

-------------------------------------------------------------------------------
The following function runs the functions on the test data:

> main :: IO()
> main = do putStr "The test data is:\n"
> putStr "1st set: \n"
> putStr ("a = " ++ (show a_matrix) ++ "\n")
> putStr ("b = " ++ (show b_vector) ++ "\n")
> putStr "2nd set: \n"
> putStr ("a = " ++ (show a2_matrix) ++ "\n")
> putStr ("b = " ++ (show b2_vector) ++ "\n")
> putStr "3rd set: \n"
> putStr ("a = " ++ (show a3_matrix) ++ "\n")
> putStr ("b = " ++ (show b3_vector) ++ "\n")


------------------------------
Test data (need a matrix A and a vector b)

> a_matrix :: Matrix Rational
> a_matrix = [[2,3],[1,-1]]
> b_vector :: Vector Rational
> b_vector = [25,10]

Related link from Roti

Wednesday, January 17, 2007

Debug ruby with xmpfilter

XMPFilter คือเครื่องมือที่ช่วยให้เรา
ทดสอบ ruby code ได้ง่ายขึ้น
โดยมันจะช่วยพิมพ์ผลลัพท์ตามจุดต่างๆ ทำให้เรา debug program ได้ง่ายขึ้น

สมมติว่าเรามี code, เราอยากจะเห็นว่าเกิดอะไรขึ้นกับ n เราก็เลยใส่ # => ลงไปข้างท้ายบรรทัด
[1,2,3].collect do |n|
n + 1 # =>
end


ถ้าเรานำ code นี้ไป run ผ่าน xmp process
เราก็จะได้ output แบบนี้
[1,2,3].collect do |n|
n + 1 # => 2, 3, 4
end


แต่ที่ชอบมากที่สุด ก็คือมัน integrate เข้ากับทั้ง vi และ emacs
อย่างใน emacs เราสามารถสั่ง evaluate โดยใช้ M-x xmp

Related link from Roti

Friday, January 12, 2007

Erlang Application ในไทย

(ข้อความต่อไปนี้ เป็นการเผยแพร่ศาสนา erlang
คนเชื่อคนง่าย กรุณาใช้วิจารณญาณ ในการรับฟัง)

Luke Gorrie เขาเขียนไว้ใน blog ดังนี้

We've developed and marketed a system for mobile phone companies to keep track of all the mobile phones their customers are using and to automatically send configurations for picture messaging, web browsing, and so on. We've installed these systems in over 60 countries and have more than 200 million of you puny humans represented in our Mnesia databases. We're the market leaders and have only a fraction of our competitors' staff size, but of course you guessed this when I said "Erlang". :-)

ดูแผนที่ที่เขาไป มีไทยด้วยนะครับ

Note: mnesia เป็นชื่อ database ใน erlang

Related link from Roti