Friday, March 10, 2006

Virtual Desktop Manager for Mac Os X

หามานาน
สมหวังสักที
Desktop Manager

Related link from Roti

Pattern การ implement Object ใน Prototype.js (1.4.0)

style ปกติที่เราใช้สร้าง javascript object
ก็คือการใช้ function
ตัวอย่าง

function Person(name, age) {
this.name = name;
this.age = age;
this.dump = function() {
return this.name + ", " + this.age;
}
}

var p = new Person("pann", 1);

ซึ่งก็มีหลายคนออกมาชี้ว่า
วิธีนี้ ถ้าเรามี object จำนวนมาก
มันจะเปลือง memory นะ, เพราะ method dump
มันถูก declare ขึ้นมา 1 function ต่อ 1 object
ก็เลยมีการพลิกแพลงออกไปใช้ prototype
(เวลา javascript object ถูกเรียกใช้งาน มันจะมองหา attribute ภายใน
scope ของมันก่อน ถ้าไม่เจอก็จะค้นหาจาก object ที่ pointer prototype ชี้อยู่)

function Person(name, age) {
this.name = name;
this.age = age;
}

Person.prototype = {
dump: function() {
return this.name + ", " + this.age;
}
}


Prototype.js ก็เห็นดีเห็นงามกับแนวทางที่ 2 (อันนี้เป็นสาเหตุ ว่าทำไม library ถึงชื่อ prototype)
แต่ตบแต่ง style เสียใหม่
ได้หน้าตา การประกาศ object ออกมาแบบนี้

var Person = Class.create();

Person.prototype = {
initialize: function(name, age) {
this.name = name;
this.age = age;
},

dump: function() {
return this.name + ", " + this.age;
}
}

ซึ่งก็ดูดีขึ้นนะ (ถ้าเข้าใจว่ามันทำงานอย่างไร)
magic อยู่ที่ function Class

var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}

เมื่อเราเรียก var Person = Class.create()
ตัวแปร Person จะชี้ไปยัง function ที่ return กลับออกมาจาก Class object
และเมื่อเราเรียก Person.new ก็จะเกิดการเรียกใช้ function ที่ชื่อ initialize
ซึ่งถูก declare ไว้ใน Person.prototype object

เมื่อมี object แล้วก็ต้องมีการ extend หรือ inheritance
ใครที่มาจากสาย java แล้วใช้ความคิดแบบ java เข้ามาจับ
รับรองว่าได้ปวดหัวกับการ debug แน่นอน
คำแนะนำที่ดี ก็คือ อย่า design แบบ deep hierachy tree เลย
พวก polymorphic หรือ overloading
ก็อย่าไปนึกถึง

แต่ถ้าอยากลองดู ลองอ่านอันนี้ดู Object Hierarchy and Inheritance in Javascript
ซึ่งดูเหมือนจะเป็น technique แบบเก่า
ถ้าอยากได้แบบใหม่ๆหน่อย ก็ลองอ่านนี่ดู
Javascript Inheritance
แต่ผมไม่ค่อยชอบ technique ที่เขาแนะนำเท่าไร
มันดูแปลกๆในส่วนของการ copyPrototype

ใน Prototype.js ก็มี method extend ให้ใช้เหมือนกัน
แต่ส่วนใหญ่จะใช้ในลักษณะของ Mixin แบบ ruby เสียมากกว่า
โดยการ design จะใช้วิธีเสริม function เข้าไปใน object ที่มีอยู่แล้ว
เช่น

var Enumerable = {
...

findAll: function(iterator) {
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
results.push(value);
});
return results;
},

...
}

Object.extend(Array.prototype, Enumerable);

ทำให้เราสามารถทำแบบนี้ได้


[1,2,3].findAll(function(value) {
return value > 1;
})
// => [2,3]

Related link from Roti

ลานนาจัง กับ ทักษิน

แถาบ้านมีคนญี่ปุ่นอยู่คนหนึ่ง ชื่อ ยูโกะจัง
ทำงานเป็น air hostage อยู่การบินไทย
ยูโกะมีลูกสาวคนหนึ่ง ชื่อ ลานนาจัง
(ชื่อไทยซะด้วย)

