Tuesday, November 28, 2006

Prototype Parameter?

คุณ pete ถามมา

คือเวลาผมใช้ prototype ส่ง parameter เนี่ยมันก็จะอยู่ในรูป 'name=abcd&surname=refd' ใช่ไหมครับ ที่อยากถามคือถ้าหากผมมีตัวแปรชื่อ check เป็น array รับค่ามาจาก checkbox ในเว็บเพจเนี่ย
การส่งตัวแปรแบบ array สามารถทำได้หรือเปล่าครับ


ถ้าใช้ method serialize ใน Form object
มันจะทำให้เราเองครับ
ลองไปทดสอบดูได้ที่ web นี้ครับ
Prototype: Form Serialization and Deserialization
มีหน้าจอให้เราลอง submit ดูด้วย

method ข้างบน มันจะให้ค่าทั้งหมดใน form กลับมา
แต่ถ้าเกิดเราอยากได้แค่ array ของเฉพาะตัวแปรนั้นๆชุดเดียว
ก็ลองดูที่ blog นี้ครับ
Quick Tip: Getting array of checked values using prototype

Related link from Roti

Maven vs. Ant

ช่วงนี้ mk, community builder ของเรา
เกิดต้องหันมาจับ java
ก็เลย post ตั้งคำถาม ไว้จำนวนหนึ่ง
ผมจะค่อยๆหยิบมาทยอยเขียนตอบ
โดยเริ่มที่คำถาม "Ant กับ Maven ต่างกันอย่างไร"

เริ่มที่ Ant ก่อน
Ant คือ build tool ตัวหนึ่ง
เขียนโดย James Duncan Davidson ซึ่งเป็นคนเขียน Tomcat
วัตถุประสงค์ในตอนแรกที่เขาเขียน ก็ชัดเจนมาก
นั่นคือ ใช้ในการ build tomcat

การทำงานของ ant ก็คล้ายๆพวก makefile ของพวก unix
มีหน้าที่คำ build ให้ได้ target file
ซึ่งอาจจะเป็น jar file, war file, javadoc file, ฯลฯ
ซึ่งแน่นอนว่าประเด็นที่สำคัญในการ build ก็คือ ลำดับการทำงาน
ดังนั้นการเขียน ant ก็คือ การร้อยเรียงลำดับการทำงานต่างๆเข้าด้วยกัน

ที่นี้แล้ว maven หล่ะ
maven ก็มีที่กำเนิดคล้ายๆ ant
โดยเกิดในระหว่างการพัฒนาโปรเจค jakarta turbine
(อันนี้เป็น web framework รุ่นแรกๆของ java)
สาเหตุก็คือเมื่อ project ใหญ่ขึ้นมาก
เรามักจะ split project ออกเป็น sub project ย่อยๆ
project structure มีลักษณะเป็น hierarchy structure
แต่ละ sub project ก็มี team ทำงานแยกกัน

+ project X
+ sub project Domain
+ sub project Service
+ sub project Web App
+ sub project Main App
+ sub project Admin App

คนที่เคยใช้ ant กับ project ที่มีลักษณะแบบนี้
จะรู้ว่าการ maintain ant file เป็นเรื่องน่ารำคาญใจเรื่องหนึ่งทีเดียว
การเขียน ant script จะใช้วิธี copy & paste ไปมา
ถ้าเปิดดู build file แต่ละตัว ก็จะเห็นว่ามีส่วนที่ซ้ำกันไปซ้ำกันมาเต็มไปหมด
jar file ของ subproject ก็ซ้ำๆกัน
แถมยังถูก check-in เข้า version control
นอกจากนี้ยังต้องทำ ant script ตัวใหญ่
ไว้คอยคุมลำดับการ build ของโปรเจค, ฯลฯ

maven ก็เลยเกิดมา เพื่อเติมรอยโหว่ในจุดนี้
ลองดูวัตถุประสงค์ของ maven

  • Making the build process easy
    หลักการของ maven ก็คือ ทำอย่างไรให้ช่วงเวลาที่ใช้ในการ setup
    build file น้อยที่สุด
    อันนี้ก็เลยมี feature พวก archetype,
    library repository ที่ช่วยแยก library ออกจาก project

  • Providing a uniform build system
    ถ้าเราเข้าใจกลไกการ build ของ project ที่ใช้ maven อันหนึ่ง
    เราก็จะเข้าใจ project อื่นๆที่ใช้ maven ทันที

  • Providing quality project information
    maven ให้ความสำคัญของ กลไกการ generate document จาก code

  • Providing guidelines for best practices development
    อันนี้ค่อนข้างสำคัญ, สมัยแรกๆที่ใช้ ant
    project แต่ละ project ก็จะมี idea การวางโครงสร้าง directory, การตั้งชื่อ
    กันหลากหลายมาก
    ส่วนของ maven ก็เลยกำหนดมาตรฐาน (default, best practices) ขึ้นมาอันหนึ่ง

  • Allowing transparent migration to new features
    ตรงนี้ประสบการณ์ผมไม่ตรงที่โฆษณาไว้
    จำได้ว่า maven1.x เคย upgrade version แล้ว build มันมั่ว
    ต้องลบทิ้งลงใหม่


feature ที่ผมชอบใน maven ก็มี
  • share repository
    library ที่เราใช้ใน project ต่างๆ จะรวมเก็บไว้ที่เดียว
  • transitive dependency
    ระบุ dependency เฉพาะตัวที่เราต้องการ
    พวกที่เหลือเดี๋ยว maven จะหามาให้เอง
  • การเขียน build file ในลักษณะ extend
    พวก sub project จะ extend คุณสมบัติจาก parent project


ส่วนที่ไม่ค่อยชอบ
  • เริ่มต้นไม่ถูก ไม่รู้จะเรียกคำสั่งไหน เมื่อไร
    จะรู้ได้ไงว่ามีคำสั่งอะไรใช้บ้าง
  • การ integrate project ที่มีโครงสร้างแบบ hierarchy
    เข้ากับ eclipse (IDE) นี่ มันไม่ธรรมดาเหมือนกัน
    ไม่ยาก แต่ก็ไม่สนุก


ที่นี้ก็มาถึงคำถามสำหรับการเลือกใช้
สำหรับผมนะ
project เขียนคนเดียว ไม่ยั่งยืน ผมใช้ build ของ IDE
project เล็กๆที่เผยแพร่ให้คนอื่น ใช้ ant
project กลางๆ ถ้ารีบก็ใช้ ant, ถ้าไม่รีบก็ maven
(เนื่องจากการเรียนรู้ maven ใช้เวลามากกว่า ant)
project ใหญ่เป็นเรื่องเป็นราว ใช้ maven

Related link from Roti

Monday, November 27, 2006

Currying

Christopher Diggins เขาเขียนเรื่อง Typing like a Functional Programme
article นี้ช่วยเฉลยให้ผมเข้าใจเรื่อง currying ขึ้นอีกหน่อย
(เห็นศัพท์นี้บ่อย แต่ไม่ get ว่ามันคืออะไร)

ตัวอย่างที่เขาอธิบายก็คือ
function add_ints
ปกติเวลาเราเขียน imperative language เช่น java
add_ints จะเขียนแบบนี้
public int add_ints(int x, int y) { return x + y; }


ถ้าจะเขียนเป็น functional language (ocaml, haskell, ...)
เราต้อง declare type ก่อน
ซึ่ง type ของ add_ints เขียนได้ดังนี้
add_ints: int -> int -> int

อ่านได้ว่า add_ints รับ parameter ชนิด int 2 ตัว
แล้ว return ค่าเป็น int

จะเห็นว่ามันดูแปลกๆ เพราะในความคิดแบบ imperative ของเราแล้ว
มันควรจะเขียนแบบนี้มากกว่า
add_ints: (int , int) -> int
add_ints: (int -> int) -> int


ที่เป็นเช่นนี้เพราะ ใน Haskell (ขอยกตัวอย่างเฉพาะ haskell) มันพิสดารตรงที่ว่า
ถ้าเรา pass parameter แค่ตัวเดียวให้กับ add_ints version java
ผลก็คือ code จะ compile ไม่ผ่าน
แต่สำหรับกับพวก haskell แล้ว
การ pass parameter ตัวเดียวให้กับ add_ints
มันจะ return กลับมาเป็น function อีก function หนึ่งแทน
โดย function นั้นจะรับ parameter ที่เป็น int ตัวเดียว
และเมื่อเรา call function นั้นอีกทอด เราก็จะได้ผลบวกที่ต้องการ

ลองดูตัวอย่าง
add_ints :: int -> int -> int
add_ints x y = x + y

ลอง run ดู
Main> add_ints 1 7
8
Main> (add_ints 2) 4
6


ใครสนใจอ่าน currying ต่อได้ใน wikipedia

Related link from Roti

Emacs Register

สงสัยเรื่อง feature register ใน emacs มานานแล้ว
วันนี้ได้ฤกษ์หาคำตอบสักที
register ใน emacs ก็คือตัวแปรที่เราสามารถ save ค่าต่างๆลงไปได้
โดยปกติเราจะตั้งชื่อให้กับแต่ละ register ด้วยตัวอักษรหนึ่งตัว

ที่นี้ก็มาถึงคำถามถัดไป
แล้วอะไรหล่ะที่เก็บลง register ได้บ้าง
ตรงนี้แหล่ะที่มันดูดี
เนื่องจากเราสามารถเก็บ content ได้หลากหลายเช่น
  • เก็บ String, Number
    อันนี้ธรรมดามาก
  • เก็บ Marker (position ใน buffer)
  • Window or Frame configuration position
    ใช้เก็บ ตำแหน่งและขนาดของ window หรือ frame
  • file
    ใช้เก็บชื่อ file ทำให้กระโดดไป edit file ที่ต้องการได้ง่ายๆ


short-cut ที่เราใช้สร้าง register จะค่อนข้างหลากหลาย
เนื่องจากมีประเภท content ที่เก็บได้หลายแบบ
เช่น ถ้าจะจำหน้าต่างที่เปิดในปัจจุบัน เราจะใช้ c-x r w
ตามด้วยชื่อ register
หรือถ้าจะจำตำแหน่งใน buffer ก็จะใช้ c-x r <SPC>
แล้วก็ตามด้วยชื่อ register เช่นกัน

ส่วน short-cut ที่ใช้ กระโดดไปยัง register ที่ต้องการ
จะมีตัวเดียว ใช้ได้กับทุกประเภท content
นั่นคือ c-x r j ตามด้วยชื่อ register

ตอนนี้ที่ผมใช้เป็นหลัก ก็คือการจำ window ที่เปิดไว้
จะได้กระโดดกลับมาที่ layout ที่ต้องการได้ง่ายๆ

Related link from Roti

Sunday, November 26, 2006

Emacs-23

ใครที่เคยใช้ emacs จะมีความรู้สึกอย่างหนึ่งก็คือ
font มันไม่สวยเอาเสียเลย
เนื่องจากมันไม่ใช่ anti-alias

ส่วนตัวผม, ปกติผมใช้ emacs บน mac
emacs บนนั้น, font มันจะเนียนสวยมาก
เวลามาใช้บน linux จะรู้สึกขัดอกขัดใจเล็กน้อย

ตอนนี้ที่ branch emacs-unicode-2
(ซึ่งเขาว่ากันว่า จะเป็น branch สำหรับ emacs version 23)
มีการ merge เอา branch ที่มี feature xft เข้ามาแล้ว
ดังนั้นใครที่ต้องการ emacs xft
ก็ควรจะ checkout ออกจาก branch นี้โดยตรง

ขั้นตอนการ build สามารถอ่านได้ที่นี้
XftGnuEmacs

ผมลองบน ubuntu แล้ว สวยงามดีที่เดี่ยว


Related link from Roti

Friday, November 24, 2006

CForms

CForms คือ framework ย่อยๆใน Apache Cocoon
ที่ออกแบบมาเพื่อใช้จัดการเรื่องการ submit ข้อมูลผ่าน html form

CForms มีองค์ประกอบ 2 ส่วนคือ
  • Form Model คือ definition ของ data ที่จะ submit เข้ามา
  • Form Template คือ layout ของ widget
    ที่จะสร้างเป็นหน้าจอให้ผู้ใช้เห็น

แน่นอนว่าด้วยชื่อเสียงของ Cocoon ที่เป็น Framework แห่ง xml
ทั้ง form model และ template ก็ต้อง describe ด้วย xml

สำหรับตัว Form model สิ่งที่ผมชอบก็คือ
เรากำหนด definition ของ form ผ่านทาง xml อย่างเดียว
ไม่จำเป็นต้องไปเขียน java class ใดๆเลย
ลองดูตัวอย่าง form model
<fd:form
xmlns:fd="http://apache.org/cocoon/forms/1.0#definition">

<fd:widgets>
<fd:field id="name" required="true">
<fd:label>Name:</fd:label>
<fd:datatype base="string"/>
<fd:validation>
<fd:length min="2"/>
</fd:validation>
</fd:field>

<fd:field id="email" required="true">
<fd:label>Email address:</fd:label>
<fd:datatype base="string"/>
<fd:validation>
<fd:email/>
</fd:validation>
</fd:field>

</fd:widgets>
</fd:form>

จะเห็นว่าใน form หนึ่งๆ ประกอบด้วย widget หลายๆอัน
ในตัวอย่างของเราชนิดของ widget ที่ใช้ก็คือ Field widget
โดยแต่ละ field ก็จะมีการกำหนด label, datatype, validation
(CForms provide build-in widget มาให้พอสมควร
และเปิดช่องให้เรา define custom widget เข้าไปได้)

ส่วนหน้าตาของ form template ก็จะมีหน้าตาแบบนี้
<html xmlns:ft="http://apache.org/cocoon/forms/1.0#template"
xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">

<jx:import uri="resource://org/apache/cocoon/forms/generation/jx-macros.xml"/>

<head>
<title>Registration form</title>
</head>
<body>
<h1>Registration</h1>
<ft:form-template action="#{$continuation/id}.continue" method="POST">
<ft:widget-label id="name"/>
<ft:widget id="name"/>
<br/>
<ft:widget-label id="email"/>
<ft:widget id="email"/>

<input type="submit"/>
</ft:form-template>
</body>
</html>

จะเห็นว่ามีการ map widget เข้ากับบริเวณต่างๆใน template
เมื่อมีการ render page นี้, component ย่อยแต่ละตัว ก็จะรับผิดชอบ render ตัวเอง
แล้วนำผลลัพท์ที่ได้มาแทนที่ลงไป

และเมื่อ form ถูก submit กลับเข้ามา,
CForms ก็จะแจกให้ component แต่ละตัว
รับผิดชอบในการดึงข้อมูลออกจาก HttpRequest
และนำข้อมูลท่ี่ได้ไปใส่ไว้ใน form instance

เวลาจะนำ CForm ไปใช้ เรามักจะใช้ผ่าน flowscript
ลองดูตัวอย่าง
cocoon.load("resource://org/apache/cocoon/forms/flow/javascript/Form.js");

function registration() {
var form = new Form("registration_definition.xml");

form.showForm("registration-display-pipeline");

var viewData = { "username" : form.getChild("name").getValue() }
cocoon.sendPage("registration-success-pipeline", viewData);
}

โปรแกรมตัวอย่างนี้ จะแสดงหน้าจอให้ user กรอก และเมื่อ user submit เข้ามา
ก็จะทำการแสดงหน้า success
จุดเด่นของ flowscript ก็คือ
1. ใช้ syntax javascript ซึ่ง implement ได้เร็วกว่า java code
2. implement โดยใช้ continuation ทำให้เขียน code อยู่เป็นกลุ่มก้อน ง่ายต่อการ maintain
framework ปัจจุบันที่ใช้ continuation style แบบนี้ ก็คือ Seaside ที่ใช้ภาษา smalltalk,
แล้วก็ web framework ของ DrScheme ที่เขียนด้วยภาษา scheme,
ส่วนในค่าย java นี้ก็มีแค่ cocoon ตัวเดียว
(่jetty continuations เป็นอีกเรื่องหนึ่ง ที่ใช้ศัทพ์เดียวกัน แต่คนละ concept)

ในโปรแกรมข้างบน จุดที่เกิด continuation ก็คือ method form.showForm
ซึ่ง cocoon จะทำการ pause execution ไว้ก่อน
เมื่อ user submit เข้ามา จึงจะเริ่มทำงานต่อจากจุดเดิม

ทั้งหมดข้างบน เป็นแค่ demo การใช้ง่านง่ายๆ
แต่เวลานำไปใช้จริงๆ ข้อมูลนำมาใช้บน form
มักจะอยู่ในรูป xml หรือ beans
ดังนั้นจึงต้องมีขบวนการ binding เกิดขึ้นด้วย
CForms ใช้ XPath เข้ามาช่วยในการ binding
ลองดูตัวอย่าง
<fb:context xmlns:fb="http://apache.org/cocoon/forms/1.0#binding" path="/" >
<fb:value id="name" path="name"/>
<fb:value id="email" path="email"/>
</fb:context>

attribute path ข้างบน ก็คือ xpath ที่ชี้ไปยัง xml element ที่ต้องการ bind

ส่วนประเด็นสมัยนิยม ก็คือเรื่อง Ajax
ตัว CForms ใช้หลักการ partial renderer
ดังนั้นในตอนที่เราเขียน template ก็ต้องใช้พวก tag พวก div, span
เข้ามา grouping บริเวณที่จะเกิดการ replace
ส่วนการ handler request
เนื่องจาก cocoon เป็นเจ้าพ่อแห่ง pipeline
ดังนั้นเราก็แค่แทรก tranformer กับ selector ที่ใช้ handle ajax
เข้าไปใน sitemap

เท่าที่ดูมา CForms ก็ดูเข้าท่าดีเหมือนกัน
ประเด็นที่ต่างกับพวก Tapestry หรือ JSF ก็คือ
  • ใน Tapestry form จะปนๆอยู่กับ controller
    แต่ใน CForms, Forms จะแยกออกจาก controller อย่างชัดเจน
    (seperation of concern จะดีกว่า)
  • ใน JSF เวลาจะเลือกประเภทการ render เราทำได้โดยเปลี่ยน RenderKit
    ใน CForms เนื่องจากเราใช้ concept ของการ transform
    ดังนั้นการเปลี่ยนการ render ก็คือการเปลี่ยน XLST
    ส่วนใน Tapestry ไม่มี concept แบบนี้
  • สามารถใช้ได้โดยไม่ต้องรู้ java เลย


ส่วนข้อเสียที่เห็นได้ชัดก็คือ XML เยอะจริงๆ

Related link from Roti

Thursday, November 23, 2006

Eclipse JDT, ASTParser

ปัจจัยหนึ่งที่ทำให้ Eclipse ได้เปรียบ netbeans (หมายถึง netbeans ตัวเก่าๆนะ ตัวใหม่นี่ยังไม่มีข้อมูล)
ก็คือตัว Java Parser
ซึ่ง bundle อยู่ใน package eclipse JDT (java development tools)

เมื่อใดก็ตามที่เราเปิด source code ขึ้นมาใน editor
eclipse จะใช้ ASTParser ทำการ parse source code
ไปเป็น AST (Abstract Syntax Tree)
ข้อมูล AST ที่ได้จะถูกนำไปใช้หลายๆที่ เช่นใช้ใน Outline view
แต่ที่หนึ่งที่สำคัญก็คือ มันใช้เป็นข้อมูลสำหรับการทำ Refactoring

ลองดู code ตัวอย่างนี้
สมมติเรามี

int x;
x = 2 * 3;

ถ้าเราต้องการ refactor ยุบให้เหลือแค่นี้
int x = 2 * 3;


ผมจะลองเขียน code ให้ดูว่า ถ้าใช้ Eclipse JDT api
เข้ามายุบ source code ข้างบนนั้น
เราจะต้องเขียนอย่างไรบ้าง
เริ่มด้วยการ parse java code ก่อน

ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setKind(ASTParser.K_STATEMENTS);
String src = "int x; x= 2 * 3;";
parser.setSource(src.toCharArray());
ASTNode node = parser.createAST(null);

AST.JLS3 คือ version ของ java code ที่เราจะ parse
ตัว ASTParser มี choice ให้เลือกอยู่แค่ 2 ตัวคือ JLS3 กับ JLS2
ตัว JLS3 จะ support syntax ของ Java 1.5

ขั้นถัดไปก็คือทำการหาว่า จุดไหนที่ทำ refactor ได้บ้าง
โดยเราจะค้นหา statement ที่เป็น variable declaration
กับ statement ที่เป็น assignment
การค้นหานี้ เราจะใช้ visitor pattern ในการค้นหา
(Note: เขียนแบบสั้นๆ พอให้ทำงานได้ ไม่เช็คเงื่อนไขใดๆทั้งสิ้น)

final ArrayList list = new ArrayList();
final HashMap map = new HashMap();