ตอนนี้ ลานนาจัง อายุได้ 7 เดือนแล้ว
กำลังน่ารักเลย

วันก่อนภรรยาผมเล่าให้ฟังว่า
ยูโกะจังบ่นให้ฟังว่า

ลานนาจังเกิดวันเดียวกับทักษิน worry นะคะ..
โตขึ้นมาจะเป็นยังไง ...
money money หรือเปล่า, material girl...

Note: กรุณาอ่านออกเสียงแบบคนญี่ปุ่นพูดไทย

Related link from Roti

Form Object ใน Prototype.js (1.4.0)

หลังจากดู presentation A (Re)-Introduction to javaScript
ของคุณ Simon Willison จบแล้ว ก็เกิดความเข้าใจใหม่ๆขึ้นมาอีกมาก

เดิมผมจะมีปัญหากับการอ่าน javascript ที่เขียนแนว Object อยู่มาก
ที่เป็นแบบนี้ ก็เพราะ ผมเอาแนวคิดของ java (class-based) ไปตีความเจ้า javascript (Prototype-based)
ก็เลยเกิดอาการ มึนๆ งงๆ
แต่หลังจากเรียนรู้ ruby, lisp มาระยะหนึ่ง
ซึ่งช่วยขยายกรอบความคิดเกี่ยวกับเรื่อง programing language ขึ้นอีกเยอะ
ก็เลยทำให้หลังจากดู presentation ข้างบนจบ (slides ยาวมาก)
ก็เลยเกิดอาการ Satori เล็กๆขึ้นมา

ผลของ Satori ก็เลยทำให้เกิดความฮึกเหิม ย้อนกลับไปใล่ดู
source code ของ Prototype.js
โดยเลือกดูส่วนที่เกี่่ยวกับการจัดการ Form ก่อน

Object ของ Prototype ที่ใช้จัดการกับ form
ใช้ชื่อตรงตัวเลยว่า Form
ใน source code มีการประกาศไว้ดังนี้

var Form = {
serialize: function(form) {
...
},

getElements: function(form) {
...
},

...
}


method ประกอบด้วย
  • serialize
    return string ที่ใช้ในการ submit form ผ่าน ajax
    ตัวอย่างการใช้งาน
    สมมติ html ดังนี้

    <form id="myform" action="#">
    <input name="input1" type="text" value="xxx"/>
    <input type="checkbox" name="input3" checked="checked" />
    <input name="input2" type="submit"/>
    </form>

    แล้วใช้คำสั่ง Form.serialize

    Form.serialize('myform'); // => input1=xxx&input3=on&input2=

  • getElements
    รับ parameter เป็น form เหมือนกัน
    ผลลัพท์ที่ได้คือ Array ของ Element ที่อยู่ใน form (เฉพาะพวกที่ใช้ input เช่น input, textarea, ...)
  • getInputs
    ค้นหา Element ประเภท input โดย
    รับ parameter เป็น form, ประเภทของ input และ ชื่อของ element นัั้น
    เช่น

    Form.getInputs('myform', 'text', 'input1')

  • disable
    ไว้สั่ง diable form ที่ต้องการ
  • enable
    สั่ง enable form ที่ต้องการ
  • findFirstElement
    อันนี้ดูไม่ค่อยมีประโยชน์เลย รู้สึกว่าจะมีไว้ใช้ใน focusFirstElement
  • focusFirstElement
  • reset


เห็นได้ว่า method ทั้งหมด มี require parameter
เป็น form element หรือ form name ทั้งสิ้น (รับได้ทั้ง 2 แบบ)

Helper object ที่ Form เรียกใช้ มีอยู่ 2 ตัวคือ
  • Form.Element
    มีแค่ 2 method คือ
    • serialize(element)
      อันนี้ถูกเรียกจาก Form.serialize โดยมีเป้าหมายพื่อ encode ข้อมูลเพื่อ submit
    • getValue(element)
      อันนี้ไว้ใช้ get ค่าที่อยู่ใน Element ที่ต้องการ
      รับ parameter เป็น element id หรือ element object ก็ได้

  • Form.Element.Serializers
    อันนี้เป็น lower layer แล้ว ถูกเรียกใช้จาก Form.Element อีกที


ใน Prototype มี Helper Function ที่ชื่อ $F
ซึ่งจริงๆแล้ว ก็คือ short-cut ของ Form.Element.getValue นี่เอง

var $F = Form.Element.getValue;

Related link from Roti

Thursday, March 09, 2006

Synergy

ได้โปรแกรมดีๆมาช่วยงานอีกตัวแล้ว
Synergy เป็นโปรแกรมที่่ช่วยให้เรา share keyboard และ mouse
ระหว่างเครื่องคอมพิวเตอร์ โดยไม่ต้องใช้ hardware
รวมทั้งยัง support การ share ระหว่าง platform ด้วย (windows, Linux/Unix, Mac OS X)

การใช้งานก็ไม่ยาก
เครื่องคอมพิวเตอร์ที่เราจะใช้ keyboard และ mouse
จะ start ใน mode ของ server
ส่วนเครื่องที่เหลือ start ใน mode client

การ start ใน mode server ต้องมี config file ด้วย
หน้าที่ของ config file ก็คือจัดเรียง screen
ว่าเครื่องไหนอยู่ขวา, ซ้าย, บน, ล่าง เมื่อเทียบกับเครื่องอื่น
การจัดเรียงนี้ จะช่วยให้เราลาก mouse ข้ามเครื่องได้

ตัวอย่าง config ของผม

section: screens
g5.local: # my Apple G5
erp: # my Laptop Gentoo
end

section: links
g5.local:
left = erp

erp:
right = g5.local
end

section: options
keystroke(alt+f1) = switchInDirection(left)
keystroke(alt+f2) = switchInDirection(right)
end

Related link from Roti

Wednesday, March 08, 2006

Search Rails api with ri

เดิมเวลาผมจำไม่ได้ว่า method ที่ต้องการมี argument อะไรให้ pass บ้าง
ก็จะ start gem_server แล้วใช้ browser ค้นดู

document ของ rails ในกรณีนี้
ได้มาจากการใช้ program rdoc generate html files ขึ้นมา
ซึ่งปกติเวลาเรา install rails ด้วย gem
มันจะ automatic ทำให้อยู่แล้ว

วันนี้มีอีก solution หนึ่ง
ก็คือการใช้ ri ในการ search
โดยปกติ ri จะค้นหา document ที่อยู่ภายใต้ site-directory
(เครื่องผมอยู่ที่ /usr/share/ri)
กับภายใต้ ~/.rdoc

เราสามารถใช้คำสั่ง rdoc --ri
เพื่อสร้าง output file ที่ ri สามารถใช้ได้
โดย files ที่ได้จะอยู่ภายใต้ directory ~/.rdoc

ตัวอย่างเช่น ถ้าผมต้องการให้ ri สามารถ search activerecord ได้
ก็จะทำการสั่งดังนี้

cd /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib
rdoc --ri


สำเหตุที่ใช้ ri ก็เพราะว่าต้องการเอาไปใช้กับ emacs

Related link from Roti

pack200

ตกข่าวอีกตามเคย
พึ่งรู้ว่า java web start ของ jdk1.5 support gzip format
ที่ได้จากโปรแกรม pack200
(ช่วย compress jar file ให้มีขนาดเล็กลงได้)

อ่านที่นี่
Pack200 and Compression
ตัวอย่างที่ sun แสดงไว้ เขาใช้ servlet เป็นคนเลือก format ในการส่งกลับ
กรณีที่ใช้ apache อย่างเดียว ก็ให้ดูตัวอย่างการ config จาก link นี้
How to use Pack200 for your Java Web Start applications on Apache Web Server

ตอนที่เห็นครั้งแรก ก็นึกว่ามันเป็น compress format ใหม่ๆ
แต่จริงๆแล้วมันก็คือ gzip format ธรรมดานี่แหล่ะ
โดยขั้นตอนการทำงาน เท่าที่ดู (เดา)
ก็คือ
เริ่มจาก มันจะ unpack jar เราก่อน (jar ก็เป็น compress format แบบหนึ่ง)
จากนั้นก็ pack กลับภายใต้ชื่อ file-name.pack
ตรงนี้ไม่รู้ว่า format เป็นอะไร
แต่ถ้าลองเทียบกับ tar format แล้ว
มันจะมีขนาดเล็กว่านิดหน่อย
(ทดสอบโดยใช้คำสั่ง jar xf เพื่อ extract jar file ออกมา
จากนั้นก็ใช้คำสั่ง tar cf กับเนื้อหานั้นๆ)
สุดท้ายก็ compress pack format ด้วย gzip
(file ที่ได้ ก็เลยชื่อ file-name.pack.gz)