node.accept(new ASTVisitor() {
@SuppressWarnings("unchecked")
public boolean visit(VariableDeclarationStatement node) {
list.add(node);
return false;
}

public boolean visit(Assignment assignment) {
Expression left = assignment.getLeftHandSide();
map.put(left.toString(), assignment);
return false;
}
});

ขั้นสุดท้ายก็คือการแก้ไข AST ให้ตรงตามที่เราต้องการ
// loop ไปตาม declaration statement ที่หามาได้
for (Iterator iter = list.iterator(); iter.hasNext();) {

VariableDeclarationStatement stmt = (VariableDeclarationStatement) iter.next();
// เนื่องจาก declarable statement หนึ่งๆ
// มีได้หลายตัวแปรพร้อมๆกัน
// ดังนั้นเราต้อง loop ไปตามตัวแปรแต่ละตัวอีกที
List fragment = stmt.fragments();
for (Iterator iterator = fragment.iterator(); iterator.hasNext();) {
VariableDeclarationFragment f = (VariableDeclarationFragment) iterator.next();
//ทำเฉพาะ case ที่ตัวแปรไม่ได้มีการ initlize ไว้
if (f.getInitializer() == null) {
// ค้นหา assigment ที่มีตัวแปรเดียวกัน
Assignment assignment = (Assignment) map.get(f.getName().toString());
Expression right = assignment.getRightHandSide();
f.setInitializer(copyExpression(right));
assignment.getParent().delete();
}
}
}

จะเห็นว่า เราแค่ copy right hand side ของ Assignment statement
มาใส่ตรง Initialize value ของ Variable declaration Statement
จากนั้นก็ลบ assignment statement ทิ้งเสีย

สนใจรายละเอียด
ลองตามไปอ่าน Tutorial ของ Eclipse ที่ชื่อ Abstract Syntax Tree

Related link from Roti

Wednesday, November 22, 2006

F3

ห่างเหินจาก Swing มานาน
เลยพึ่งได้ยินข่าว F3
F3 ย่อจาก "Form Follows Function".
เป็น project ของ Chris Oliver
โดยเขา design declarative script language
สำหรับการสร้าง gui ขึ้นมา
จุดเด่นของมันก็คือ มัน support ทั้ง Swing และ Java2D

ลองดูตัวอย่าง ที่ผม copy มาจาก tutorial ของเขา
Frame {
title: "Hello World F3"
width: 200
content: Label {
text: "Hello World"
}
visible: true
}



จะเห็นว่า ภาษามีลักษณะคล้ายๆ javascript

ที่นี้ลองแบบมี model + binding ด้วย
class HelloWorldModel {
attribute saying: String;
}

var model = HelloWorldModel {
saying: "Hello World"
};

var win = Frame {
title: "Hello World F3"
width: 200
content: Label {
text: bind model.saying
}
visible: true
};



ลองดูลูกผสมระหว่าง 2D กับ Swing

Canvas {
content: Group {
transform: []
content:
[Rect {
x: 20
y: 20
height: 80
width: 300
arcHeight: 20
arcWidth: 20
fill: cyan
stroke: purple
strokeWidth: 2
},
Ellipse {
cx: 150
cy: 80
radiusX: 100
radiusY: 50
fill: orange
stroke: blue
strokeWidth: 2
},
View {
transform: translate(150, 70)
content: Button {
cursor: DEFAULT
text: "Click Me!"
}
},
Polygon {
points: [5, 5, 25, 5, 15, 25]
fill: gray
stroke: black
strokeWidth: 3
},
View {
transform: translate(100, 40)
content: TextField {
columns: 15
value: "This is a text field"
}
}]
}
}



ที่น่าสนใจก็คือ มันเป็น graphic ที่สามารถ transform ได้ด้วย
ทำให้เราทำ swing เอียงๆ แบบนี้ แล้วยังสามารถป้อนข้อมูลได้ด้วย

Related link from Roti

Tuesday, November 21, 2006

Saori

Saori ไม่ใช่ชื่อสาวญี่ปุ่น
แต่เป็นชื่อกรรมวิธีทอผ้าด้วยมือแบบหนึ่ง
ถ้าลองใช้ google ค้นหาคำนี้จากเฉพาะ site ในประเทศไทย
จะเห็นว่ามีอยู่ที่หนึ่งที่เกี่ยวข้องกับ ซึนามิ
นั่นคือโครงการ saori for tsunami thailand
ที่จัดตั้งโดย มูลนิธิมายา โคตมี



ใครเจอป้ายแบบนี้ ก็อุดหนุนเขาได้เลยครับ

จุดเด่นของเครื่องทอผ้าของ saori คือความง่ายในการใช้
เนื่องจากออกแบบมาโดยคำนึงถึงผู้พิการด้วย

ใน site www.saoriworcester.com เขาแปลหลักการ 4 ข้อ
"The way of saori" ไว้ดังนี้
1. Consider the differences between machines and people
ชอบตัวอย่างที่เขาพูดถึง
ปัจจุบันเรามีแนวโน้มจะมองทุกอย่างในแง่จักรกลมากขึ้น
เช่น ใช้ศัทพ์ว่า "human resources" แทนที่จะเรียกว่า "human beings"
2. Let's adventure beyond our imagination (Explore with all your might).
อย่างที่รู้กัน การทำงานสร้างสรรค์ ช่วยให้เราค้นพบ ธรรมชาติที่ซ่อนอยู่ในตัวตนของเรา
3. Let's look out through eyes that shine
อันนี้สิที่ผมชอบ ตรงกับที่ผมเคยเขียนในเรื่อง "อันเนื่องจากการเดิน"
ด้วย "eyes that shine" จะทำให้เราค้นพบ
สิ่งมหัศจรรย์เล็กๆน้อยๆรอบตัวเรา
ไม่ว่าจะเป็นลวดลายแตกร้าวของอิฐ, ดอกหญ้าเล็กๆข้างกำแพง
4. Let's learn from everyone in the group
friendships, friendships, friendships...
กิจกรรมที่ไม่เลือกชนชั้นอย่างนี้ เป็นสะพานเชื่อมความสัมพันธ์
ระหว่างคนต่างที่มาได้เป็นอย่างดี

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

ทอผ้ามันมีเสน่ห์ดี
สำหรับคนเมืองอย่างเรา การได้ใส่เสื้อที่ทำกับมือ
มันน่าจะให้ความรู้สึกที่ดีมากนะ



ภาพจาก Photogallery ของ saoriworcester.com

Related link from Roti

Friday, November 17, 2006

ถ้าเป็น yaws หล่ะ

เห็น Guruguru เขาลอง compare Rails กับ Web.py ดู
มีผลลัพท์จากคำสั่ง
ab -n 300 -c 100
เปรียบเทียบให้ดู
ผลลัพท์ ก็ไม่เป็นที่น่าแปลกใจสำหรับผมนะ
แต่ด้วยความมันส์ในอารมณ์ อยากรู้ว่า ถ้าเป็น yaws (web server ของ erlang) หล่ะ
ค่าที่ได้จะออกมาประมาณไหน

Disclaimer
เนื่องจากเครื่องก็คนละเครื่อง นำมาเปรียบอะไรกันไม่ได้หรอกนะ

source code
<erl>
out(A) ->
{ok, Name} = queryvar(A, "name"),
{html, f("hello ~s", [Name])}.
</erl>


ผลการทดสอบ

Server Software: Yaws/1.61
Server Hostname: 127.0.0.1
Server Port: 8000

Document Path: /hello.yaws?name=world,
Document Length: 13 bytes

Concurrency Level: 100
Time taken for tests: 0.319860 seconds
Complete requests: 300
Failed requests: 4
(Connect: 4, Length: 0, Exceptions: 0)
Write errors: 0
Total transferred: 52500 bytes
HTML transferred: 3900 bytes
Requests per second: 937.91 [#/sec] (mean)
Time per request: 106.620 [ms] (mean)
Time per request: 1.066 [ms] (mean, across all concurrent requests)
Transfer rate: 159.44 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.5 0 7
Processing: 1 8 3.3 8 22
Waiting: 1 7 3.2 7 21
Total: 2 8 4.1 8 22

Percentage of the requests served within a certain time (ms)
50% 8
66% 10
75% 10
80% 10
90% 14
95% 19
98% 20
99% 21
100% 22 (longest request)


ผลที่ได้ รู้สึกจะดีเกิดคาดไปหน่อย
หวังว่าคงไม่ได้ทำอะไรผิดนะ

Note: ทำไมตัวเลข total transfered ของเรา มันมากกว่าของเขา 5 เท่าหว่า
Document Length ก็เท่ากัน

Related link from Roti

IBOutlet

เมื่อวานไป train เรื่อง cocoa ที่ทาง Apple จัดให้ฟรีมา
มีประเด็นติดใจเรื่อง IBOutlet
ว่าจริงๆแล้วมันคืออะไร
ประเด็นหลักๆที่เป็นจุดเริ่มต้น ก็คือ
ใน XCode การ paint หน้าจอ gui เราจะทำผ่าน Interface Builder
ทุกอย่างที่ paint หรือ compose จะเก็บไว้ pack ในโครงสร้างที่เรียกว่า NIB file
ซึ่งมันตรงข้ามกับ approch ของ java ที่เวลาเรา paint gui
สิ่งต่างๆที่ paint หรือ setting จะถูก generate ออกมาในรูป java code
,ดังนั้นพวก widget ต่างๆของ swing
ที่เราเลือก paint ลงไป จะเห็นเป็นตัวแปรกันจะๆ ใน source code เลย
ถ้าอยาก customize widget ไหน
ก็สามารถเขียน code เข้าไปแก้ได้ทันที

ประเด็นคำถามที่เกิดขึ้นเมื่อวาน ก็คือ แล้วถ้าเราอยาก access object ต่างๆ
ที่อยู่ใน gui หล่ะ เราจะทำอย่างไร
เช่นอยากเข้าไป customize format ของ NSTextfield
มีคำตอบหนึ่งที่ได้มา ก็คือการใช้ IBOutlet
แต่ก็เป็นคำตอบที่เลาๆ คือไม่ exactly ว่า IBOutlet คืออะไร

Note: สำหรับคนที่ไม่รู้จัก IBOutlet
ลองดูตัวอย่างภาพการใช้งาน

@interface ConverterController : NSObject
{
IBOutlet NSTextField *amountField;
IBOutlet Converter *converter;
IBOutlet NSTextField *dollarField;
IBOutlet NSTextField *rateField;
}


ลองหานิยามของ IBOutlet ใน AppKit ดู
จะพบว่ามันอยู่ใน file
<AppKit/NSNibDeclarations.h>
และมีนิยามแบบนี้

#ifndef IBOutlet
#define IBOutlet
#endif

Bingo, มันคือ macro เปล่าๆ ที่ไม่มีผลในการ compile
ดังนั้นสำหรับผมแล้ว IBOutlet คือ marker อันหนึ่งใน source code
ที่ถูกใช้โดย interface builder
(IB ที่เห็นเป็น prefix ของ IBOutlet ย่อมาจาก Interface Builder)
ทำให้เราสามารถลากโยง(ผ่านทาง GUI)
ให้ instance (controller)
สามารถ access UI widget ที่เราต้องการได้
หรือถ้าพูดในมุมมองของ oop, IBOutlet
ช่วยให้เรากำหนด relationship ระหว่าง object
ผ่านทาง GUI tool (drag-drop).

สำหรับประเด็นในตอน runtime
นั้นขึ้นอยู่กับ strategy การเก็บ Nib file
ของ apple ว่าเป็นแบบ pure serialize, pure definition,
หรือ definition + serialize
(pure definition ถ้ายกตัวอย่างก็เช่น xul ของ mozzila)
ถ้าการเก็บมีรูปแบบของ definition เข้ามาปน
ก็จะมีประเด็นว่า หลังจาก initialize object ขึ้นมา จาก definition file แล้ว
ก็จะต้องมีการ set dependency ตาม relationshipt ที่ได้ define ไว้

Related link from Roti

ไม่แม่น

ผมมีปัญหาเรื่องความจำ
คือเป็นคนไม่ชอบจำแบบแม่นยำ (เรียกกฎหมายไม่ได้แน่)
แต่ชอบจำเลาๆ ผสมกับความรู้สึกนิดๆ
ถ้าส่วนผสมของความรู้สึกมากหน่อย
ก็จะจำเพี้ยนไปได้เยอะ

อย่างเช่น
ผมจำได้เลาๆว่า float มัน ไม่ exactly
เช่นค่า float 0.1 ใน computer มันไม่ใช่ 0.1 จริงๆ
แต่ก็ไม่รู้ว่า จริงๆแล้วมันเป็นเท่าไร
แต่ประเด็นก็คือ ความจำในส่วนนี้ผมผสมความรู้สึกมากไปหน่อย
ค่าที่อยู่ในใจ ก็เลยเพี้ยนค่อนข้างสูง เช่นเพี้ยนไปเป็น 0.103 อะไรแบบนี้

ปัญหาก็จะเกิดเวลาที่มีประเด็นปัญหาทาง software ให้ต้องวินิจฉัย
แล้วเรานำความรู้เลาๆไปร่วมวินิจฉัย
ซึ๋งบางครั้งความเพี้ยนนี้จะพาเราเข้าป่าไปได้เหมือนกัน

วันนี้ก็เลยนั่งหาว่า float 0.1 จริงๆแล้วมีค่าเท่าไร
คำตอบคือ ค่า float 0.1 คือ
1.10011001100110011001101 × 2^-4
หรือประมาณ 0.100000001

*อ้างอิง What Every Computer Scientist Should Know About Floating-Point Arithmetic

Note: Lew ก็เคยเขียนเรื่องนี้ใน in-depth ของ blognone
Decimal

Related link from Roti

Wednesday, November 15, 2006

ประสบการณ์

พึ่งโดดงานพาลูกไปเที่ยวทะเลมา 2 วัน
ได้อ่าน post เรื่อง ประสบการณ์ ที่ eYacht
ก็เลยซาบซึ้งเป็นพิเศษ

Related link from Roti

Tuesday, November 14, 2006

Ubuntu -> TIS-620

บริษัท ผมยังมีโปรแกรมเก่าๆ ที่ต้อง maintain ด้วย terminal อยู่
เดิมที่อยู่ใน windows ก็จะใช้พวก teraterm
ตอนนี้ย้ายมาใช้ ubuntu edgy ก็เจอปัญหาใหม่

ปัญหาแรก ก็คือจะ set encoding อย่างไร
ลองสั่ง locales -a แล้ว ก็มองไม่เห็น th_TH
ทดลองสั่ง
sudo dpkg-reconfigure locales
แทนที่จะขึ้นหน้าจอฟ้าๆมาให้เลือก
มันก็ดัน automatic generate en_*.utf8 ขึ้นมาเยอะแยะไปหมด

เอาใหม่ หันไปใช้ synaptic
เลือกลง language support th
อ้าได้ th_TH.utf8 มาแล้วโว้ย แต่ยังขาด TIS-620 อยู่

สุดท้ายก็ลองแก้ file
/var/lib/locales/supported.d/th
เพิ่มบรรทัด
th_TH.TIS-620 TIS-620
สั่ง sudo dpkg-reconfigure locales ซ้ำ

สำเร็จอย่างงงๆ
(เป็นการมั่วให้ได้ผลลัพท์ แต่ไม่เข้าใจว่าเกิดอะไรเบื้องหลังบ้าง
เข้าข่าย Programming by Coincidence)

Related link from Roti

The Pledge

วันนี้เปิด TV. ไปสะดุดตากับรายการ reality series ที่ชื่อ The Pledge
ที่ถ่ายทำคนธรรมดา 15 คน ที่ commit ว่าจะเข้าร่วมการแข่งขันไตรกีฬา
ที่สะดุดตา ก็เพราะ
  • รายการ Triathlon นี้จัดที่ภูเก็ต (Laguna Phuket Triathlon)
  • ผมก็เคย commit เข้าร่วมรายการนี้เหมือนกัน

เห็นแล้ว ก็เลยอยากนำมาเผยแพร่ต่อ

สาเหตุหลักๆที่ผมเคยเข้าแข่ง Triathlon ก็คือ
"ความอยากที่จะลองทำสิ่งที่ไม่คิดว่าจะทำได้"
อย่างว่ายน้ำ ผมมาหัดว่าย freestyle ตอนอายุ 25
เริ่มแรกนี่ สระ 10 เมตร ยังว่ายไม่ถึงเลย
หรือวิ่งก็เหมือนกัน เป็นคนไม่ชอบวิ่งมาแต่เด็ก
เวลาเล่นกีฬา ก็จะเลือกที่มันวิ่งน้อยสุด

ลองอ่านบันทึกผมในช่วงนั้นดูว่าบรรยากาศมันเป็นอย่างไร

เช้าวันที่ 2
ผมเข้าไปจัดของในบริเวณจุดเปลี่ยนการแข่งขั้น
ตอนประมาณ 6.30 น.
คนค่อยๆทยอยกันมา
บรรยากาศคึกคักมาก
ทั้งเจ้าหน้าที่และนักกีฬา
แต่ละคนอยู่ในชุดทะมัดทะแมงมากเลย
ผมได้ที่จอดจักรยานในสุด ช่วยให้
หลบความวุ่นวายใด้มากขึ้น
การเตรียมก็เป็นการเตรียมอุปกรณ์
ชุดต่างๆที่ต้องใช้ รวมทั้งอาหาร+น้ำดึ่ม
ช่วงนี้นักกีฬาต้องทยอยให้เจ้าหน้าที่เขียน
เบอร์ตามตัว มีเขียนที่ไหล่ซ้าย ใหล่ขวา
ต้นขาหน้าซ้าย ข้างขาขวา กับน่องขวา
ผมได้เบอร์ 311

ช่วง 7.15 ได้เวลาเดินทางไปจุดปล่อยตัว
ว่ายน้ำ วันนี้แสงสวยมากเลย ฟ้าครึ้มๆแต่
มีแสงแดดสาดลงมา ทำให้บรรยากาศดู
อิ่มตาดี ยิ่งมีนักกีฬา 400 คน ในชุดว่ายน้ำ
หลากสี + หมวกว่ายน้ำสีเหลือง + ทะเลเรียบ
บรรยากาศ สุดบรรยาย
ก่อนปล่อยตัว พวกนักกีฬาก็ลงไปว่ายวอร์ม
ในน้ำกัน ผมก็เลยถือโอกาศลงไปฉี่ด้วย
จากนั้นก็ขึ้นมากินน้ำไปอีกขวดเพื่อป้องกัน
ไม่ให้ปากเค็มมากนักเวลาว่ายน้ำ
8.00 น. เริ่มการปล่อยตัว ทุกคนวิ่งกรูกันลงน้ำ
ผมวิ่งช้าๆออกไป เพราะไม่อยากไปแย่งที่ว่าย
กับเขา ha ha แต่หลบไม่พ้นแฮะ การว่ายน้ำ
เป็นกีฬาที่ค่อนข้างโกลาหลเหมือนกัน ว่ายกัน
ไหล่เบียดใหล่ มือชนขาเลย ช่วงที่ว่ายอยู่
มีอยู่คนหนึ่งความเร็วเท่ากับผมเลยเจอกัน
ตลอดทาง เขาคอยตัดหน้าตัดหลังอยู่ตลอด
เวลา เดี๋ยวก็ว่ายไปทางซ้าย เดียวก็ตัดมาทาง
ขวา ไม่รู้ว่าผมว่ายเบี้ยวหรือเขาว่ายเบี้ยวกันแน่
ทุ่นแรกอยู่ห่างฝั่งไป 300 เมตร
ส่วนทุ่นที่สองวางขนานฝั่งไปอีก 400 เมตร
ทุ่น 3 ก็ว่างขนานฝั่งไปอีก 400 เมตร
กว่าจะถึงแต่ละทุ่น มองแล้วมองอีก
ทุ่นสุดท้ายห่างฝั่ง 330 เมตร คราวนี้ใจชื้น
แล้วมองเห็นฝั่งแล้ว เริ่ม speed ปนหอบเล็กๆ
ถึงผั่งได้รู้สึกดีใจมาก หันไปมองข้างหลังแล้ว
ต้องร้องไชโย เพราะพบว่ายังมีคนข้างหลังเราอีก
พอสมควร (ไม่เป็นที่โหล่แล้ว) จากนั้นก็วิ่งขึ้นฝั่งไป
ลง lagoon น้ำจึดเพื่อจะว่ายอีก 370 เมตร
อันนี้สิเริ่มเหนื่อยแล้ว เริ่มเสียอาการ (ว่ายเอียง
ไปเอียงมา ) อ้อข่วงที่ไกล้ๆผั่ง
เริ่มปวดฉี่อีกครั้ง แต่ฉี่ไม่ออก สงสัยกำลังเหนื่อย
มั้ง สมองคิดใหญ่ เฮ้ยถ้าไม่ฉี่เดี๋ยวตอนแข่ง
จักรยานจะฉี่ยังไงหล่ะ ก็เลยเบ่งใหญ่เลย
เฮ้อ เป็นการฉี่แบบระยะยาว ในทะเลนิดหนึ่ง
แล้วเก็บไปต่อในน้ำจึดอีกนิดหนึ่ง
พอถึงอีกฝั่ง ก็วิ่งช่วงสั้นๆเพื่อไปเอาจักรยาน
บรรยากาศบังคับให้ต้องวิ่ง ทั้งๆที่อยากจะเดิน
มากกว่า ไปถึงจักรยาน ใส่รองเท้า เสื้อกางเกง
พร้อมกับกินกล้วยไป 1 ลูก แล้วก็วิ่งพาจักรยาน
ออกมา แหมกองเชียร์คึกคักมาก
ทำให้วิ่งฉิวเลย (ปกติจะอู้มาก) ขึ้นจักรยานได้ก็
ไปโลด

ช่วงจักรยาน ระยะทาง 55 กิโลเมตร ช่วง 8
กิโลแรกเป็นภูเขาสูง
เจอเขาปุ๊บก็จอดเข็นปั๊บ : ) ไม่น่าเกลียดหรอก
เพราะมีเพื่อนเข็นเต็มเลย แต่ตอนลงเขานี่สิ
สนุกมาก แต่ต้องระวังแหกโค้ง
ช่วงที่ 2 เป็นเนินเล็ก เนินกลาง โค้งเล็กโค้งน้อย
เป็นทางถนัด ก็เลยค่อยๆใส่แซงไปเรื่อยๆ
ระหว่างทางจะผ่านชุมชนเป็นระยะระยะ
ก็จะมีเด็กคอย hello กับผู้ใหญ่นั่งดูเป็นกลุ่มๆ
หน้าที่เราก็คอยแจกยิ้มอย่างเดียว
พอช่วงกิโลที่ 40 แรงหมด (ซ้อมมาแค่นั้น)
หมดแรงนี่หมดจริงๆเลยนะ ป้อแป้ๆไปเรื่อยๆ
พวกที่เราแซงไปก็ค่อยๆทะยอยแซงกลับมาจนหมด
ผมก็กัดฟันขี่ต่อไปอีก 15 กิโล พวกกลุ่มหลังๆ
ก็เริ่มคุ้นหน้าคุ้นตากันตอนนี้แหล่ะ