ลองทดลองกับ jar file ดังนี้
  • oscar.jar
    (OSGi framework)

    jar size 149469 bytes
    pack200 size 45426 bytes
    jar.gz size 138213 bytes

  • SwingSet2.jar
    เป็น demo ที่ bundle มากับ jdk

    jar size 1432007 bytes
    pack200 size 1148563 bytes
    jar.gz size 1390818 bytes

  • Stylepad.jar
    มากับ demo เหมือนกัน

    jar size 102221 bytes
    pack200 size 65864 bytes
    jar.gz size 96329 bytes

Related link from Roti

รูปเส้นทางขี่จักรยาน trip-น่าน




ตัวอย่างเส้นทางที่ขี่ งามมาก ขี่ไต่ไปตามสันเขา
ภาพที่เห็น รู้สึกจะเป็นแถว กิ่วมรณะ
ที่ได้ชื่อนี้ ก็เพราะว่า สมัยที่ยังมีการปะทะกันอยู่
จุดนี้คือจุดซุ่มโจมตีของ ผกค. (ชัยภูมิเหมาะสมมาก)

พี่ๆที่ไปด้วย เขาลงเรื่องไว้ที่นี่
http://thaimtb.com/cgi-bin/viewkatoo.pl?id=81687
http://www.thaimtb.com/cgi-bin/viewkatoo.pl?id=81340

Related link from Roti

Embeded Java



อาทิตย์ก่อนได้ลองเล่น Snap ซึ่งเป็น product ของ ImSys
ตัวอย่าง features
  • Sun certified J2ME-CLDC
  • Native Java execution
  • 10/100Base-T Etherne
  • 2 Mbytes flash memory
  • 8 Mbytes DRAM


feature ที่ระบุว่าสามารถทำ native java execution
ก็เพราะ cpu ที่ snap board ใช้ (CISC/WISC)
สามารถ program ระดับ microcode ได้
(แก้ไขระหว่าง runtime ได้อีกต่างหาก)
ก็เลยสามารถ implement ให้ interpret java byte code ได้

Note: คำว่า WISC ย่อมาจาก Writable Instruction Set Computing

การพัฒนา java ก็ใช้ developer tool อะไรก็ได้
ขอให้ compile ให้ได้ byte code แล้วกัน
พอได้ class file ก็ใช้ ftp load โปรแกรมลงไป (snap start ftp server ได้)

ตอนแรก กะว่าจะทดลองลง Oscar (OSGi Framework) ดู
ปรากฎว่ามีปัญหาเรื่องขนาด เพราะ OSGi ดูเหมือนจะเล็ก แต่จริงๆแล้วขนาดไม่เบาเลย
ก็เลยเลือกแต่ core กับ shell bundle ลงไป
สุดท้ายไปติดปัญหาว่า snap ไม่ support jar file ก็เลยล้มเลยความตั้งใจ

จากนั้นก็แอบดู model ของการ implement cgi program
ก็ง่ายๆ ตรงไปตรงมาดี หน้าตาประมาณนี้

public class HelloCgi implements HttpCgi {
public void execute(Hashtable variables, OutputStream os) throws .. {
....

}
}

ตอน start server ก็แค่

HttpServer hs = new HttpServer();
Thread t = new Thread(hs)
hs.addCgi(new HelloCgi());
t.start();


ยังเหลือที่อยากลองอีกอย่าง ก็คือ อยากลองดูว่า เราสามารถ implement Jini บน snap ได้หรือไม่?

Related link from Roti

Monday, March 06, 2006

How to be an expert

เห็นที่ bact' ลง link video แสดงการเล่น yoyo ชั้นเซียนแล้ว
ไปอ่านเจอ How to be an expert ก็เลยเอาทำ link ไว้

Related link from Roti