พอกลับมาถึงจุดเปลี่ยนจักรยาน คราวนี้ใครจะวง
ใครจะวิ่ง กูไม่วิ่งแล้ว เดินจูงจักรยานไปเก็บ
นั่งพักเหนื่อยสักพัก (เอ้อระเหยเลยแหล่ะ)
คว้ากล้วยออกมากินอีกหนึ่งลูก
กิน chocolate อีก 4 อัน ค่อยๆเปลี่ยนเสื้อกับรองเท้า
ระหว่างนั้นก็จะมีคนเข้ามาเป็นระยะๆ แต่ละคน
เข้ามาปุ๊บก็วิ่งออกไปปั๋บ ไม่รู้จะรีบร้อนไปไหนกัน

ถึงช่วงวิ่งนี่สิ โหดของจริง กิโลแรก ตะคริวกินสองขา
เลยทั้งเหนือเข่า และน่อง โชคดีที่หน่วยพยาบาลผ่านมา
เขาเห็นเรากระย่องกระแย่งก็เลยปราดเข้ามาทายาให้
ค่อยสบายขึ้นหน่อย
ในช่วงวิ่งนี้มีจุดให้น้ำทุก 2 กิโลเมตร ผมหยุดกิน
ทุกจุดจุดละสองแก้ว ช่วงนี้เป็นช่วงวิ่งสลับเดิน
(จริงๆแล้วเดินมากกว่าวิ่ง) มันเหนื่อยแล้ว ประกอบ
กับเห็นคนเดินเยอะแยะ เมื่อมีตัวอย่างแล้วก็เลยต้อง
ทำตามสักหน่อย เดี๋ยวเขาจะว่าเราเป็นพวกนอกคอก
ช่วงนี้แหล่ะได้เพื่อนเยอะ ทักทายกันไปเรื่อย
อากาศตอนวิ่งร้อนมากจ้ะ แดดตอนเที่ยงเปรี้ยงเลย
ถึงเส้นชัยได้รู้สึกดีใจที่สุด (ไม่เป็นที่โหล่แล้ว : )
แค่เกือบๆ เฉยๆ )

Related link from Roti

Monday, November 13, 2006

Ruby 's Core Extension ใน Rails

เห็นคุณ Apirak post เรื่อง เจอของเจ๋งใน ruby
เลยขอโฆษณา feature ของ Rails หน่อย

ข้อดีอย่างหนึ่งของ Ruby ก็คือ Class มัน Open
ความหมายก็คือ เราสามารถ extends class ได้
โดยไม่ต้องไปยุ่งกับการ edit และ recompile ตัว source ของมัน

ถ้าเราไปดูใน Module ActiveSupport ของ rails
จะเห็นว่ามันมี directory อยู่อัน ที่ชื่อ core_ext
ตรงนี้คือที่ rails ใช้เก็บ extension ต่างๆ ที่ rails ต่อยอดจาก ruby core class



อย่างตัวอย่างที่คุณ Apirak ยกมา
x = x + 1.month 

ถ้าลองเปิด file core_ext/nummeric/times.rb ดู
จะเห็นว่าเขาเขียนไว้ประมาณนี้
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Numeric #:nodoc:

...
module Time

def seconds
self
end
alias :second :seconds

def minutes
self * 60
end
alias :minute :minutes

def hours
self * 60.minutes
end
alias :hour :hours

def days
self * 24.hours
end
alias :day :days

def weeks
self * 7.days
end
alias :week :weeks

...

จะเห็นว่าเขียนเป็น module อยู่
file ที่ include จริงๆ จะอยู่ใน core_ext/numeric.rb
class Numeric #:nodoc:
include ActiveSupport::CoreExtensions::Numeric::Time
include ActiveSupport::CoreExtensions::Numeric::Bytes
end


ลองดูตัวอย่างอื่นๆ ที่ rails เขา extends ไว้
1.even? # => false
2.odd? # => false

1.ordinalize # => "1st"
3.ordinalize # => "3.rd"

[1,2,3].to_sentence # => "1, 2, and 3"


ของที่บ้านเราใช้กัน ก็น่าจะพวก
11.to_thai # => สิบเอ็ด

Related link from Roti

NJUG #2

วันนี้ไปงาน narisa java user group ที่จัดโดย comunities ของ www.narisa.com
มี roofimon เป็นหัวเรือใหญ่ แล้วก็ dean4j หรือ xcaliber เป็นผู้สนับสนุน
รูปแบบ work ใช้ได้เลย, นั่งพูดคุยกันในร้านอาหาร
โดยมีบรรยากาศเป็นแบบไม่เป็นทางการ
(งานนี้จัดที่ bangkok jazz house ตรงถนนพญาไท)
ดูรูปที่ Nonster ถ่ายได้ที่นี่ Link

เมื่อเปรียบเทียบกับงาน blognone แล้ว
ส่วนที่แตกต่างจาก blognone ก็คือ
ลักษณะการ present จะเป็นแบบโต้ตอบมากกว่า
นั่นคือมีการพูดเสริม หรือพูดถาม ณ ขณะที่ทำการ present
ไม่ต้องรอให้บรรยายจบ แล้วค่อยถาม
ซึ่งผมว่ามันดีกว่าบรรยายแบบ solo คนเดียว

ปัญหาหนึ่งที่ต้องเจอในการ meeting
ก็คือเรื่องการทำให้คนที่มาเจอกัน เกิดความคุ้นเคยกัน
และพูดคุยกันได้ (อันนี้เป็นปัญหาที่ codefest ของ nectec ก็เจอ)
บรรยากาศตอนแรก ระหว่างที่รอให้เริ่มงาน
คนที่คุยไม่เก่งอาจจะเกิดความรู้สึกอึดอัดได้
เพราะลักษณะการนั่งที่ค่อนข้างไกล้ชิด หันหน้าชนกัน
พวกนี้ต้องแก้โดยการมี คนที่มีลักษณะสบายๆ
มีบุคลิกเข้ากับคนง่าย
มาคอยเป็นคนเชื่อมประสานให้เกิดการพูดคุย
(หรือไม่ก็ต้องใช้วิธีมอมเหล้า)
โชคดีที่บุคลิกของ roofimon เขาเป็น type นี้อยู่แล้ว
ก็เลยช่วยให้บรรยากาศสบายขึ้น

ที่น่าสนใจอีกเรื่องก็คือ กลุ่มคนที่ไป ~20 คน
มีผู้ที่อ่าน blognone แค่ 3-4 คน
???

ส่วนเรื่องที่พูดคุยกัน ก็มีเรื่อง
Acegi กับ tapestry

เรื่อง Acegi นี้ ถึงเคยใช้แล้ว
แล้วก็เคย post ไว้ด้วย Acegi อีกที
แต่ก็ลืมไปเกือบหมดแล้ว
แถมกลับไปอ่าน ก็รู้สึกว่า ที่เรารู้ตอนนั้น มันเป็นแค่ short cut ให้พอทำงานได้
ไม่ได้ get idea จริงๆ ว่าอะไรเป็นอะไร
มานั่งฟังคราวนี้ คิดว่า get idea แล้ว
ขอบคุณวิทยากรด้วย
(กลับมา ก็ไปเปิด Reference ของ Acegi หน้า 18-19 อ่านทบทวนอีกที)

ส่วนเรื่อง tapestry ที่ผมพูด
เกิดความผิดพลาดขึ้น 2 อย่าง
อย่างแรกก็คือ
ผมนึกว่าจะมีการพูดเรื่อง JSF ก่อน
เลยฝากเนื้อหาทั้งหลายไว้ให้คนที่พูด JSF เป็นคนพูด
ปรากฎว่าหัวข้อ JSF งดไป
(ซวยละสิ ใครจะเกริ่นนำให้วะ)
ข้อผิดผลาดที่สองก็คือ
เจ้า linux มันต่อ projector แล้วกลายร่างเป็น mode 800x600 อีกแล้ว
ทำให้การ demo ที่เป็นกะว่าจะค่อยๆขึ้นรูปขึ้นร่าง มันทำไม่ได้
เพราะ eclipse dialog มันล้นจอ
ตัว layout manager ของ SWT ก็ดันไม่ได้ออกแบบมา กรณีที่จอเล็กว่าเนื้อหา
ก็เลยไม่มี scrollbar ขึ้นมาช่วย scroll

พอ config dialog ไม่ได้ ก็ทำให้ขั้นตอนมันขาดไปขั้นหนึ่ง
จะหันไปแก้ xml file ด้วยมือ ก็ไม่แน่ใจว่าจะหาเจอหรือเปล่า
(Note:
กลับมาบ้าน แล้วยังติดใจอยู่ ลองใช้คำสั่ง grep -R หาดู
จึงรู้ว่าตัว config นี้มันเก็บไว้ใน directory
WORKSPACE_NAME/.metadata/.plugins/org.eclipse.debug.core/lauches/
)
ผลก็เลย demo ไม่ได้ตามที่เตรียม step ไว้
ก็เลยขอติดเป็นการบ้านไว้กับคนที่ไป NJUG ในครั้งนี้
ว่าคราวหน้าจะจัดเป็น workshop ให้แล้วกัน
(พูดอีกอย่าง ก็คือ จะเตรียมตัวให้มากกว่านี้)

Related link from Roti

Wednesday, November 08, 2006

อันเนื่องมาจากการเดิน

เห็น bact' เขา post เรื่องเดินเล่นทองหล่อตอนดึกแล้ว
ขอร่วมเล่าบ้าง

เนื่องจากบ้านผมอยู่ไกล้ที่ทำงาน ระยะทางแค่ 1.2 km
ดังนั้นการไปทำงาน ส่วนใหญ่ก็จะใช้การเดินเท้า
เส้นทางที่เดินไปก็เป็นเส้นทางธรรมดาๆในกรุงเทพนี่แหล่ะ
ใครที่ไป เมเจอร์รัชดาบ่อยๆ เส้นที่ว่านี้ ก็คือเส้นที่เลียบลานจอดรถของเมเจอร์

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

พอถึงหน้าหนาว หน้านี้เป็นหน้าดอกไม้บาน
ดอกดาวเรืองที่ปลูกตามทางเดิน ก็จะแข่งกันออกดอก
สีเหลืองส้ม ตัดกับฟ้าใสดี
ที่ชอบมากในหน้าหนาว ก็คือลม
ปกติเราจะมองไม่เห็นการเคลื่อนไหวของลม
แต่เส้นทางที่ผมเดิน มันมีต้นมะขามเทศอยู่ช่วงหนึ่ง
พอช่วงหน้าหนาว ใบมันจะร่วงลงมา
ทำให้เวลาเดินผ่านแล้ว เราจะมองเห็นความเคลื่อนไหวของลม
บางทีมันจะเดินไปกับเรา บางทีก็วิ่งสวน
บางครั้งก็หมุนวนเล่น

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

บรรดาตัวละคร ระหว่างทางก็มี
นกกระจอก, นกเอี้ยงสาลิกา ขาด้วน
อีกา 2 ตัว, นกเขาเล็ก, นกเขาใหญ่
ผมชอบดูพฤติกรรมของนกอยู่แล้ว
ก็เลยมีความสุขกับการได้สังเกตเจ้าพวกนี้

ส่วนตัวละครที่เป็นคนนั้น ผมชอบพี่ที่เป็นคนกวาดถนนของ กทม. มากเลย
เขาไม่ได้แค่ทำให้ถนนสะอาด
แต่เขาเป็นคนปลูกดอกไม้ ดูแลต้นไม้ตามทางเดิน

ปัจจุบันเส้นทางเส้นนี้ คลายเสน่ห์ไปหมดแล้ว
ตั้งแต่ห้างเมเจอร์เทปูน ทำลานจอดรถ
ดอกดาวเรืองหายไป เหลือแต่ดอกพังพวยที่มีความอึดต่อไอร้อนของปูน
ต้นไม้ใหญ่บางต้นถูกตัด คงเพราะกลัวกิ่งหล่นไปใส่รถที่จอดข้างใต้

Related link from Roti

Tuesday, November 07, 2006

Wirble

Wirble เป็น set ของ library ที่ช่วยให้เราใช้ irb (ruby interactive shell)
ได้อย่างมีความสุขมากยิ่งขึ้น
feature
  • สามารถเรียกใช้ ri จากใน irb ได้เลย
  • output ที่ได้มีสีสรรสวยงาม (colorize)
  • persistent command history

Related link from Roti

Friday, November 03, 2006

XBRL

XBRL ย่อมาจาก Extensible Business Reporting Language
เป็นความพยายามที่จะกำหนดมาตรฐานข้อมูลของงบการเงิน
ประเด็นก็คือ เขาต้องการให้ข้อมูลไหลจากที่หนึ่ง(publisher) ไปยังอีกที่หนึ่ง(consumer) ได้เร็วขึ้น
ใครได้ลองเล่นดู จะพบคำตอบว่าเมื่อบัญชีเจอกับ xml จะเกิดอะไรขึ้น

ตัวโครงสร้างของ XBRL ออกแบบไว้ดีเหมือนกัน
โดยแยกส่วนระหว่าง content กับ representation ออกจากกัน
นั่นคือ ตัว item ที่รายงาน จะอยู่ในรูป flat (list เรียงกันไปเป็นตับ)
ส่วน representation จะแยกออกไปอยู่ในอีกกลุ่ม file หนึ่ง (แน่นอนว่าเป็น xml)

แน่นอนเล่ามาแค่นี้ ไม่น่ามีความซับซ้อนอะไรมาก
ความซับซ้อน จะเริ่มต้นที่ว่า
representation นั้นสามารถทำการ override ได้
เช่นมาตรฐานระดับ country กำหนดว่า รูปแบบการ present เป็น แบบนี้

+ A
- sub1
- sub2
- sub3

แต่บริษัทเราอยาก present เป็นแบบนี้แทน

+ A
- sub1
+ B
+ sub2
+ sub3

XBRL เปิดโอกาสให้เรา override รูปแบบการนำเสนอได้
(ซึ่งจะเห็นได้ว่า การเปลี่ยนรูปแบบนำเสนอนี้
ไม่ได้ทำให้ข้อมูลระดับ item loss ไป)

ผมลองดูข้อมูล XBRL ของบริษัทในอเมริกาบริษัทหนึ่ง
แล้วทดลอง plot graph ความสัมพันธ์ระหว่าง xml, xsd ต่างๆ
ได้หน้าตา graph ออกมาดังนี้
สีเหลืองคือระดับที่บริษัททำ
สีเขียวคือระดับประเทศ
สีแดงคือมาตรฐานกลาง(ระดับโลก)

รูปแรกเป็นระดับ link ที่เราเห็นที่ระดับ syntax ของ xml



รูปนี้มาจากรูปเดิม แต่เป็นเพิ่ม link ระดับ semantic ที่เกิดจากการ extend เข้าไปด้วย



Note: อเมริกานี้มันทำอะไรซับซ้อนดีจริงๆ
แล้วใครคือผู้ได้ประโยชน์จากเรื่องแบบนี้

Update: เอารูป xbrl intance ของเกาหลีมาให้ดู
เห็นมันสวยดี

Related link from Roti

rails application in one exe file

ใครอยาก pack Rails Application ให้เหลือแค่ single execute file
แล้ว run บน native แบบนี้

C:\rails> demo.exe

อ่าน "Distributing Rails Applications"
Note: ใช้ SQLite เป็น Database

Related link from Roti

Tuesday, October 31, 2006

Lift

Tom White เขาพูดถึง Lift, Framework ที่ใช้ช่วยในการ testing
เขายกตัวอย่างใน post Lift Off
เปรียบเทียบวิธีเดิมที่ใช้ HttpUnit เทียบกับที่ใช้ Lift

HttpUnit
public class HttpUnitGoogleTest extends TestCase {

public void testGoogleImageSearch() throws Exception {
WebConversation conversation = new WebConversation();
WebResponse page = conversation.getResponse("http://www.google.com/");
assertEquals(page.getTitle(), "Google");
page = page.getLinkWith("Images").click();
WebForm form = page.getForms()[0];
form.setParameter("q", "kizoom");
page = form.submit();
assertTrue(page.getText().contains("<b>Kizoom</b> summer party"));
boolean foundImage = false;
for (WebImage i : page.getImages()) {
if (i.getSource().endsWith("summer04.jpg")) {
foundImage = true;
break;
}
}
assertTrue(foundImage);
}

}


Lift
public class GoogleTest extends NavigatingLiftTestCase {

public void testGoogleImageSearch() throws Exception {
goTo("http://www.google.com/");
assertThat(page, has(title("Google")));
clickOn(link("Images"));
enter("kizoom", into(textField()));
clickOn(button("Search Images"));
assertThat(page, has(text("Kizoom summer party")));
assertThat(it, has(image().withUrlThat(endsWith("summer04.jpg"))));
}
}

Related link from Roti

DataProvider ใน TestNG

พึ่งเห็น feature นี้ใน TestNG
Note: สังเกตนะว่า test case method รับ parameter ได้ด้วย
@DataProvider(name = "test1")
public Object[][] createData1() {
return new Object[][] {
{ "Cedric", new Integer(36) },
{ "Anne", new Integer(37)},
};
}

@Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
System.out.println(n1 + " " + n2);
}

ดูวิธีแบ่ง code กับ data สวยไปอีกแบบ

อย่างเมื่อก่อนถ้าผมต้อง test หลายๆ case หน้าตาที่ใช้ใน junit จะออกมาแบบนี้
public void testFormat() {
AST ast = parse(cmd, "(b10)");
assertFormat(ast, "b", null, "10");

ast = parse(cmd, "(c15)");
assertFormat(ast, "c", null, "15");

ast = parse(cmd, "(-c15)");
assertFormat(ast, "c", "-", "15");

...
...(ยาวไปอีก 1 หน้ากระดาษ)

Related link from Roti

Monday, October 30, 2006

รายงาน Blognone Tech Day #2

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

เรื่อง Relax NG นี่เคยตามไปอ่าน สมัยที่ bact'
เคย post ไว้ แต่ก็ไม่ซาบซื้ง
เจอคุณ James เปิดตัวอย่างให้ดู 10 กว่าตัวอย่าง
ก็ Satori เลย

ส่วนคุณ Theppitak ก็หน้าตาเหมือนในรูปที่ลงไว้ใน blog เป๊ะเลย
หน้าเด็กอีกต่างหาก
เห็นแล้วต้องฟันธงเลย ต้องบุคลิกอย่างนี้เท่านั้นแหล่ะที่สามารถเข้าร่วมกับ ต้นน้ำ(upstream) ได้
(อันนี้เป็นคำชมนะ สำหรับคนที่คิดว่าประโยคมันกำกวม)

ส่วนตัว Opencare ก็พึ่งรู้ว่าใช้ ActiveMQ,
ซึ่งเป็น tool ที่ผมจับอยู่แล้ว
อันนี้แหล่ะที่ผมน่าจะ contributed ได้โดยไม่ใช่แรงมากนัก
ไว้จะเข้าไปดูว่าจะช่วยอะไรตรงไหนได้บ้าง

หัวข้อ Intellectual Property ของ Mk ก็ถือว่าเป็น present ที่ดีมาก
จังหวะ กับ flow ลงตัวมาก
(ช่วงนี้เล่านิทานให้ลูกฟังบ่อย
นิทานที่ดี จังหวะ ภาพ การเล่าเรื่อง
จะลงตัว ทำให้ทั้งคนเล่าก็สนุก คนฟังก็สนุก)

ZWSP ของลิ่ว เริ่มเห็นเป็นรูปเป็นร่างแล้ว
เห็นประเด็นเรื่อง editor แล้ว
ชักอยากลองเขียนเป็น emacs extension แบบที่คุณ James เขียน Relax NG แล้วสิ

WiMAX
ในที่สุดก็รู้ว่ามันคืออะไร,
(จริงๆแล้ว ปีนี้มีน้องฝึกงานที่มาขอ consult เรื่อง project จบ
ก็ทำเรื่อง WiMAX simulation)

OPLC
อันนี้ไม่ค่อยได้ฟัง เท่าไร เพราะต้องไปนั่งปรับ resolution ของ slide
เนื่องจาก projector มันไม่ยอมแสดงผล 1024x768

Emerging Technology
จากหัวข้อนี้ ผมสนใจ embed มากขึ้นแฮะ
สงสัยต้องขอไปฝึกงานที่บริษัทฯแฟน ที่เขาทำ electronic device แล้ว

ประเด็น Feedback ของงาน
ผมเชื่อว่า คนที่ไป blognone ทุกคน มี potential ที่จะเล่าเรื่องได้ทุกคน
ดังนั้นทำอย่างไรให้งาน blognone คราวหน้า ก้าวผ่านขนบเดิมๆ
ที่ว่า ความรู้มาจากการบรรยาย (พิธีกรนั่งโต๊ะพูด)
กลายเป็นการแลกเปลี่ยน อย่างไม่เป็นทางการ
ทุกคนสลับกันเป็นผู้เล่า และผู้ฟัง
แน่นอนว่า เราไม่สามารถเปลี่ยนวัฒนธรรมของเราได้อย่างทันทีทันใด
ดังนั้นช่วงแรกๆที่ทำ อาจจะต้องค่อยๆเปลี่ยนวิธีบรรยายก่อน
จากเดิมที่เป็นคนเดียวพูด ทำให้มันกลายเป็นการสนทนาของคนหลายๆคน
ไม่ใช่บรรยาย ถามตอบนะ แต่เป็นแบบ ร่วมกันเล่าเรื่อง
(มีแก่นเรื่อง แจกไปก่อน แล้วพวกที่ต้องสนทนา จะเตรียมในส่วนที่ตนสนใจ)

Related link from Roti

Tuesday, October 24, 2006

The Art of Complex Problem Solving

The Art of Complex Problem Solving
เอามาฝาก bact'
ไม้รู้ว่าเคยเห็นหรือยัง

Related link from Roti

กบตัวน่อย

เห็นที่ keng เขียนถึง DocWeb ใน Speed high, realiable low แล้ว
อดยิ้มไม่ได้ เพราะตัวเองก็เป็นเหมือนกัน
คำว่า "เป็น" นี้หมายถึง
อาการ "หืมห์ มีคนทำแบบนี้ด้วยหรือ. page แบบ dynamic แต่ไม่เก็บข้อมูลลง Database,
ทุกอย่างอยู่ใน log file หมด. ถ้า server ล่ม ก็แค่สั่ง rerun log file."

สมัยแรกๆที่ใช้ java อย่างเดียว เวลาเจอแนวทาง solution แบบนี้แล้ว
มักจะส่ายหัว แล้วก็มองข้ามไป
แต่หลังจากที่อ่านมาก ทดลองมากขึ้น (กับภาษาอื่นๆ)
ก็พบว่า "เออ เรานี่ กำหนดกรอบ มาครอบตัวเราไว้เองนี่หว่า"

อย่างเมื่อต้นเดือนที่เขียนถึง Prevayler
ซึ่งทำงาน เหมือนกับที่ James Gosling เขาใช้ใน DocWeb นั่นแหล่ะ
ถ้าเป็นเมื่อสมัย 2 ปีก่อน รับรองว่า แค่เข้าไปอ่าน feature ก็ยังไม่อ่านเลย
(เพราะโดนกรอบความคิดจำกัดไว้)

**UPDATE**
จาก Mailing list ของ Erlang
We are in the process of eliminating databases. Why did we use them in
the first place? You just do. If you are an engineer and I say I need
to store a lot of data and your answer is not "A database!", you fail
CS101. No one ever asks, "how do you want to access it, why do you
think you need a database".

Related link from Roti

Friday, October 20, 2006

IOC in Tapestry 5

ใน Tapestry 5 นี้
Howard (คนเขียน) เขาจะ implement IOC ขึ้นมาเอง
(เดิมใช้ Hivemind อยู่, ถ้าจะท้าวความให้ลึกอีกหน่อย
Hivemind เกิดขึ้นเพราะต้องการให้เป็น infrastructure ของ Tapestry)
ประเด็นก็คือ เขาไม่มีเวลาพอที่ maintain Hivemind ในรูป Generic IOC container
เพราะต้องการที่จะ customize IOC สำหรับ Tapestry โดยเฉพาะ

แนวของ IOC ตัวใหม่นี้ จะลดการใช้ XML ลง
ลองดูตัวอย่างการ inject แบบนี้ดู น่าสนใจดี
public static Indexer buildIndexer(
@InjectService("JobScheduler") JobScheduler scheduler,
@InjectService("FileSystem") FileSystem fileSystem)
{
IndexerImpl indexer = new IndexerImpl(fileSystem);

scheduler.scheduleDailyJob(indexer);

return indexer;
}


แน่นอน ข้างบนนี้เป็นทางเลือกแบบหนึ่ง
แบบที่คนจำนวนหนึ่งชอบ ก็คือ automatic wire โดยไม่ต้อง config เลย
ก็มีเหมือนกัน

Related link from Roti

ไปสัมมนา BiZIT

เมื่อวันพุธแอบเปลี่ยนบรรยากาศ แว่บไปงานสัมมนาของ BiZIT มา
ในงานก็เจอน้อง OHM ที่เปลี่ยนบรรยากาศมาจากโคราช
(เจอกัน เพราะเป็นพวกนั่งแถวหน้าเหมือนกัน เลยเจอกันง่ายหน่อย)

section ที่เข้าฟังก็มี
"IT Innovation for Business Empowering" ของ อาจารย์ยืน ภู่สุวรรณ
ที่ชอบสุดก็คือคำถามของ section นี้ มีคนถามประเด็นว่า
"ในยุคเริ่มต้นของ internet เรามี DNS เป็นตัว solve ว่าอะไร อยู่ที่ไหน
พอมาในยุค webservice เรามี UDDI ที่ใช้ solve เช่นกัน ว่าอะไรอยู่ที่ไหน
ที่นี้ ในยุคที่ platform เริ่มย้ายขึ้นมาอยู่บน web ,มันจะมีกลไกอะไรมาแบบนี้อีกไหม"
คำถามที่ดี คือคำถามที่ไม่มีคำตอบ

"บทบาทและทิศทางของ SOA ในองค์กร"
หัวข้อนี้ฟังแล้วเข้าใจแล้ว ว่า SOA คืออะไร,
SOA ก็คือ ดินแดนในฝัน(Utopia) ของพวกเราชาว IT
ถ้าใครอยากไปให้ถึงดินแดนนั้น
IBM มีแนวทางที่ถ้าท่านเลือกไปปฏิบัติแล้ว,
รับรองว่าจะเดินทางถึง SOA land แน่นอน.
Note: ไม่เลวร้ายขนาดนั้นหรอกนะ ผมแค่ล้อ IBM เล่น
ในการบรรยาย ก็มี issue ที่น่าสนใจเหมิือนกัน

"Digital Right Management on Multimedia Content"
อาจารย์พันธุ์ปิติ เปี่ยมสง่า แกพูดเก่งดีนะ
มีเสียงเล็กเสียงน้อย ฟังเพลินดี

"Multi-Threaded Chip Technology"
ฟังจบก็รู้ว่า มันน่าจะเร็ว
แต่ก็งงงวยเหมือนเดิมว่า multi thread ใน chip มันเป็นอย่างไร
(วิทยากรเขาเก่งนะ แต่เขาตั้งใจ จะไม่แตะด้าน technical มากเกินไป)

"RFID for Business Efficiency Improvement"
อ้า ฟัังแล้วได้ข้อสรุปว่า
RFID มันมีประเด็นเกี่ยวกับ characteristic ของ คลื่นวิทยุ
ความยากในการ implement ส่วนหนึ่งก็จะอยู่ที่ตรงนี้
เช่น align ของ เสาอากาศ ควรจะเป็นอย่างไร,
มีความชื้นสูง จะเกิดปัญหาอย่างไร

ปล.
ความรู้ที่ได้มากสุด ก็คือคุยกับ OHM แล้วล้วงเอาความลับ
ของการผลิต Harddisk ออกมา
(OHM เขาทำอยู่ seagate)
ใครที่ไปงาน blognone techday แล้วบังเอิญนั่งข้าง OHM
อย่าลืมชวนคุยเรื่อง Harddisk นะ
รับรองว่าได้ความรู้กลับมาเต็มที่แน่นอน

Related link from Roti

Pugs

Pugs คือ Perl6 ที่ implement ด้วย Haskell
มุมที่ผมสนใจ คงไม่ใช่เรื่อง perl6
แต่เป็นเรื่อง parser library ที่ Pugs ใช้
ซึ่งก็คือ Parsec กับ Happy

ในไทยมีคน blog เรื่อง Pugs แล้วด้วย
อ่านดูได้ที่นี่ Guruguru

Related link from Roti

Into the Ravines

Martin Fowler เขียน comment ดีๆไว้อีกแล้ว
คราวนี้เป็นเรื่องเกี่ยวกับ nature ของการเรียนรู้สิ่งใหม่ๆ
ImprovementRavine
แค่เปิดฉากเริ่มต้น ก็ชอบใจเสียแล้ว

If you care about what you do, you care about getting better at it.


The point is that when you try a new technique it'll often make you worse, at least initially. You have to work with something unfamiliar, perhaps also unlearn something else that gets in the way. During that period you performance has dipped. Only with perseverance can you get through this and reach a higher plateau.

Related link from Roti

Tuesday, October 17, 2006

Mercurial

ช่วงนี้มี project เล็กๆน้อยๆเต็มไปหมด
อยากทำ version control ได้
แต่ไม่อยากไปนั่ง create repository ที่ server
หรือลง subversion server ที่เครื่องตัวเอง
ก็เลยมองหา Revision Control ตระกูล Distributed มาลองใช้ดู

ลองใช้อยู่ 2 ตัวคือ Mercurial กับ Darcs
สุดท้ายก็ไปจบลงที่ Mercurial เพราะ
  • คำสั่งมันดูไกล้เคียงกับ svn ดี
  • เวลาจะ sync ข้ามเครื่อง
    ตัว Mercurial สามารถ start embed web server ได้เองเลย
    ไม่ต้องเสียเวลาไปทำ link ไว้ใน apache htdocs

Related link from Roti

Monday, October 16, 2006

คำชม

น่าสนใจนะ ระหว่างคำชม
"You are a good drawer" กับ
"You did a good job drawing"
อันไหนมี effect ต่อเด็กอย่างไร

Link

Related link from Roti

Migrator

ใครที่ได้ใช้ Rails แล้ว
เวลากลับมาใช้ Java ก็มักจะนำเอาบางอย่างติดมือกลับมาด้วย
อย่าง project Migrator นี้ก็เหมือนกัน
เกิดจากคนเขียนที่เคยใช้ Rails มาก่อน แล้วต้องกลับมาทำ java project

Project ที่แล้วของผม
ก็มีการนำเอา concept ของ Migration มา apply ใช้เหมือนกัน
เนื่องจากการพัฒนา ใช้ methodology แบบ Agile,
schema ของ Database จะค่อยๆ evolve
ก็เลยอยากให้สามารถเก็บ version ของ Database Schema ได้ด้วย
(เนื่องจาก script sql อยู่ใน codebase ที่เก็บลง version control)

Related link from Roti

Tuesday, October 10, 2006

Rails Multibyte Support

Changeset 5223 เพิ่ม feature ในการ support multibyte
ลองดูตัวอย่าง

>> $KCODE='UTF8'
=> "UTF8"
>> name = 'ภาษาไทย'
=> "ภาษาไทย"

>> name.length
=> 21
>> name.chars.length
=> 7

>> name.reverse
=> "\242\270룠蒹ಸ੸ಸ࠸\340"
>> name.chars.reverse
=> #<ActiveSupport::Multibyte::Chars:0x28ad624 @string="ยทไาษาภ">
>> name.chars.reverse.to_s
=> "ยทไาษาภ"

>> name[1..3]
=> "\270\240\340"
>> name[0..3]
=> "ภ\340"
>> name.chars[0..3].to_s
=> "ภาษา"

Related link from Roti

Monday, October 09, 2006

ทดสอบ Cometd

วันนี้ทดลองทดสอบ Cometd
โดย definition ของ Cometd ก็คือ

Cometd is a scalable HTTP-based event routing bus that uses a push technology pattern known as Comet.

สิ่งที่ Cometd พยายามทำ ก็คือ การกำหนดมาตรฐาน protocol สำหรับ client กับ cometd server
ตัว draft ของ Protocol สามารถดูได้ที่นี่
http://svn.xantus.org/shortbus/trunk/bayeux/protocol.txt

ตัว Cometd server ตอนนี้เห็นว่ามี implement ด้วย
python, http://svn.xantus.org/shortbus/trunk/cometd-twisted/
perl http://svn.xantus.org/shortbus/trunk/cometd-perl/
แล้วก็ Java
(ผมก็กะว่าจะทำ erlang version เหมือนกัน)

ในฝั่ง Java ตอนนี้มี Jetty เป็นหัวหอก
โดยใน jetty version 6 , jetty provide CometdServlet มาให้เลย (อยู่ใน directory extras)

ที่ Jetty เป็นหัวหอกในเรื่องนี้ ก็เพราะเขามี feature Continuations ที่คนอื่นยังไม่มี
เขาก็เลย implement และผลักดัน Cometd ได้อย่างไม่เกรงกลัวว่าจะทำให้เกิดปัญหา server overload
(เคยเขียนเรื่อง Jetty Continuations ไปแล้ว ตามอ่านได้ที่นี่ Link)

สำหรับในส่วน client ตอนนี้ก็มี Dojo ที่ implement ใน Trunk แล้ว
โดยอยู่ใน package dojo.io.cometd
ประเด็นที่น่าสนใจใน Dojo Cometd client ก็คือ
technique ของการ implement มีให้เลือกหลายแบบคือ
  • iFrame
  • mime-message-block
  • long-poll
  • callback-polling

ผมลองทดสอบแค่ long-poll
เท่าที่ลองทดสอบดูในเบื้องต้น ก็พบปัญหาว่า
jetty return response ในตอน handshake กลับมาไม่ตรงตาม Spec ใน protocol
(แทนที่จะ return array ครอบ json Object, มันกลับ return json Object มาเลย,
ผมใช้วิธี quickfix แก้ source code ใน dojo ให้ทำงานได้ไปก่อน)
ปัญหาอีกข้อที่เจอก็คือ ตัว Demo ยัง run ใน IE หรือ Safari ไม่ได้

Related link from Roti

Camlp4

วันนี้มีเหตุให้ต้อง compile โปรแกรมที่เขียนด้วย OCaml
ก็เลยทำให้ได้รู้จักกับ Camlp4

Camlp4 เป็นโปรแกรมที่เปิดให้เราสามารถ modify syntax ของ OCaml ได้
ทำให้เราสร้าง DSL หรือ customize OCaml syntax ได้

ไว้ให้ผมเป็น OCaml ก่อน แล้วจะเขียนอธิบายเรื่องนี้ให้ฟัง

Related link from Roti

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

Friday, September 29, 2006

Agile

บทบ่นล่าสุดของ Steve Yegge ,Good-Agile-Bad-Agile
พูดถึง Agile software developement
(คนอะไร เขียน blog โคตรยาวเลย, ผมขี้เกียจอ่านทั้งหมด ก็เลยเลือก scan อ่าน)
ในประเด็นว่า อะไรที่ชอบ อะไรที่ไม่ชอบ
แล้่วก็ยกตัวอย่าง บรรยากาศที่ทำงานของ Google ว่ามันเจ๋งอย่างไร

- there are managers, sort of, but most of them code at least half-time, making them more like tech leads.
(บริษัทฯเราก็เข้าข่ายนี้เหมือนกัน)

- developers can switch teams and/or projects any time they want, no questions asked; just say the word and the movers will show up the next day to put you in your new office with your new team.

- Google has a philosophy of not ever telling developers what to work on, and they take it pretty seriously.

- developers are strongly encouraged to spend 20% of their time (and I mean their M-F, 8-5 time, not weekends or personal time) working on whatever they want, as long as it's not their main project.
(อ้า ข้อนี้ก็ตรงกัน แต่ของเราเผลอๆ สัดส่วนอาจมากกว่า 20 %)

- there aren't very many meetings. I'd say an average developer attends perhaps 3 meetings a week, including their 1:1 with their lead.
(อันนี้ บริษัทฯ ผมน้อยกว่ามาก, บางอาทิตย์ก็ไม่มี meeting)

- it's quiet. Engineers are quietly focused on their work, as individuals or sometimes in little groups or 2 to 5.
(ไม่เหมือนกัน ที่บริษัทฯของผมเสียงดังมาก
บางวันก็มีเสียงร้องให้ของลูกชายผมด้วย)

- there aren't Gantt charts or date-task-owner spreadsheets or any other visible project-management artifacts in evidence, not that I've ever seen.
(ของผมนานๆจะมีที โดยมากมักจะมีในช่วงเริ่มต้นโครงการ)

ส่วนที่ชอบก็คงในส่วน comment ที่มีคนตอบกลับ
(ยาวกว่าบทบ่นอีก)
มีที่ตรงใจอยู่อันหนึ่ง Link
ก็คือ Agile มันเป็นเรื่องของ culture
เพราะเมื่อต้นอาทิตย์ก็ได้เข้าไปที่ ตลาดหลักทรัพย์ฯ
โดยเข้าไปอธิบายเรื่อง methodology ที่บริษัทฯใช้อยู่
(เนื่องจากจะมีโปรเจคที่ต้องทำร่วมกัน ก็เลยต้องแลกเปลี่ยนกันก่อน)
ก็สัมผัสได้ถึง mismatch ของวัฒนธรรมองค์กรอยู่เหมือนกัน

Related link from Roti

Thursday, September 28, 2006

Nuxeo & OSGi

Nuxeo ก็เป็นอีกรายที่เปลี่ยน Architecture มาใช้ OSGi
ลองอ่านเหตุผลในการ switch ของเขาดู Link

ตัวอย่าง use case ในการใช้ extension-point ของ Nuxeo ก็เช่น
  • define actions and menus
  • define content schemas
  • define views
  • define content objects
  • define permissions
  • define PageFlows
  • define Business Process
  • define content trnsformations
  • define rule for rule engine
  • define script extension (JRuby, Jython,...)
  • define JMS Event queue
  • define event type
  • define security policies
  • define Access Control Policies
  • define Storage Backend
  • define query engine
  • define indexing engine


ใครที่ยังไม่เคยเห็น Architecture ของ OSGi ขอแนะนำให้ทดลองเล่นหรืออ่านดูครับ
โดยเฉพาะ model ในส่วน Extension Point หรือ Plugin
ออกแบบได้งามมากๆ

Related link from Roti

Wednesday, September 27, 2006

My Neighbor Totoro



หนังเรื่อง My Neighbor Totoro กลายเป็นหนังเรื่องโปรดของครอบครัวผมไปแล้ว
ไม่ว่าจะเป็น พ่อ แม่ ปู่ ย่า หรือ เจ้าลูกชาย

หนังเรื่องนี้เป็นหนังที่ดูซ้ำได้โดยไม่เบื่อ
ผมดูกับลูกชายไปสามรอบแล้ว ก็ยังสนุกอยู่
(เมื่อกี๊แฟนเดินมาแซวว่า ของฉันดูไปห้ารอบแล้ว)

Related link from Roti